sh: Simplify mksyntax and make it fit for cross-compiling.

Now it outputs fixed files, which use constants provided by the C standard
library to determine appropriate values for the target machine.

Before, mksyntax inspected the host machine which resulted in subtle
breakage if e.g. char is signed on the host and unsigned on the target such
as when cross-compiling on x86 for ARM.

Tested using -funsigned-char on amd64. Compiling build-tools without it and
sh itself with it causes various tests to fail without this change but not
with this change. With consistent -funsigned-char, tests pass with or
without this change.

The mksyntax program could be removed and syntax.c and syntax.h committed to
the repository.

Submitted by:	Christoph Mallon
MFC after:	2 weeks
This commit is contained in:
Jilles Tjoelker 2013-02-07 22:42:33 +00:00
parent 6db8a9b0f4
commit 1767d529f2

View File

@ -103,23 +103,16 @@ static char writer[] = "\
static FILE *cfile;
static FILE *hfile;
static const char *syntax[513];
static int base;
static int size; /* number of values which a char variable can have */
static int nbits; /* number of bits in a character */
static void filltable(const char *);
static void init(void);
static void add_default(void);
static void finish(void);
static void init(const char *);
static void add(const char *, const char *);
static void print(const char *);
static void output_type_macros(void);
int
main(int argc __unused, char **argv __unused)
{
char c;
char d;
int sign;
int i;
char buf[80];
int pos;
@ -136,27 +129,8 @@ main(int argc __unused, char **argv __unused)
fputs(writer, hfile);
fputs(writer, cfile);
/* Determine the characteristics of chars. */
c = -1;
sign = (c > 0) ? 0 : 1;
for (nbits = 1 ; ; nbits++) {
d = (1 << nbits) - 1;
if (d == c)
break;
}
#if 0
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
#endif
if (nbits > 9) {
fputs("Characters can't have more than 9 bits\n", stderr);
exit(2);
}
size = (1 << nbits) + 1;
base = 1;
if (sign)
base += 1 << (nbits - 1);
fputs("#include <sys/cdefs.h>\n", hfile);
fputs("#include <limits.h>\n\n", hfile);
/* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile);
@ -177,8 +151,8 @@ main(int argc __unused, char **argv __unused)
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
}
putc('\n', hfile);
fprintf(hfile, "#define SYNBASE %d\n", base);
fprintf(hfile, "#define PEOF %d\n\n", -base);
fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile);
fputs("#define PEOF -SYNBASE\n\n", hfile);
putc('\n', hfile);
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
@ -189,10 +163,13 @@ main(int argc __unused, char **argv __unused)
putc('\n', hfile);
/* Generate the syntax tables. */
fputs("#include \"parser.h\"\n", cfile);
fputs("#include \"shell.h\"\n", cfile);
fputs("#include \"syntax.h\"\n\n", cfile);
init();
fputs("/* syntax table used when not in quotes */\n", cfile);
init("basesyntax");
add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("'", "CSQUOTE");
@ -201,9 +178,11 @@ main(int argc __unused, char **argv __unused)
add("$", "CVAR");
add("}", "CENDVAR");
add("<>();&| \t", "CSPCL");
print("basesyntax");
init();
finish();
fputs("\n/* syntax table used when in double quotes */\n", cfile);
init("dqsyntax");
add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("\"", "CENDQUOTE");
@ -212,17 +191,21 @@ main(int argc __unused, char **argv __unused)
add("}", "CENDVAR");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
print("dqsyntax");
init();
finish();
fputs("\n/* syntax table used when in single quotes */\n", cfile);
init("sqsyntax");
add_default();
add("\n", "CNL");
add("\\", "CSBACK");
add("'", "CENDQUOTE");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
print("sqsyntax");
init();
finish();
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
init("arisyntax");
add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("`", "CBQUOTE");
@ -231,52 +214,68 @@ main(int argc __unused, char **argv __unused)
add("}", "CENDVAR");
add("(", "CLP");
add(")", "CRP");
print("arisyntax");
filltable("0");
finish();
fputs("\n/* character classification table */\n", cfile);
init("is_type");
add("0123456789", "ISDIGIT");
add("abcdefghijklmnopqrstuvwxyz", "ISLOWER");
add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER");
add("_", "ISUNDER");
add("#?$!-*@", "ISSPECL");
print("is_type");
finish();
exit(0);
}
/*
* Clear the syntax table.
* Output the header and declaration of a syntax table.
*/
static void
filltable(const char *dftval)
init(const char *name)
{
int i;
fprintf(hfile, "extern const char %s[];\n", name);
fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name);
}
for (i = 0 ; i < size ; i++)
syntax[i] = dftval;
static void
add_one(const char *key, const char *type)
{
fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type);
}
/*
* Initialize the syntax table with default values.
* Add default values to the syntax table.
*/
static void
init(void)
add_default(void)
{
filltable("CWORD");
syntax[0] = "CEOF";
syntax[base + CTLESC] = "CCTL";
syntax[base + CTLVAR] = "CCTL";
syntax[base + CTLENDVAR] = "CCTL";
syntax[base + CTLBACKQ] = "CCTL";
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
syntax[base + CTLARI] = "CCTL";
syntax[base + CTLENDARI] = "CCTL";
syntax[base + CTLQUOTEMARK] = "CCTL";
syntax[base + CTLQUOTEEND] = "CCTL";
add_one("PEOF", "CEOF");
add_one("CTLESC", "CCTL");
add_one("CTLVAR", "CCTL");
add_one("CTLENDVAR", "CCTL");
add_one("CTLBACKQ", "CCTL");
add_one("CTLBACKQ + CTLQUOTE", "CCTL");
add_one("CTLARI", "CCTL");
add_one("CTLENDARI", "CCTL");
add_one("CTLQUOTEMARK", "CCTL");
add_one("CTLQUOTEEND", "CCTL");
}
/*
* Output the footer of a syntax table.
*/
static void
finish(void)
{
fputs("};\n", cfile);
}
@ -287,44 +286,23 @@ init(void)
static void
add(const char *p, const char *type)
{
while (*p)
syntax[*p++ + base] = type;
}
for (; *p; ++p) {
char c = *p;
switch (c) {
case '\t': c = 't'; break;
case '\n': c = 'n'; break;
case '\'': c = '\''; break;
case '\\': c = '\\'; break;
/*
* Output the syntax table.
*/
static void
print(const char *name)
{
int i;
int col;
fprintf(hfile, "extern const char %s[];\n", name);
fprintf(cfile, "const char %s[%d] = {\n", name, size);
col = 0;
for (i = 0 ; i < size ; i++) {
if (i == 0) {
fputs(" ", cfile);
} else if ((i & 03) == 0) {
fputs(",\n ", cfile);
col = 0;
} else {
putc(',', cfile);
while (++col < 9 * (i & 03))
putc(' ', cfile);
default:
fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type);
continue;
}
fputs(syntax[i], cfile);
col += strlen(syntax[i]);
fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type);
}
fputs("\n};\n", cfile);
}
/*
* Output character classification macros (e.g. is_digit). If digits are
* contiguous, we can test for them quickly.