# New Ticket Created by Jürgen Bömmels # Please include the string: [perl #24224] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=24224 >
Hi, Back in Feburary, when I hacked up macro support for IMCC I implemented the macro_table as a static preallocated array of fixed size and used a linear search for lookup. Now I have took the time and transformed it to use a HASH. The macros are now stored in a global HASH named macro_hash. They are indexed by their name. So the lookup of a macro is a simple hash_get. Furthermore i moved the inplace definition of the ".constant" rule to a support function, the definition got quite fat. There are still some things to do: - a global hash is still not totally right. It should be moved to the interpreter structure - The size of the expansion is still limited in some way by a fixed buffer of size 4096. This needs to go away. Comments bö -- attachment 1 ------------------------------------------------------ url: http://rt.perl.org/rt2/attach/66091/49389/4aa72c/macro_hash.diff
Index: languages/imcc/imcc.l =================================================================== RCS file: /cvs/public/parrot/languages/imcc/imcc.l,v retrieving revision 1.67 diff -u -r1.67 imcc.l --- languages/imcc/imcc.l 14 Oct 2003 07:40:02 -0000 1.67 +++ languages/imcc/imcc.l 15 Oct 2003 16:59:31 -0000 @@ -15,6 +15,7 @@ #include <string.h> #include "imc.h" #include "parser.h" +#include "parrot/hash.h" #define MAX_PARAM 16 @@ -30,9 +31,9 @@ int line; }; -/* XXX: boe: rework this hack to use a hash */ -struct macro_t macros[256]; -int num_macros = 0; +/* XXX boe: This should not be global */ +HASH *macro_hash = 0; +char *current_macro = 0; char temp_buffer[4096]; @@ -58,6 +59,7 @@ static int yylex_skip (YYSTYPE *valp, void *interp, const char *skip); static int read_macro (YYSTYPE *valp, void *interp); +static int read_constant (YYSTYPE *valp, void *interp); static int expand_macro (YYSTYPE *valp, void *interp, const char *name); static void include_file (char *file_name); static int in_pod; @@ -242,31 +244,7 @@ } <emit>".constant" { - int c; - char *name; - struct macro_t *m; - - BEGIN(macro); - c = yylex_skip(valp, interp, " "); - if (c != IDENTIFIER) - fataly(EX_SOFTWARE, sourcefile, line, - "Constant names must be identifiers"); - - name = str_dup(valp->s); - - c = yylex_skip(valp, interp, " "); - if (c != INTC && c != FLOATC && c != STRINGC && c != REG) - fataly(EX_SOFTWARE, sourcefile, line, - "Constant '%s' value must be a number, " - "stringliteral or register", name); - - m = macros + num_macros++; - m->name = name; - m->expansion = str_dup (valp->s); - m->params.num_param = 0; - - BEGIN (emit); - return MACRO; + return read_constant(valp, interp); } <*>".include" { @@ -389,7 +367,6 @@ <macro>"$"{ID}":" return LABEL; <macro>".local"{WS}+ { char *label; - char *name = macros[num_macros].name; if (yylex(valp, interp) != LABEL) fataly(EX_SOFTWARE, sourcefile, line, "LABEL expected"); @@ -397,8 +374,8 @@ if (valp) { YYCHOP(); - label = mem_sys_allocate(strlen(name) + yyleng + 15); - sprintf(label, "local__%s__%s__$:", name, yytext+1); + label = mem_sys_allocate(strlen(current_macro) + yyleng + 15); + sprintf(label, "local__%s__%s__$:", current_macro, yytext+1); valp->s = label; } @@ -408,11 +385,10 @@ <macro>".$"{ID} { char *label; - char *name = macros[num_macros].name; if (valp) { - label = mem_sys_allocate(strlen(name) + yyleng + 15); - sprintf(label, "local__%s__%s__$", name, yytext+2); + label = mem_sys_allocate(strlen(current_macro) + yyleng + 15); + sprintf(label, "local__%s__%s__$", current_macro, yytext+2); valp->s = label; } @@ -570,8 +546,13 @@ read_macro (YYSTYPE *valp, void *interp) { int c; - struct macro_t *m = macros + num_macros; + struct macro_t *m = mem_sys_allocate(sizeof(struct macro_t)); + HASH_ENTRY value; + STRING *key; int start_cond; + char *last_macro = current_macro; + + if (!macro_hash) new_hash(interp, ¯o_hash); temp_buffer[0]='\0'; @@ -586,6 +567,8 @@ m->name = valp->s; m->line = line; + current_macro = valp->s; + /* white space is allowed between macro and opening paren) */ c = yylex_skip(valp, interp, " "); @@ -609,11 +592,56 @@ } free(valp->s); + current_macro = last_macro; + BEGIN(start_cond); - macros[num_macros].expansion = str_dup(temp_buffer); + m->expansion = str_dup(temp_buffer); + + key = string_from_cstring(interp, m->name, 0); + value.type = enum_type_PMC; + value.val.pmc_val = (PMC*)m; + hash_put(interp, macro_hash, key, &value); + + return MACRO; +} + +static int +read_constant (YYSTYPE *valp, void *interp) +{ + int c; + char *name; + struct macro_t *m; + STRING *key; + HASH_ENTRY value; + + if (!macro_hash) new_hash(interp, ¯o_hash); + + BEGIN(macro); + c = yylex_skip(valp, interp, " "); + if (c != IDENTIFIER) + fataly(EX_SOFTWARE, sourcefile, line, + "Constant names must be identifiers"); - num_macros++; + name = str_dup(valp->s); + + c = yylex_skip(valp, interp, " "); + if (c != INTC && c != FLOATC && c != STRINGC && c != REG) + fataly(EX_SOFTWARE, sourcefile, line, + "Constant '%s' value must be a number, " + "stringliteral or register", name); + + m = mem_sys_allocate(sizeof(struct macro_t)); + m->name = name; + m->expansion = str_dup (valp->s); + m->params.num_param = 0; + + key = string_from_cstring(interp, m->name, 0); + value.type = enum_type_PMC; + value.val.pmc_val = (PMC*)m; + hash_put(interp, macro_hash, key, &value); + + BEGIN (emit); return MACRO; } @@ -637,15 +665,15 @@ } static struct macro_t * -find_macro (const char* name) +find_macro (const char* name, void *interp) { - int i; + STRING *key = string_from_cstring(interp, name, 0); + HASH_ENTRY *value; - for (i = 0; i < num_macros; i++) { - if (strcmp(name, macros[i].name) == 0) return macros + i; - } + if (!macro_hash) return NULL; - return NULL; + value = hash_get(interp, macro_hash, key); + return value ? (struct macro_t *)value->val.pmc_val : NULL; } static int @@ -671,7 +699,7 @@ return 1; } - m = find_macro(name); + m = find_macro(name, interp); frame->params = &m->params; if (m) { /* remember macro name for error reporting