Subversion Repositories HelenOS

Rev

Rev 2716 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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