Subversion Repositories HelenOS

Rev

Rev 2716 | Details | Compare with Previous | 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>
2716 cejka 59
#include <stdlib.h>
2714 cejka 60
#include <string.h>
61
#include <sys/types.h>
62
#include "../parser.h"
63
 
64
 
65
struct synclass {
66
    char *name;
67
    char *comment;
68
};
69
 
70
/* Syntax classes */
71
struct synclass synclass[] = {
72
    { "CWORD",  "character is nothing special" },
73
    { "CNL",    "newline character" },
74
    { "CBACK",  "a backslash character" },
75
    { "CSQUOTE",    "single quote" },
76
    { "CDQUOTE",    "double quote" },
77
    { "CENDQUOTE",  "a terminating quote" },
78
    { "CBQUOTE",    "backwards single quote" },
79
    { "CVAR",   "a dollar sign" },
80
    { "CENDVAR",    "a '}' character" },
81
    { "CLP",    "a left paren in arithmetic" },
82
    { "CRP",    "a right paren in arithmetic" },
83
    { "CEOF",   "end of file" },
84
    { "CCTL",   "like CWORD, except it must be escaped" },
85
    { "CSPCL",  "these terminate a word" },
86
    { NULL,     NULL }
87
};
88
 
89
 
90
/*
91
 * Syntax classes for is_ functions.  Warning:  if you add new classes
92
 * you may have to change the definition of the is_in_name macro.
93
 */
94
struct synclass is_entry[] = {
95
    { "ISDIGIT",    "a digit" },
96
    { "ISUPPER",    "an upper case letter" },
97
    { "ISLOWER",    "a lower case letter" },
98
    { "ISUNDER",    "an underscore" },
99
    { "ISSPECL",    "the name of a special parameter" },
100
    { NULL,     NULL }
101
};
102
 
103
static char writer[] = "\
104
/*\n\
105
 * This file was generated by the mksyntax program.\n\
106
 */\n\
107
\n";
108
 
109
 
110
static FILE *cfile;
111
static FILE *hfile;
112
static char *syntax[513];
113
static int base;
114
static int size;    /* number of values which a char variable can have */
115
static int nbits;   /* number of bits in a character */
116
static int digit_contig;/* true if digits are contiguous */
117
 
118
static void filltable(char *);
119
static void init(void);
120
static void add(char *, char *);
121
static void print(char *);
122
static void output_type_macros(void);
123
static void digit_convert(void);
124
int main(int, char **);
125
 
126
int
127
main(argc, argv)
128
    int argc;
129
    char **argv;
