/much/ better error handling

This commit is contained in:
Bill Currie 2001-06-28 21:26:40 +00:00
parent eef9e8e2dc
commit 6dfee9968b
4 changed files with 73 additions and 52 deletions

View file

@ -61,3 +61,6 @@ expr_t *function_expr (expr_t *e1, expr_t *e2);
def_t *emit_statement (opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c); def_t *emit_statement (opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c);
void emit_expr (expr_t *e); void emit_expr (expr_t *e);
expr_t *error (expr_t *e, const char *fmt, ...);
void warning (expr_t *e, const char *fmt, ...);

View file

@ -7,7 +7,6 @@
#include "scope.h" #include "scope.h"
#include "qc-parse.h" #include "qc-parse.h"
void yyerror (const char*);
extern function_t *current_func; extern function_t *current_func;
static etype_t qc_types[] = { static etype_t qc_types[] = {
@ -71,6 +70,48 @@ get_type (expr_t *e)
return ev_void; return ev_void;
} }
expr_t *
error (expr_t *e, const char *fmt, ...)
{
va_list args;
string_t file = s_file;
int line = pr_source_line;
va_start (args, fmt);
if (e) {
file = e->file;
line = e->line;
}
fprintf (stderr, "%s:%d: ", strings + file, line);
vfprintf (stderr, fmt, args);
fputs ("\n", stderr);
if (e) {
e = new_expr ();
e->type = ex_int;
}
va_end (args);
pr_error_count++;
return e;
}
void
warning (expr_t *e, const char *fmt, ...)
{
va_list args;
string_t file = s_file;
int line = pr_source_line;
va_start (args, fmt);
if (e) {
file = e->file;
line = e->line;
}
fprintf (stderr, "%s:%d: warning:", strings + file, line);
vfprintf (stderr, fmt, args);
fputs ("\n", stderr);
va_end (args);
}
expr_t * expr_t *
new_expr (void) new_expr (void)
{ {
@ -261,8 +302,7 @@ do_op_string (int op, expr_t *e1, expr_t *e2)
e1->e.int_val = strcmp (s1, s2) != 0; e1->e.int_val = strcmp (s1, s2) != 0;
break; break;
default: default:
yyerror ("invalid operand for string"); return error (e1, "invalid operand for string");
return 0;
} }
return e1; return e1;
} }
@ -325,8 +365,7 @@ do_op_float (int op, expr_t *e1, expr_t *e2)
e1->e.int_val = f1 != f2; e1->e.int_val = f1 != f2;
break; break;
default: default:
yyerror ("invalid operand for string"); return error (e1, "invalid operand for string");
return 0;
} }
return e1; return e1;
} }
@ -363,8 +402,7 @@ do_op_vector (int op, expr_t *e1, expr_t *e2)
|| (v1[2] != v2[2]); || (v1[2] != v2[2]);
break; break;
default: default:
yyerror ("invalid operand for string"); return error (e1, "invalid operand for string");
return 0;
} }
return e1; return e1;
} }
@ -372,8 +410,7 @@ do_op_vector (int op, expr_t *e1, expr_t *e2)
static expr_t * static expr_t *
do_op_huh (int op, expr_t *e1, expr_t *e2) do_op_huh (int op, expr_t *e1, expr_t *e2)
{ {
yyerror ("funny constant"); return error (e1, "funny constant");
return 0;
} }
static expr_t *(*do_op[]) (int op, expr_t *e1, expr_t *e2) = { static expr_t *(*do_op[]) (int op, expr_t *e1, expr_t *e2) = {
@ -399,11 +436,9 @@ binary_const (int op, expr_t *e1, expr_t *e2)
if (t1 == t2) { if (t1 == t2) {
return do_op[t1](op, e1, e2); return do_op[t1](op, e1, e2);
} else { } else {
yyerror ("type missmatch for"); return error (e1, "type missmatch for %d (%c)",
fprintf (stderr, "%d (%c)\n", op, (op > ' ' && op < 127) ? op : ' '); op, (op > ' ' && op < 127) ? op : ' ');
return 0;
} }
return 0;
} }
static expr_t * static expr_t *
@ -416,8 +451,7 @@ field_expr (expr_t *e1, expr_t *e2)
t2 = get_type (e2); t2 = get_type (e2);
if (t1 != ev_entity || t2 != ev_field) { if (t1 != ev_entity || t2 != ev_field) {
yyerror ("type missmatch for ."); return error (e1, "type missmatch for .");
return 0;
} }
e = new_binary_expr ('.', e1, e2); e = new_binary_expr ('.', e1, e2);
@ -440,14 +474,13 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
if ((op == '&' || op == '|') if ((op == '&' || op == '|')
&& e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) { && e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) {
fprintf (stderr, "%s:%d: warning: ambiguous logic. Suggest explicit parentheses with expressions involving ! and %c\n", warning (e1, "ambiguous logic. Suggest explicit parentheses with expressions involving ! and %c", op);
strings + e1->file, e1->line, op);
} }
t1 = get_type (e1); t1 = get_type (e1);
t2 = get_type (e2); t2 = get_type (e2);
if (t1 == ev_void || t2 == ev_void) { if (t1 == ev_void || t2 == ev_void) {
yyerror ("internal error"); error (e1, "internal error");
abort (); abort ();
} }
@ -489,9 +522,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
} }
default: default:
type_mismatch: type_mismatch:
yyerror ("type missmatch"); return error (e1, "type missmatch %d %d", t1, t2);
fprintf (stderr, "%d %d\n", t1, t2);
return 0;
} }
} }
} }
@ -524,7 +555,7 @@ unary_expr (int op, expr_t *e)
e->e.float_val *= -1; e->e.float_val *= -1;
return e; return e;
case ex_string: case ex_string:
return 0; // FIXME return error (e, "invalid type for unary -");
case ex_vector: case ex_vector:
e->e.vector_val[0] *= -1; e->e.vector_val[0] *= -1;
e->e.vector_val[1] *= -1; e->e.vector_val[1] *= -1;
@ -580,7 +611,7 @@ unary_expr (int op, expr_t *e)
default: default:
abort (); abort ();
} }
yyerror ("internal error"); error (e, "internal error");
abort (); abort ();
} }
@ -595,9 +626,7 @@ function_expr (expr_t *e1, expr_t *e2)
t1 = get_type (e1); t1 = get_type (e1);
if (t1 != ev_func) { if (t1 != ev_func) {
yyerror ("called object is not a function"); return error (e1, "called object is not a function %d", t1);
fprintf (stderr, "%d\n", t1);
return 0;
} }
ftype = e1->type == ex_def ftype = e1->type == ex_def
@ -607,16 +636,13 @@ function_expr (expr_t *e1, expr_t *e2)
for (e = e2; e; e = e->next) for (e = e2; e; e = e->next)
parm_count++; parm_count++;
if (parm_count > 8) { if (parm_count > 8) {
yyerror ("more than 8 paramters"); return error (e1, "more than 8 paramters");
return 0;
} }
if (ftype->num_parms != -1) { if (ftype->num_parms != -1) {
if (parm_count > ftype->num_parms) { if (parm_count > ftype->num_parms) {
yyerror ("too many arguments"); return error (e1, "too many arguments");
return 0;
} else if (parm_count < ftype->num_parms) { } else if (parm_count < ftype->num_parms) {
yyerror ("too few arguments"); return error (e1, "too few arguments");
return 0;
} }
} }
e = new_binary_expr ('c', e1, e2); e = new_binary_expr ('c', e1, e2);
@ -739,8 +765,7 @@ emit_assign_expr (expr_t *e)
def_a->ofs = ofs; def_a->ofs = ofs;
def_a->initialized = 0; def_a->initialized = 0;
} else { } else {
fprintf (stderr, "%s:%d: assignment to constant %s\n", error (e1, "assignment to constant %s", def_a->name);
strings + e->file, e->line, def_a->name);
} }
} }
if (e2->type == ex_expr) { if (e2->type == ex_expr) {
@ -927,9 +952,8 @@ emit_expr (expr_t *e)
emit_statement (op_state, def_a, def_b, 0); emit_statement (op_state, def_a, def_b, 0);
break; break;
default: default:
fprintf (stderr, warning (e, "unused expression ignored");
"%s:%d: warning: unused expression ignored\n", break;
strings + e->file, e->line);
} }
break; break;
case ex_uexpr: case ex_uexpr:
@ -944,9 +968,7 @@ emit_expr (expr_t *e)
emit_branch (op_goto, 0, e->e.expr.e1); emit_branch (op_goto, 0, e->e.expr.e1);
break; break;
default: default:
fprintf (stderr, warning (e, "unused expression ignored");
"%s:%d: warning: unused expression ignored\n",
strings + e->file, e->line);
emit_expr (e->e.expr.e1); emit_expr (e->e.expr.e1);
break; break;
} }
@ -957,8 +979,7 @@ emit_expr (expr_t *e)
case ex_string: case ex_string:
case ex_vector: case ex_vector:
case ex_quaternion: case ex_quaternion:
fprintf (stderr, "%s:%d: warning: unused expression ignored\n", warning (e, "unused expression ignored");
strings + e->file, e->line);
break; break;
} }
PR_FreeTempDefs (); PR_FreeTempDefs ();

