Implement --traditional so qfcc can be a nicer qcc. This disables several

keywords (quaternion integer function for break continue switch case default
NIL struct enum typedef) and converts some errors to warnings (assignment to
constants, insufficient function arguments, return; from non-void function,
anal function `pointer' type checks)
This commit is contained in:
Bill Currie 2002-02-18 06:23:59 +00:00
parent 7c9a19283b
commit d1fcfd1939
5 changed files with 59 additions and 33 deletions

View file

@ -594,6 +594,7 @@ typedef struct {
int verbosity; // 0=silent, goes up to 2 currently int verbosity; // 0=silent, goes up to 2 currently
qboolean save_temps; // save temporary files qboolean save_temps; // save temporary files
qboolean files_dat; // generate files.dat qboolean files_dat; // generate files.dat
qboolean traditional; // behave more like qcc
} options_t; } options_t;
extern options_t options; extern options_t options;

View file

@ -192,6 +192,9 @@ emit_assign_expr (int oper, expr_t *e)
warning (e1, "assignment to constant %s (Moooooooo!)", warning (e1, "assignment to constant %s (Moooooooo!)",
def_a->name); def_a->name);
} else { } else {
if (options.traditional)
warning (e1, "assignment to constant %s", def_a->name);
else
error (e1, "assignment to constant %s", def_a->name); error (e1, "assignment to constant %s", def_a->name);
} }
} }

View file

@ -1449,7 +1449,9 @@ function_expr (expr_t *e1, expr_t *e2)
if (parm_count > ftype->num_parms) { if (parm_count > ftype->num_parms) {
return error (e1, "too many arguments"); return error (e1, "too many arguments");
} else if (parm_count < ftype->num_parms) { } else if (parm_count < ftype->num_parms) {
if (!options.traditional)
return error (e1, "too few arguments"); return error (e1, "too few arguments");
warning (e1, "too few arguments");
} }
} }
for (i = parm_count, e = e2; i > 0; i--, e = e->next) { for (i = parm_count, e = e2; i > 0; i--, e = e->next) {
@ -1524,9 +1526,18 @@ expr_t *
return_expr (function_t *f, expr_t *e) return_expr (function_t *f, expr_t *e)
{ {
if (!e) { if (!e) {
if (f->def->type->aux_type != &type_void) if (f->def->type->aux_type != &type_void) {
return error (e, "return from non-void function without a value"); if (options.traditional) {
warning (e, "return from non-void function without a value");
e = new_expr ();
e->type = ex_nil;
} else { } else {
e = error (e, "return from non-void function without a value");
return e;
}
}
}
if (e) {
type_t *t = get_type (e); type_t *t = get_type (e);
if (f->def->type->aux_type == &type_void) if (f->def->type->aux_type == &type_void)
@ -1737,10 +1748,14 @@ assign_expr (expr_t *e1, expr_t *e2)
convert_nil (e2, t2); convert_nil (e2, t2);
} }
if (t1 != t2) if (t1 != t2) {
if (!options.traditional || t1->type != ev_func || t2->type != ev_func)
return type_mismatch (e1, e2, op); return type_mismatch (e1, e2, op);
else warning (e1, "assignment between disparate function types");
type = t1; type = t1;
} else {
type = t1;
}
if (is_indirect (e1) && is_indirect (e2)) { if (is_indirect (e1) && is_indirect (e2)) {
expr_t *temp = new_temp_def_expr (t1); expr_t *temp = new_temp_def_expr (t1);

View file

@ -216,34 +216,35 @@ typedef struct {
const char *name; const char *name;
int value; int value;
type_t *type; type_t *type;
int traditional;
int version; int version;
} keyword_t; } keyword_t;
static keyword_t keywords[] = { static keyword_t keywords[] = {
{"void", TYPE, &type_void, PROG_ID_VERSION}, {"void", TYPE, &type_void, 1, PROG_ID_VERSION},
{"float", TYPE, &type_float, PROG_ID_VERSION}, {"float", TYPE, &type_float, 1, PROG_ID_VERSION},
{"string", TYPE, &type_string, PROG_ID_VERSION}, {"string", TYPE, &type_string, 1, PROG_ID_VERSION},
{"vector", TYPE, &type_vector, PROG_ID_VERSION}, {"vector", TYPE, &type_vector, 1, PROG_ID_VERSION},
{"entity", TYPE, &type_entity, PROG_ID_VERSION}, {"entity", TYPE, &type_entity, 1, PROG_ID_VERSION},
{"quaternion", TYPE, &type_quaternion, PROG_VERSION}, {"quaternion", TYPE, &type_quaternion, 0, PROG_VERSION},
{"integer", TYPE, &type_integer, PROG_VERSION}, {"integer", TYPE, &type_integer, 0, PROG_VERSION},
{"function", TYPE, &type_function, PROG_VERSION}, {"function", TYPE, &type_function, 0, PROG_VERSION},
{"local", LOCAL, 0, PROG_ID_VERSION}, {"local", LOCAL, 0, 1, PROG_ID_VERSION},
{"return", RETURN, 0, PROG_ID_VERSION}, {"return", RETURN, 0, 1, PROG_ID_VERSION},
{"while", WHILE, 0, PROG_ID_VERSION}, {"while", WHILE, 0, 1, PROG_ID_VERSION},
{"do", DO, 0, PROG_ID_VERSION}, {"do", DO, 0, 1, PROG_ID_VERSION},
{"if", IF, 0, PROG_ID_VERSION}, {"if", IF, 0, 1, PROG_ID_VERSION},
{"else", ELSE, 0, PROG_ID_VERSION}, {"else", ELSE, 0, 1, PROG_ID_VERSION},
{"for", FOR, 0, PROG_ID_VERSION}, {"for", FOR, 0, 0, PROG_ID_VERSION},
{"break", BREAK, 0, PROG_ID_VERSION}, {"break", BREAK, 0, 0, PROG_ID_VERSION},
{"continue", CONTINUE, 0, PROG_ID_VERSION}, {"continue", CONTINUE, 0, 0, PROG_ID_VERSION},
{"switch", SWITCH, 0, PROG_ID_VERSION}, {"switch", SWITCH, 0, 0, PROG_ID_VERSION},
{"case", CASE, 0, PROG_ID_VERSION}, {"case", CASE, 0, 0, PROG_ID_VERSION},
{"default", DEFAULT, 0, PROG_ID_VERSION}, {"default", DEFAULT, 0, 0, PROG_ID_VERSION},
{"NIL", NIL, 0, PROG_ID_VERSION}, {"NIL", NIL, 0, 0, PROG_ID_VERSION},
{"struct", STRUCT, 0, PROG_VERSION}, {"struct", STRUCT, 0, 0, PROG_VERSION},
{"enum", ENUM, 0, PROG_ID_VERSION}, {"enum", ENUM, 0, 0, PROG_ID_VERSION},
{"typedef", TYPEDEF, 0, PROG_ID_VERSION}, {"typedef", TYPEDEF, 0, 0, PROG_ID_VERSION},
}; };
static const char * static const char *
@ -263,7 +264,8 @@ type_or_name (char *token)
int i; int i;
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0); keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++) for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
if (keywords[i].version <= options.code.progsversion) if (keywords[i].traditional >= options.traditional
&& keywords[i].version <= options.code.progsversion)
Hash_Add (keyword_tab, &keywords[i]); Hash_Add (keyword_tab, &keywords[i]);
} }
keyword = Hash_Find (keyword_tab, token); keyword = Hash_Find (keyword_tab, token);

View file

@ -80,6 +80,7 @@ static struct option const long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'}, {"version", no_argument, 0, 'V'},
{"files", no_argument, 0, 'F'}, {"files", no_argument, 0, 'F'},
{"traditional", no_argument, 0, 't'},
#ifdef USE_CPP #ifdef USE_CPP
{"define", required_argument, 0, 'D'}, {"define", required_argument, 0, 'D'},
{"include", required_argument, 0, 'I'}, {"include", required_argument, 0, 'I'},
@ -857,6 +858,10 @@ DecodeArgs (int argc, char **argv)
case 'g': // debug case 'g': // debug
options.code.debug = true; options.code.debug = true;
break; break;
case 't': // traditional
options.traditional = true;
options.code.progsversion = PROG_ID_VERSION;
break;
case 'C':{ // code options case 'C':{ // code options
char *opts = strdup (optarg); char *opts = strdup (optarg);
char *temp = strtok (opts, ","); char *temp = strtok (opts, ",");