From d1fcfd193982be6d7e3e03cbd5681e6f444845c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Feb 2002 06:23:59 +0000 Subject: [PATCH] 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) --- tools/qfcc/include/qfcc.h | 1 + tools/qfcc/source/emit.c | 5 +++- tools/qfcc/source/expr.c | 29 ++++++++++++++++----- tools/qfcc/source/qc-lex.l | 52 ++++++++++++++++++++------------------ tools/qfcc/source/qfcc.c | 5 ++++ 5 files changed, 59 insertions(+), 33 deletions(-) diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 14817aaf1..2286f8bb0 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -594,6 +594,7 @@ typedef struct { int verbosity; // 0=silent, goes up to 2 currently qboolean save_temps; // save temporary files qboolean files_dat; // generate files.dat + qboolean traditional; // behave more like qcc } options_t; extern options_t options; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index c92bfa658..efbcb47cd 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -192,7 +192,10 @@ emit_assign_expr (int oper, expr_t *e) warning (e1, "assignment to constant %s (Moooooooo!)", def_a->name); } else { - error (e1, "assignment to constant %s", def_a->name); + if (options.traditional) + warning (e1, "assignment to constant %s", def_a->name); + else + error (e1, "assignment to constant %s", def_a->name); } } def_b = emit_sub_expr (e2, def_a); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0140339b6..8d6d303d4 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1449,7 +1449,9 @@ function_expr (expr_t *e1, expr_t *e2) if (parm_count > ftype->num_parms) { return error (e1, "too many arguments"); } else if (parm_count < ftype->num_parms) { - return error (e1, "too few arguments"); + if (!options.traditional) + return error (e1, "too few arguments"); + warning (e1, "too few arguments"); } } 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) { if (!e) { - if (f->def->type->aux_type != &type_void) - return error (e, "return from non-void function without a value"); - } else { + if (f->def->type->aux_type != &type_void) { + if (options.traditional) { + warning (e, "return from non-void function without a value"); + e = new_expr (); + e->type = ex_nil; + } else { + e = error (e, "return from non-void function without a value"); + return e; + } + } + } + if (e) { type_t *t = get_type (e); if (f->def->type->aux_type == &type_void) @@ -1737,10 +1748,14 @@ assign_expr (expr_t *e1, expr_t *e2) convert_nil (e2, t2); } - if (t1 != t2) - return type_mismatch (e1, e2, op); - else + if (t1 != t2) { + if (!options.traditional || t1->type != ev_func || t2->type != ev_func) + return type_mismatch (e1, e2, op); + warning (e1, "assignment between disparate function types"); type = t1; + } else { + type = t1; + } if (is_indirect (e1) && is_indirect (e2)) { expr_t *temp = new_temp_def_expr (t1); diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index ceb1bc123..730cd7dcd 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -216,34 +216,35 @@ typedef struct { const char *name; int value; type_t *type; + int traditional; int version; } keyword_t; static keyword_t keywords[] = { - {"void", TYPE, &type_void, PROG_ID_VERSION}, - {"float", TYPE, &type_float, PROG_ID_VERSION}, - {"string", TYPE, &type_string, PROG_ID_VERSION}, - {"vector", TYPE, &type_vector, PROG_ID_VERSION}, - {"entity", TYPE, &type_entity, PROG_ID_VERSION}, - {"quaternion", TYPE, &type_quaternion, PROG_VERSION}, - {"integer", TYPE, &type_integer, PROG_VERSION}, - {"function", TYPE, &type_function, PROG_VERSION}, - {"local", LOCAL, 0, PROG_ID_VERSION}, - {"return", RETURN, 0, PROG_ID_VERSION}, - {"while", WHILE, 0, PROG_ID_VERSION}, - {"do", DO, 0, PROG_ID_VERSION}, - {"if", IF, 0, PROG_ID_VERSION}, - {"else", ELSE, 0, PROG_ID_VERSION}, - {"for", FOR, 0, PROG_ID_VERSION}, - {"break", BREAK, 0, PROG_ID_VERSION}, - {"continue", CONTINUE, 0, PROG_ID_VERSION}, - {"switch", SWITCH, 0, PROG_ID_VERSION}, - {"case", CASE, 0, PROG_ID_VERSION}, - {"default", DEFAULT, 0, PROG_ID_VERSION}, - {"NIL", NIL, 0, PROG_ID_VERSION}, - {"struct", STRUCT, 0, PROG_VERSION}, - {"enum", ENUM, 0, PROG_ID_VERSION}, - {"typedef", TYPEDEF, 0, PROG_ID_VERSION}, + {"void", TYPE, &type_void, 1, PROG_ID_VERSION}, + {"float", TYPE, &type_float, 1, PROG_ID_VERSION}, + {"string", TYPE, &type_string, 1, PROG_ID_VERSION}, + {"vector", TYPE, &type_vector, 1, PROG_ID_VERSION}, + {"entity", TYPE, &type_entity, 1, PROG_ID_VERSION}, + {"quaternion", TYPE, &type_quaternion, 0, PROG_VERSION}, + {"integer", TYPE, &type_integer, 0, PROG_VERSION}, + {"function", TYPE, &type_function, 0, PROG_VERSION}, + {"local", LOCAL, 0, 1, PROG_ID_VERSION}, + {"return", RETURN, 0, 1, PROG_ID_VERSION}, + {"while", WHILE, 0, 1, PROG_ID_VERSION}, + {"do", DO, 0, 1, PROG_ID_VERSION}, + {"if", IF, 0, 1, PROG_ID_VERSION}, + {"else", ELSE, 0, 1, PROG_ID_VERSION}, + {"for", FOR, 0, 0, PROG_ID_VERSION}, + {"break", BREAK, 0, 0, PROG_ID_VERSION}, + {"continue", CONTINUE, 0, 0, PROG_ID_VERSION}, + {"switch", SWITCH, 0, 0, PROG_ID_VERSION}, + {"case", CASE, 0, 0, PROG_ID_VERSION}, + {"default", DEFAULT, 0, 0, PROG_ID_VERSION}, + {"NIL", NIL, 0, 0, PROG_ID_VERSION}, + {"struct", STRUCT, 0, 0, PROG_VERSION}, + {"enum", ENUM, 0, 0, PROG_ID_VERSION}, + {"typedef", TYPEDEF, 0, 0, PROG_ID_VERSION}, }; static const char * @@ -263,7 +264,8 @@ type_or_name (char *token) int i; keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0); 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]); } keyword = Hash_Find (keyword_tab, token); diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index fb11b2a8f..47513d27b 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -80,6 +80,7 @@ static struct option const long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"files", no_argument, 0, 'F'}, + {"traditional", no_argument, 0, 't'}, #ifdef USE_CPP {"define", required_argument, 0, 'D'}, {"include", required_argument, 0, 'I'}, @@ -857,6 +858,10 @@ DecodeArgs (int argc, char **argv) case 'g': // debug options.code.debug = true; break; + case 't': // traditional + options.traditional = true; + options.code.progsversion = PROG_ID_VERSION; + break; case 'C':{ // code options char *opts = strdup (optarg); char *temp = strtok (opts, ",");