0
|
1 /*
|
|
2 * deref.c
|
|
3
|
|
4 * compile command: gcc -g -o deref deref.c
|
|
5
|
|
6 * execute command: deref filename.texi > newfile.texi
|
|
7
|
|
8 * To: bob@gnu.ai.mit.edu
|
|
9 * Subject: another tool
|
|
10 * Date: 18 Dec 91 16:03:13 EST (Wed)
|
|
11 * From: gatech!skeeve!arnold@eddie.mit.edu (Arnold D. Robbins)
|
|
12 *
|
|
13 * Here is deref.c. It turns texinfo cross references back into the
|
|
14 * one argument form. It has the same limitations as fixref; one xref per
|
|
15 * line and can't cross lines. You can use it to find references that do
|
|
16 * cross a line boundary this way:
|
|
17 *
|
|
18 * deref < manual > /dev/null 2>errs
|
|
19 *
|
|
20 * (This assumes bash or /bin/sh.) The file errs will have list of lines
|
|
21 * where deref could not find matching braces.
|
|
22 *
|
|
23 * A gawk manual processed by deref goes through makeinfo without complaint.
|
|
24 * Compile with gcc and you should be set.
|
|
25 *
|
|
26 * Enjoy,
|
|
27 *
|
|
28 * Arnold
|
|
29 * -----------
|
|
30 */
|
|
31
|
|
32 /*
|
|
33 * deref.c
|
|
34 *
|
|
35 * Make all texinfo references into the one argument form.
|
|
36 *
|
|
37 * Arnold Robbins
|
|
38 * arnold@skeeve.atl.ga.us
|
|
39 * December, 1991
|
|
40 *
|
|
41 * Copyright, 1991, Arnold Robbins
|
|
42 */
|
|
43
|
|
44 /*
|
|
45 * LIMITATIONS:
|
|
46 * One texinfo cross reference per line.
|
|
47 * Cross references may not cross newlines.
|
|
48 * Use of fgets for input (to be fixed).
|
|
49 */
|
|
50
|
|
51 #include <stdio.h>
|
|
52 #include <ctype.h>
|
|
53 #include <errno.h>
|
|
54
|
|
55 /* for gcc on the 3B1, delete if this gives you grief */
|
|
56 extern int fclose (FILE * fp);
|
|
57 extern int fprintf (FILE * fp, const char *str,...);
|
|
58
|
|
59 extern char *strerror (int errno);
|
|
60 extern char *strchr (char *cp, int ch);
|
|
61 extern int strncmp (const char *s1, const char *s2, int count);
|
|
62
|
|
63 extern int errno;
|
|
64
|
|
65 void process (FILE * fp);
|
|
66 void repair (char *line, char *ref, int toffset);
|
|
67
|
|
68 int Errs = 0;
|
|
69 char *Name = "stdin";
|
|
70 int Line = 0;
|
|
71 char *Me;
|
|
72
|
|
73 /* main --- handle arguments, global vars for errors */
|
|
74
|
|
75 int
|
|
76 main (int argc, char **argv)
|
|
77 {
|
|
78 FILE *fp;
|
|
79
|
|
80 Me = argv[0];
|
|
81
|
|
82 if (argc == 1)
|
|
83 process (stdin);
|
|
84 else
|
|
85 for (argc--, argv++; *argv != NULL; argc--, argv++)
|
|
86 {
|
|
87 if (argv[0][0] == '-' && argv[0][1] == '\0')
|
|
88 {
|
|
89 Name = "stdin";
|
|
90 Line = 0;
|
|
91 process (stdin);
|
|
92 }
|
|
93 else if ((fp = fopen (*argv, "r")) != NULL)
|
|
94 {
|
|
95 Name = *argv;
|
|
96 Line = 0;
|
|
97 process (fp);
|
|
98 fclose (fp);
|
|
99 }
|
|
100 else
|
|
101 {
|
|
102 fprintf (stderr, "%s: can not open: %s\n",
|
|
103 *argv, strerror (errno));
|
|
104 Errs++;
|
|
105 }
|
|
106 }
|
|
107 return Errs != 0;
|
|
108 }
|
|
109
|
|
110 /* isref --- decide if we've seen a texinfo cross reference */
|
|
111
|
|
112 int
|
|
113 isref (char *cp)
|
|
114 {
|
|
115 if (strncmp (cp, "@ref{", 5) == 0)
|
|
116 return 5;
|
|
117 if (strncmp (cp, "@xref{", 6) == 0)
|
|
118 return 6;
|
|
119 if (strncmp (cp, "@pxref{", 7) == 0)
|
|
120 return 7;
|
|
121 return 0;
|
|
122 }
|
|
123
|
|
124 /* process --- read files, look for references, fix them up */
|
|
125
|
|
126 void
|
|
127 process (FILE * fp)
|
|
128 {
|
|
129 char buf[BUFSIZ];
|
|
130 char *cp;
|
|
131 int count;
|
|
132
|
|
133 while (fgets (buf, sizeof buf, fp) != NULL)
|
|
134 {
|
|
135 Line++;
|
|
136 cp = strchr (buf, '@');
|
|
137 if (cp == NULL)
|
|
138 {
|
|
139 fputs (buf, stdout);
|
|
140 continue;
|
|
141 }
|
|
142 do
|
|
143 {
|
|
144 count = isref (cp);
|
|
145 if (count == 0)
|
|
146 {
|
|
147 cp++;
|
|
148 cp = strchr (cp, '@');
|
|
149 if (cp == NULL)
|
|
150 {
|
|
151 fputs (buf, stdout);
|
|
152 goto next;
|
|
153 }
|
|
154 continue;
|
|
155 }
|
|
156 /* got one */
|
|
157 repair (buf, cp, count);
|
|
158 break;
|
|
159 }
|
|
160 while (cp != NULL);
|
|
161 next:;
|
|
162 }
|
|
163 }
|
|
164
|
|
165 /* repair --- turn all texinfo cross references into the one argument form */
|
|
166
|
|
167 void
|
|
168 repair (char *line, char *ref, int toffset)
|
|
169 {
|
|
170 int braces = 1; /* have seen first left brace */
|
|
171 char *cp;
|
|
172
|
|
173 ref += toffset;
|
|
174
|
|
175 /* output line up to and including left brace in reference */
|
|
176 for (cp = line; cp <= ref; cp++)
|
|
177 putchar (*cp);
|
|
178
|
|
179 /* output node name */
|
|
180 for (; *cp && *cp != '}' && *cp != ',' && *cp != '\n'; cp++)
|
|
181 putchar (*cp);
|
|
182
|
|
183 if (*cp != '}')
|
|
184 { /* could have been one arg xref */
|
|
185 /* skip to matching right brace */
|
|
186 for (; braces > 0; cp++)
|
|
187 {
|
|
188 switch (*cp)
|
|
189 {
|
|
190 case '@':
|
|
191 cp++; /* blindly skip next character */
|
|
192 break;
|
|
193 case '{':
|
|
194 braces++;
|
|
195 break;
|
|
196 case '}':
|
|
197 braces--;
|
|
198 break;
|
|
199 case '\n':
|
|
200 case '\0':
|
|
201 Errs++;
|
|
202 fprintf (stderr,
|
|
203 "%s: %s: %d: mismatched braces\n",
|
|
204 Me, Name, Line);
|
|
205 goto out;
|
|
206 default:
|
|
207 break;
|
|
208 }
|
|
209 }
|
|
210 out:
|
|
211 ;
|
|
212 }
|
|
213
|
|
214 putchar ('}');
|
|
215 if (*cp == '}')
|
|
216 cp++;
|
|
217
|
|
218 /* now the rest of the line */
|
|
219 for (; *cp; cp++)
|
|
220 putchar (*cp);
|
|
221 return;
|
|
222 }
|
|
223
|
|
224 /* strerror --- return error string, delete if in your library */
|
|
225
|
|
226 char *
|
|
227 strerror (int errno)
|
|
228 {
|
|
229 static char buf[100];
|
|
230 extern int sys_nerr;
|
|
231 extern char *sys_errlist[];
|
|
232
|
|
233 if (errno < sys_nerr && errno >= 0)
|
|
234 return sys_errlist[errno];
|
|
235
|
|
236 sprintf (buf, "unknown error %d", errno);
|
|
237 return buf;
|
|
238 }
|