1 /*
2 * deref.c
3 *
4 * Make all texinfo references into the one argument form.
5 *
6 * Arnold Robbins
7 * arnold@gnu.org
8 * Written: December, 1991
9 * Released: November, 1998
10 *
11 * Copyright, 1991, 1998 Arnold David Robbins
12 *
13 * DEREF is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * DEREF is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
26 */
27
28 /*
29 * LIMITATIONS:
30 * One texinfo cross reference per line.
31 * Cross references may not cross newlines.
32 * Use of fgets for input (to be fixed).
33 */
34
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <errno.h>
38
39 /* for gcc on the 3B1, delete if this gives you grief */
40 extern int fclose(FILE *fp);
41 extern int fprintf(FILE *fp, const char *str, ...);
42 /* extern int sprintf(char *str, const char *fmt, ...); */
43 extern int fputs(char *buf, FILE *fp);
44
45 extern char *strerror(int errno);
46 extern char *strchr(char *cp, int ch);
47 extern int strncmp(const char *s1, const char *s2, int count);
48
49 extern int errno;
50
51 void process(FILE *fp);
52 void repair(char *line, char *ref, int toffset);
53
54 int Errs = 0;
55 char *Name = "stdin";
56 int Line = 0;
57 char *Me;
58
59 /* main --- handle arguments, global vars for errors */
60
61 int
main(int argc,char ** argv)62 main(int argc, char **argv)
63 {
64 FILE *fp;
65
66 Me = argv[0];
67
68 if (argc == 1)
69 process(stdin);
70 else
71 for (argc--, argv++; *argv != NULL; argc--, argv++) {
72 if (argv[0][0] == '-' && argv[0][1] == '\0') {
73 Name = "stdin";
74 Line = 0;
75 process(stdin);
76 } else if ((fp = fopen(*argv, "r")) != NULL) {
77 Name = *argv;
78 Line = 0;
79 process(fp);
80 fclose(fp);
81 } else {
82 fprintf(stderr, "%s: can not open: %s\n",
83 *argv, strerror(errno));
84 Errs++;
85 }
86 }
87 return Errs != 0;
88 }
89
90 /* isref --- decide if we've seen a texinfo cross reference */
91
92 int
isref(char * cp)93 isref(char *cp)
94 {
95 if (strncmp(cp, "@ref{", 5) == 0)
96 return 5;
97 if (strncmp(cp, "@xref{", 6) == 0)
98 return 6;
99 if (strncmp(cp, "@pxref{", 7) == 0)
100 return 7;
101 return 0;
102 }
103
104 /* process --- read files, look for references, fix them up */
105
106 void
process(FILE * fp)107 process(FILE *fp)
108 {
109 char buf[BUFSIZ];
110 char *cp;
111 int count;
112
113 while (fgets(buf, sizeof buf, fp) != NULL) {
114 Line++;
115 cp = strchr(buf, '@');
116 if (cp == NULL) {
117 fputs(buf, stdout);
118 continue;
119 }
120 do {
121 count = isref(cp);
122 if (count == 0) {
123 cp++;
124 cp = strchr(cp, '@');
125 if (cp == NULL) {
126 fputs(buf, stdout);
127 goto next;
128 }
129 continue;
130 }
131 /* got one */
132 repair(buf, cp, count);
133 break;
134 } while (cp != NULL);
135 next: ;
136 }
137 }
138
139 /* repair --- turn all texinfo cross references into the one argument form */
140
141 void
repair(char * line,char * ref,int toffset)142 repair(char *line, char *ref, int toffset)
143 {
144 int braces = 1; /* have seen first left brace */
145 char *cp;
146
147 ref += toffset;
148
149 /* output line up to and including left brace in reference */
150 for (cp = line; cp <= ref; cp++)
151 putchar(*cp);
152
153 /* output node name */
154 for (; *cp && *cp != '}' && *cp != ',' && *cp != '\n'; cp++)
155 putchar(*cp);
156
157 if (*cp != '}') { /* could have been one arg xref */
158 /* skip to matching right brace */
159 for (; braces > 0; cp++) {
160 switch (*cp) {
161 case '@':
162 cp++; /* blindly skip next character */
163 break;
164 case '{':
165 braces++;
166 break;
167 case '}':
168 braces--;
169 break;
170 case '\n':
171 case '\0':
172 Errs++;
173 fprintf(stderr,
174 "%s: %s: %d: mismatched braces\n",
175 Me, Name, Line);
176 goto out;
177 default:
178 break;
179 }
180 }
181 out:
182 ;
183 }
184
185 putchar('}');
186 if (*cp == '}')
187 cp++;
188
189 /* now the rest of the line */
190 for (; *cp; cp++)
191 putchar(*cp);
192 return;
193 }
194
195 /* strerror --- return error string, delete if in your library */
196
197 char *
strerror(int errno)198 strerror(int errno)
199 {
200 static char buf[100];
201 extern int sys_nerr;
202 extern char *sys_errlist[];
203
204 if (errno < sys_nerr && errno >= 0)
205 return sys_errlist[errno];
206
207 sprintf(buf, "unknown error %d", errno);
208 return buf;
209 }
210