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