130
{
131
#ifdef  TARGET_CHAR
132
    TARGET_CHAR c;
133
    TARGET_CHAR d;
134
#else
135
    char c;
136
    char d;
137
#endif
138
    int sign;
139
    int i;
140
    char buf[80];
141
    int pos;
142
    static char digit[] = "0123456789";
143
 
144
    /* Create output files */
145
    if ((cfile = fopen("syntax.c", "w")) == NULL) {
146
        perror("syntax.c");
147
        exit(2);
148
    }
149
    if ((hfile = fopen("syntax.h", "w")) == NULL) {
150
        perror("syntax.h");
151
        exit(2);
152
    }
153
    fputs(writer, hfile);
154
    fputs(writer, cfile);
155
 
156
    /* Determine the characteristics of chars. */
157
    c = -1;
158
    if (c <= 0)
159
        sign = 1;
160
    else
161
        sign = 0;
162
    for (nbits = 1 ; ; nbits++) {
163
        d = (1 << nbits) - 1;
164
        if (d == c)
165
            break;
166
    }
167
    printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
168
    if (nbits > 9) {
169
        fputs("Characters can't have more than 9 bits\n", stderr);
170
        exit(2);
171
    }
172
    size = (1 << nbits) + 1;
173
    base = 1;
174
    if (sign)
175
        base += 1 << (nbits - 1);
176
    digit_contig = 1;
177
    for (i = 0 ; i < 10 ; i++) {
178
        if (digit[i] != '0' + i)
179
            digit_contig = 0;
180
    }
181
 
182
    fputs("#include <sys/cdefs.h>\n", hfile);
183
    fputs("#include <ctype.h>\n", hfile);
184
 
185
    /* Generate the #define statements in the header file */
186
    fputs("/* Syntax classes */\n", hfile);
187
    for (i = 0 ; synclass[i].name ; i++) {
188
        sprintf(buf, "#define %s %d", synclass[i].name, i);
189
        fputs(buf, hfile);
190
        for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
191
            putc('\t', hfile);
192
        fprintf(hfile, "/* %s */\n", synclass[i].comment);
193
    }
194
    putc('\n', hfile);
195
    fputs("/* Syntax classes for is_ functions */\n", hfile);
196
    for (i = 0 ; is_entry[i].name ; i++) {
197
        sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
198
        fputs(buf, hfile);
199
        for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
200
            putc('\t', hfile);
201
        fprintf(hfile, "/* %s */\n", is_entry[i].comment);
202
    }
203
    putc('\n', hfile);
204
    fprintf(hfile, "#define SYNBASE %d\n", base);
205
    fprintf(hfile, "#define PEOF %d\n\n", -base);
206
    if (sign)
207
        fprintf(hfile, "#define UPEOF %d\n\n", -base);
208
    else
209
        fprintf(hfile, "#define UPEOF ((unsigned char) %d)\n\n", -base);
210
    putc('\n', hfile);
211
    fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
212
    fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
213
    fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
214
    fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
215
    putc('\n', hfile);
216
    output_type_macros();       /* is_digit, etc. */
217
    putc('\n', hfile);
218
 
219
    /* Generate the syntax tables. */
220
    fputs("#include \"shell.h\"\n", cfile);
221
    fputs("#include \"syntax.h\"\n\n", cfile);
222
    init();
223
    fputs("/* syntax table used when not in quotes */\n", cfile);
224
    add("\n", "CNL");
225
    add("\\", "CBACK");
226
    add("'", "CSQUOTE");
227
    add("\"", "CDQUOTE");
228
    add("`", "CBQUOTE");
229
    add("$", "CVAR");
230
    add("}", "CENDVAR");
231
    add("<>();&| \t", "CSPCL");
232
    print("basesyntax");
233
    init();
234
    fputs("\n/* syntax table used when in double quotes */\n", cfile);
235
    add("\n", "CNL");
236
    add("\\", "CBACK");
237
    add("\"", "CENDQUOTE");
238
    add("`", "CBQUOTE");
239
    add("$", "CVAR");
240
    add("}", "CENDVAR");
241
    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
242
    add("!*?[=~:/-]", "CCTL");
243
    print("dqsyntax");
244
    init();
245
    fputs("\n/* syntax table used when in single quotes */\n", cfile);
246
    add("\n", "CNL");
247
    add("'", "CENDQUOTE");
248
    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
249
    add("!*?[=~:/-]\\", "CCTL");
250
    print("sqsyntax");
251
    init();
252
    fputs("\n/* syntax table used when in arithmetic */\n", cfile);
253
    add("\n", "CNL");
254
    add("\\", "CBACK");
255
    add("`", "CBQUOTE");
256
    add("'", "CSQUOTE");
257
    add("\"", "CDQUOTE");
258
    add("$", "CVAR");
259
    add("}", "CENDVAR");
260
    add("(", "CLP");
261
    add(")", "CRP");
262
    print("arisyntax");
263
    filltable("0");
264
    fputs("\n/* character classification table */\n", cfile);
265
    add("0123456789", "ISDIGIT");
266
    add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
267
    add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
268
    add("_", "ISUNDER");
269
    add("#?$!-*@", "ISSPECL");
270
    print("is_type");
271
    if (! digit_contig)
272
        digit_convert();
273
    exit(0);
274
    /* NOTREACHED */
275
}
276
 
277
 
278
 
279
/*
280
 * Clear the syntax table.
281
 */
282
 
283
static void
284
filltable(dftval)
285
    char *dftval;
286
{
287
    int i;
288
 
289
    for (i = 0 ; i < size ; i++)
290
        syntax[i] = dftval;
291
}
292
 
293
 
