xref: /netbsd-src/external/gpl2/texinfo/dist/util/deref.c (revision 29619d2afe564e54d657b83e5a3ae89584f83720)
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