View file

@ -6,8 +6,6 @@
#define YY_NO_UNPUT #define YY_NO_UNPUT
void error (char*s){fprintf(stderr,"%s:%d: %s\n",strings+s_file,pr_source_line,s);}
int type_or_name (char *token); int type_or_name (char *token);
int do_grab (char *token); int do_grab (char *token);
@ -40,7 +38,7 @@ m ([\-+]?)
while (c == '*') while (c == '*')
c = input (); c = input ();
if (c == EOF) if (c == EOF)
error ("EOF in comment"); error (0, "EOF in comment");
if (c == '\n') if (c == '\n')
pr_source_line++; pr_source_line++;
} while (c != '/' && c != EOF); } while (c != '/' && c != EOF);
@ -129,7 +127,7 @@ m ([\-+]?)
<*>{s}* /* skip */ <*>{s}* /* skip */
<*>. error ("all your typo are belong to us"); <*>. error (0, "all your typo are belong to us");
%% %%

View file

@ -10,7 +10,7 @@ extern int pr_source_line;
void void
yyerror (const char *s) yyerror (const char *s)
{ {
fprintf (stderr, "%s:%d, %s %s\n", strings + s_file, pr_source_line, yytext, s); error (0, "%s %s\n", strings + s_file, pr_source_line, yytext, s);
} }
int yylex (void); int yylex (void);
@ -180,8 +180,7 @@ param_list
| param_list ',' param | param_list ',' param
{ {
if ($3->next) { if ($3->next) {
yyerror ("parameter redeclared"); error (0, "parameter redeclared: %s", $3->name);
yyerror ($3->name);
$$ = $1; $$ = $1;
} else { } else {
$3->next = $1; $3->next = $1;
@ -213,10 +212,10 @@ opt_initializer
| '=' '#' const | '=' '#' const
{ {
if (current_type->type != ev_func) { if (current_type->type != ev_func) {
yyerror ("note a function"); error (0, "%s is not a function");
} else { } else {
if ($3->type != ex_int && $3->type != ex_float) { if ($3->type != ex_int && $3->type != ex_float) {
yyerror ("invalid constant for = #"); error (0, "invalid constant for = #");
} else { } else {
function_t *f; function_t *f;
@ -480,7 +479,7 @@ parse_params (def_t *parms)
for (p = parms; p; p = p->next, new.num_parms++) for (p = parms; p; p = p->next, new.num_parms++)
; ;
if (new.num_parms > MAX_PARMS) { if (new.num_parms > MAX_PARMS) {
yyerror ("too many params"); error (0, "too many params");
return current_type; return current_type;
} }
i = 1; i = 1;