This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / bin / sh / mksyntax.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38char copyright[] =
39"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
40 All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
78ed81a3 44/*static char sccsid[] = "from: @(#)mksyntax.c 5.2 (Berkeley) 3/8/91";*/
45static char rcsid[] = "mksyntax.c,v 1.4 1993/08/01 18:58:06 mycroft Exp";
15637ed4
RG
46#endif /* not lint */
47
48/*
49 * This program creates syntax.h and syntax.c.
50 */
51
52#include <stdio.h>
53#include "parser.h"
54
55
56struct synclass {
57 char *name;
58 char *comment;
59};
60
61/* Syntax classes */
62struct synclass synclass[] = {
63 "CWORD", "character is nothing special",
64 "CNL", "newline character",
65 "CBACK", "a backslash character",
66 "CSQUOTE", "single quote",
67 "CDQUOTE", "double quote",
68 "CENDQUOTE", "a terminating quote",
69 "CBQUOTE", "backwards single quote",
70 "CVAR", "a dollar sign",
71 "CENDVAR", "a '}' character",
72 "CEOF", "end of file",
73 "CCTL", "like CWORD, except it must be escaped",
74 "CSPCL", "these terminate a word",
75 NULL, NULL
76};
77
78
79/*
80 * Syntax classes for is_ functions. Warning: if you add new classes
81 * you may have to change the definition of the is_in_name macro.
82 */
83struct synclass is_entry[] = {
84 "ISDIGIT", "a digit",
85 "ISUPPER", "an upper case letter",
86 "ISLOWER", "a lower case letter",
87 "ISUNDER", "an underscore",
88 "ISSPECL", "the name of a special parameter",
89 NULL, NULL,
90};
91
92char writer[] = "\
93/*\n\
94 * This file was generated by the mksyntax program.\n\
95 */\n\
96\n";
97
98
99FILE *cfile;
100FILE *hfile;
101char *syntax[513];
102int base;
103int size; /* number of values which a char variable can have */
104int nbits; /* number of bits in a character */
105int digit_contig; /* true if digits are contiguous */
106
107
108main() {
109 char c;
110 char d;
111 int sign;
112 int i;
113 char buf[80];
114 int pos;
115 static char digit[] = "0123456789";
116
117 /* Create output files */
118 if ((cfile = fopen("syntax.c", "w")) == NULL) {
119 perror("syntax.c");
120 exit(2);
121 }
122 if ((hfile = fopen("syntax.h", "w")) == NULL) {
123 perror("syntax.h");
124 exit(2);
125 }
126 fputs(writer, hfile);
127 fputs(writer, cfile);
128
129 /* Determine the characteristics of chars. */
130 c = -1;
131 if (c < 0)
132 sign = 1;
133 else
134 sign = 0;
135 for (nbits = 1 ; ; nbits++) {
136 d = (1 << nbits) - 1;
137 if (d == c)
138 break;
139 }
140 printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
141 if (nbits > 9) {
142 fputs("Characters can't have more than 9 bits\n", stderr);
143 exit(2);
144 }
145 size = (1 << nbits) + 1;
146 base = 1;
147 if (sign)
148 base += 1 << (nbits - 1);
149 digit_contig = 1;
150 for (i = 0 ; i < 10 ; i++) {
151 if (digit[i] != '0' + i)
152 digit_contig = 0;
153 }
154
155 fputs("#include <sys/cdefs.h>\n", hfile);
156
157 /* Generate the #define statements in the header file */
158 fputs("/* Syntax classes */\n", hfile);
159 for (i = 0 ; synclass[i].name ; i++) {
160 sprintf(buf, "#define %s %d", synclass[i].name, i);
161 fputs(buf, hfile);
162 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
163 putc('\t', hfile);
164 fprintf(hfile, "/* %s */\n", synclass[i].comment);
165 }
166 putc('\n', hfile);
167 fputs("/* Syntax classes for is_ functions */\n", hfile);
168 for (i = 0 ; is_entry[i].name ; i++) {
169 sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
170 fputs(buf, hfile);
171 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
172 putc('\t', hfile);
173 fprintf(hfile, "/* %s */\n", is_entry[i].comment);
174 }
175 putc('\n', hfile);
176 fprintf(hfile, "#define SYNBASE %d\n", base);
177 fprintf(hfile, "#define PEOF %d\n\n", -base);
178 putc('\n', hfile);
179 fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
180 fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
181 fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
182 putc('\n', hfile);
183 output_type_macros(); /* is_digit, etc. */
184 putc('\n', hfile);
185
186 /* Generate the syntax tables. */
187 fputs("#include \"shell.h\"\n", cfile);
188 fputs("#include \"syntax.h\"\n\n", cfile);
189 init();
190 fputs("/* syntax table used when not in quotes */\n", cfile);
191 add("\n", "CNL");
192 add("\\", "CBACK");
193 add("'", "CSQUOTE");
194 add("\"", "CDQUOTE");
195 add("`", "CBQUOTE");
196 add("$", "CVAR");
197 add("}", "CENDVAR");
198 add("<>();&| \t", "CSPCL");
199 print("basesyntax");
200 init();
201 fputs("\n/* syntax table used when in double quotes */\n", cfile);
202 add("\n", "CNL");
203 add("\\", "CBACK");
204 add("\"", "CENDQUOTE");
205 add("`", "CBQUOTE");
206 add("$", "CVAR");
207 add("}", "CENDVAR");
208 add("!*?[=", "CCTL");
209 print("dqsyntax");
210 init();
211 fputs("\n/* syntax table used when in single quotes */\n", cfile);
212 add("\n", "CNL");
213 add("'", "CENDQUOTE");
214 add("!*?[=", "CCTL");
215 print("sqsyntax");
216 filltable("0");
217 fputs("\n/* character classification table */\n", cfile);
218 add("0123456789", "ISDIGIT");
219 add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
220 add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
221 add("_", "ISUNDER");
222 add("#?$!-*@", "ISSPECL");
223 print("is_type");
224 if (! digit_contig)
225 digit_convert();
226 exit(0);
227}
228
229
230
231/*
232 * Clear the syntax table.
233 */
234
235filltable(dftval)
236 char *dftval;
237 {
238 int i;
239
240 for (i = 0 ; i < size ; i++)
241 syntax[i] = dftval;
242}
243
244
245/*
246 * Initialize the syntax table with default values.
247 */
248
249init() {
250 filltable("CWORD");
251 syntax[0] = "CEOF";
252 syntax[base + CTLESC] = "CCTL";
253 syntax[base + CTLVAR] = "CCTL";
254 syntax[base + CTLENDVAR] = "CCTL";
255 syntax[base + CTLBACKQ] = "CCTL";
256 syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
257}
258
259
260/*
261 * Add entries to the syntax table.
262 */
263
264add(p, type)
265 char *p, *type;
266 {
267 while (*p)
268 syntax[*p++ + base] = type;
269}
270
271
272
273/*
274 * Output the syntax table.
275 */
276
277print(name)
278 char *name;
279 {
280 int i;
281 int col;
282
283 fprintf(hfile, "extern const char %s[];\n", name);
284 fprintf(cfile, "const char %s[%d] = {\n", name, size);
285 col = 0;
286 for (i = 0 ; i < size ; i++) {
287 if (i == 0) {
288 fputs(" ", cfile);
289 } else if ((i & 03) == 0) {
290 fputs(",\n ", cfile);
291 col = 0;
292 } else {
293 putc(',', cfile);
294 while (++col < 9 * (i & 03))
295 putc(' ', cfile);
296 }
297 fputs(syntax[i], cfile);
298 col += strlen(syntax[i]);
299 }
300 fputs("\n};\n", cfile);
301}
302
303
304
305/*
306 * Output character classification macros (e.g. is_digit). If digits are
307 * contiguous, we can test for them quickly.
308 */
309
310char *macro[] = {
311 "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
312 "#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
313 "#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
314 "#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
315 "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
316 NULL
317};
318
319output_type_macros() {
320 char **pp;
321
322 if (digit_contig)
323 macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
324 for (pp = macro ; *pp ; pp++)
325 fprintf(hfile, "%s\n", *pp);
326 if (digit_contig)
327 fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
328 else
329 fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
330}
331
332
333
334/*
335 * Output digit conversion table (if digits are not contiguous).
336 */
337
338digit_convert() {
339 int maxdigit;
340 static char digit[] = "0123456789";
341 char *p;
342 int i;
343
344 maxdigit = 0;
345 for (p = digit ; *p ; p++)
346 if (*p > maxdigit)
347 maxdigit = *p;
348 fputs("extern const char digit_value[];\n", hfile);
349 fputs("\n\nconst char digit_value[] = {\n", cfile);
350 for (i = 0 ; i <= maxdigit ; i++) {
351 for (p = digit ; *p && *p != i ; p++);
352 if (*p == '\0')
353 p = digit;
354 fprintf(cfile, " %d,\n", p - digit);
355 }
356 fputs("};\n", cfile);
357}