# 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