diff --git a/tools/widl/header.c b/tools/widl/header.c index 24f27cbe03ee50c4a93a03f6d529269cd6f1eb9c..33bd3fb4fd6209b7e8b7f28b70501fffa4c60527 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -78,8 +78,8 @@ static void write_array(FILE *h, expr_t *v) while (NEXT_LINK(v)) v = NEXT_LINK(v); fprintf(h, "["); while (v) { - if (v->type == EXPR_NUM) - fprintf(h, "%ld", v->u.lval); /* statically sized array */ + if (v->is_const) + fprintf(h, "%ld", v->cval); /* statically sized array */ else fprintf(h, "1"); /* dynamically sized array */ if (PREV_LINK(v)) @@ -99,6 +99,21 @@ static void write_field(FILE *h, var_t *v) fprintf(h, " "); write_pident(h, v); } + else { + /* not all C/C++ compilers support anonymous structs and unions */ + switch (v->type->type) { + case RPC_FC_STRUCT: + case RPC_FC_ENCAPSULATED_UNION: + fprintf(h, " DUMMYSTRUCTNAME"); + break; + case RPC_FC_NON_ENCAPSULATED_UNION: + fprintf(h, " DUMMYUNIONNAME"); + break; + default: + /* ? */ + break; + } + } write_array(h, v->array); fprintf(h, ";\n"); } @@ -124,8 +139,10 @@ static void write_enums(FILE *h, var_t *v) if (get_name(v)) { indent(0); write_name(h, v); - if (v->has_val) - fprintf(h, " = %ld", v->lval); + if (v->eval) { + fprintf(h, " = "); + write_expr(h, v->eval); + } } if (PREV_LINK(v)) fprintf(h, ",\n"); @@ -181,6 +198,7 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n) if (t->defined && !t->written) { if (t->name) fprintf(h, "enum %s {\n", t->name); else fprintf(h, "enum {\n"); + t->written = TRUE; indentation++; write_enums(h, t->fields); indent(-1); @@ -189,29 +207,13 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n) else fprintf(h, "enum %s", t->name); break; case RPC_FC_STRUCT: - if (t->defined && !t->written) { - if (t->name) fprintf(h, "struct %s {\n", t->name); - else fprintf(h, "struct {\n"); - indentation++; - write_fields(h, t->fields); - indent(-1); - fprintf(h, "}"); - } - else fprintf(h, "struct %s", t->name); - break; case RPC_FC_ENCAPSULATED_UNION: if (t->defined && !t->written) { - var_t *d = t->fields; if (t->name) fprintf(h, "struct %s {\n", t->name); else fprintf(h, "struct {\n"); + t->written = TRUE; indentation++; - write_field(h, d); - indent(0); - fprintf(h, "union {\n"); - indentation++; - write_fields(h, NEXT_LINK(d)); - indent(-1); - fprintf(h, "} u;\n"); + write_fields(h, t->fields); indent(-1); fprintf(h, "}"); } @@ -221,6 +223,7 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n) if (t->defined && !t->written) { if (t->name) fprintf(h, "union %s {\n", t->name); else fprintf(h, "union {\n"); + t->written = TRUE; indentation++; write_fields(h, t->fields); indent(-1); @@ -262,6 +265,89 @@ void write_typedef(type_t *type, var_t *names) fprintf(header, ";\n\n"); } +static void do_write_expr(FILE *h, expr_t *e, int p) +{ + switch (e->type) { + case EXPR_VOID: + break; + case EXPR_NUM: + fprintf(h, "%ld", e->u.lval); + break; + case EXPR_HEXNUM: + fprintf(h, "0x%lx", e->u.lval); + break; + case EXPR_IDENTIFIER: + fprintf(h, "%s", e->u.sval); + break; + case EXPR_NEG: + fprintf(h, "-"); + do_write_expr(h, e->ref, 1); + break; + case EXPR_PPTR: + fprintf(h, "*"); + do_write_expr(h, e->ref, 1); + break; + case EXPR_CAST: + fprintf(h, "("); + write_type(h, e->u.tref->ref, NULL, e->u.tref->name); + fprintf(h, ")"); + do_write_expr(h, e->ref, 1); + break; + case EXPR_SIZEOF: + fprintf(h, "sizeof("); + write_type(h, e->u.tref->ref, NULL, e->u.tref->name); + fprintf(h, ")"); + break; + case EXPR_SHL: + case EXPR_SHR: + case EXPR_MUL: + case EXPR_DIV: + case EXPR_ADD: + case EXPR_SUB: + case EXPR_AND: + case EXPR_OR: + if (p) fprintf(h, "("); + do_write_expr(h, e->ref, 1); + switch (e->type) { + case EXPR_SHL: fprintf(h, " << "); break; + case EXPR_SHR: fprintf(h, " >> "); break; + case EXPR_MUL: fprintf(h, " * "); break; + case EXPR_DIV: fprintf(h, " / "); break; + case EXPR_ADD: fprintf(h, " + "); break; + case EXPR_SUB: fprintf(h, " - "); break; + case EXPR_AND: fprintf(h, " & "); break; + case EXPR_OR: fprintf(h, " | "); break; + default: break; + } + do_write_expr(h, e->u.ext, 1); + if (p) fprintf(h, ")"); + break; + } +} + +void write_expr(FILE *h, expr_t *e) +{ + do_write_expr(h, e, 0); +} + +void write_constdef(var_t *v) +{ + fprintf(header, "#define %s (", get_name(v)); + write_expr(header, v->eval); + fprintf(header, ")\n\n"); +} + +void write_externdef(var_t *v) +{ + fprintf(header, "extern const "); + write_type(header, v->type, NULL, v->tname); + if (get_name(v)) { + fprintf(header, " "); + write_pident(header, v); + } + fprintf(header, ";\n\n"); +} + /********** INTERFACES **********/ uuid_t *get_uuid(attr_t *a) diff --git a/tools/widl/header.h b/tools/widl/header.h index d1d1a36f0388d572feb7bf61a44de0cae3deff08..68316605b183b5144308e05d4bbeab173f223b84 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -32,5 +32,8 @@ extern void write_method_args(FILE *h, var_t *arg, char *name); extern void write_forward(type_t *iface); extern void write_interface(type_t *iface); extern void write_typedef(type_t *type, var_t *names); +extern void write_expr(FILE *h, expr_t *e); +extern void write_constdef(var_t *v); +extern void write_externdef(var_t *v); #endif diff --git a/tools/widl/parser.h b/tools/widl/parser.h index fb84ed6919dbe29b10dd9bb2db066eac89a71c99..20a7e2af4744088e798b487bf917cf11d569d40a 100644 --- a/tools/widl/parser.h +++ b/tools/widl/parser.h @@ -31,7 +31,7 @@ extern int yy_flex_debug; int yylex(void); extern int import_stack_ptr; -void do_import(char *fname); +int do_import(char *fname); void abort_import(void); #define parse_only import_stack_ptr diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 6483293633d309d778307d05d1c0e66687644151..5c4c6e242442218ebff995b9631fa81f77271ef9 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -118,7 +118,10 @@ static uuid_t* parse_uuid(const char*u) yylval.uuid = parse_uuid(yytext); return aUUID; } -{hex} | +{hex} { + yylval.num = strtol(yytext, NULL, 0); + return aHEXNUM; + } {int} { yylval.num = strtol(yytext, NULL, 0); return aNUM; @@ -145,7 +148,7 @@ int yywrap(void) } #endif -static struct { +static struct keyword { const char *kw; int token; int val; @@ -241,16 +244,34 @@ static struct { {"version", tVERSION}, {"void", tVOID}, {"wchar_t", tWCHAR}, - {"wire_marshal", tWIREMARSHAL}, - {NULL} + {"wire_marshal", tWIREMARSHAL} }; +#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) +#define KWP(p) ((struct keyword *)(p)) + +static int kw_cmp_func(const void *s1, const void *s2) +{ + return strcmp(KWP(s1)->kw, KWP(s2)->kw); +} +#define KW_BSEARCH static int kw_token(const char *kw) { - int i; - for (i=0; keywords[i].kw; i++) - if (strcmp(kw, keywords[i].kw) == 0) - return keywords[i].token; + struct keyword key, *kwp; + key.kw = kw; +#ifdef KW_BSEARCH + kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func); +#else + { + int i; + for (kwp=NULL, i=0; i < NKEYWORDS; i++) + if (!kw_cmp_func(&key, &keywords[i])) { + kwp = &keywords[i]; + break; + } + } +#endif + if (kwp) return kwp->token; yylval.str = xstrdup(kw); return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; } @@ -293,7 +314,7 @@ struct imports { struct imports *next; } *first_import; -void do_import(char *fname) +int do_import(char *fname) { FILE *f; char *hname, *path; @@ -312,7 +333,7 @@ void do_import(char *fname) import = first_import; while (import && strcmp(import->name, fname)) import = import->next; - if (import) return; /* already imported */ + if (import) return 0; /* already imported */ import = xmalloc(sizeof(struct imports)); import->name = xstrdup(fname); @@ -334,6 +355,7 @@ void do_import(char *fname) import_stack[ptr].state = YY_CURRENT_BUFFER; yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); + return 1; } void abort_import(void) diff --git a/tools/widl/parser.y b/tools/widl/parser.y index a1e720f95cd5a0f3a3977c7bf7f26c516750f42e..3838b0ce757380840f2d15b73612f4509afdbf78 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -67,6 +67,7 @@ static attr_t *make_attrp(enum attr_type type, void *val); static expr_t *make_expr(enum expr_type type); static expr_t *make_exprl(enum expr_type type, long val); static expr_t *make_exprs(enum expr_type type, char *val); +static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr); static expr_t *make_expr1(enum expr_type type, expr_t *expr); static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2); static type_t *make_type(BYTE type, type_t *ref); @@ -84,6 +85,9 @@ static type_t *find_type2(char *name, int t); static type_t *get_type(BYTE type, char *name, int t); static type_t *get_typev(BYTE type, var_t *name, int t); +static var_t *reg_const(var_t *var); +static var_t *find_const(char *name, int f); + #define tsENUM 1 #define tsSTRUCT 2 #define tsUNION 3 @@ -106,7 +110,7 @@ static type_t std_int = { "int" }; %token <str> aIDENTIFIER %token <str> aKNOWNTYPE -%token <num> aNUM +%token <num> aNUM aHEXNUM %token <str> aSTRING %token <uuid> aUUID %token aEOF @@ -154,16 +158,16 @@ static type_t std_int = { "int" }; %token tPOINTERTYPE %type <attr> m_attributes attributes attrib_list attribute -%type <expr> aexprs aexpr_list aexpr array +%type <expr> exprs expr_list expr array expr_const %type <type> inherit interface interfacehdr interfacedef lib_statements %type <type> base_type int_std %type <type> enumdef structdef typedef uniondef %type <tref> type %type <var> m_args no_args args arg -%type <var> fields field s_field cases case enums enum_list enum constdef +%type <var> fields field s_field cases case enums enum_list enum constdef externdef %type <var> m_ident t_ident ident p_ident pident pident_list %type <func> funcdef int_statements -%type <num> expr pointer_type +%type <num> pointer_type %left ',' %left '|' @@ -193,10 +197,10 @@ int_statements: { $$ = NULL; } ; statement: ';' {} - | constdef {} + | constdef ';' { if (!parse_only) { write_constdef($1); } } | cppquote {} | enumdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } } - | externdef ';' {} + | externdef ';' { if (!parse_only) { write_externdef($1); } } | import {} /* | interface ';' {} */ /* | interfacedef {} */ @@ -207,7 +211,8 @@ statement: ';' {} cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only) fprintf(header, "%s\n", $3); } ; -import_start: tIMPORT aSTRING ';' { do_import($2); } +import_start: tIMPORT aSTRING ';' { assert(yychar == YYEMPTY); + if (!do_import($2)) yychar = aEOF; } ; import: import_start input aEOF {} ; @@ -234,33 +239,8 @@ arg: attributes type pident array { $$ = $3; } ; -aexprs: { $$ = make_expr(EXPR_VOID); } - | aexpr_list - ; - -aexpr_list: aexpr - | aexpr_list ',' aexpr { LINK($3, $1); $$ = $3; } - ; - -aexpr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } - | aIDENTIFIER { $$ = make_exprs(EXPR_IDENTIFIER, $1); } - | aexpr '|' aexpr { $$ = make_expr2(EXPR_OR , $1, $3); } - | aexpr '&' aexpr { $$ = make_expr2(EXPR_AND, $1, $3); } - | aexpr '+' aexpr { $$ = make_expr2(EXPR_ADD, $1, $3); } - | aexpr '-' aexpr { $$ = make_expr2(EXPR_SUB, $1, $3); } - | aexpr '*' aexpr { $$ = make_expr2(EXPR_MUL, $1, $3); } - | aexpr '/' aexpr { $$ = make_expr2(EXPR_DIV, $1, $3); } - | aexpr SHL aexpr { $$ = make_expr2(EXPR_SHL, $1, $3); } - | aexpr SHR aexpr { $$ = make_expr2(EXPR_SHR, $1, $3); } - | '-' aexpr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); } - | '*' aexpr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } - | '(' type ')' aexpr %prec CAST { $$ = $4; /* FIXME */ free($2); } - | '(' aexpr ')' { $$ = $2; } - | tSIZEOF '(' type ')' { $$ = make_exprl(EXPR_NUM, 0); /* FIXME */ free($3); warning("can't do sizeof() yet\n"); } - ; - array: { $$ = NULL; } - | '[' aexprs ']' { $$ = $2; } + | '[' exprs ']' { $$ = $2; } | '[' '*' ']' { $$ = make_expr(EXPR_VOID); } ; @@ -286,15 +266,15 @@ attribute: | tDEFAULT { $$ = make_attr(ATTR_DEFAULT); } | tIIDIS '(' ident ')' { $$ = make_attrp(ATTR_IIDIS, $3); } | tIN { $$ = make_attr(ATTR_IN); } - | tLENGTHIS '(' aexprs ')' { $$ = NULL; } + | tLENGTHIS '(' exprs ')' { $$ = NULL; } | tLOCAL { $$ = make_attr(ATTR_LOCAL); } | tOBJECT { $$ = make_attr(ATTR_OBJECT); } | tOLEAUTOMATION { $$ = make_attr(ATTR_OLEAUTOMATION); } | tOUT { $$ = make_attr(ATTR_OUT); } | tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); } - | tSIZEIS '(' aexprs ')' { $$ = NULL; } + | tSIZEIS '(' exprs ')' { $$ = NULL; } | tSTRING { $$ = make_attr(ATTR_STRING); } - | tSWITCHIS '(' aexpr ')' { $$ = NULL; } + | tSWITCHIS '(' expr ')' { $$ = NULL; } | tSWITCHTYPE '(' type ')' { $$ = NULL; } | tUUID '(' aUUID ')' { $$ = make_attrp(ATTR_UUID, $3); } | tV1ENUM { $$ = make_attr(ATTR_V1ENUM); } @@ -308,17 +288,25 @@ callconv: ; cases: { $$ = NULL; } - | cases case { LINK($2, $1); $$ = $2; } + | cases case { if ($2) { LINK($2, $1); $$ = $2; } + else { $$ = $1; } + } ; -case: tCASE expr ':' field { $$ = $4; } - | tDEFAULT ':' field { $$ = $3; } +case: tCASE expr ':' field { /* attr_t *a = NULL; */ /* FIXME */ + $$ = $4; if (!$$) $$ = make_var(NULL); + /* LINK(a, $$->attrs); $$->attrs = a; */ + } + | tDEFAULT ':' field { attr_t *a = make_attr(ATTR_DEFAULT); + $$ = $3; if (!$$) $$ = make_var(NULL); + LINK(a, $$->attrs); $$->attrs = a; + } ; -constdef: tCONST type ident '=' expr { $$ = $3; +constdef: tCONST type ident '=' expr_const { $$ = reg_const($3); set_type($$, $2, NULL); - $$->has_val = TRUE; - $$->lval = $5; + $$->eval = $5; + $$->lval = $5->cval; } ; @@ -328,14 +316,19 @@ enums: { $$ = NULL; } ; enum_list: enum - | enum_list ',' enum { LINK($3, $1); $$ = $3; } + | enum_list ',' enum { LINK($3, $1); $$ = $3; + if ($1 && !$3->eval) + $3->lval = $1->lval + 1; + } ; -enum: ident '=' expr { $$ = $1; - $$->has_val = TRUE; - $$->lval = $3; +enum: ident '=' expr_const { $$ = reg_const($1); + $$->eval = $3; + $$->lval = $3->cval; + } + | ident { $$ = reg_const($1); + $$->lval = 0; /* default for first enum entry */ } - | ident { $$ = $1; } ; enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM); @@ -344,24 +337,46 @@ enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM } ; -expr_list: expr {} - | expr_list ',' expr {} +exprs: { $$ = make_expr(EXPR_VOID); } + | expr_list ; -expr: aNUM - | aIDENTIFIER { $$ = 0; /* FIXME */ } - | expr '|' expr { $$ = $1 | $3; } - | expr '&' expr { $$ = $1 & $3; } - | expr SHL expr { $$ = $1 << $3; } - | expr SHR expr { $$ = $1 >> $3; } - | '-' expr %prec NEG { $$ = -$2; } +expr_list: expr + | expr_list ',' expr { LINK($3, $1); $$ = $3; } ; -externdef: tEXTERN tCONST type ident +expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } + | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); } + | aIDENTIFIER { $$ = make_exprs(EXPR_IDENTIFIER, $1); } + | expr '|' expr { $$ = make_expr2(EXPR_OR , $1, $3); } + | expr '&' expr { $$ = make_expr2(EXPR_AND, $1, $3); } + | expr '+' expr { $$ = make_expr2(EXPR_ADD, $1, $3); } + | expr '-' expr { $$ = make_expr2(EXPR_SUB, $1, $3); } + | expr '*' expr { $$ = make_expr2(EXPR_MUL, $1, $3); } + | expr '/' expr { $$ = make_expr2(EXPR_DIV, $1, $3); } + | expr SHL expr { $$ = make_expr2(EXPR_SHL, $1, $3); } + | expr SHR expr { $$ = make_expr2(EXPR_SHR, $1, $3); } + | '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); } + | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } + | '(' type ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, $2, $4); } + | tSIZEOF '(' type ')' { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); } + | '(' expr ')' { $$ = $2; } + ; + +expr_const: expr { $$ = $1; + if (!$$->is_const) yyerror("expression is not constant\n"); + } + ; + +externdef: tEXTERN tCONST type ident { $$ = $4; + set_type($$, $3, NULL); + } ; fields: { $$ = NULL; } - | fields field { LINK($2, $1); $$ = $2; } + | fields field { if ($2) { LINK($2, $1); $$ = $2; } + else { $$ = $1; } + } ; field: s_field ';' { $$ = $1; } @@ -508,8 +523,13 @@ uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATE } | tUNION t_ident tSWITCH '(' s_field ')' - m_ident '{' cases '}' { $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION); - LINK($5, $9); $$->fields = $5; + m_ident '{' cases '}' { var_t *u = $7; + $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION); + if (!u) u = make_var("tagged_union"); + u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL); + u->type->fields = $9; + u->type->defined = TRUE; + LINK(u, $5); $$->fields = u; $$->defined = TRUE; } ; @@ -554,6 +574,7 @@ static expr_t *make_expr(enum expr_type type) e->type = type; e->ref = NULL; e->u.lval = 0; + e->is_const = FALSE; INIT_LINK(e); return e; } @@ -564,90 +585,121 @@ static expr_t *make_exprl(enum expr_type type, long val) e->type = type; e->ref = NULL; e->u.lval = val; + e->is_const = FALSE; INIT_LINK(e); + /* check for numeric constant */ + if (type == EXPR_NUM || type == EXPR_HEXNUM) { + e->is_const = TRUE; + e->cval = val; + } return e; } static expr_t *make_exprs(enum expr_type type, char *val) { - expr_t *e = xmalloc(sizeof(expr_t)); - /* FIXME: if type is EXPR_IDENTIFIER, we could check for match against const - * declaration, and change to appropriate type and value if so */ + expr_t *e; + e = xmalloc(sizeof(expr_t)); e->type = type; e->ref = NULL; e->u.sval = val; + e->is_const = FALSE; INIT_LINK(e); + /* check for predefined constants */ + if (type == EXPR_IDENTIFIER) { + var_t *c = find_const(val, 0); + if (c) { + e->u.sval = c->name; + free(val); + e->is_const = TRUE; + e->cval = c->lval; + } + } + return e; +} + +static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr; + e->u.tref = tref; + e->is_const = FALSE; + INIT_LINK(e); + /* check for cast of constant expression */ + if (type == EXPR_CAST && expr->is_const) { + e->is_const = TRUE; + e->cval = expr->cval; + } return e; } static expr_t *make_expr1(enum expr_type type, expr_t *expr) { expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr; + e->u.lval = 0; + e->is_const = FALSE; + INIT_LINK(e); /* check for compile-time optimization */ - if (expr->type == EXPR_NUM) { + if (expr->is_const) { + e->is_const = TRUE; switch (type) { case EXPR_NEG: - expr->u.lval = -expr->u.lval; - return expr; + e->cval = -expr->cval; + break; default: + e->is_const = FALSE; break; } } - e = xmalloc(sizeof(expr_t)); - e->type = type; - e->ref = expr; - e->u.lval = 0; - INIT_LINK(e); return e; } static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) { expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr1; + e->u.ext = expr2; + e->is_const = FALSE; + INIT_LINK(e); /* check for compile-time optimization */ - if (expr1->type == EXPR_NUM && expr2->type == EXPR_NUM) { + if (expr1->is_const && expr2->is_const) { + e->is_const = TRUE; switch (type) { case EXPR_ADD: - expr1->u.lval += expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval + expr2->cval; + break; case EXPR_SUB: - expr1->u.lval -= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval - expr2->cval; + break; case EXPR_MUL: - expr1->u.lval *= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval * expr2->cval; + break; case EXPR_DIV: - expr1->u.lval /= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval / expr2->cval; + break; case EXPR_OR: - expr1->u.lval |= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval | expr2->cval; + break; case EXPR_AND: - expr1->u.lval &= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval & expr2->cval; + break; case EXPR_SHL: - expr1->u.lval <<= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval << expr2->cval; + break; case EXPR_SHR: - expr1->u.lval >>= expr2->u.lval; - free(expr2); - return expr1; + e->cval = expr1->cval >> expr2->cval; + break; default: + e->is_const = FALSE; break; } } - e = xmalloc(sizeof(expr_t)); - e->type = type; - e->ref = expr1; - e->u.ext = expr2; - INIT_LINK(e); return e; } @@ -718,7 +770,7 @@ static var_t *make_var(char *name) v->tname = NULL; v->attrs = NULL; v->array = NULL; - v->has_val = FALSE; + v->eval = NULL; v->lval = 0; INIT_LINK(v); return v; @@ -735,6 +787,22 @@ static func_t *make_func(var_t *def, var_t *args) return f; } +#define HASHMAX 64 + +static int hash_ident(const char *name) +{ + const char *p = name; + int sum = 0; + /* a simple sum hash is probably good enough */ + while (*p) { + sum += *p; + p++; + } + return sum & (HASHMAX-1); +} + +/***** type repository *****/ + struct rtype { char *name; type_t *type; @@ -742,21 +810,23 @@ struct rtype { struct rtype *next; }; -struct rtype *first_type; +struct rtype *type_hash[HASHMAX]; static type_t *reg_type(type_t *type, char *name, int t) { struct rtype *nt; + int hash; if (!name) { yyerror("registering named type without name\n"); return type; } + hash = hash_ident(name); nt = xmalloc(sizeof(struct rtype)); nt->name = name; nt->type = type; nt->t = t; - nt->next = first_type; - first_type = nt; + nt->next = type_hash[hash]; + type_hash[hash] = nt; return type; } @@ -791,7 +861,7 @@ static type_t *reg_types(type_t *type, var_t *names, int t) static type_t *find_type(char *name, int t) { - struct rtype *cur = first_type; + struct rtype *cur = type_hash[hash_ident(name)]; while (cur && (cur->t != t || strcmp(cur->name, name))) cur = cur->next; if (!cur) { @@ -810,7 +880,7 @@ static type_t *find_type2(char *name, int t) int is_type(const char *name) { - struct rtype *cur = first_type; + struct rtype *cur = type_hash[hash_ident(name)]; while (cur && (cur->t || strcmp(cur->name, name))) cur = cur->next; if (cur) return TRUE; @@ -822,7 +892,7 @@ static type_t *get_type(BYTE type, char *name, int t) struct rtype *cur = NULL; type_t *tp; if (name) { - cur = first_type; + cur = type_hash[hash_ident(name)]; while (cur && (cur->t != t || strcmp(cur->name, name))) cur = cur->next; } @@ -845,3 +915,42 @@ static type_t *get_typev(BYTE type, var_t *name, int t) } return get_type(type, sname, t); } + +/***** constant repository *****/ + +struct rconst { + char *name; + var_t *var; + struct rconst *next; +}; + +struct rconst *const_hash[HASHMAX]; + +static var_t *reg_const(var_t *var) +{ + struct rconst *nc; + int hash; + if (!var->name) { + yyerror("registering constant without name\n"); + return var; + } + hash = hash_ident(var->name); + nc = xmalloc(sizeof(struct rconst)); + nc->name = var->name; + nc->var = var; + nc->next = const_hash[hash]; + const_hash[hash] = nc; + return var; +} + +static var_t *find_const(char *name, int f) +{ + struct rconst *cur = const_hash[hash_ident(name)]; + while (cur && strcmp(cur->name, name)) + cur = cur->next; + if (!cur) { + if (f) yyerror("constant %s not found\n", name); + return NULL; + } + return cur->var; +} diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 6607318bc19152f7e67f54b4c3447719bb8aad8e..9060bd17005edd566fda0c87cdb8b4168f059131 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -67,10 +67,12 @@ enum expr_type { EXPR_VOID, EXPR_NUM, + EXPR_HEXNUM, EXPR_IDENTIFIER, EXPR_NEG, EXPR_PPTR, EXPR_CAST, + EXPR_SIZEOF, EXPR_SHL, EXPR_SHR, EXPR_MUL, @@ -98,7 +100,10 @@ struct _expr_t { long lval; char *sval; expr_t *ext; + typeref_t *tref; } u; + int is_const; + long cval; /* parser-internal */ DECL_LINK(expr_t) }; @@ -131,7 +136,7 @@ struct _var_t { type_t *type; char *tname; attr_t *attrs; - int has_val; + expr_t *eval; long lval; /* parser-internal */