From b226d24b52f7d7fcd5ff1dee2f9019ac17df63b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 May 2002 05:15:19 +0000 Subject: [PATCH] rework the param parsing to make selectors easier to handle --- tools/qfcc/include/function.h | 51 ++++++++ tools/qfcc/include/qfcc.h | 6 - tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/source/expr.c | 1 + tools/qfcc/source/function.c | 204 ++++++++++++++++++++++++++++++++ tools/qfcc/source/pr_lex.c | 3 +- tools/qfcc/source/qc-lex.l | 2 +- tools/qfcc/source/qc-parse.y | 217 ++++++---------------------------- tools/qfcc/source/type.c | 1 + 9 files changed, 293 insertions(+), 194 deletions(-) create mode 100644 tools/qfcc/include/function.h create mode 100644 tools/qfcc/source/function.c diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h new file mode 100644 index 000000000..9d73b789a --- /dev/null +++ b/tools/qfcc/include/function.h @@ -0,0 +1,51 @@ +/* + #FILENAME# + + #DESCRIPTION# + + Copyright (C) 2001 #AUTHOR# + + Author: #AUTHOR# + Date: #DATE# + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __function_h +#define __function_h + +typedef struct param_s { + struct param_s *next; + const char *selector; + type_t *type; + const char *name; +} param_t; + +param_t *new_param (const char *selector, type_t *type, const char *name); + +type_t *parse_params (type_t *type, param_t *params); +void build_scope (function_t *f, def_t *func, param_t *params); +function_t *new_function (void); +void build_function (function_t *f); +void finish_function (function_t *f); +void emit_function (function_t *f, expr_t *e); + +#endif//__function_h diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 37fd1dd07..1c88a5c42 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -331,11 +331,6 @@ typedef struct def_s { struct def_s *parent; // vector/quaternion member } def_t; -typedef struct param_s { - def_t *params; - int elipsis; -} param_t; - //============================================================================ // pr_loc.h -- program local defs @@ -502,7 +497,6 @@ void PR_PrintDefs (void); void PR_PrintFunction (def_t *def); void PR_SkipToSemicolon (void); -extern char pr_parm_names[MAX_PARMS][MAX_NAME]; extern qboolean pr_trace; #define G_FLOAT(o) (pr_globals[o]) diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 35ba907d7..0e49206cc 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -37,7 +37,7 @@ YFLAGS = -d bin_PROGRAMS= qfcc -qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c struct.c switch.c type.c +qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c function.c struct.c switch.c type.c qfcc_LDADD= $(QFCC_LIBS) qfcc_DEPENDENCIES= $(QFCC_DEPS) EXTRA_DIST= qc-parse.h diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 69a00a8eb..7e9592c0f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -37,6 +37,7 @@ static const char rcsid[] = #include #include "qfcc.h" +#include "function.h" #include "struct.h" #include "type.h" #include "qc-parse.h" diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c new file mode 100644 index 000000000..2b0471531 --- /dev/null +++ b/tools/qfcc/source/function.c @@ -0,0 +1,204 @@ +/* + function.c + + QC function support code + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2002/5/7 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#include "qfcc.h" + +#include "function.h" +#include "type.h" + +param_t * +new_param (const char *selector, type_t *type, const char *name) +{ + param_t *param = malloc (sizeof (param_t)); + + param->next = 0; + param->selector = selector; + param->type = type; + param->name = name; + + return param; +} + +type_t * +parse_params (type_t *type, param_t *parms) +{ + int ellipsis = 0, i; + param_t *p; + type_t new; + + memset (&new, 0, sizeof (new)); + new.type = ev_func; + new.aux_type = type; + new.num_parms = 0; + + if (parms && !parms->selector && !parms->type && !parms->name) { + ellipsis = 1; + parms = parms->next; + } + + if (ellipsis) { + new.num_parms = -1; // variable args + } else if (!parms) { + } else { + for (p = parms; p; p = p->next, new.num_parms++) + ; + if (new.num_parms > MAX_PARMS) { + error (0, "too many params"); + return type; + } + i = 1; + do { + //puts (parms->name); + new.parm_types[new.num_parms - i] = parms->type; + i++; + parms = parms->next; + } while (parms); + } + //print_type (&new); puts(""); + return PR_FindType (&new); +} + +void +build_scope (function_t *f, def_t *func, param_t *params) +{ + int i, count; + def_t *def; + param_t **param_list, *p; + + for (p = params, count = 0; p; p = p->next, count++) + ; + param_list = alloca (sizeof (param_t *) * i); + i = count; + for (p = params; p; p = p->next) + param_list[--i] = p; + + func->alloc = &func->locals; + + for (i = 0; i < count; i++) { + if (!param_list[i]->selector + && !param_list[i]->type + && !param_list[i]->name) + continue; // ellipsis marker + def = PR_GetDef (param_list[i]->type, param_list[i]->name, + func, func->alloc); + f->parm_ofs[i] = def->ofs; + if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i - 1]) + Error ("bad parm order"); + def->used = 1; // don't warn for unused params + PR_DefInitialized (def); // params are assumed to be initialized + } +} + +function_t * +new_function (void) +{ + function_t *f; + + f = calloc (1, sizeof (function_t)); + f->next = pr_functions; + pr_functions = f; + + return f; +} + +void +build_function (function_t *f) +{ + f->def->constant = 1; + f->def->initialized = 1; + G_FUNCTION (f->def->ofs) = numfunctions; +} + +void +finish_function (function_t *f) +{ + dfunction_t *df; + int i; + + // fill in the dfunction + df = &functions[numfunctions]; + numfunctions++; + f->dfunc = df; + + if (f->builtin) + df->first_statement = -f->builtin; + else + df->first_statement = f->code; + + df->s_name = ReuseString (f->def->name); + df->s_file = s_file; + df->numparms = f->def->type->num_parms; + df->locals = f->def->locals; + df->parm_start = 0; + for (i = 0; i < df->numparms; i++) + df->parm_size[i] = pr_type_size[f->def->type->parm_types[i]->type]; + + if (f->aux) { + def_t *def; + f->aux->function = df - functions; + for (def = f->def->scope_next; def; def = def->scope_next) { + if (def->name) { + ddef_t *d = new_local (); + d->type = def->type->type; + d->ofs = def->ofs; + d->s_name = ReuseString (def->name); + + f->aux->num_locals++; + } + } + } +} + +void +emit_function (function_t *f, expr_t *e) +{ + //printf (" %s =\n", f->def->name); + + if (f->aux) + lineno_base = f->aux->source_line; + + pr_scope = f->def; + while (e) { + //printf ("%d ", pr_source_line); + //print_expr (e); + //puts(""); + + emit_expr (e); + e = e->next; + } + emit_statement (pr_source_line, op_done, 0, 0, 0); + PR_FlushScope (pr_scope, 0); + pr_scope = 0; + PR_ResetTempDefs (); + + //puts (""); +} diff --git a/tools/qfcc/source/pr_lex.c b/tools/qfcc/source/pr_lex.c index 5d60f9aa9..63979811c 100644 --- a/tools/qfcc/source/pr_lex.c +++ b/tools/qfcc/source/pr_lex.c @@ -34,11 +34,10 @@ static const char rcsid[] = #include #include "qfcc.h" +#include "function.h" int pr_source_line; -char pr_parm_names[MAX_PARMS][MAX_NAME]; - char *pr_file_p; char *pr_line_start; // start of current source line diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 466e50cbc..137cba164 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -172,7 +172,7 @@ m ([\-+]?) return yytext[0]; } -"..." return ELIPSIS; +"..." return ELLIPSIS; "<<" return SHL; ">>" return SHR; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 4aa74f49c..ee0d8cbde 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -35,6 +35,7 @@ static const char rcsid[] = #include #include +#include "function.h" #include "struct.h" #include "switch.h" #include "type.h" @@ -54,12 +55,6 @@ yyerror (const char *s) int yylex (void); type_t *PR_FindType (type_t *new); -type_t *parse_params (type_t *type, def_t *parms, int elipsis); -function_t *new_function (void); -void build_function (function_t *f); -void finish_function (function_t *f); -void emit_function (function_t *f, expr_t *e); -void build_scope (function_t *f, def_t *func); type_t *build_type (int is_field, type_t *type); type_t *build_array_type (type_t *type, int size); @@ -89,7 +84,7 @@ typedef struct { float quaternion_val[4]; function_t *function; struct switch_block_s *switch_block; - param_t params; + struct param_s *param; } %right '=' ASX PAS /* pointer assign */ @@ -108,7 +103,7 @@ typedef struct { %token VECTOR_VAL %token QUATERNION_VAL -%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL +%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS NIL %token IFBE IFB IFAE IFA %token SWITCH CASE DEFAULT STRUCT ENUM TYPEDEF %token ELE_START @@ -118,9 +113,10 @@ typedef struct { %token PROTOCOL PUBLIC SELECTOR %type type type_name -%type function_decl +%type function_decl %type array_decl -%type param param_list def_name +%type param param_list +%type def_name %type def_item def_list %type const opt_expr expr arg_list element_list element_list1 element %type string_val opt_state_expr @@ -131,6 +127,8 @@ typedef struct { %type switch_block %type param_scope +%type selector + %expect 1 %{ @@ -138,6 +136,7 @@ typedef struct { type_t *current_type; def_t *current_def; function_t *current_func; +param_t *current_params; expr_t *local_expr; expr_t *break_label; expr_t *continue_label; @@ -218,7 +217,8 @@ type | type array_decl { $$ = build_type (0, build_array_type ($1, $2)); } | type_name function_decl { - $$ = build_type (0, parse_params ($1, $2.params, $2.elipsis)); + current_params = $2; + $$ = build_type (0, parse_params ($1, $2)); } | type_name { $$ = build_type (0, $1); } | '(' type ')' { $$ = $2; } @@ -236,26 +236,23 @@ function_decl } ')' { - $$.params = $3; - $$.elipsis = 0; + $$ = $3; } - | '(' param_scope param_list ',' ELIPSIS ')' + | '(' param_scope param_list ',' ELLIPSIS ')' { PR_FlushScope (pr_scope, 1); pr_scope = $2; - $$.params = $3; - $$.elipsis = 1; + $$ = new_param (0, 0, 0); + $$->next = $3; } - | '(' ELIPSIS ')' + | '(' ELLIPSIS ')' { - $$.params = 0; - $$.elipsis = 1; + $$ = new_param (0, 0, 0); } | '(' ')' { - $$.params = 0; - $$.elipsis = 0; + $$ = 0; } ; @@ -273,22 +270,13 @@ param_list : param | param_list ',' param { - if ($3->next) { - error (0, "parameter redeclared: %s", $3->name); - $$ = $1; - } else { - $3->next = $1; - $$ = $3; - } + $3->next = $1; + $$ = $3; } ; param - : type {current_type = $1;} def_name - { - $3->type = $1; - $$ = $3; - } + : type NAME { $$ = new_param (0, $1, $2); } ; array_decl @@ -493,7 +481,7 @@ begin_function lineno->fa.func = $$->aux - auxfunctions; } pr_scope = current_def; - build_scope ($$, current_def); + build_scope ($$, current_def, current_params); } ; @@ -980,11 +968,11 @@ methoddecl optparmlist : /* empty */ - | ',' ELIPSIS + | ',' ELLIPSIS ; unaryselector - : selector + : selector { /* XXX */ } ; keywordselector @@ -993,18 +981,18 @@ keywordselector ; selector - : NAME { /* XXX */ } + : NAME ; keyworddecl - : selector ':' '(' type ')' NAME - | selector ':' NAME - | ':' '(' type ')' NAME - | ':' NAME + : selector ':' '(' type ')' NAME { /* XXX */ } + | selector ':' NAME { /* XXX */ } + | ':' '(' type ')' NAME { /* XXX */ } + | ':' NAME { /* XXX */ } ; messageargs - : selector + : selector { /* XXX */ } | keywordarglist ; @@ -1018,7 +1006,7 @@ keywordexpr ; keywordarg - : selector ':' keywordexpr + : selector ':' keywordexpr { /* XXX */ } | ':' keywordexpr ; @@ -1039,7 +1027,7 @@ obj_messageexpr ; selectorarg - : selector + : selector { /* XXX */ } | keywordnamelist ; @@ -1049,7 +1037,7 @@ keywordnamelist ; keywordname - : selector ':' + : selector ':' { /* XXX */ } | ':' ; @@ -1060,60 +1048,6 @@ obj_string %% -type_t * -parse_params (type_t *type, def_t *parms, int elipsis) -{ - type_t new; - def_t *p; - int i; - - memset (&new, 0, sizeof (new)); - new.type = ev_func; - new.aux_type = type; - new.num_parms = 0; - - if (elipsis) { - new.num_parms = -1; // variable args - } else if (!parms) { - } else { - for (p = parms; p; p = p->next, new.num_parms++) - ; - if (new.num_parms > MAX_PARMS) { - error (0, "too many params"); - return current_type; - } - i = 1; - do { - //puts (parms->name); - strcpy (pr_parm_names[new.num_parms - i], parms->name); - new.parm_types[new.num_parms - i] = parms->type; - i++; - parms = parms->next; - } while (parms); - } - //print_type (&new); puts(""); - return PR_FindType (&new); -} - -void -build_scope (function_t *f, def_t *func) -{ - int i; - def_t *def; - type_t *ftype = func->type; - - func->alloc = &func->locals; - - for (i = 0; i < ftype->num_parms; i++) { - def = PR_GetDef (ftype->parm_types[i], pr_parm_names[i], func, func->alloc); - f->parm_ofs[i] = def->ofs; - if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i - 1]) - Error ("bad parm order"); - def->used = 1; // don't warn for unused params - PR_DefInitialized (def); // params are assumed to be initialized - } -} - type_t * build_type (int is_field, type_t *type) { @@ -1140,91 +1074,6 @@ build_array_type (type_t *type, int size) return PR_FindType (&new); } -function_t * -new_function (void) -{ - function_t *f; - - f = calloc (1, sizeof (function_t)); - f->next = pr_functions; - pr_functions = f; - - return f; -} - -void -build_function (function_t *f) -{ - f->def->constant = 1; - f->def->initialized = 1; - G_FUNCTION (f->def->ofs) = numfunctions; -} - -void -finish_function (function_t *f) -{ - dfunction_t *df; - int i; - - // fill in the dfunction - df = &functions[numfunctions]; - numfunctions++; - f->dfunc = df; - - if (f->builtin) - df->first_statement = -f->builtin; - else - df->first_statement = f->code; - - df->s_name = ReuseString (f->def->name); - df->s_file = s_file; - df->numparms = f->def->type->num_parms; - df->locals = f->def->locals; - df->parm_start = 0; - for (i = 0; i < df->numparms; i++) - df->parm_size[i] = pr_type_size[f->def->type->parm_types[i]->type]; - - if (f->aux) { - def_t *def; - f->aux->function = df - functions; - for (def = f->def->scope_next; def; def = def->scope_next) { - if (def->name) { - ddef_t *d = new_local (); - d->type = def->type->type; - d->ofs = def->ofs; - d->s_name = ReuseString (def->name); - - f->aux->num_locals++; - } - } - } -} - -void -emit_function (function_t *f, expr_t *e) -{ - //printf (" %s =\n", f->def->name); - - if (f->aux) - lineno_base = f->aux->source_line; - - pr_scope = f->def; - while (e) { - //printf ("%d ", pr_source_line); - //print_expr (e); - //puts(""); - - emit_expr (e); - e = e->next; - } - emit_statement (pr_source_line, op_done, 0, 0, 0); - PR_FlushScope (pr_scope, 0); - pr_scope = 0; - PR_ResetTempDefs (); - - //puts (""); -} - typedef struct { def_t *def; int state; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index ee66e045e..ae51a83ad 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -35,6 +35,7 @@ static const char rcsid[] = #include "QF/hash.h" #include "qfcc.h" +#include "function.h" typedef struct { const char *name;