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