294
/*
295
 * Initialize the syntax table with default values.
296
 */
297
 
298
static void
299
init()
300
{
301
    filltable("CWORD");
302
    syntax[0] = "CEOF";
303
#ifdef TARGET_CHAR
304
    syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
305
    syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
306
    syntax[base + (TARGET_CHAR)CTLENDVAR] = "CCTL";
307
    syntax[base + (TARGET_CHAR)CTLBACKQ] = "CCTL";
308
    syntax[base + (TARGET_CHAR)CTLBACKQ + (TARGET_CHAR)CTLQUOTE] = "CCTL";
309
    syntax[base + (TARGET_CHAR)CTLARI] = "CCTL";
310
    syntax[base + (TARGET_CHAR)CTLENDARI] = "CCTL";
311
    syntax[base + (TARGET_CHAR)CTLQUOTEMARK] = "CCTL";
312
#else
313
    syntax[base + CTLESC] = "CCTL";
314
    syntax[base + CTLVAR] = "CCTL";
315
    syntax[base + CTLENDVAR] = "CCTL";
316
    syntax[base + CTLBACKQ] = "CCTL";
317
    syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
318
    syntax[base + CTLARI] = "CCTL";
319
    syntax[base + CTLENDARI] = "CCTL";
320
    syntax[base + CTLQUOTEMARK] = "CCTL";
321
#endif /* TARGET_CHAR */
322
}
323
 
324
 
325
/*
326
 * Add entries to the syntax table.
327
 */
328
 
329
static void
330
add(p, type)
331
    char *p, *type;
332
{
333
    while (*p)
334
        syntax[*p++ + base] = type;
335
}
336
 
337
 
338
 
339
/*
340
 * Output the syntax table.
341
 */
342
 
343
static void
344
print(name)
345
    char *name;
346
{
347
    int i;
348
    int col;
349
 
350
    fprintf(hfile, "extern const char %s[];\n", name);
351
    fprintf(cfile, "const char %s[%d] = {\n", name, size);
352
    col = 0;
353
    for (i = 0 ; i < size ; i++) {
354
        if (i == 0) {
355
            fputs("      ", cfile);
356
        } else if ((i & 03) == 0) {
357
            fputs(",\n      ", cfile);
358
            col = 0;
359
        } else {
360
            putc(',', cfile);
361
            while (++col < 9 * (i & 03))
362
                putc(' ', cfile);
363
        }
364
        fputs(syntax[i], cfile);
365
        col += strlen(syntax[i]);
366
    }
367
    fputs("\n};\n", cfile);
368
}
369
 
370
 
371
 
372
/*
373
 * Output character classification macros (e.g. is_digit).  If digits are
374
 * contiguous, we can test for them quickly.
375
 */
376
 
377
static char *macro[] = {
378
    "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
379
    "#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
380
    "#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
381
    "#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
382
    "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
383
    NULL
384
};
385
 
386
static void
387
output_type_macros()
388
{
389
    char **pp;
390
 
391
    if (digit_contig)
392
        macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
393
    for (pp = macro ; *pp ; pp++)
394
        fprintf(hfile, "%s\n", *pp);
395
    if (digit_contig)
396
        fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
397
    else
398
        fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
399
}
400
 
401
 
402
 
403
/*
404
 * Output digit conversion table (if digits are not contiguous).
405
 */
406
 
407
static void
408
digit_convert()
409
{
410
    int maxdigit;
411
    static char digit[] = "0123456789";
412
    char *p;
413
    int i;
414
 
415
    maxdigit = 0;
416
    for (p = digit ; *p ; p++)
417
        if (*p > maxdigit)
418
            maxdigit = *p;
419
    fputs("extern const char digit_value[];\n", hfile);
420
    fputs("\n\nconst char digit_value[] = {\n", cfile);
421
    for (i = 0 ; i <= maxdigit ; i++) {
422
        for (p = digit ; *p && *p != i ; p++);
423
        if (*p == '\0')
424
            p = digit;
425
        fprintf(cfile, "      %ld,\n", (long)(p - digit));
426
    }
427
    fputs("};\n", cfile);
428
}