xref: /csrg-svn/bin/sh/mksyntax.c (revision 69272)
147132Sbostic /*-
260698Sbostic  * Copyright (c) 1991, 1993
360698Sbostic  *	The Regents of the University of California.  All rights reserved.
447132Sbostic  *
547132Sbostic  * This code is derived from software contributed to Berkeley by
647132Sbostic  * Kenneth Almquist.
747132Sbostic  *
847132Sbostic  * %sccs.include.redist.c%
947132Sbostic  */
1047132Sbostic 
1147132Sbostic #ifndef lint
1260698Sbostic static char copyright[] =
1360698Sbostic "@(#) Copyright (c) 1991, 1993\n\
1460698Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1547132Sbostic #endif /* not lint */
1647132Sbostic 
1747132Sbostic #ifndef lint
18*69272Schristos static char sccsid[] = "@(#)mksyntax.c	8.2 (Berkeley) 05/04/95";
1947132Sbostic #endif /* not lint */
2047132Sbostic 
2147132Sbostic /*
2247132Sbostic  * This program creates syntax.h and syntax.c.
2347132Sbostic  */
2447132Sbostic 
2547132Sbostic #include <stdio.h>
26*69272Schristos #include <string.h>
2747132Sbostic #include "parser.h"
2847132Sbostic 
2947132Sbostic 
3047132Sbostic struct synclass {
3147132Sbostic 	char *name;
3247132Sbostic 	char *comment;
3347132Sbostic };
3447132Sbostic 
3547132Sbostic /* Syntax classes */
3647132Sbostic struct synclass synclass[] = {
37*69272Schristos 	{ "CWORD",	"character is nothing special" },
38*69272Schristos 	{ "CNL",	"newline character" },
39*69272Schristos 	{ "CBACK",	"a backslash character" },
40*69272Schristos 	{ "CSQUOTE",	"single quote" },
41*69272Schristos 	{ "CDQUOTE",	"double quote" },
42*69272Schristos 	{ "CENDQUOTE",	"a terminating quote" },
43*69272Schristos 	{ "CBQUOTE",	"backwards single quote" },
44*69272Schristos 	{ "CVAR",	"a dollar sign" },
45*69272Schristos 	{ "CENDVAR",	"a '}' character" },
46*69272Schristos 	{ "CLP",	"a left paren in arithmetic" },
47*69272Schristos 	{ "CRP",	"a right paren in arithmetic" },
48*69272Schristos 	{ "CEOF",	"end of file" },
49*69272Schristos 	{ "CCTL",	"like CWORD, except it must be escaped" },
50*69272Schristos 	{ "CSPCL",	"these terminate a word" },
51*69272Schristos 	{ NULL,		NULL }
5247132Sbostic };
5347132Sbostic 
5447132Sbostic 
5547132Sbostic /*
5647132Sbostic  * Syntax classes for is_ functions.  Warning:  if you add new classes
5747132Sbostic  * you may have to change the definition of the is_in_name macro.
5847132Sbostic  */
5947132Sbostic struct synclass is_entry[] = {
60*69272Schristos 	{ "ISDIGIT",	"a digit" },
61*69272Schristos 	{ "ISUPPER",	"an upper case letter" },
62*69272Schristos 	{ "ISLOWER",	"a lower case letter" },
63*69272Schristos 	{ "ISUNDER",	"an underscore" },
64*69272Schristos 	{ "ISSPECL",	"the name of a special parameter" },
65*69272Schristos 	{ NULL, 	NULL }
6647132Sbostic };
6747132Sbostic 
68*69272Schristos static char writer[] = "\
6947132Sbostic /*\n\
7047132Sbostic  * This file was generated by the mksyntax program.\n\
7147132Sbostic  */\n\
7247132Sbostic \n";
7347132Sbostic 
7447132Sbostic 
75*69272Schristos static FILE *cfile;
76*69272Schristos static FILE *hfile;
77*69272Schristos static char *syntax[513];
78*69272Schristos static int base;
79*69272Schristos static int size;	/* number of values which a char variable can have */
80*69272Schristos static int nbits;	/* number of bits in a character */
81*69272Schristos static int digit_contig;/* true if digits are contiguous */
8247132Sbostic 
83*69272Schristos static void filltable __P((char *));
84*69272Schristos static void init __P((void));
85*69272Schristos static void add __P((char *, char *));
86*69272Schristos static void print __P((char *));
87*69272Schristos static void output_type_macros __P((void));
88*69272Schristos static void digit_convert __P((void));
8947132Sbostic 
90*69272Schristos int
main(argc,argv)91*69272Schristos main(argc, argv)
92*69272Schristos 	int argc;
93*69272Schristos 	char **argv;
94*69272Schristos {
9547132Sbostic 	char c;
9647132Sbostic 	char d;
9747132Sbostic 	int sign;
9847132Sbostic 	int i;
9947132Sbostic 	char buf[80];
10047132Sbostic 	int pos;
10147132Sbostic 	static char digit[] = "0123456789";
10247132Sbostic 
10347132Sbostic 	/* Create output files */
10447132Sbostic 	if ((cfile = fopen("syntax.c", "w")) == NULL) {
10547132Sbostic 		perror("syntax.c");
10647132Sbostic 		exit(2);
10747132Sbostic 	}
10847132Sbostic 	if ((hfile = fopen("syntax.h", "w")) == NULL) {
10947132Sbostic 		perror("syntax.h");
11047132Sbostic 		exit(2);
11147132Sbostic 	}
11247132Sbostic 	fputs(writer, hfile);
11347132Sbostic 	fputs(writer, cfile);
11447132Sbostic 
11547132Sbostic 	/* Determine the characteristics of chars. */
11647132Sbostic 	c = -1;
11747132Sbostic 	if (c < 0)
11847132Sbostic 		sign = 1;
11947132Sbostic 	else
12047132Sbostic 		sign = 0;
12147132Sbostic 	for (nbits = 1 ; ; nbits++) {
12247132Sbostic 		d = (1 << nbits) - 1;
12347132Sbostic 		if (d == c)
12447132Sbostic 			break;
12547132Sbostic 	}
12647132Sbostic 	printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
12747132Sbostic 	if (nbits > 9) {
12847132Sbostic 		fputs("Characters can't have more than 9 bits\n", stderr);
12947132Sbostic 		exit(2);
13047132Sbostic 	}
13147132Sbostic 	size = (1 << nbits) + 1;
13247132Sbostic 	base = 1;
13347132Sbostic 	if (sign)
13447132Sbostic 		base += 1 << (nbits - 1);
13547132Sbostic 	digit_contig = 1;
13647132Sbostic 	for (i = 0 ; i < 10 ; i++) {
13747132Sbostic 		if (digit[i] != '0' + i)
13847132Sbostic 			digit_contig = 0;
13947132Sbostic 	}
14047132Sbostic 
14147166Sbostic 	fputs("#include <sys/cdefs.h>\n", hfile);
14247166Sbostic 
14347132Sbostic 	/* Generate the #define statements in the header file */
14447132Sbostic 	fputs("/* Syntax classes */\n", hfile);
14547132Sbostic 	for (i = 0 ; synclass[i].name ; i++) {
14647132Sbostic 		sprintf(buf, "#define %s %d", synclass[i].name, i);
14747132Sbostic 		fputs(buf, hfile);
148*69272Schristos 		for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
14947132Sbostic 			putc('\t', hfile);
15047132Sbostic 		fprintf(hfile, "/* %s */\n", synclass[i].comment);
15147132Sbostic 	}
15247132Sbostic 	putc('\n', hfile);
15347132Sbostic 	fputs("/* Syntax classes for is_ functions */\n", hfile);
15447132Sbostic 	for (i = 0 ; is_entry[i].name ; i++) {
15547132Sbostic 		sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
15647132Sbostic 		fputs(buf, hfile);
157*69272Schristos 		for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
15847132Sbostic 			putc('\t', hfile);
15947132Sbostic 		fprintf(hfile, "/* %s */\n", is_entry[i].comment);
16047132Sbostic 	}
16147132Sbostic 	putc('\n', hfile);
16247132Sbostic 	fprintf(hfile, "#define SYNBASE %d\n", base);
16347132Sbostic 	fprintf(hfile, "#define PEOF %d\n\n", -base);
16447132Sbostic 	putc('\n', hfile);
16547132Sbostic 	fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
16647132Sbostic 	fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
16747132Sbostic 	fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
16853301Smarc 	fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
16947132Sbostic 	putc('\n', hfile);
17047132Sbostic 	output_type_macros();		/* is_digit, etc. */
17147132Sbostic 	putc('\n', hfile);
17247132Sbostic 
17347132Sbostic 	/* Generate the syntax tables. */
17447132Sbostic 	fputs("#include \"shell.h\"\n", cfile);
17547132Sbostic 	fputs("#include \"syntax.h\"\n\n", cfile);
17647132Sbostic 	init();
17747132Sbostic 	fputs("/* syntax table used when not in quotes */\n", cfile);
17847132Sbostic 	add("\n", "CNL");
17947132Sbostic 	add("\\", "CBACK");
18047132Sbostic 	add("'", "CSQUOTE");
18147132Sbostic 	add("\"", "CDQUOTE");
18247132Sbostic 	add("`", "CBQUOTE");
18347132Sbostic 	add("$", "CVAR");
18447132Sbostic 	add("}", "CENDVAR");
18547132Sbostic 	add("<>();&| \t", "CSPCL");
18647132Sbostic 	print("basesyntax");
18747132Sbostic 	init();
18847132Sbostic 	fputs("\n/* syntax table used when in double quotes */\n", cfile);
18947132Sbostic 	add("\n", "CNL");
19047132Sbostic 	add("\\", "CBACK");
19147132Sbostic 	add("\"", "CENDQUOTE");
19247132Sbostic 	add("`", "CBQUOTE");
19347132Sbostic 	add("$", "CVAR");
19447132Sbostic 	add("}", "CENDVAR");
195*69272Schristos 	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
196*69272Schristos 	add("!*?[=~:/-", "CCTL");
19747132Sbostic 	print("dqsyntax");
19847132Sbostic 	init();
19947132Sbostic 	fputs("\n/* syntax table used when in single quotes */\n", cfile);
20047132Sbostic 	add("\n", "CNL");
20147132Sbostic 	add("'", "CENDQUOTE");
202*69272Schristos 	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
203*69272Schristos 	add("!*?[=~:/-", "CCTL");
20447132Sbostic 	print("sqsyntax");
20553301Smarc 	init();
20653301Smarc 	fputs("\n/* syntax table used when in arithmetic */\n", cfile);
20753301Smarc 	add("\n", "CNL");
20853301Smarc 	add("\\", "CBACK");
20953301Smarc 	add("`", "CBQUOTE");
21053301Smarc 	add("'", "CSQUOTE");
21153301Smarc 	add("\"", "CDQUOTE");
21253301Smarc 	add("$", "CVAR");
21353301Smarc 	add("}", "CENDVAR");
21453301Smarc 	add("(", "CLP");
21553301Smarc 	add(")", "CRP");
21653301Smarc 	print("arisyntax");
21747132Sbostic 	filltable("0");
21847132Sbostic 	fputs("\n/* character classification table */\n", cfile);
21947132Sbostic 	add("0123456789", "ISDIGIT");
22047132Sbostic 	add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
22147132Sbostic 	add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
22247132Sbostic 	add("_", "ISUNDER");
22347132Sbostic 	add("#?$!-*@", "ISSPECL");
22447132Sbostic 	print("is_type");
22547132Sbostic 	if (! digit_contig)
22647132Sbostic 		digit_convert();
22747132Sbostic 	exit(0);
22847132Sbostic }
22947132Sbostic 
23047132Sbostic 
23147132Sbostic 
23247132Sbostic /*
23347132Sbostic  * Clear the syntax table.
23447132Sbostic  */
23547132Sbostic 
236*69272Schristos static void
filltable(dftval)23747132Sbostic filltable(dftval)
23847132Sbostic 	char *dftval;
239*69272Schristos {
24047132Sbostic 	int i;
24147132Sbostic 
24247132Sbostic 	for (i = 0 ; i < size ; i++)
24347132Sbostic 		syntax[i] = dftval;
24447132Sbostic }
24547132Sbostic 
24647132Sbostic 
24747132Sbostic /*
24847132Sbostic  * Initialize the syntax table with default values.
24947132Sbostic  */
25047132Sbostic 
251*69272Schristos static void
init()252*69272Schristos init()
253*69272Schristos {
25447132Sbostic 	filltable("CWORD");
25547132Sbostic 	syntax[0] = "CEOF";
25647132Sbostic 	syntax[base + CTLESC] = "CCTL";
25747132Sbostic 	syntax[base + CTLVAR] = "CCTL";
25847132Sbostic 	syntax[base + CTLENDVAR] = "CCTL";
25947132Sbostic 	syntax[base + CTLBACKQ] = "CCTL";
26047132Sbostic 	syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
26153301Smarc 	syntax[base + CTLARI] = "CCTL";
26253301Smarc 	syntax[base + CTLENDARI] = "CCTL";
26347132Sbostic }
26447132Sbostic 
26547132Sbostic 
26647132Sbostic /*
26747132Sbostic  * Add entries to the syntax table.
26847132Sbostic  */
26947132Sbostic 
270*69272Schristos static void
add(p,type)27147132Sbostic add(p, type)
27247132Sbostic 	char *p, *type;
273*69272Schristos {
27447132Sbostic 	while (*p)
27547132Sbostic 		syntax[*p++ + base] = type;
27647132Sbostic }
27747132Sbostic 
27847132Sbostic 
27947132Sbostic 
28047132Sbostic /*
28147132Sbostic  * Output the syntax table.
28247132Sbostic  */
28347132Sbostic 
284*69272Schristos static void
print(name)28547132Sbostic print(name)
28647132Sbostic 	char *name;
287*69272Schristos {
28847132Sbostic 	int i;
28947132Sbostic 	int col;
29047132Sbostic 
29147132Sbostic 	fprintf(hfile, "extern const char %s[];\n", name);
29247132Sbostic 	fprintf(cfile, "const char %s[%d] = {\n", name, size);
29347132Sbostic 	col = 0;
29447132Sbostic 	for (i = 0 ; i < size ; i++) {
29547132Sbostic 		if (i == 0) {
29647132Sbostic 			fputs("      ", cfile);
29747132Sbostic 		} else if ((i & 03) == 0) {
29847132Sbostic 			fputs(",\n      ", cfile);
29947132Sbostic 			col = 0;
30047132Sbostic 		} else {
30147132Sbostic 			putc(',', cfile);
30247132Sbostic 			while (++col < 9 * (i & 03))
30347132Sbostic 				putc(' ', cfile);
30447132Sbostic 		}
30547132Sbostic 		fputs(syntax[i], cfile);
30647132Sbostic 		col += strlen(syntax[i]);
30747132Sbostic 	}
30847132Sbostic 	fputs("\n};\n", cfile);
30947132Sbostic }
31047132Sbostic 
31147132Sbostic 
31247132Sbostic 
31347132Sbostic /*
31447132Sbostic  * Output character classification macros (e.g. is_digit).  If digits are
31547132Sbostic  * contiguous, we can test for them quickly.
31647132Sbostic  */
31747132Sbostic 
318*69272Schristos static char *macro[] = {
31947132Sbostic 	"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
32047132Sbostic 	"#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
32147132Sbostic 	"#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
32247132Sbostic 	"#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
32347132Sbostic 	"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
32447132Sbostic 	NULL
32547132Sbostic };
32647132Sbostic 
327*69272Schristos static void
output_type_macros()328*69272Schristos output_type_macros()
329*69272Schristos {
33047132Sbostic 	char **pp;
33147132Sbostic 
33247132Sbostic 	if (digit_contig)
33347132Sbostic 		macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
33447132Sbostic 	for (pp = macro ; *pp ; pp++)
33547132Sbostic 		fprintf(hfile, "%s\n", *pp);
33647132Sbostic 	if (digit_contig)
33747132Sbostic 		fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
33847132Sbostic 	else
33947132Sbostic 		fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
34047132Sbostic }
34147132Sbostic 
34247132Sbostic 
34347132Sbostic 
34447132Sbostic /*
34547132Sbostic  * Output digit conversion table (if digits are not contiguous).
34647132Sbostic  */
34747132Sbostic 
348*69272Schristos static void
digit_convert()349*69272Schristos digit_convert()
350*69272Schristos {
35147132Sbostic 	int maxdigit;
35247132Sbostic 	static char digit[] = "0123456789";
35347132Sbostic 	char *p;
35447132Sbostic 	int i;
35547132Sbostic 
35647132Sbostic 	maxdigit = 0;
35747132Sbostic 	for (p = digit ; *p ; p++)
35847132Sbostic 		if (*p > maxdigit)
35947132Sbostic 			maxdigit = *p;
36047132Sbostic 	fputs("extern const char digit_value[];\n", hfile);
36147132Sbostic 	fputs("\n\nconst char digit_value[] = {\n", cfile);
36247132Sbostic 	for (i = 0 ; i <= maxdigit ; i++) {
36347132Sbostic 		for (p = digit ; *p && *p != i ; p++);
36447132Sbostic 		if (*p == '\0')
36547132Sbostic 			p = digit;
36647132Sbostic 		fprintf(cfile, "      %d,\n", p - digit);
36747132Sbostic 	}
36847132Sbostic 	fputs("};\n", cfile);
36947132Sbostic }
370