diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 7b7aa1515..0ee07f943 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -36,12 +36,12 @@ typedef struct function_s { struct function_s *next; - dfunction_t *dfunc; pr_auxfunction_t *aux; // debug info; int builtin; // if non 0, call an internal function int code; // first statement int function_num; - const char *file; // source file with definition + string_t s_file; // source file with definition + string_t s_name; int file_line; struct def_s *def; struct scope_s *scope; @@ -67,10 +67,11 @@ param_t *_reverse_params (param_t *params, param_t *next); param_t *reverse_params (param_t *params); struct type_s *parse_params (struct type_s *type, param_t *params); void build_scope (function_t *f, struct def_s *func, param_t *params); -function_t *new_function (void); +function_t *new_function (const char *name); function_t *build_builtin_function (struct def_s *def, struct expr_s *bi_val); void build_function (function_t *f); void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); +int function_parms (function_t *f, byte *parm_size); #endif//__function_h diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index bb0e4175f..73b000cef 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -92,6 +92,8 @@ extern string_t s_file; // filename for function definition const char *strip_path (const char *filename); +const char *save_string (const char *str); + #define ALLOC(s, t, n, v) \ do { \ if (!free_##n) { \ diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 76efd753c..b25ba6411 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -475,7 +475,7 @@ class_finish_module (void) exec_class_def = get_def (&type_obj_exec_class, "__obj_exec_class", pr.scope, 1); - exec_class_func = new_function (); + exec_class_func = new_function ("__obj_exec_class"); exec_class_func->builtin = 0; exec_class_func->def = exec_class_def; exec_class_func->refs = new_reloc (exec_class_def->ofs, rel_def_func); @@ -483,7 +483,7 @@ class_finish_module (void) finish_function (exec_class_func); init_def = get_def (&type_function, ".ctor", pr.scope, 1); - init_func = new_function (); + init_func = new_function (".ctor"); init_func->def = init_def; init_func->refs = new_reloc (init_def->ofs, rel_def_func); init_func->code = pr.num_statements; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 46569674e..f81ded148 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -134,9 +134,10 @@ static void vector_component (def_t *vec, int comp, scope_t *scope) { def_t *d; + const char *name; - d = new_def (&type_float, va (vector_component_names[comp], vec->name), - scope); + name = save_string (va (vector_component_names[comp], vec->name)); + d = new_def (&type_float, name, scope); d->used = 1; d->parent = vec; d->ofs = vec->ofs + comp; @@ -147,9 +148,10 @@ static void vector_field_component (def_t *vec, int comp, scope_t *scope) { def_t *d; + const char *name; - d = new_def (&type_floatfield, va (vector_component_names[comp], vec->name), - scope); + name = save_string (va (vector_component_names[comp], vec->name)); + d = new_def (&type_floatfield, name, scope); d->used = 1; // always `used' d->parent = vec; d->ofs = vec->ofs + comp; @@ -217,7 +219,7 @@ new_def (type_t *type, const char *name, scope_t *scope) def->return_addr = __builtin_return_address (0); - def->name = name ? strdup (name) : 0; + def->name = name; def->type = type; def->scope = scope; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 064db525d..b51560e92 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -669,21 +669,20 @@ print_expr (expr_t *e) static expr_t * do_op_string (int op, expr_t *e1, expr_t *e2) { - int len; - char *buf; const char *s1, *s2; + static dstring_t *temp_str; s1 = e1->e.string_val ? e1->e.string_val : ""; s2 = e2->e.string_val ? e2->e.string_val : ""; switch (op) { case '+': - len = strlen (s1) + strlen (s2) + 1; - buf = malloc (len); - SYS_CHECKMEM (buf); - strcpy (buf, s1); - strcat (buf, s2); - e1->e.string_val = buf; + if (!temp_str) + temp_str = dstring_newstr (); + dstring_clearstr (temp_str); + dstring_appendstr (temp_str, s1); + dstring_appendstr (temp_str, s2); + e1->e.string_val = save_string (temp_str->str); break; case LT: e1->type = ex_integer; diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index d44701c0f..11a3b4dd6 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -54,11 +54,15 @@ static const char rcsid[] = #include "reloc.h" #include "type.h" +static param_t *free_params; +static function_t *free_functions; + param_t * new_param (const char *selector, type_t *type, const char *name) { - param_t *param = malloc (sizeof (param_t)); + param_t *param; + ALLOC (4096, param_t, params, param); param->next = 0; param->selector = selector; param->type = type; @@ -165,14 +169,17 @@ build_scope (function_t *f, def_t *func, param_t *params) } function_t * -new_function (void) +new_function (const char *name) { function_t *f; - f = calloc (1, sizeof (function_t)); + ALLOC (1024, function_t, functions, f); + *pr.func_tail = f; pr.func_tail = &f->next; f->function_num = pr.num_functions++; + f->s_name = ReuseString (name); + f->s_file = s_file; return f; } @@ -191,7 +198,7 @@ build_builtin_function (def_t *def, expr_t *bi_val) return 0; } - f = new_function (); + f = new_function (def->name); f->builtin = bi_val->type == ex_integer ? bi_val->e.integer_val : (int)bi_val->e.float_val; @@ -213,28 +220,6 @@ build_function (function_t *f) void finish_function (function_t *f) { - dfunction_t *df; - int i, count; - - df = calloc (1, sizeof (dfunction_t)); - 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; - if (f->scope) - df->locals = f->scope->space->size; - df->parm_start = 0; - if ((count = df->numparms) < 0) - count = -count - 1; - for (i = 0; i < count; i++) - df->parm_size[i] = type_size (f->def->type->parm_types[i]); - if (f->aux) { def_t *def; f->aux->function = f->function_num; @@ -275,3 +260,18 @@ emit_function (function_t *f, expr_t *e) //puts (""); } + +int +function_parms (function_t *f, byte *parm_size) +{ + int count, i; + + if (f->def->type->num_parms >= 0) + count = f->def->type->num_parms; + else + count = -f->def->type->num_parms - 1; + + for (i = 0; i < count; i++) + parm_size[i] = type_size (f->def->type->parm_types[i]); + return f->def->type->num_parms; +} diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index bc1f16a31..de848cec2 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -166,8 +166,8 @@ setup_data (void) for (d = pr.scope->head; d; d = d->def_next) write_def (d, def++, &reloc); for (f = pr.func_head; f; f = f->next) { - func->name = LittleLong (f->dfunc->s_name); - func->file = LittleLong (f->dfunc->s_file); + func->name = LittleLong (f->s_name); + func->file = LittleLong (f->s_file); func->line = LittleLong (f->def->line); func->builtin = LittleLong (f->builtin); func->code = LittleLong (f->code); @@ -182,8 +182,7 @@ setup_data (void) func->num_local_defs = LittleLong (f->scope->num_defs); if (f->aux) func->line_info = LittleLong (f->aux->line_info); - func->num_parms = LittleLong (f->dfunc->numparms); - memcpy (func->parm_size, f->dfunc->parm_size, MAX_PARMS); + func->num_parms = LittleLong (function_parms (f, func->parm_size)); func->relocs = LittleLong (reloc - relocs); write_relocs (f->refs, &reloc); diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 649c0f5aa..c02f6178a 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -43,8 +43,10 @@ static const char rcsid[] = #include #include +#include #include #include + #include "qfcc.h" #include "expr.h" #include "class.h" @@ -62,7 +64,7 @@ int do_grab (char *token); void add_frame_macro (char *token); -char *make_string (char *token); +const char *make_string (char *token); extern YYSTYPE yylval; extern int element_flag; @@ -136,18 +138,18 @@ m ([\-+]?) } '(\\[^xX0-7\r\n]|[^'\r\n]|\\[xX][0-9A-Fa-f]+|\\[0-7]+)*' { - char *str = make_string (yytext); + const char *str = make_string (yytext); if (str[1]) warning (0, "multibyte char constant"); yylval.integer_val = *str; - free (str); return INT_VAL; } ^#{s}+{DIGIT}+{s}+\"(\.|[^"\n])*\".*$ { char *p; char *s; + const char *str; int line; p = yytext + 1; @@ -157,12 +159,11 @@ m ([\-+]?) p++; if (!*p) error (0, "Unexpected end of file"); - s = make_string (p); // grab the filename + str = make_string (p); // grab the filename while (*p && *p != '\n') // ignore flags p++; pr_source_line = line - 1; - s_file = ReuseString (strip_path (s)); - free (s); + s_file = ReuseString (strip_path (str)); } [+\-*/&|^%]= { @@ -335,7 +336,7 @@ type_or_name (char *token) yylval.type = type; return TYPE; } - yylval.string_val = strdup (token); + yylval.string_val = save_string (token); return NAME; } @@ -369,7 +370,6 @@ static void frame_free (void *_f, void *unused) { frame_t *f = (frame_t *)_f; - free ((char*)f->name); f->next = free_frames; free_frames = f; } @@ -412,7 +412,7 @@ add_frame_macro (char *token) frame_t *frame; ALLOC (1024, frame_t, frames, frame); - frame->name = strdup (token); + frame->name = save_string (token); frame->num = frame_number++; Hash_Add (frame_tab, frame); } @@ -425,18 +425,22 @@ clear_frame_macros (void) Hash_FlushTable (frame_tab); } -char * +const char * make_string (char *token) { - char *str, *s; + char s[2]; int c; int i; int mask; int boldnext; int quote; + static dstring_t *str; - s = str = malloc (strlen (token) + 1); - SYS_CHECKMEM (str); + if (!str) + str = dstring_newstr (); + dstring_clearstr (str); + + s[1] = 0; mask = 0x00; boldnext = 0; @@ -574,17 +578,17 @@ make_string (char *token) break; } } else if (c == quote) { - *s++ = 0; break;; } if (boldnext) c = c ^ 0x80; boldnext = 0; c = c ^ mask; - *s++ = c; + s[0] = c; + dstring_appendstr (str, s); } while (1); - return str; + return save_string (str->str); } static void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index b54d80bbc..532841726 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -96,7 +96,7 @@ void free_local_inits (hashtab_t *def_list); expr_t *expr; int integer_val; float float_val; - char *string_val; + const char *string_val; float vector_val[3]; float quaternion_val[4]; struct function_s *function; @@ -479,7 +479,7 @@ opt_comma begin_function : /*empty*/ { - $$ = current_func = new_function (); + $$ = current_func = new_function (current_def->name); $$->def = current_def; $$->refs = new_reloc ($$->def->ofs, rel_def_func); $$->code = pr.num_statements; @@ -1204,29 +1204,29 @@ keywordselector selector : NAME - | TYPE { $$ = strdup (yytext); } + | TYPE { $$ = save_string (yytext); } | reserved_word ; reserved_word - : LOCAL { $$ = strdup (yytext); } - | RETURN { $$ = strdup (yytext); } - | WHILE { $$ = strdup (yytext); } - | DO { $$ = strdup (yytext); } - | IF { $$ = strdup (yytext); } - | ELSE { $$ = strdup (yytext); } - | FOR { $$ = strdup (yytext); } - | BREAK { $$ = strdup (yytext); } - | CONTINUE { $$ = strdup (yytext); } - | SWITCH { $$ = strdup (yytext); } - | CASE { $$ = strdup (yytext); } - | DEFAULT { $$ = strdup (yytext); } - | NIL { $$ = strdup (yytext); } - | STRUCT { $$ = strdup (yytext); } - | UNION { $$ = strdup (yytext); } - | ENUM { $$ = strdup (yytext); } - | TYPEDEF { $$ = strdup (yytext); } - | SUPER { $$ = strdup (yytext); } + : LOCAL { $$ = save_string (yytext); } + | RETURN { $$ = save_string (yytext); } + | WHILE { $$ = save_string (yytext); } + | DO { $$ = save_string (yytext); } + | IF { $$ = save_string (yytext); } + | ELSE { $$ = save_string (yytext); } + | FOR { $$ = save_string (yytext); } + | BREAK { $$ = save_string (yytext); } + | CONTINUE { $$ = save_string (yytext); } + | SWITCH { $$ = save_string (yytext); } + | CASE { $$ = save_string (yytext); } + | DEFAULT { $$ = save_string (yytext); } + | NIL { $$ = save_string (yytext); } + | STRUCT { $$ = save_string (yytext); } + | UNION { $$ = save_string (yytext); } + | ENUM { $$ = save_string (yytext); } + | TYPEDEF { $$ = save_string (yytext); } + | SUPER { $$ = save_string (yytext); } ; keyworddecl diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 31a3a25ec..c737a9135 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -98,6 +98,27 @@ const char *big_function = 0; ddef_t *fields; int numfielddefs; +hashtab_t *saved_strings; + +static const char * +ss_get_key (void *s, void *unused) +{ + return (const char *)s; +} + +const char * +save_string (const char *str) +{ + char *s; + if (!saved_strings) + saved_strings = Hash_NewTable (16381, ss_get_key, 0, 0); + s = Hash_Find (saved_strings, str); + if (s) + return s; + s = strdup (str); + Hash_Add (saved_strings, s); + return s; +} void InitData (void) @@ -134,8 +155,8 @@ WriteData (int crc) FILE *h; int i; - globals = calloc (pr.scope->num_defs, sizeof (ddef_t)); - fields = calloc (pr.scope->num_defs, sizeof (ddef_t)); + globals = calloc (pr.scope->num_defs + 1, sizeof (ddef_t)); + fields = calloc (pr.scope->num_defs + 1, sizeof (ddef_t)); for (def = pr.scope->head; def; def = def->def_next) { if (!def->global || !def->name) @@ -192,20 +213,17 @@ WriteData (int crc) SafeWrite (h, pr.statements, pr.num_statements * sizeof (dstatement_t)); { - function_t *f; + dfunction_t *df; progs.ofs_functions = ftell (h); progs.numfunctions = pr.num_functions; - pr.functions = malloc (pr.num_functions * sizeof (dfunction_t)); - for (i = 1, f = pr.func_head; f; i++, f = f->next) { - pr.functions[i].first_statement = - LittleLong (f->dfunc->first_statement); - pr.functions[i].parm_start = LittleLong (f->dfunc->parm_start); - pr.functions[i].s_name = LittleLong (f->dfunc->s_name); - pr.functions[i].s_file = LittleLong (f->dfunc->s_file); - pr.functions[i].numparms = LittleLong (f->dfunc->numparms); - pr.functions[i].locals = LittleLong (f->dfunc->locals); - memcpy (pr.functions[i].parm_size, f->dfunc->parm_size, MAX_PARMS); + for (i = 0, df = pr.functions + 1; i < pr.num_functions; i++, df++) { + df->first_statement = LittleLong (df->first_statement); + df->parm_start = LittleLong (df->parm_start); + df->s_name = LittleLong (df->s_name); + df->s_file = LittleLong (df->s_file); + df->numparms = LittleLong (df->numparms); + df->locals = LittleLong (df->locals); } SafeWrite (h, pr.functions, pr.num_functions * sizeof (dfunction_t)); } @@ -320,6 +338,7 @@ finish_compilation (void) def_t *def; expr_t e; ex_label_t *l; + dfunction_t *df; class_finish_module (); // check to make sure all functions prototyped have code @@ -351,14 +370,25 @@ finish_compilation (void) relocate_refs (def->refs, def->ofs); } - for (f = pr.func_head; f; f = f->next) { - if (f->builtin || !f->code) + pr.functions = calloc (pr.num_functions + 1, sizeof (dfunction_t)); + for (df = pr.functions + 1, f = pr.func_head; f; df++, f = f->next) { + df->s_name = f->s_name; + df->s_file = f->s_file; + df->numparms = function_parms (f, df->parm_size); + if (f->scope) + df->locals = f->scope->space->size; + if (f->builtin) { + df->first_statement = -f->builtin; continue; + } + if (!f->code) + continue; + df->first_statement = f->code; if (f->scope->space->size > num_localdefs) { num_localdefs = f->scope->space->size; big_function = f->def->name; } - f->dfunc->parm_start = pr.near_data->size; + df->parm_start = pr.near_data->size; for (def = f->scope->head; def; def = def->def_next) { if (def->absolute) continue; diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 477361966..069f32cf8 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -116,7 +116,7 @@ new_reloc (int ofs, reloc_type type) { reloc_t *ref; - ALLOC (1024, reloc_t, refs, ref); + ALLOC (16384, reloc_t, refs, ref); ref->ofs = ofs; ref->type = type; return ref; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 44d19940a..e6657f053 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -146,7 +146,7 @@ new_struct (const char *name) strct->type->class = (struct class_s *)strct; strct->is_union = 0; if (name) { - strct->type->name = strdup (name); + strct->type->name = save_string (name); Hash_Add (structs, strct); } return strct->type;