mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
/much/ better error handling
This commit is contained in:
parent
eef9e8e2dc
commit
6dfee9968b
4 changed files with 73 additions and 52 deletions
|
@ -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, ...);
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue