fix bug that can cause recursive .forward files to fail
[unix-history] / usr / src / bin / sh / mksyntax.c
CommitLineData
83fe7000 1/*-
d1b73048
KB
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
83fe7000
KB
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * %sccs.include.redist.c%
9 */
10
11#ifndef lint
d1b73048
KB
12static char copyright[] =
13"@(#) Copyright (c) 1991, 1993\n\
14 The Regents of the University of California. All rights reserved.\n";
83fe7000
KB
15#endif /* not lint */
16
17#ifndef lint
d1b73048 18static char sccsid[] = "@(#)mksyntax.c 8.1 (Berkeley) %G%";
83fe7000
KB
19#endif /* not lint */
20
21/*
22 * This program creates syntax.h and syntax.c.
23 */
24
25#include <stdio.h>
26#include "parser.h"
27
28
29struct synclass {
30 char *name;
31 char *comment;
32};
33
34/* Syntax classes */
35struct synclass synclass[] = {
36 "CWORD", "character is nothing special",
37 "CNL", "newline character",
38 "CBACK", "a backslash character",
39 "CSQUOTE", "single quote",
40 "CDQUOTE", "double quote",
41 "CENDQUOTE", "a terminating quote",
42 "CBQUOTE", "backwards single quote",
43 "CVAR", "a dollar sign",
44 "CENDVAR", "a '}' character",
32df586e
MT
45 "CLP", "a left paren in arithmetic",
46 "CRP", "a right paren in arithmetic",
83fe7000
KB
47 "CEOF", "end of file",
48 "CCTL", "like CWORD, except it must be escaped",
49 "CSPCL", "these terminate a word",
50 NULL, NULL
51};
52
53
54/*
55 * Syntax classes for is_ functions. Warning: if you add new classes
56 * you may have to change the definition of the is_in_name macro.
57 */
58struct synclass is_entry[] = {
59 "ISDIGIT", "a digit",
60 "ISUPPER", "an upper case letter",
61 "ISLOWER", "a lower case letter",
62 "ISUNDER", "an underscore",
63 "ISSPECL", "the name of a special parameter",
64 NULL, NULL,
65};
66
67char writer[] = "\
68/*\n\
69 * This file was generated by the mksyntax program.\n\
70 */\n\
71\n";
72
73
74FILE *cfile;
75FILE *hfile;
76char *syntax[513];
77int base;
78int size; /* number of values which a char variable can have */
79int nbits; /* number of bits in a character */
80int digit_contig; /* true if digits are contiguous */
81
82
83main() {
84 char c;
85 char d;
86 int sign;
87 int i;
88 char buf[80];
89 int pos;
90 static char digit[] = "0123456789";
91
92 /* Create output files */
93 if ((cfile = fopen("syntax.c", "w")) == NULL) {
94 perror("syntax.c");
95 exit(2);
96 }
97 if ((hfile = fopen("syntax.h", "w")) == NULL) {
98 perror("syntax.h");
99 exit(2);
100 }
101 fputs(writer, hfile);
102 fputs(writer, cfile);
103
104 /* Determine the characteristics of chars. */
105 c = -1;
106 if (c < 0)
107 sign = 1;
108 else
109 sign = 0;
110 for (nbits = 1 ; ; nbits++) {
111 d = (1 << nbits) - 1;
112 if (d == c)
113 break;
114 }
115 printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
116 if (nbits > 9) {
117 fputs("Characters can't have more than 9 bits\n", stderr);
118 exit(2);
119 }
120 size = (1 << nbits) + 1;
121 base = 1;
122 if (sign)
123 base += 1 << (nbits - 1);
124 digit_contig = 1;
125 for (i = 0 ; i < 10 ; i++) {
126 if (digit[i] != '0' + i)
127 digit_contig = 0;
128 }
129
b775bf58
KB
130 fputs("#include <sys/cdefs.h>\n", hfile);
131
83fe7000
KB
132 /* Generate the #define statements in the header file */
133 fputs("/* Syntax classes */\n", hfile);
134 for (i = 0 ; synclass[i].name ; i++) {
135 sprintf(buf, "#define %s %d", synclass[i].name, i);
136 fputs(buf, hfile);
137 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
138 putc('\t', hfile);
139 fprintf(hfile, "/* %s */\n", synclass[i].comment);
140 }
141 putc('\n', hfile);
142 fputs("/* Syntax classes for is_ functions */\n", hfile);
143 for (i = 0 ; is_entry[i].name ; i++) {
144 sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
145 fputs(buf, hfile);
146 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
147 putc('\t', hfile);
148 fprintf(hfile, "/* %s */\n", is_entry[i].comment);
149 }
150 putc('\n', hfile);
151 fprintf(hfile, "#define SYNBASE %d\n", base);
152 fprintf(hfile, "#define PEOF %d\n\n", -base);
153 putc('\n', hfile);
154 fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
155 fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
156 fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
32df586e 157 fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
83fe7000
KB
158 putc('\n', hfile);
159 output_type_macros(); /* is_digit, etc. */
160 putc('\n', hfile);
161
162 /* Generate the syntax tables. */
163 fputs("#include \"shell.h\"\n", cfile);
164 fputs("#include \"syntax.h\"\n\n", cfile);
165 init();
166 fputs("/* syntax table used when not in quotes */\n", cfile);
167 add("\n", "CNL");
168 add("\\", "CBACK");
169 add("'", "CSQUOTE");
170 add("\"", "CDQUOTE");
171 add("`", "CBQUOTE");
172 add("$", "CVAR");
173 add("}", "CENDVAR");
174 add("<>();&| \t", "CSPCL");
175 print("basesyntax");
176 init();
177 fputs("\n/* syntax table used when in double quotes */\n", cfile);
178 add("\n", "CNL");
179 add("\\", "CBACK");
180 add("\"", "CENDQUOTE");
181 add("`", "CBQUOTE");
182 add("$", "CVAR");
183 add("}", "CENDVAR");
32df586e 184 add("!*?[=~:/", "CCTL"); /* ':/' for tilde - yuck */
83fe7000
KB
185 print("dqsyntax");
186 init();
187 fputs("\n/* syntax table used when in single quotes */\n", cfile);
188 add("\n", "CNL");
189 add("'", "CENDQUOTE");
32df586e 190 add("!*?[=~:/", "CCTL"); /* ':/' for tilde - yuck */
83fe7000 191 print("sqsyntax");
32df586e
MT
192 init();
193 fputs("\n/* syntax table used when in arithmetic */\n", cfile);
194 add("\n", "CNL");
195 add("\\", "CBACK");
196 add("`", "CBQUOTE");
197 add("'", "CSQUOTE");
198 add("\"", "CDQUOTE");
199 add("$", "CVAR");
200 add("}", "CENDVAR");
201 add("(", "CLP");
202 add(")", "CRP");
203 print("arisyntax");
83fe7000
KB
204 filltable("0");
205 fputs("\n/* character classification table */\n", cfile);
206 add("0123456789", "ISDIGIT");
207 add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
208 add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
209 add("_", "ISUNDER");
210 add("#?$!-*@", "ISSPECL");
211 print("is_type");
212 if (! digit_contig)
213 digit_convert();
214 exit(0);
215}
216
217
218
219/*
220 * Clear the syntax table.
221 */
222
223filltable(dftval)
224 char *dftval;
225 {
226 int i;
227
228 for (i = 0 ; i < size ; i++)
229 syntax[i] = dftval;
230}
231
232
233/*
234 * Initialize the syntax table with default values.
235 */
236
237init() {
238 filltable("CWORD");
239 syntax[0] = "CEOF";
240 syntax[base + CTLESC] = "CCTL";
241 syntax[base + CTLVAR] = "CCTL";
242 syntax[base + CTLENDVAR] = "CCTL";
243 syntax[base + CTLBACKQ] = "CCTL";
244 syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
32df586e
MT
245 syntax[base + CTLARI] = "CCTL";
246 syntax[base + CTLENDARI] = "CCTL";
83fe7000
KB
247}
248
249
250/*
251 * Add entries to the syntax table.
252 */
253
254add(p, type)
255 char *p, *type;
256 {
257 while (*p)
258 syntax[*p++ + base] = type;
259}
260
261
262
263/*
264 * Output the syntax table.
265 */
266
267print(name)
268 char *name;
269 {
270 int i;
271 int col;
272
273 fprintf(hfile, "extern const char %s[];\n", name);
274 fprintf(cfile, "const char %s[%d] = {\n", name, size);
275 col = 0;
276 for (i = 0 ; i < size ; i++) {
277 if (i == 0) {
278 fputs(" ", cfile);
279 } else if ((i & 03) == 0) {
280 fputs(",\n ", cfile);
281 col = 0;
282 } else {
283 putc(',', cfile);
284 while (++col < 9 * (i & 03))
285 putc(' ', cfile);
286 }
287 fputs(syntax[i], cfile);
288 col += strlen(syntax[i]);
289 }
290 fputs("\n};\n", cfile);
291}
292
293
294
295/*
296 * Output character classification macros (e.g. is_digit). If digits are
297 * contiguous, we can test for them quickly.
298 */
299
300char *macro[] = {
301 "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
302 "#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
303 "#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
304 "#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
305 "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
306 NULL
307};
308
309output_type_macros() {
310 char **pp;
311
312 if (digit_contig)
313 macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
314 for (pp = macro ; *pp ; pp++)
315 fprintf(hfile, "%s\n", *pp);
316 if (digit_contig)
317 fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
318 else
319 fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
320}
321
322
323
324/*
325 * Output digit conversion table (if digits are not contiguous).
326 */
327
328digit_convert() {
329 int maxdigit;
330 static char digit[] = "0123456789";
331 char *p;
332 int i;
333
334 maxdigit = 0;
335 for (p = digit ; *p ; p++)
336 if (*p > maxdigit)
337 maxdigit = *p;
338 fputs("extern const char digit_value[];\n", hfile);
339 fputs("\n\nconst char digit_value[] = {\n", cfile);
340 for (i = 0 ; i <= maxdigit ; i++) {
341 for (p = digit ; *p && *p != i ; p++);
342 if (*p == '\0')
343 p = digit;
344 fprintf(cfile, " %d,\n", p - digit);
345 }
346 fputs("};\n", cfile);
347}