From 03c7d468069114272c239d38fa38909a896ca604 Mon Sep 17 00:00:00 2001 From: Ove Kaaven Date: Tue, 12 Nov 2002 02:12:35 +0000 Subject: [PATCH] Support for enums, arrays, encapsulated unions, signed/unsigned qualifiers, UUIDs, include guards, the new ICOM_DEFINE1 macro, and some other improvements. --- tools/widl/header.c | 154 ++++++++++++++++++---- tools/widl/parser.l | 32 ++++- tools/widl/parser.y | 291 +++++++++++++++++++++++++++++++---------- tools/widl/proxy.c | 23 ++-- tools/widl/widl.c | 39 +++++- tools/widl/widltypes.h | 37 +++++- 6 files changed, 464 insertions(+), 112 deletions(-) diff --git a/tools/widl/header.c b/tools/widl/header.c index c910a9ab420..95dc3521d89 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -53,13 +53,13 @@ int is_void(type_t *t, var_t *v) return 0; } -static void write_pident(var_t *v) +static void write_pident(FILE *h, var_t *v) { int c; for (c=0; cptr_level; c++) { - fprintf(header, "*"); + fprintf(h, "*"); } - if (v->name) fprintf(header, "%s", v->name); + if (v->name) fprintf(h, "%s", v->name); } void write_name(FILE *h, var_t *v) @@ -72,22 +72,66 @@ char* get_name(var_t *v) return v->name; } +static void write_array(FILE *h, expr_t *v) +{ + if (!v) return; + 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 */ + else + fprintf(h, "1"); /* dynamically sized array */ + if (PREV_LINK(v)) + fprintf(h, ", "); + v = PREV_LINK(v); + } + fprintf(h, "]"); +} + +static void write_field(FILE *h, var_t *v) +{ + if (!v) return; + if (v->type) { + indent(0); + write_type(h, v->type, NULL, v->tname); + if (get_name(v)) { + fprintf(h, " "); + write_pident(h, v); + } + write_array(h, v->array); + fprintf(h, ";\n"); + } +} + static void write_fields(FILE *h, var_t *v) +{ + var_t *first = v; + if (!v) return; + while (NEXT_LINK(v)) v = NEXT_LINK(v); + while (v) { + write_field(h, v); + if (v == first) break; + v = PREV_LINK(v); + } +} + +static void write_enums(FILE *h, var_t *v) { if (!v) return; while (NEXT_LINK(v)) v = NEXT_LINK(v); while (v) { - if (v->type) { + if (get_name(v)) { indent(0); - write_type(h, v->type, NULL, v->tname); - if (get_name(v)) { - fprintf(header, " "); - write_pident(v); - } - fprintf(header, ";\n"); + write_name(h, v); + if (v->has_val) + fprintf(h, " = %ld", v->lval); } + if (PREV_LINK(v)) + fprintf(h, ",\n"); v = PREV_LINK(v); } + fprintf(h, "\n"); } void write_type(FILE *h, type_t *t, var_t *v, char *n) @@ -98,25 +142,52 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n) else { if (t->is_const) fprintf(h, "const "); if (t->type) { + if (t->sign > 0) fprintf(h, "signed "); + else if (t->sign < 0) fprintf(h, "unsigned "); switch (t->type) { case RPC_FC_BYTE: - fprintf(h, "byte"); + if (t->ref) fprintf(h, t->ref->name); + else fprintf(h, "byte"); break; case RPC_FC_CHAR: - fprintf(h, "char"); + if (t->ref) fprintf(h, t->ref->name); + else fprintf(h, "char"); + break; + case RPC_FC_WCHAR: + fprintf(h, "wchar_t"); break; case RPC_FC_USHORT: - fprintf(h, "unsigned "); case RPC_FC_SHORT: if (t->ref) fprintf(h, t->ref->name); - fprintf(h, "short"); + else fprintf(h, "short"); break; case RPC_FC_ULONG: - fprintf(h, "unsigned "); case RPC_FC_LONG: if (t->ref) fprintf(h, t->ref->name); else fprintf(h, "long"); break; + case RPC_FC_HYPER: + if (t->ref) fprintf(h, t->ref->name); + else fprintf(h, "__int64"); + break; + case RPC_FC_FLOAT: + fprintf(h, "float"); + break; + case RPC_FC_DOUBLE: + fprintf(h, "double"); + break; + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + if (t->defined && !t->written) { + if (t->name) fprintf(h, "enum %s {\n", t->name); + else fprintf(h, "enum {\n"); + indentation++; + write_enums(h, t->fields); + indent(-1); + fprintf(h, "}"); + } + 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); @@ -128,6 +199,24 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n) } 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"); + indentation++; + write_field(h, d); + indent(0); + fprintf(h, "union {\n"); + indentation++; + write_fields(h, NEXT_LINK(d)); + indent(-1); + fprintf(h, "} u;\n"); + indent(-1); + fprintf(h, "}"); + } + else fprintf(h, "struct %s", t->name); + break; case RPC_FC_NON_ENCAPSULATED_UNION: if (t->defined && !t->written) { if (t->name) fprintf(h, "union %s {\n", t->name); @@ -165,16 +254,25 @@ void write_typedef(type_t *type, var_t *names) write_type(header, type, NULL, tname); fprintf(header, " "); while (names) { - write_pident(names); + write_pident(header, names); if (PREV_LINK(names)) fprintf(header, ", "); names = PREV_LINK(names); } - fprintf(header, ";\n"); + fprintf(header, ";\n\n"); } /********** INTERFACES **********/ +UUID *get_uuid(attr_t *a) +{ + while (a) { + if (a->type == ATTR_UUID) return a->u.pval; + a = NEXT_LINK(a); + } + return NULL; +} + int is_object(attr_t *a) { while (a) { @@ -364,12 +462,21 @@ static void write_method_proto(type_t *iface) void write_forward(type_t *iface) { - if (!iface->written) { + if (is_object(iface->attrs) && !iface->written) { fprintf(header, "typedef struct %s %s;\n", iface->name, iface->name); iface->written = TRUE; } } +void write_guid(type_t *iface) +{ + UUID *uuid = get_uuid(iface->attrs); + if (!uuid) return; + fprintf(header, "DEFINE_GUID(IID_%s, 0x%08lx, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n", + iface->name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], + uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); +} + void write_interface(type_t *iface) { if (!is_object(iface->attrs)) { @@ -386,18 +493,19 @@ void write_interface(type_t *iface) fprintf(header, "/*****************************************************************************\n"); fprintf(header, " * %s interface\n", iface->name); fprintf(header, " */\n"); + write_guid(iface); write_forward(iface); - if (iface->ref) - fprintf(header, "#define ICOM_INTERFACE %s\n", iface->name); + fprintf(header, "#define ICOM_INTERFACE %s\n", iface->name); write_method_def(iface); fprintf(header, "#define %s_IMETHODS \\\n", iface->name); if (iface->ref) fprintf(header, " %s_IMETHODS \\\n", iface->ref->name); fprintf(header, " %s_METHODS \\\n", iface->name); - if (iface->ref) { + if (iface->ref) fprintf(header, "ICOM_DEFINE(%s,%s)\n", iface->name, iface->ref->name); - fprintf(header, "#undef ICOM_INTERFACE\n"); - } + else + fprintf(header, "ICOM_DEFINE1(%s)\n", iface->name); + fprintf(header, "#undef ICOM_INTERFACE\n"); fprintf(header, "\n"); write_method_macro(iface, iface->name); fprintf(header, "\n"); diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 872fd3552c9..4e93cd811e1 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -75,6 +75,26 @@ int import_stack_ptr = 0; static void pop_import(void); +static UUID* parse_uuid(const char*u) +{ + UUID* uuid = xmalloc(sizeof(UUID)); + char b[3]; + /* it would be nice to use UuidFromStringA */ + uuid->Data1 = strtol(u, NULL, 16); + uuid->Data2 = strtol(u+9, NULL, 16); + uuid->Data3 = strtol(u+14, NULL, 16); + b[2] = 0; + memcpy(b, u+19, 2); uuid->Data4[0] = strtol(b, NULL, 16); + memcpy(b, u+21, 2); uuid->Data4[1] = strtol(b, NULL, 16); + memcpy(b, u+24, 2); uuid->Data4[2] = strtol(b, NULL, 16); + memcpy(b, u+26, 2); uuid->Data4[3] = strtol(b, NULL, 16); + memcpy(b, u+28, 2); uuid->Data4[4] = strtol(b, NULL, 16); + memcpy(b, u+30, 2); uuid->Data4[5] = strtol(b, NULL, 16); + memcpy(b, u+32, 2); uuid->Data4[6] = strtol(b, NULL, 16); + memcpy(b, u+34, 2); uuid->Data4[7] = strtol(b, NULL, 16); + return uuid; +} + %} /* @@ -94,9 +114,15 @@ static void pop_import(void); \\\" addcchar(yytext[1]); \\. addcchar('\\'); addcchar(yytext[1]); . addcchar(yytext[0]); -{uuid} return aUUID; -{hex} return aNUM; -{int} return aNUM; +{uuid} { + yylval.uuid = parse_uuid(yytext); + return aUUID; + } +{hex} | +{int} { + yylval.num = strtol(yytext, NULL, 0); + return aNUM; + } {cident} return kw_token(yytext); \n {ws} diff --git a/tools/widl/parser.y b/tools/widl/parser.y index e84899ec921..c76306243a4 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -64,11 +64,16 @@ static attr_t *make_attr(enum attr_type type); static attr_t *make_attrv(enum attr_type type, DWORD val); 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_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); static typeref_t *make_tref(char *name, type_t *ref); static typeref_t *uniq_tref(typeref_t *ref); static type_t *type_ref(typeref_t *ref); -static void set_type(var_t *v, typeref_t *ref); +static void set_type(var_t *v, typeref_t *ref, expr_t *arr); static var_t *make_var(char *name); static func_t *make_func(var_t *def, var_t *args); @@ -83,16 +88,19 @@ static type_t *get_typev(BYTE type, var_t *name, int t); #define tsSTRUCT 2 #define tsUNION 3 +static type_t std_bool = { "boolean" }; static type_t std_int = { "int" }; %} %union { attr_t *attr; + expr_t *expr; type_t *type; typeref_t *tref; var_t *var; func_t *func; char *str; + UUID *uuid; int num; } @@ -145,14 +153,15 @@ static type_t std_int = { "int" }; %token tPOINTERTYPE %type m_attributes attributes attrib_list attribute -%type inherit interface interfacedef +%type aexprs aexpr_list aexpr array +%type inherit interface interfacedef lib_statements %type base_type int_std %type enumdef structdef typedef uniondef %type type %type m_args no_args args arg -%type fields field +%type fields field s_field cases case enums enum_list enum constdef %type m_ident t_ident ident p_ident pident pident_list -%type funcdef statements +%type funcdef int_statements %type expr pointer_type %left ',' @@ -167,22 +176,38 @@ static type_t std_int = { "int" }; %% -statements: { $$ = NULL; } - | statements funcdef ';' { LINK($2, $1); $$ = $2; } - | statements statement +input: lib_statements { /* FIXME */ } + ; + +lib_statements: { $$ = NULL; } + | lib_statements import + | lib_statements interface ';' + | lib_statements interfacedef { LINK($2, $1); $$ = $2; } +/* | lib_statements librarydef (when implemented) */ + | lib_statements statement + ; + +/* we can't import from inside interfaces yet + * (it's not entirely clear how Microsoft manages that yet, + * but in MIDL you can derive a class from a base class and then + * import the base class definition from inside the interface, + * which I don't quite know how to pull off in yacc/bison yet) */ +int_statements: { $$ = NULL; } + | int_statements funcdef ';' { LINK($2, $1); $$ = $2; } + | int_statements statement ; statement: ';' {} | constdef {} | cppquote {} - | enumdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } } + | enumdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } } | externdef ';' {} - | import {} - | interface ';' {} - | interfacedef {} - | structdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } } +/* | import {} */ +/* | interface ';' {} */ +/* | interfacedef {} */ + | structdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } } | typedef ';' {} - | uniondef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } } + | uniondef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } } ; cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only) fprintf(header, "%s\n", $3); } @@ -204,40 +229,42 @@ args: arg /* split into two rules to get bison to resolve a tVOID conflict */ arg: attributes type pident array { $$ = $3; - set_type($$, $2); - $$->attrs = $1; /* FIXME: array */ + set_type($$, $2, $4); + $$->attrs = $1; } | type pident array { $$ = $2; - set_type($$, $1); /* FIXME: array */ + set_type($$, $1, $3); } ; -aexprs: +aexprs: { $$ = make_expr(EXPR_VOID); } | aexpr_list ; aexpr_list: aexpr - | aexprs ',' aexpr + | aexpr_list ',' aexpr { LINK($3, $1); $$ = $3; } ; -aexpr: aNUM {} - | aIDENTIFIER {} - | aexpr '|' aexpr - | aexpr '&' aexpr - | aexpr '+' aexpr - | aexpr '-' aexpr - | aexpr '*' aexpr - | aexpr '/' aexpr - | '-' aexpr %prec NEG - | '*' aexpr %prec PPTR - | '(' type ')' aexpr %prec CAST - | '(' aexpr ')' - | tSIZEOF '(' type ')' +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: - | '[' aexprs ']' - | '[' '*' ']' +array: { $$ = NULL; } + | '[' aexprs ']' { $$ = $2; } + | '[' '*' ']' { $$ = make_expr(EXPR_VOID); } ; m_attributes: { $$ = NULL; } @@ -272,7 +299,7 @@ attribute: | tSTRING { $$ = make_attr(ATTR_STRING); } | tSWITCHIS '(' aexpr ')' { $$ = NULL; } | tSWITCHTYPE '(' type ')' { $$ = NULL; } - | tUUID '(' aUUID ')' { $$ = NULL; } + | tUUID '(' aUUID ')' { $$ = make_attrp(ATTR_UUID, $3); } | tV1ENUM { $$ = make_attr(ATTR_V1ENUM); } | tVERSION '(' version ')' { $$ = NULL; } | tWIREMARSHAL '(' type ')' { $$ = make_attrp(ATTR_WIREMARSHAL, type_ref($3)); } @@ -283,31 +310,39 @@ callconv: | tSTDCALL ; -cases: - | cases case +cases: { $$ = NULL; } + | cases case { LINK($2, $1); $$ = $2; } ; -case: tCASE expr ':' field - | tDEFAULT ':' field +case: tCASE expr ':' field { $$ = $4; } + | tDEFAULT ':' field { $$ = $3; } ; -constdef: tCONST type ident '=' expr +constdef: tCONST type ident '=' expr { $$ = $3; + set_type($$, $2, NULL); + $$->has_val = TRUE; + $$->lval = $5; + } ; -enums: - | enum_list ',' +enums: { $$ = NULL; } + | enum_list ',' { $$ = $1; } | enum_list ; enum_list: enum - | enum_list ',' enum + | enum_list ',' enum { LINK($3, $1); $$ = $3; } ; -enum: ident '=' expr {} - | ident {} +enum: ident '=' expr { $$ = $1; + $$->has_val = TRUE; + $$->lval = $3; + } + | ident { $$ = $1; } ; -enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_SHORT /* FIXME */, $2, tsENUM); +enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM); + $$->fields = $4; $$->defined = TRUE; } ; @@ -317,11 +352,12 @@ expr_list: expr {} ; expr: aNUM - | aIDENTIFIER {} - | expr '|' expr {} - | expr SHL expr {} - | expr SHR expr {} - | '-' expr %prec NEG {} + | 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; } ; externdef: tEXTERN tCONST type ident @@ -331,15 +367,18 @@ fields: { $$ = NULL; } | fields field { LINK($2, $1); $$ = $2; } ; -field: m_attributes type pident array ';' { $$ = $3; set_type($$, $2); $$->attrs = $1; /* FIXME: array */ } +field: s_field ';' { $$ = $1; } | m_attributes uniondef ';' { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; } | attributes ';' { $$ = make_var(NULL); $$->attrs = $1; } | ';' { $$ = NULL; } ; +s_field: m_attributes type pident array { $$ = $3; set_type($$, $2, $4); $$->attrs = $1; } + ; + funcdef: m_attributes type callconv pident - '(' m_args ')' { set_type($4, $2); + '(' m_args ')' { set_type($4, $2, NULL); $4->attrs = $1; $$ = make_func($4, $6); } @@ -358,15 +397,20 @@ ident: aIDENTIFIER { $$ = make_var($1); } ; base_type: tBYTE { $$ = make_type(RPC_FC_BYTE, NULL); } - | tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); } - | tUNSIGNED tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); } | tWCHAR { $$ = make_type(RPC_FC_WCHAR, NULL); } | int_std - | tSIGNED int_std { $$ = $2; /* FIXME */ } - | tUNSIGNED int_std { $$ = $2; /* FIXME */ } + | tSIGNED int_std { $$ = $2; $$->sign = 1; } + | tUNSIGNED int_std { $$ = $2; $$->sign = -1; + switch ($$->type) { + case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break; + case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break; + case RPC_FC_LONG: $$->type = RPC_FC_ULONG; break; + default: break; + } + } | tFLOAT { $$ = make_type(RPC_FC_FLOAT, NULL); } | tDOUBLE { $$ = make_type(RPC_FC_DOUBLE, NULL); } - | tBOOLEAN { $$ = make_type(RPC_FC_BYTE, NULL); /* ? */ } + | tBOOLEAN { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ } ; m_int: @@ -378,6 +422,7 @@ int_std: tINT { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */ | tLONG m_int { $$ = make_type(RPC_FC_LONG, NULL); } | tHYPER m_int { $$ = make_type(RPC_FC_HYPER, NULL); } | tINT64 { $$ = make_type(RPC_FC_HYPER, NULL); } + | tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); } ; inherit: { $$ = NULL; } @@ -389,7 +434,7 @@ interface: tINTERFACE aIDENTIFIER { $$ = get_type(RPC_FC_IP, $2, 0); if (!parse ; interfacedef: attributes interface inherit - '{' statements '}' { $$ = $2; + '{' int_statements '}' { $$ = $2; if ($$->defined) yyerror("multiple definition error\n"); $$->ref = $3; $$->attrs = $1; @@ -400,7 +445,7 @@ interfacedef: attributes interface inherit ; p_ident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; } - | tCONST p_ident { $$ = $2; } + | tCONST p_ident { $$ = $2; /* FIXME */ } ; pident: ident @@ -451,8 +496,9 @@ uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATE $$->defined = TRUE; } | tUNION t_ident - tSWITCH '(' type ident ')' + tSWITCH '(' s_field ')' m_ident '{' cases '}' { $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION); + LINK($5, $9); $$->fields = $5; $$->defined = TRUE; } ; @@ -469,6 +515,7 @@ static attr_t *make_attr(enum attr_type type) attr_t *a = xmalloc(sizeof(attr_t)); a->type = type; a->u.ival = 0; + INIT_LINK(a); return a; } @@ -477,6 +524,7 @@ static attr_t *make_attrv(enum attr_type type, DWORD val) attr_t *a = xmalloc(sizeof(attr_t)); a->type = type; a->u.ival = val; + INIT_LINK(a); return a; } @@ -485,9 +533,111 @@ static attr_t *make_attrp(enum attr_type type, void *val) attr_t *a = xmalloc(sizeof(attr_t)); a->type = type; a->u.pval = val; + INIT_LINK(a); return a; } +static expr_t *make_expr(enum expr_type type) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.lval = 0; + INIT_LINK(e); + return e; +} + +static expr_t *make_exprl(enum expr_type type, long val) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.lval = val; + INIT_LINK(e); + 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 */ + e->type = type; + e->ref = NULL; + e->u.sval = val; + INIT_LINK(e); + return e; +} + +static expr_t *make_expr1(enum expr_type type, expr_t *expr) +{ + expr_t *e; + /* check for compile-time optimization */ + if (expr->type == EXPR_NUM) { + switch (type) { + case EXPR_NEG: + expr->u.lval = -expr->u.lval; + return expr; + default: + } + } + 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; + /* check for compile-time optimization */ + if (expr1->type == EXPR_NUM && expr2->type == EXPR_NUM) { + switch (type) { + case EXPR_ADD: + expr1->u.lval += expr2->u.lval; + free(expr2); + return expr1; + case EXPR_SUB: + expr1->u.lval -= expr2->u.lval; + free(expr2); + return expr1; + case EXPR_MUL: + expr1->u.lval *= expr2->u.lval; + free(expr2); + return expr1; + case EXPR_DIV: + expr1->u.lval /= expr2->u.lval; + free(expr2); + return expr1; + case EXPR_OR: + expr1->u.lval |= expr2->u.lval; + free(expr2); + return expr1; + case EXPR_AND: + expr1->u.lval &= expr2->u.lval; + free(expr2); + return expr1; + case EXPR_SHL: + expr1->u.lval <<= expr2->u.lval; + free(expr2); + return expr1; + case EXPR_SHR: + expr1->u.lval >>= expr2->u.lval; + free(expr2); + return expr1; + default: + } + } + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr1; + e->u.ext = expr2; + INIT_LINK(e); + return e; +} + static type_t *make_type(BYTE type, type_t *ref) { type_t *t = xmalloc(sizeof(type_t)); @@ -500,6 +650,7 @@ static type_t *make_type(BYTE type, type_t *ref) t->fields = NULL; t->ignore = parse_only; t->is_const = FALSE; + t->sign = 0; t->defined = FALSE; t->written = FALSE; INIT_LINK(t); @@ -536,12 +687,13 @@ static type_t *type_ref(typeref_t *ref) return t; } -static void set_type(var_t *v, typeref_t *ref) +static void set_type(var_t *v, typeref_t *ref, expr_t *arr) { v->type = ref->ref; v->tname = ref->name; ref->name = NULL; free(ref); + v->array = arr; } static var_t *make_var(char *name) @@ -552,6 +704,9 @@ static var_t *make_var(char *name) v->type = NULL; v->tname = NULL; v->attrs = NULL; + v->array = NULL; + v->has_val = FALSE; + v->lval = 0; INIT_LINK(v); return v; } @@ -574,7 +729,7 @@ struct rtype { struct rtype *next; }; -struct rtype *first; +struct rtype *first_type; static type_t *reg_type(type_t *type, char *name, int t) { @@ -587,8 +742,8 @@ static type_t *reg_type(type_t *type, char *name, int t) nt->name = name; nt->type = type; nt->t = t; - nt->next = first; - first = nt; + nt->next = first_type; + first_type = nt; return type; } @@ -623,7 +778,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; + struct rtype *cur = first_type; while (cur && (cur->t != t || strcmp(cur->name, name))) cur = cur->next; if (!cur) { @@ -642,7 +797,7 @@ static type_t *find_type2(char *name, int t) int is_type(const char *name) { - struct rtype *cur = first; + struct rtype *cur = first_type; while (cur && (cur->t || strcmp(cur->name, name))) cur = cur->next; if (cur) return TRUE; @@ -654,7 +809,7 @@ static type_t *get_type(BYTE type, char *name, int t) struct rtype *cur = NULL; type_t *tp; if (name) { - cur = first; + cur = first_type; while (cur && (cur->t != t || strcmp(cur->name, name))) cur = cur->next; } diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index 2cf3ff1caf8..b47efbfdb8c 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -302,12 +302,13 @@ void finish_proxy(void) { if_list *lcur = if_first; if_list *cur; + char *file_id = "XXX"; int c; if (!lcur) return; while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur); - fprintf(proxy, "const CInterfaceProxyVtbl* _XXX_ProxyVtblList[] = {\n"); + fprintf(proxy, "const CInterfaceProxyVtbl* _%s_ProxyVtblList[] = {\n", file_id); cur = lcur; while (cur) { fprintf(proxy, " (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name); @@ -317,7 +318,7 @@ void finish_proxy(void) fprintf(proxy, "};\n"); fprintf(proxy, "\n"); - fprintf(proxy, "const CInterfaceStubVtbl* _XXX_StubVtblList[] = {\n"); + fprintf(proxy, "const CInterfaceStubVtbl* _%s_StubVtblList[] = {\n", file_id); cur = lcur; while (cur) { fprintf(proxy, " (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name); @@ -327,7 +328,7 @@ void finish_proxy(void) fprintf(proxy, "};\n"); fprintf(proxy, "\n"); - fprintf(proxy, "const PCInterfaceName _XXX_InterfaceNamesList[] = {\n"); + fprintf(proxy, "const PCInterfaceName _%s_InterfaceNamesList[] = {\n", file_id); cur = lcur; while (cur) { fprintf(proxy, " \"%s\",\n", cur->iface->name); @@ -337,14 +338,14 @@ void finish_proxy(void) fprintf(proxy, "};\n"); fprintf(proxy, "\n"); - fprintf(proxy, "#define _XXX_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n"); + fprintf(proxy, "#define _%s_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n", file_id); fprintf(proxy, "\n"); - fprintf(proxy, "int __stdcall _XXX_IID_Lookup(const IID* pIID, int* pIndex)\n"); + fprintf(proxy, "int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id); fprintf(proxy, "{\n"); cur = lcur; c = 0; while (cur) { - fprintf(proxy, " if (!_XXX_CHECK_IID(%d)) {\n", c); + fprintf(proxy, " if (!_%s_CHECK_IID(%d)) {\n", file_id, c); fprintf(proxy, " *pIndex = %d\n", c); fprintf(proxy, " return 1;\n"); fprintf(proxy, " }\n"); @@ -355,12 +356,12 @@ void finish_proxy(void) fprintf(proxy, "}\n"); fprintf(proxy, "\n"); - fprintf(proxy, "const ExtendedProxyFileInfo XXX_ProxyFileInfo = {\n"); - fprintf(proxy, " (PCInterfaceProxyVtblList*)&_XXX_ProxyVtblList,\n"); - fprintf(proxy, " (PCInterfaceStubVtblList*)&_XXX_StubVtblList,\n"); - fprintf(proxy, " (const PCInterfaceName*)&_XXX_InterfaceNamesList,\n"); + fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo = {\n", file_id); + fprintf(proxy, " (PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id); + fprintf(proxy, " (PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id); + fprintf(proxy, " (const PCInterfaceName*)&_%s_InterfaceNamesList,\n", file_id); fprintf(proxy, " 0,\n"); - fprintf(proxy, " &_XXX_IID_Lookup,\n"); + fprintf(proxy, " &_%s_IID_Lookup,\n", file_id); fprintf(proxy, " %d,\n", c); fprintf(proxy, " 1\n"); fprintf(proxy, "};\n"); diff --git a/tools/widl/widl.c b/tools/widl/widl.c index 349d1c79f40..5fef1826922 100644 --- a/tools/widl/widl.c +++ b/tools/widl/widl.c @@ -70,6 +70,7 @@ int no_preprocess = 0; char *input_name; char *header_name; +char *header_token; char *proxy_name; char *temp_name; @@ -85,6 +86,23 @@ int getopt (int argc, char *const *argv, const char *optstring); static void rm_tempfile(void); static void segvhandler(int sig); +static char *make_token(const char *name) +{ + char *token; + char *slash; + int i; + + slash = strrchr(name, '/'); + if (slash) name = slash + 1; + + token = xstrdup(name); + for (i=0; token[i]; i++) { + if (!isalnum(token[i])) token[i] = '_'; + else token[i] = toupper(token[i]); + } + return token; +} + int main(int argc,char *argv[]) { extern char* optarg; @@ -175,20 +193,29 @@ int main(int argc,char *argv[]) if(ret) exit(1); if(preprocess_only) exit(0); - input_name = temp_name; + if(!(yyin = fopen(temp_name, "r"))) { + fprintf(stderr, "Could not open %s for input\n", temp_name); + return 1; + } + } + else { + if(!(yyin = fopen(input_name, "r"))) { + fprintf(stderr, "Could not open %s for input\n", input_name); + return 1; + } } - if(!(yyin = fopen(input_name, "r"))) { - fprintf(stderr, "Could not open %s for input\n", input_name); - return 1; - } + header_token = make_token(header_name); header = fopen(header_name, "w"); - fprintf(header, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION); + fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name); + fprintf(header, "#ifndef __WIDL_%s\n", header_token); + fprintf(header, "#define __WIDL_%s\n", header_token); ret = yyparse(); finish_proxy(); + fprintf(header, "#endif /* __WIDL_%s */\n", header_token); fclose(header); fclose(yyin); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 9975410f948..eff0f822e18 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -26,6 +26,7 @@ #include "wine/rpcfc.h" typedef struct _attr_t attr_t; +typedef struct _expr_t expr_t; typedef struct _type_t type_t; typedef struct _typeref_t typeref_t; typedef struct _var_t var_t; @@ -57,10 +58,29 @@ enum attr_type ATTR_POINTERDEFAULT, ATTR_POINTERTYPE, ATTR_STRING, + ATTR_UUID, ATTR_V1ENUM, ATTR_WIREMARSHAL, }; +enum expr_type +{ + EXPR_VOID, + EXPR_NUM, + EXPR_IDENTIFIER, + EXPR_NEG, + EXPR_PPTR, + EXPR_CAST, + EXPR_SHL, + EXPR_SHR, + EXPR_MUL, + EXPR_DIV, + EXPR_ADD, + EXPR_SUB, + EXPR_AND, + EXPR_OR, +}; + struct _attr_t { enum attr_type type; union { @@ -71,6 +91,18 @@ struct _attr_t { DECL_LINK(attr_t) }; +struct _expr_t { + enum expr_type type; + expr_t *ref; + union { + long lval; + char *sval; + expr_t *ext; + } u; + /* parser-internal */ + DECL_LINK(expr_t) +}; + struct _type_t { char *name; BYTE type; @@ -79,7 +111,7 @@ struct _type_t { attr_t *attrs; func_t *funcs; var_t *fields; - int ignore, is_const; + int ignore, is_const, sign; int defined, written; /* parser-internal */ @@ -95,9 +127,12 @@ struct _typeref_t { struct _var_t { char *name; int ptr_level; + expr_t *array; type_t *type; char *tname; attr_t *attrs; + int has_val; + long lval; /* parser-internal */ DECL_LINK(var_t)