need to change iphlen earlier; icmp_error needs original ip_len; cleanups
[unix-history] / usr / src / usr.bin / mkstr / mkstr.c
CommitLineData
22e155fc
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
4f5df788
KB
3 * All rights reserved.
4 *
6ecf3d85 5 * %sccs.include.redist.c%
22e155fc
DF
6 */
7
8#ifndef lint
9char copyright[] =
10"@(#) Copyright (c) 1980 Regents of the University of California.\n\
11 All rights reserved.\n";
4f5df788 12#endif /* not lint */
22e155fc
DF
13
14#ifndef lint
6ecf3d85 15static char sccsid[] = "@(#)mkstr.c 5.4 (Berkeley) %G%";
4f5df788 16#endif /* not lint */
22e155fc 17
fe6c8cd8
BJ
18#include <stdio.h>
19
20#define ungetchar(c) ungetc(c, stdin)
21
22long ftell();
23char *calloc();
24/*
25 * mkstr - create a string error message file by massaging C source
26 *
27 * Bill Joy UCB August 1977
28 *
29 * Modified March 1978 to hash old messages to be able to recompile
30 * without addding messages to the message file (usually)
31 *
32 * Based on an earlier program conceived by Bill Joy and Chuck Haley
33 *
34 * Program to create a string error message file
35 * from a group of C programs. Arguments are the name
36 * of the file where the strings are to be placed, the
37 * prefix of the new files where the processed source text
38 * is to be placed, and the files to be processed.
39 *
40 * The program looks for 'error("' in the source stream.
41 * Whenever it finds this, the following characters from the '"'
42 * to a '"' are replaced by 'seekpt' where seekpt is a
43 * pointer into the error message file.
44 * If the '(' is not immediately followed by a '"' no change occurs.
45 *
46 * The optional '-' causes strings to be added at the end of the
47 * existing error message file for recompilation of single routines.
48 */
49
50
51FILE *mesgread, *mesgwrite;
52char *progname;
53char usagestr[] = "usage: %s [ - ] mesgfile prefix file ...\n";
54char name[100], *np;
55
56main(argc, argv)
57 int argc;
58 char *argv[];
59{
60 char addon = 0;
61
62 argc--, progname = *argv++;
63 if (argc > 1 && argv[0][0] == '-')
64 addon++, argc--, argv++;
65 if (argc < 3)
66 fprintf(stderr, usagestr, progname), exit(1);
67 mesgwrite = fopen(argv[0], addon ? "a" : "w");
68 if (mesgwrite == NULL)
69 perror(argv[0]), exit(1);
70 mesgread = fopen(argv[0], "r");
71 if (mesgread == NULL)
72 perror(argv[0]), exit(1);
73 inithash();
74 argc--, argv++;
75 strcpy(name, argv[0]);
76 np = name + strlen(name);
77 argc--, argv++;
78 do {
79 strcpy(np, argv[0]);
80 if (freopen(name, "w", stdout) == NULL)
81 perror(name), exit(1);
82 if (freopen(argv[0], "r", stdin) == NULL)
83 perror(argv[0]), exit(1);
84 process();
85 argc--, argv++;
86 } while (argc > 0);
87 exit(0);
88}
89
90process()
91{
92 register char *cp;
93 register c;
94
95 for (;;) {
96 c = getchar();
97 if (c == EOF)
98 return;
99 if (c != 'e') {
100 putchar(c);
101 continue;
102 }
103 if (match("error(")) {
104 printf("error(");
105 c = getchar();
106 if (c != '"')
107 putchar(c);
108 else
109 copystr();
110 }
111 }
112}
113
114match(ocp)
115 char *ocp;
116{
117 register char *cp;
118 register c;
119
120 for (cp = ocp + 1; *cp; cp++) {
121 c = getchar();
122 if (c != *cp) {
123 while (ocp < cp)
124 putchar(*ocp++);
125 ungetchar(c);
126 return (0);
127 }
128 }
129 return (1);
130}
131
132copystr()
133{
134 register c, ch;
135 char buf[512];
136 register char *cp = buf;
137
138 for (;;) {
139 c = getchar();
140 if (c == EOF)
141 break;
142 switch (c) {
143
144 case '"':
145 *cp++ = 0;
146 goto out;
147 case '\\':
148 c = getchar();
149 switch (c) {
150
151 case 'b':
152 c = '\b';
153 break;
154 case 't':
155 c = '\t';
156 break;
157 case 'r':
158 c = '\r';
159 break;
160 case 'n':
161 c = '\n';
162 break;
163 case '\n':
164 continue;
165 case 'f':
166 c = '\f';
167 break;
168 case '0':
169 c = 0;
170 break;
171 case '\\':
172 break;
173 default:
174 if (!octdigit(c))
175 break;
176 c -= '0';
177 ch = getchar();
178 if (!octdigit(ch))
179 break;
180 c <<= 7, c += ch - '0';
181 ch = getchar();
182 if (!octdigit(ch))
183 break;
184 c <<= 3, c+= ch - '0', ch = -1;
185 break;
186 }
187 }
188 *cp++ = c;
189 }
190out:
191 *cp = 0;
192 printf("%d", hashit(buf, 1, NULL));
193}
194
195octdigit(c)
196 char c;
197{
198
199 return (c >= '0' && c <= '7');
200}
201
202inithash()
203{
204 char buf[512];
205 int mesgpt = 0;
206
207 rewind(mesgread);
208 while (fgetNUL(buf, sizeof buf, mesgread) != NULL) {
209 hashit(buf, 0, mesgpt);
210 mesgpt += strlen(buf) + 2;
211 }
212}
213
214#define NBUCKETS 511
215
216struct hash {
217 long hval;
218 unsigned hpt;
219 struct hash *hnext;
220} *bucket[NBUCKETS];
221
222hashit(str, really, fakept)
223 char *str;
224 char really;
225 unsigned fakept;
226{
227 int i;
228 register struct hash *hp;
229 char buf[512];
230 long hashval = 0;
231 register char *cp;
232
233 if (really)
234 fflush(mesgwrite);
235 for (cp = str; *cp;)
236 hashval = (hashval << 1) + *cp++;
237 i = hashval % NBUCKETS;
238 if (i < 0)
239 i += NBUCKETS;
240 if (really != 0)
241 for (hp = bucket[i]; hp != 0; hp = hp->hnext)
242 if (hp->hval == hashval) {
243 fseek(mesgread, (long) hp->hpt, 0);
244 fgetNUL(buf, sizeof buf, mesgread);
245/*
246 fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf);
247*/
248 if (strcmp(buf, str) == 0)
249 break;
250 }
251 if (!really || hp == 0) {
252 hp = (struct hash *) calloc(1, sizeof *hp);
253 hp->hnext = bucket[i];
254 hp->hval = hashval;
255 hp->hpt = really ? ftell(mesgwrite) : fakept;
256 if (really) {
257 fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite);
258 fwrite("\n", sizeof (char), 1, mesgwrite);
259 }
260 bucket[i] = hp;
261 }
262/*
263 fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt);
264*/
265 return (hp->hpt);
266}
267
268#include <sys/types.h>
269#include <sys/stat.h>
270
271fgetNUL(obuf, rmdr, file)
272 char *obuf;
273 register int rmdr;
274 FILE *file;
275{
276 register c;
277 register char *buf = obuf;
278
279 while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF)
280 *buf++ = c;
281 *buf++ = 0;
282 getc(file);
283 return ((feof(file) || ferror(file)) ? NULL : 1);
284}