xref: /titanic_51/usr/src/cmd/vi/misc/mkstr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * University Copyright- Copyright (c) 1982, 1986, 1988
28  * The Regents of the University of California
29  * All Rights Reserved
30  *
31  * University Acknowledgment- Portions of this document are derived from
32  * software developed by the University of California, Berkeley, and its
33  * contributors.
34  */
35 
36 #pragma ident	"%Z%%M%	%I%	%E% SMI"
37 #include <stdio.h>
38 
39 #define	ungetchar(c)	ungetc(c, stdin)
40 
41 long	ftell();
42 char	*calloc();
43 /*
44  * mkstr - create a string error message file by massaging C source
45  *
46  * Modified March 1978 to hash old messages to be able to recompile
47  * without adding messages to the message file (usually)
48  *
49  * Program to create a string error message file
50  * from a group of C programs.  Arguments are the name
51  * of the file where the strings are to be placed, the
52  * prefix of the new files where the processed source text
53  * is to be placed, and the files to be processed.
54  *
55  * The program looks for 'error("' in the source stream.
56  * Whenever it finds this, the following characters from the '"'
57  * to a '"' are replaced by 'seekpt' where seekpt is a
58  * pointer into the error message file.
59  * If the '(' is not immediately followed by a '"' no change occurs.
60  *
61  * The optional '-' causes strings to be added at the end of the
62  * existing error message file for recompilation of single routines.
63  */
64 
65 
66 FILE	*mesgread, *mesgwrite;
67 char	*progname;
68 char	usagestr[] =	"usage: %s [ - ] mesgfile prefix file ...\n";
69 char	name[100], *np;
70 
71 main(argc, argv)
72 	int argc;
73 	char *argv[];
74 {
75 	char addon = 0;
76 
77 	argc--, progname = *argv++;
78 	if (argc > 1 && argv[0][0] == '-')
79 		addon++, argc--, argv++;
80 	if (argc < 3)
81 		fprintf(stderr, usagestr, progname), exit(1);
82 	mesgwrite = fopen(argv[0], addon ? "a" : "w");
83 	if (mesgwrite == NULL)
84 		perror(argv[0]), exit(1);
85 	mesgread = fopen(argv[0], "r");
86 	if (mesgread == NULL)
87 		perror(argv[0]), exit(1);
88 	inithash();
89 	argc--, argv++;
90 	strcpy(name, argv[0]);
91 	np = name + strlen(name);
92 	argc--, argv++;
93 	do {
94 		strcpy(np, argv[0]);
95 		if (freopen(name, "w", stdout) == NULL)
96 			perror(name), exit(1);
97 		if (freopen(argv[0], "r", stdin) == NULL)
98 			perror(argv[0]), exit(1);
99 		process();
100 		argc--, argv++;
101 	} while (argc > 0);
102 	exit(0);
103 }
104 
105 process()
106 {
107 	register c;
108 
109 	for (;;) {
110 		c = getchar();
111 		if (c == EOF)
112 			return;
113 		if (c != 'e') {
114 			putchar(c);
115 			continue;
116 		}
117 		if (match("error(")) {
118 			printf("error(");
119 			c = getchar();
120 			if (c != '"')
121 				putchar(c);
122 			else
123 				copystr();
124 		}
125 	}
126 }
127 
128 match(ocp)
129 	char *ocp;
130 {
131 	register char *cp;
132 	register c;
133 
134 	for (cp = ocp + 1; *cp; cp++) {
135 		c = getchar();
136 		if (c != *cp) {
137 			while (ocp < cp)
138 				putchar(*ocp++);
139 			ungetchar(c);
140 			return (0);
141 		}
142 	}
143 	return (1);
144 }
145 
146 copystr()
147 {
148 	register c, ch;
149 	char buf[512];
150 	register char *cp = buf;
151 
152 	for (;;) {
153 		c = getchar();
154 		if (c == EOF)
155 			break;
156 		switch (c) {
157 
158 		case '"':
159 			*cp++ = 0;
160 			goto out;
161 		case '\\':
162 			c = getchar();
163 			switch (c) {
164 
165 			case 'b':
166 				c = '\b';
167 				break;
168 			case 't':
169 				c = '\t';
170 				break;
171 			case 'r':
172 				c = '\r';
173 				break;
174 			case 'n':
175 				c = '\n';
176 				break;
177 			case '\n':
178 				continue;
179 			case 'f':
180 				c = '\f';
181 				break;
182 			case '0':
183 				c = 0;
184 				break;
185 			case '\\':
186 				break;
187 			default:
188 				if (!octdigit(c))
189 					break;
190 				c -= '0';
191 				ch = getchar();
192 				if (!octdigit(ch))
193 					break;
194 				c <<= 7, c += ch - '0';
195 				ch = getchar();
196 				if (!octdigit(ch))
197 					break;
198 				c <<= 3, c+= ch - '0', ch = -1;
199 				break;
200 			}
201 		}
202 		*cp++ = c;
203 	}
204 out:
205 	*cp = 0;
206 	printf("%d", hashit(buf, 1, NULL));
207 }
208 
209 octdigit(c)
210 	char c;
211 {
212 
213 	return (c >= '0' && c <= '7');
214 }
215 
216 inithash()
217 {
218 	char buf[512];
219 	int mesgpt = 0;
220 
221 	rewind(mesgread);
222 	while (fgetNUL(buf, sizeof buf, mesgread) != NULL) {
223 		hashit(buf, 0, mesgpt);
224 		mesgpt += strlen(buf) + 2;
225 	}
226 }
227 
228 #define	NBUCKETS	511
229 
230 struct	hash {
231 	long	hval;
232 	unsigned hpt;
233 	struct	hash *hnext;
234 } *bucket[NBUCKETS];
235 
236 hashit(str, really, fakept)
237 	char *str;
238 	char really;
239 	unsigned fakept;
240 {
241 	int i;
242 	register struct hash *hp;
243 	char buf[512];
244 	long hashval = 0;
245 	register char *cp;
246 
247 	if (really)
248 		fflush(mesgwrite);
249 	for (cp = str; *cp;)
250 		hashval = (hashval << 1) + *cp++;
251 	i = hashval % NBUCKETS;
252 	if (i < 0)
253 		i += NBUCKETS;
254 	if (really != 0)
255 		for (hp = bucket[i]; hp != 0; hp = hp->hnext)
256 		if (hp->hval == hashval) {
257 			fseek(mesgread, (long) hp->hpt, 0);
258 			fgetNUL(buf, sizeof buf, mesgread);
259 /*
260 			fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf);
261 */
262 			if (strcmp(buf, str) == 0)
263 				break;
264 		}
265 	if (!really || hp == 0) {
266 		hp = (struct hash *) calloc(1, sizeof *hp);
267 		hp->hnext = bucket[i];
268 		hp->hval = hashval;
269 		hp->hpt = really ? ftell(mesgwrite) : fakept;
270 		if (really) {
271 			fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite);
272 			fwrite("\n", sizeof (char), 1, mesgwrite);
273 		}
274 		bucket[i] = hp;
275 	}
276 /*
277 	fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt);
278 */
279 	return (hp->hpt);
280 }
281 
282 #include <sys/types.h>
283 #include <sys/stat.h>
284 
285 fgetNUL(obuf, rmdr, file)
286 	char *obuf;
287 	register int rmdr;
288 	FILE *file;
289 {
290 	register c;
291 	register char *buf = obuf;
292 
293 	while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF)
294 		*buf++ = c;
295 	*buf++ = 0;
296 	getc(file);
297 	return ((feof(file) || ferror(file)) ? NULL : 1);
298 }
299