Some cleanup for expressions, sanitizing the structure a bit especially for abstract operations with multiple args.
I also found out about named bison variables, implicit (as `$token` referring to `token`), or explicit (as `$name` referring to `token[name]`). I think it would make the rules much more readable so I started using them here. My plan is to add them progressively to the rules, unless there's some good reason not to (like idk how portable they are, if that's something we should be worried about).
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/client.c | 1 - tools/widl/expr.c | 1 - tools/widl/expr.h | 41 ----------------------------------------- tools/widl/header.c | 1 - tools/widl/parser.y | 1 - tools/widl/proxy.c | 1 - tools/widl/typegen.c | 1 - tools/widl/widl.h | 23 +++++++++++++++++++++++ 8 files changed, 23 insertions(+), 47 deletions(-) delete mode 100644 tools/widl/expr.h
diff --git a/tools/widl/client.c b/tools/widl/client.c index 704be91cb78..66dd766a00c 100644 --- a/tools/widl/client.c +++ b/tools/widl/client.c @@ -32,7 +32,6 @@
#include "widltypes.h" #include "typegen.h" -#include "expr.h"
static FILE* client; static int indent = 0; diff --git a/tools/widl/expr.c b/tools/widl/expr.c index e0c56b81089..813fbdab680 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -30,7 +30,6 @@
#include "widl.h" #include "utils.h" -#include "expr.h" #include "header.h" #include "typetree.h" #include "typegen.h" diff --git a/tools/widl/expr.h b/tools/widl/expr.h deleted file mode 100644 index 7b0e1b2c7ba..00000000000 --- a/tools/widl/expr.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Expression Abstract Syntax Tree Functions - * - * Copyright 2002 Ove Kaaven - * Copyright 2006-2008 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -struct expr_loc -{ - const var_t *v; - const char *attr; -}; - -extern expr_t *make_expr(enum expr_type type); -extern expr_t *make_exprl(enum expr_type type, int val); -extern expr_t *make_exprd(enum expr_type type, double val); -extern expr_t *make_exprs(enum expr_type type, char *val); -extern expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr); -extern expr_t *make_expr1(enum expr_type type, expr_t *expr); -extern expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2); -extern expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3); - -extern const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr); -extern int compare_expr(const expr_t *a, const expr_t *b); - -extern void write_expr(FILE *h, const expr_t *e, int brackets, int toplevel, const char *toplevel_prefix, - const type_t *cont_type, const char *local_var_prefix); diff --git a/tools/widl/header.c b/tools/widl/header.c index 624d38094f9..ae85169f630 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -30,7 +30,6 @@ #include "utils.h" #include "parser.h" #include "header.h" -#include "expr.h" #include "typetree.h" #include "typelib.h"
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index bfd41aa9807..703db705c94 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -35,7 +35,6 @@ #include "header.h" #include "typelib.h" #include "typegen.h" -#include "expr.h" #include "typetree.h"
struct _import_t diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index 3d55cd73ee7..188fd09247e 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -31,7 +31,6 @@ #include "parser.h" #include "header.h" #include "typegen.h" -#include "expr.h"
static FILE* proxy; static int indent = 0; diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index b3373ded11d..9d1d5a6ec11 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -35,7 +35,6 @@ #include "typetree.h"
#include "typegen.h" -#include "expr.h"
/* round size up to multiple of alignment */ #define ROUND_SIZE(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 7595cfe7311..d6e82412d4b 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -131,4 +131,27 @@ extern attr_list_t *check_typedef_attrs( attr_list_t *attrs ); extern attr_list_t *check_union_attrs( attr_list_t *attrs ); extern void check_arg_attrs( const var_t *arg );
+/* expr.c */ + +struct expr_loc +{ + const var_t *v; + const char *attr; +}; + +extern expr_t *make_expr( enum expr_type type ); +extern expr_t *make_exprl( enum expr_type type, int val ); +extern expr_t *make_exprd( enum expr_type type, double val ); +extern expr_t *make_exprs( enum expr_type type, char *val ); +extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); +extern expr_t *make_expr1( enum expr_type type, expr_t *expr ); +extern expr_t *make_expr2( enum expr_type type, expr_t *exp1, expr_t *exp2 ); +extern expr_t *make_expr3( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3 ); + +extern const type_t *expr_resolve_type( const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr ); +extern int compare_expr( const expr_t *a, const expr_t *b ); + +extern void write_expr( FILE *h, const expr_t *e, int brackets, int toplevel, const char *toplevel_prefix, + const type_t *cont_type, const char *local_var_prefix ); + #endif
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 813fbdab680..546a3fac445 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -110,22 +110,18 @@ static int is_float_type(const type_t *type)
expr_t *make_expr(enum expr_type type) { - expr_t *e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; - e->ref = NULL; - e->u.lval = 0; - e->is_const = FALSE; - e->cval = 0; return e; }
expr_t *make_exprl(enum expr_type type, int val) { - expr_t *e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; - e->ref = NULL; e->u.lval = val; - e->is_const = FALSE; /* check for numeric constant */ if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) { @@ -139,9 +135,9 @@ expr_t *make_exprl(enum expr_type type, int val)
expr_t *make_exprd(enum expr_type type, double val) { - expr_t *e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; - e->ref = NULL; e->u.dval = val; e->is_const = TRUE; e->cval = val; @@ -150,12 +146,10 @@ expr_t *make_exprd(enum expr_type type, double val)
expr_t *make_exprs(enum expr_type type, char *val) { - expr_t *e; - e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; - e->ref = NULL; e->u.sval = val; - e->is_const = FALSE; /* check for predefined constants */ switch (type) { @@ -198,11 +192,11 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
tref = var->declspec.type;
- e = xmalloc(sizeof(expr_t)); + e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; e->ref = expr; e->u.tref = var->declspec; - e->is_const = FALSE; if (type == EXPR_SIZEOF) { /* only do this for types that should be the same on all platforms */ @@ -249,12 +243,10 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
expr_t *make_expr1(enum expr_type type, expr_t *expr) { - expr_t *e; - e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; e->ref = expr; - e->u.lval = 0; - e->is_const = FALSE; /* check for compile-time optimization */ if (expr->is_const) { @@ -283,12 +275,11 @@ expr_t *make_expr1(enum expr_type type, expr_t *expr)
expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) { - expr_t *e; - e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; e->ref = expr1; e->u.ext = expr2; - e->is_const = FALSE; /* check for compile-time optimization */ if (expr1->is_const && expr2->is_const) { @@ -371,13 +362,12 @@ expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3) { - expr_t *e; - e = xmalloc(sizeof(expr_t)); + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); e->type = type; e->ref = expr1; e->u.ext = expr2; e->ext2 = expr3; - e->is_const = FALSE; /* check for compile-time optimization */ if (expr1->is_const && expr2->is_const && expr3->is_const) {
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 4 ++-- tools/widl/parser.y | 20 ++++++++++---------- tools/widl/widl.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 546a3fac445..b5417591f13 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -108,11 +108,11 @@ static int is_float_type(const type_t *type) type_basic_get_type(type) == TYPE_BASIC_DOUBLE)); }
-expr_t *make_expr(enum expr_type type) +expr_t *expr_void(void) { expr_t *e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); - e->type = type; + e->type = EXPR_VOID; return e; }
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 703db705c94..e1a68477c79 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -557,13 +557,13 @@ arg: attributes decl_spec m_any_declarator { if ($2->stgclass != STG_NONE && $ } ;
-array: '[' expr ']' { $$ = $2; - if (!$$->is_const || $$->cval <= 0) - error_loc("array dimension is not a positive integer constant\n"); - } - | '[' '*' ']' { $$ = make_expr(EXPR_VOID); } - | '[' ']' { $$ = make_expr(EXPR_VOID); } - ; +array: '[' expr ']' { if (!$expr->is_const) error_loc( "array dimension is not constant\n" ); + if ($expr->cval <= 0) error_loc( "array dimension is not positive\n" ); + $$ = $expr; + } + | '[' '*' ']' { $$ = expr_void(); } + | '[' ']' { $$ = expr_void(); } + ;
m_attributes : %empty { $$ = NULL; } @@ -830,9 +830,9 @@ m_exprs: m_expr { $$ = append_expr( NULL, $1 ); ;
m_expr - : %empty { $$ = make_expr(EXPR_VOID); } - | expr - ; + : %empty { $$ = expr_void(); } + | expr + ;
expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); } diff --git a/tools/widl/widl.h b/tools/widl/widl.h index d6e82412d4b..c84d23bdb29 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -139,7 +139,7 @@ struct expr_loc const char *attr; };
-extern expr_t *make_expr( enum expr_type type ); +extern expr_t *expr_void(void); extern expr_t *make_exprl( enum expr_type type, int val ); extern expr_t *make_exprd( enum expr_type type, double val ); extern expr_t *make_exprs( enum expr_type type, char *val );
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 4 ++-- tools/widl/parser.y | 2 +- tools/widl/widl.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index b5417591f13..61d3c60405b 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -133,11 +133,11 @@ expr_t *make_exprl(enum expr_type type, int val) return e; }
-expr_t *make_exprd(enum expr_type type, double val) +expr_t *expr_double( double val ) { expr_t *e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); - e->type = type; + e->type = EXPR_DOUBLE; e->u.dval = val; e->is_const = TRUE; e->cval = val; diff --git a/tools/widl/parser.y b/tools/widl/parser.y index e1a68477c79..5cca5491e89 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -836,7 +836,7 @@ m_expr
expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); } - | aDOUBLE { $$ = make_exprd(EXPR_DOUBLE, $1); } + | aDOUBLE { $$ = expr_double( $aDOUBLE ); } | tFALSE { $$ = make_exprl(EXPR_TRUEFALSE, 0); } | tNULL { $$ = make_exprl(EXPR_NUM, 0); } | tTRUE { $$ = make_exprl(EXPR_TRUEFALSE, 1); } diff --git a/tools/widl/widl.h b/tools/widl/widl.h index c84d23bdb29..97c2acc8923 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -141,7 +141,7 @@ struct expr_loc
extern expr_t *expr_void(void); extern expr_t *make_exprl( enum expr_type type, int val ); -extern expr_t *make_exprd( enum expr_type type, double val ); +extern expr_t *expr_double( double val ); extern expr_t *make_exprs( enum expr_type type, char *val ); extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); extern expr_t *make_expr1( enum expr_type type, expr_t *expr );
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 2 +- tools/widl/parser.y | 24 +++++++++++++++++------- tools/widl/widl.h | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 61d3c60405b..4ee832f2ae5 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -144,7 +144,7 @@ expr_t *expr_double( double val ) return e; }
-expr_t *make_exprs(enum expr_type type, char *val) +expr_t *expr_str( enum expr_type type, char *val ) { expr_t *e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 5cca5491e89..4f9097aa957 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -632,7 +632,11 @@ composable_attr
deprecated_attr : aSTRING ',' aIDENTIFIER ',' contract_req - { $$ = make_expr3( EXPR_MEMBER, make_exprs( EXPR_STRLIT, $1 ), make_exprs( EXPR_IDENTIFIER, $3 ), $5 ); } + { + expr_t *message = expr_str( EXPR_STRLIT, $aSTRING ); + expr_t *action = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); + $$ = make_expr3( EXPR_MEMBER, message, action, $contract_req ); + } ;
attribute @@ -840,10 +844,10 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | tFALSE { $$ = make_exprl(EXPR_TRUEFALSE, 0); } | tNULL { $$ = make_exprl(EXPR_NUM, 0); } | tTRUE { $$ = make_exprl(EXPR_TRUEFALSE, 1); } - | aSTRING { $$ = make_exprs(EXPR_STRLIT, $1); } - | aWSTRING { $$ = make_exprs(EXPR_WSTRLIT, $1); } - | aSQSTRING { $$ = make_exprs(EXPR_CHARCONST, $1); } - | aIDENTIFIER { $$ = make_exprs(EXPR_IDENTIFIER, $1); } + | aSTRING { $$ = expr_str( EXPR_STRLIT, $aSTRING ); } + | aWSTRING { $$ = expr_str( EXPR_WSTRLIT, $aWSTRING ); } + | aSQSTRING { $$ = expr_str( EXPR_CHARCONST, $aSQSTRING ); } + | aIDENTIFIER { $$ = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); } | expr '?' expr ':' expr { $$ = make_expr3(EXPR_COND, $1, $3, $5); } | expr LOGICALOR expr { $$ = make_expr2(EXPR_LOGOR, $1, $3); } | expr LOGICALAND expr { $$ = make_expr2(EXPR_LOGAND, $1, $3); } @@ -869,8 +873,14 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); } | '&' expr %prec ADDRESSOF { $$ = make_expr1(EXPR_ADDRESSOF, $2); } | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } - | expr MEMBERPTR aIDENTIFIER { $$ = make_expr2(EXPR_MEMBER, make_expr1(EXPR_PPTR, $1), make_exprs(EXPR_IDENTIFIER, $3)); } - | expr '.' aIDENTIFIER { $$ = make_expr2(EXPR_MEMBER, $1, make_exprs(EXPR_IDENTIFIER, $3)); } + | expr[obj] MEMBERPTR aIDENTIFIER { + expr_t *member = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); + $$ = make_expr2( EXPR_MEMBER, make_expr1( EXPR_PPTR, $obj ), member ); + } + | expr[obj] '.' aIDENTIFIER { + expr_t *member = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); + $$ = make_expr2( EXPR_MEMBER, $obj, member ); + } | '(' unqualified_decl_spec m_abstract_declarator ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, declare_var(NULL, $2, $3, 0), $5); free($2); free($3); } | tSIZEOF '(' unqualified_decl_spec m_abstract_declarator ')' diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 97c2acc8923..b747e17e10e 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -142,7 +142,7 @@ struct expr_loc extern expr_t *expr_void(void); extern expr_t *make_exprl( enum expr_type type, int val ); extern expr_t *expr_double( double val ); -extern expr_t *make_exprs( enum expr_type type, char *val ); +extern expr_t *expr_str( enum expr_type type, char *val ); extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); extern expr_t *make_expr1( enum expr_type type, expr_t *expr ); extern expr_t *make_expr2( enum expr_type type, expr_t *exp1, expr_t *exp2 );
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 2 +- tools/widl/parser.y | 50 +++++++++++++++++++++++---------------------- tools/widl/widl.h | 2 +- 3 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 4ee832f2ae5..37511727372 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -116,7 +116,7 @@ expr_t *expr_void(void) return e; }
-expr_t *make_exprl(enum expr_type type, int val) +expr_t *expr_int( enum expr_type type, int val ) { expr_t *e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 4f9097aa957..9e8a0d88d1c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -595,12 +595,13 @@ contract_ver: ;
contract_req - : decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICONTRACT) - error_loc("type %s is not an apicontract\n", $1->type->name); - $$ = make_exprl(EXPR_NUM, $3); - $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$); - } - ; + : decl_spec ',' contract_ver { + expr_t *contract = expr_int( EXPR_NUM, $contract_ver ); + if ($decl_spec->type->type_type != TYPE_APICONTRACT) + error_loc( "type %s is not an apicontract\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_GTREQL, declare_var( NULL, $decl_spec, make_declarator( NULL ), 0 ), contract ); + } + ;
static_attr : decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) @@ -796,21 +797,22 @@ enums | enum_list ;
-enum_list: enum { if (!$1->eval) - $1->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */); - $$ = append_var( NULL, $1 ); - } - | enum_list ',' enum { if (!$3->eval) +enum_list: enum { + if (!$enum->eval) $enum->eval = expr_int( EXPR_NUM, 0 /* default for first enum entry */ ); + $$ = append_var( NULL, $enum ); + } + | enum_list[list] ',' enum { + if (!$enum->eval) { - var_t *last = LIST_ENTRY( list_tail($$), var_t, entry ); - enum expr_type type = EXPR_NUM; - if (last->eval->type == EXPR_HEXNUM) type = EXPR_HEXNUM; - if (last->eval->cval + 1 < 0) type = EXPR_HEXNUM; - $3->eval = make_exprl(type, last->eval->cval + 1); + var_t *last = LIST_ENTRY( list_tail( $list ), var_t, entry ); + enum expr_type type = EXPR_NUM; + if (last->eval->type == EXPR_HEXNUM) type = EXPR_HEXNUM; + if (last->eval->cval + 1 < 0) type = EXPR_HEXNUM; + $enum->eval = expr_int( type, last->eval->cval + 1 ); } - $$ = append_var( $1, $3 ); - } - ; + $$ = append_var( $list, $enum ); + } + ;
enum_member: m_attributes ident { $$ = $2; $$->attrs = check_enum_member_attrs($1); @@ -838,12 +840,12 @@ m_expr | expr ;
-expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } - | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); } +expr: aNUM { $$ = expr_int( EXPR_NUM, $aNUM ); } + | aHEXNUM { $$ = expr_int( EXPR_HEXNUM, $aHEXNUM ); } | aDOUBLE { $$ = expr_double( $aDOUBLE ); } - | tFALSE { $$ = make_exprl(EXPR_TRUEFALSE, 0); } - | tNULL { $$ = make_exprl(EXPR_NUM, 0); } - | tTRUE { $$ = make_exprl(EXPR_TRUEFALSE, 1); } + | tFALSE { $$ = expr_int( EXPR_TRUEFALSE, 0 ); } + | tNULL { $$ = expr_int( EXPR_NUM, 0 ); } + | tTRUE { $$ = expr_int( EXPR_TRUEFALSE, 1 ); } | aSTRING { $$ = expr_str( EXPR_STRLIT, $aSTRING ); } | aWSTRING { $$ = expr_str( EXPR_WSTRLIT, $aWSTRING ); } | aSQSTRING { $$ = expr_str( EXPR_CHARCONST, $aSQSTRING ); } diff --git a/tools/widl/widl.h b/tools/widl/widl.h index b747e17e10e..582e34fc43f 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -140,7 +140,7 @@ struct expr_loc };
extern expr_t *expr_void(void); -extern expr_t *make_exprl( enum expr_type type, int val ); +extern expr_t *expr_int( enum expr_type type, int val ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr );
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 36 +++++++++--------------------------- tools/widl/parser.y | 23 +++++++++++------------ tools/widl/widl.h | 2 +- tools/widl/widltypes.h | 5 ++--- tools/widl/write_msft.c | 5 ++--- 5 files changed, 25 insertions(+), 46 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 37511727372..6b60d984a1a 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -116,20 +116,15 @@ expr_t *expr_void(void) return e; }
-expr_t *expr_int( enum expr_type type, int val ) +expr_t *expr_int( int val, const char *text ) { expr_t *e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); - e->type = type; + e->text = text; + e->type = EXPR_INT; e->u.lval = val; - /* check for numeric constant */ - if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) - { - /* make sure true/false value is valid */ - assert(type != EXPR_TRUEFALSE || val == 0 || val == 1); - e->is_const = TRUE; - e->cval = val; - } + e->is_const = TRUE; + e->cval = val; return e; }
@@ -503,9 +498,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc { case EXPR_VOID: break; - case EXPR_HEXNUM: - case EXPR_NUM: - case EXPR_TRUEFALSE: + case EXPR_INT: result.is_temporary = FALSE; result.type = type_new_int(TYPE_BASIC_INT, 0); break; @@ -680,21 +673,12 @@ void write_expr(FILE *h, const expr_t *e, int brackets, { case EXPR_VOID: break; - case EXPR_NUM: - fprintf(h, "%u", e->u.lval); - break; - case EXPR_HEXNUM: - fprintf(h, "0x%x", e->u.lval); + case EXPR_INT: + fprintf(h, "%s", e->text); break; case EXPR_DOUBLE: fprintf(h, "%#.15g", e->u.dval); break; - case EXPR_TRUEFALSE: - if (e->u.lval == 0) - fprintf(h, "FALSE"); - else - fprintf(h, "TRUE"); - break; case EXPR_IDENTIFIER: if (toplevel && toplevel_prefix && cont_type) { @@ -857,9 +841,7 @@ int compare_expr(const expr_t *a, const expr_t *b)
switch (a->type) { - case EXPR_NUM: - case EXPR_HEXNUM: - case EXPR_TRUEFALSE: + case EXPR_INT: return a->u.lval - b->u.lval; case EXPR_DOUBLE: return a->u.dval - b->u.dval; diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 9e8a0d88d1c..bf472a646fb 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -596,7 +596,7 @@ contract_ver:
contract_req : decl_spec ',' contract_ver { - expr_t *contract = expr_int( EXPR_NUM, $contract_ver ); + expr_t *contract = expr_int( $3, strmake( "%u", $3 ) ); if ($decl_spec->type->type_type != TYPE_APICONTRACT) error_loc( "type %s is not an apicontract\n", $decl_spec->type->name ); $$ = make_exprt( EXPR_GTREQL, declare_var( NULL, $decl_spec, make_declarator( NULL ), 0 ), contract ); @@ -798,17 +798,16 @@ enums ;
enum_list: enum { - if (!$enum->eval) $enum->eval = expr_int( EXPR_NUM, 0 /* default for first enum entry */ ); + if (!$enum->eval) $enum->eval = expr_int( 0, "0" ); $$ = append_var( NULL, $enum ); } | enum_list[list] ',' enum { if (!$enum->eval) { - var_t *last = LIST_ENTRY( list_tail( $list ), var_t, entry ); - enum expr_type type = EXPR_NUM; - if (last->eval->type == EXPR_HEXNUM) type = EXPR_HEXNUM; - if (last->eval->cval + 1 < 0) type = EXPR_HEXNUM; - $enum->eval = expr_int( type, last->eval->cval + 1 ); + expr_t *last = LIST_ENTRY( list_tail( $list ), var_t, entry )->eval; + const char *fmt = last->cval + 1 < 0 ? "0x%x" : "%u"; + if (last->text && last->text[1] == 'x') fmt = "0x%x"; + $enum->eval = expr_int( last->cval + 1, strmake( fmt, last->cval + 1 ) ); } $$ = append_var( $list, $enum ); } @@ -840,12 +839,12 @@ m_expr | expr ;
-expr: aNUM { $$ = expr_int( EXPR_NUM, $aNUM ); } - | aHEXNUM { $$ = expr_int( EXPR_HEXNUM, $aHEXNUM ); } +expr: aNUM { $$ = expr_int( $aNUM, strmake( "%u", $aNUM ) ); } + | aHEXNUM { $$ = expr_int( $aHEXNUM, strmake( "0x%x", $aHEXNUM ) ); } | aDOUBLE { $$ = expr_double( $aDOUBLE ); } - | tFALSE { $$ = expr_int( EXPR_TRUEFALSE, 0 ); } - | tNULL { $$ = expr_int( EXPR_NUM, 0 ); } - | tTRUE { $$ = expr_int( EXPR_TRUEFALSE, 1 ); } + | tFALSE { $$ = expr_int( 0, "FALSE" ); } + | tNULL { $$ = expr_int( 0, "NULL" ); } + | tTRUE { $$ = expr_int( 1, "TRUE" ); } | aSTRING { $$ = expr_str( EXPR_STRLIT, $aSTRING ); } | aWSTRING { $$ = expr_str( EXPR_WSTRLIT, $aWSTRING ); } | aSQSTRING { $$ = expr_str( EXPR_CHARCONST, $aSQSTRING ); } diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 582e34fc43f..6efb15a85ba 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -140,7 +140,7 @@ struct expr_loc };
extern expr_t *expr_void(void); -extern expr_t *expr_int( enum expr_type type, int val ); +extern expr_t *expr_int( int val, const char *text ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 1a26bb77cad..544461740de 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -189,8 +189,7 @@ enum attr_type enum expr_type { EXPR_VOID, - EXPR_NUM, - EXPR_HEXNUM, + EXPR_INT, EXPR_DOUBLE, EXPR_IDENTIFIER, EXPR_NEG, @@ -207,7 +206,6 @@ enum expr_type EXPR_AND, EXPR_OR, EXPR_COND, - EXPR_TRUEFALSE, EXPR_ADDRESSOF, EXPR_MEMBER, EXPR_ARRAY, @@ -363,6 +361,7 @@ struct _expr_t { int cval; /* parser-internal */ struct list entry; + const char *text; };
struct _attr_custdata_t { diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index ce99c23f16a..bd7607d6cc7 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1234,7 +1234,7 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e case EXPR_DOUBLE: vt = VT_R4; break; - case EXPR_NUM: + case EXPR_INT: vt = VT_I4; break; default: @@ -1296,8 +1296,7 @@ static void set_custdata_attr(msft_typelib_t *typelib, attr_custdata_t *custdata case EXPR_WSTRLIT: set_custdata(typelib, &custdata->id, VT_BSTR, custdata->pval->u.sval, offset); break; - case EXPR_HEXNUM: - case EXPR_NUM: + case EXPR_INT: set_custdata(typelib, &custdata->id, VT_I4, &custdata->pval->u.lval, offset); break; default:
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 165 ++++++++++++++++------------------------- tools/widl/header.c | 8 +- tools/widl/parser.y | 64 ++++++++-------- tools/widl/typegen.c | 18 ++--- tools/widl/widl.h | 4 +- tools/widl/widltypes.h | 6 +- 6 files changed, 114 insertions(+), 151 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 6b60d984a1a..8ea7f932771 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -190,8 +190,8 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); e->type = type; - e->ref = expr; - e->u.tref = var->declspec; + e->u.args[0] = expr; + e->tref = var->declspec; if (type == EXPR_SIZEOF) { /* only do this for types that should be the same on all platforms */ @@ -236,51 +236,37 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) return e; }
-expr_t *make_expr1(enum expr_type type, expr_t *expr) +expr_t *expr_op( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3 ) { expr_t *e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); e->type = type; - e->ref = expr; + e->u.args[0] = expr1; + e->u.args[1] = expr2; + e->u.args[2] = expr3; + + e->is_const = TRUE; + if (expr1 && !expr1->is_const) e->is_const = FALSE; + if (expr2 && !expr2->is_const) e->is_const = FALSE; + if (expr3 && !expr3->is_const) e->is_const = FALSE; + /* check for compile-time optimization */ - if (expr->is_const) + if (e->is_const) { - e->is_const = TRUE; switch (type) { case EXPR_LOGNOT: - e->cval = !expr->cval; + e->cval = !expr1->cval; break; case EXPR_POS: - e->cval = +expr->cval; + e->cval = +expr1->cval; break; case EXPR_NEG: - e->cval = -expr->cval; + e->cval = -expr1->cval; break; case EXPR_NOT: - e->cval = ~expr->cval; + e->cval = ~expr1->cval; break; - default: - e->is_const = FALSE; - break; - } - } - return e; -} - -expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) -{ - expr_t *e = xmalloc( sizeof(expr_t) ); - memset( e, 0, sizeof(*e) ); - e->type = type; - e->ref = expr1; - e->u.ext = expr2; - /* check for compile-time optimization */ - if (expr1->is_const && expr2->is_const) - { - e->is_const = TRUE; - switch (type) - { case EXPR_ADD: e->cval = expr1->cval + expr2->cval; break; @@ -347,28 +333,6 @@ expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) case EXPR_LESSEQL: e->cval = expr1->cval <= expr2->cval; break; - default: - e->is_const = FALSE; - break; - } - } - return e; -} - -expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3) -{ - expr_t *e = xmalloc( sizeof(expr_t) ); - memset( e, 0, sizeof(*e) ); - e->type = type; - e->ref = expr1; - e->u.ext = expr2; - e->ext2 = expr3; - /* check for compile-time optimization */ - if (expr1->is_const && expr2->is_const && expr3->is_const) - { - e->is_const = TRUE; - switch (type) - { case EXPR_COND: e->cval = expr1->cval ? expr2->cval : expr3->cval; break; @@ -377,6 +341,7 @@ expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *ex break; } } + return e; }
@@ -530,25 +495,25 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc break; } case EXPR_LOGNOT: - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); check_scalar_type(expr_loc, cont_type, result.type); result.is_variable = FALSE; result.is_temporary = FALSE; result.type = type_new_int(TYPE_BASIC_INT, 0); break; case EXPR_NOT: - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); check_integer_type(expr_loc, cont_type, result.type); result.is_variable = FALSE; break; case EXPR_POS: case EXPR_NEG: - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); check_arithmetic_type(expr_loc, cont_type, result.type); result.is_variable = FALSE; break; case EXPR_ADDRESSOF: - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); if (!result.is_variable) error_at( &expr_loc->v->where, "address-of operator applied to non-variable type in expression%s%s\n", expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); @@ -557,7 +522,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc result.type = type_new_pointer(result.type); break; case EXPR_PPTR: - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); if (result.type && is_ptr(result.type)) result.type = type_pointer_get_ref_type(result.type); else if(result.type && is_array(result.type) @@ -568,8 +533,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); break; case EXPR_CAST: - result = resolve_expression(expr_loc, cont_type, e->ref); - result.type = e->u.tref.type; + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); + result.type = e->tref.type; break; case EXPR_SIZEOF: result.is_temporary = FALSE; @@ -587,9 +552,9 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc case EXPR_XOR: { struct expression_type result_right; - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); result.is_variable = FALSE; - result_right = resolve_expression(expr_loc, cont_type, e->u.ext); + result_right = resolve_expression( expr_loc, cont_type, e->u.args[1] ); /* FIXME: these checks aren't strict enough for some of the operators */ check_scalar_type(expr_loc, cont_type, result.type); check_scalar_type(expr_loc, cont_type, result_right.type); @@ -605,8 +570,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc case EXPR_LESSEQL: { struct expression_type result_left, result_right; - result_left = resolve_expression(expr_loc, cont_type, e->ref); - result_right = resolve_expression(expr_loc, cont_type, e->u.ext); + result_left = resolve_expression( expr_loc, cont_type, e->u.args[0] ); + result_right = resolve_expression( expr_loc, cont_type, e->u.args[1] ); check_scalar_type(expr_loc, cont_type, result_left.type); check_scalar_type(expr_loc, cont_type, result_right.type); result.is_temporary = FALSE; @@ -614,9 +579,9 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc break; } case EXPR_MEMBER: - result = resolve_expression(expr_loc, cont_type, e->ref); - if (result.type && is_valid_member_operand(result.type)) - result = resolve_expression(expr_loc, result.type, e->u.ext); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); + if (result.type && is_valid_member_operand( result.type )) + result = resolve_expression( expr_loc, result.type, e->u.args[1] ); else error_at( &expr_loc->v->where, "'.' or '->' operator applied to a type that isn't a structure, union or enumeration in expression%s%s\n", expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); @@ -624,10 +589,10 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc case EXPR_COND: { struct expression_type result_first, result_second, result_third; - result_first = resolve_expression(expr_loc, cont_type, e->ref); + result_first = resolve_expression( expr_loc, cont_type, e->u.args[0] ); check_scalar_type(expr_loc, cont_type, result_first.type); - result_second = resolve_expression(expr_loc, cont_type, e->u.ext); - result_third = resolve_expression(expr_loc, cont_type, e->ext2); + result_second = resolve_expression( expr_loc, cont_type, e->u.args[1] ); + result_third = resolve_expression( expr_loc, cont_type, e->u.args[2] ); check_scalar_type(expr_loc, cont_type, result_second.type); check_scalar_type(expr_loc, cont_type, result_third.type); if (!is_ptr( result_second.type ) ^ !is_ptr( result_third.type )) @@ -638,12 +603,12 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc break; } case EXPR_ARRAY: - result = resolve_expression(expr_loc, cont_type, e->ref); + result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); if (result.type && is_array(result.type)) { struct expression_type index_result; result.type = type_array_get_element_type(result.type); - index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext); + index_result = resolve_expression( expr_loc, cont_type /* FIXME */, e->u.args[1] ); if (!index_result.type || !is_integer_type( index_result.type )) error_at( &expr_loc->v->where, "array subscript not of integral type in expression%s%s\n", expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); @@ -703,37 +668,37 @@ void write_expr(FILE *h, const expr_t *e, int brackets, break; case EXPR_LOGNOT: fprintf(h, "!"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_NOT: fprintf(h, "~"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_POS: fprintf(h, "+"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_NEG: fprintf(h, "-"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_ADDRESSOF: fprintf(h, "&"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_PPTR: fprintf(h, "*"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_CAST: fprintf(h, "("); - write_type_decl(h, &e->u.tref, NULL); + write_type_decl( h, &e->tref, NULL ); fprintf(h, ")"); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type_decl(h, &e->u.tref, NULL); + write_type_decl( h, &e->tref, NULL ); fprintf(h, ")"); break; case EXPR_SHL: @@ -755,7 +720,7 @@ void write_expr(FILE *h, const expr_t *e, int brackets, case EXPR_GTREQL: case EXPR_LESSEQL: if (brackets) fprintf(h, "("); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); switch (e->type) { case EXPR_SHL: fprintf(h, " << "); break; @@ -778,38 +743,38 @@ void write_expr(FILE *h, const expr_t *e, int brackets, case EXPR_LESSEQL: fprintf(h, " <= "); break; default: break; } - write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[1], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); if (brackets) fprintf(h, ")"); break; case EXPR_MEMBER: if (brackets) fprintf(h, "("); - if (e->ref->type == EXPR_PPTR) + if (e->u.args[0]->type == EXPR_PPTR) { - write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0]->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); fprintf(h, "->"); } else { - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); fprintf(h, "."); } - write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, ""); + write_expr( h, e->u.args[1], 1, 0, toplevel_prefix, cont_type, "" ); if (brackets) fprintf(h, ")"); break; case EXPR_COND: if (brackets) fprintf(h, "("); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); fprintf(h, " ? "); - write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[1], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); fprintf(h, " : "); - write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[2], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); if (brackets) fprintf(h, ")"); break; case EXPR_ARRAY: if (brackets) fprintf(h, "("); - write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); fprintf(h, "["); - write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix); + write_expr( h, e->u.args[1], 1, 1, toplevel_prefix, cont_type, local_var_prefix ); fprintf(h, "]"); if (brackets) fprintf(h, ")"); break; @@ -851,13 +816,13 @@ int compare_expr(const expr_t *a, const expr_t *b) case EXPR_CHARCONST: return strcmp(a->u.sval, b->u.sval); case EXPR_COND: - ret = compare_expr(a->ref, b->ref); + ret = compare_expr( a->u.args[0], b->u.args[0] ); if (ret != 0) return ret; - ret = compare_expr(a->u.ext, b->u.ext); + ret = compare_expr( a->u.args[1], b->u.args[1] ); if (ret != 0) return ret; - return compare_expr(a->ext2, b->ext2); + return compare_expr( a->u.args[2], b->u.args[2] ); case EXPR_OR: case EXPR_AND: case EXPR_ADD: @@ -878,12 +843,12 @@ int compare_expr(const expr_t *a, const expr_t *b) case EXPR_LESS: case EXPR_GTREQL: case EXPR_LESSEQL: - ret = compare_expr(a->ref, b->ref); + ret = compare_expr( a->u.args[0], b->u.args[0] ); if (ret != 0) return ret; - return compare_expr(a->u.ext, b->u.ext); + return compare_expr( a->u.args[1], b->u.args[1] ); case EXPR_CAST: - ret = compare_type(a->u.tref.type, b->u.tref.type); + ret = compare_type( a->tref.type, b->tref.type ); if (ret != 0) return ret; /* Fall through. */ @@ -893,9 +858,9 @@ int compare_expr(const expr_t *a, const expr_t *b) case EXPR_ADDRESSOF: case EXPR_LOGNOT: case EXPR_POS: - return compare_expr(a->ref, b->ref); + return compare_expr( a->u.args[0], b->u.args[0] ); case EXPR_SIZEOF: - return compare_type(a->u.tref.type, b->u.tref.type); + return compare_type( a->tref.type, b->tref.type ); case EXPR_VOID: return 0; } diff --git a/tools/widl/header.c b/tools/widl/header.c index ae85169f630..006e5a274a0 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1581,8 +1581,8 @@ static void write_apicontract_guard_start(FILE *header, const expr_t *expr) char *name; int ver; if (!winrt_mode) return; - type = expr->u.tref.type; - ver = expr->ref->u.lval; + type = expr->tref.type; + ver = expr->u.args[0]->u.lval; name = format_apicontract_macro(type); fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); free(name); @@ -1594,8 +1594,8 @@ static void write_apicontract_guard_end(FILE *header, const expr_t *expr) char *name; int ver; if (!winrt_mode) return; - type = expr->u.tref.type; - ver = expr->ref->u.lval; + type = expr->tref.type; + ver = expr->u.args[0]->u.lval; name = format_apicontract_macro(type); fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); free(name); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index bf472a646fb..9805e33d33d 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -636,7 +636,7 @@ deprecated_attr { expr_t *message = expr_str( EXPR_STRLIT, $aSTRING ); expr_t *action = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); - $$ = make_expr3( EXPR_MEMBER, message, action, $contract_req ); + $$ = expr_op( EXPR_MEMBER, message, action, $contract_req ); } ;
@@ -849,46 +849,48 @@ expr: aNUM { $$ = expr_int( $aNUM, strmake( | aWSTRING { $$ = expr_str( EXPR_WSTRLIT, $aWSTRING ); } | aSQSTRING { $$ = expr_str( EXPR_CHARCONST, $aSQSTRING ); } | aIDENTIFIER { $$ = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); } - | expr '?' expr ':' expr { $$ = make_expr3(EXPR_COND, $1, $3, $5); } - | expr LOGICALOR expr { $$ = make_expr2(EXPR_LOGOR, $1, $3); } - | expr LOGICALAND expr { $$ = make_expr2(EXPR_LOGAND, $1, $3); } - | expr '|' expr { $$ = make_expr2(EXPR_OR , $1, $3); } - | expr '^' expr { $$ = make_expr2(EXPR_XOR, $1, $3); } - | expr '&' expr { $$ = make_expr2(EXPR_AND, $1, $3); } - | expr EQUALITY expr { $$ = make_expr2(EXPR_EQUALITY, $1, $3); } - | expr INEQUALITY expr { $$ = make_expr2(EXPR_INEQUALITY, $1, $3); } - | expr '>' expr { $$ = make_expr2(EXPR_GTR, $1, $3); } - | expr '<' expr { $$ = make_expr2(EXPR_LESS, $1, $3); } - | expr GREATEREQUAL expr { $$ = make_expr2(EXPR_GTREQL, $1, $3); } - | expr LESSEQUAL expr { $$ = make_expr2(EXPR_LESSEQL, $1, $3); } - | expr SHL expr { $$ = make_expr2(EXPR_SHL, $1, $3); } - | expr SHR expr { $$ = make_expr2(EXPR_SHR, $1, $3); } - | expr '+' expr { $$ = make_expr2(EXPR_ADD, $1, $3); } - | expr '-' expr { $$ = make_expr2(EXPR_SUB, $1, $3); } - | expr '%' expr { $$ = make_expr2(EXPR_MOD, $1, $3); } - | expr '*' expr { $$ = make_expr2(EXPR_MUL, $1, $3); } - | expr '/' expr { $$ = make_expr2(EXPR_DIV, $1, $3); } - | '!' expr { $$ = make_expr1(EXPR_LOGNOT, $2); } - | '~' expr { $$ = make_expr1(EXPR_NOT, $2); } - | '+' expr %prec POS { $$ = make_expr1(EXPR_POS, $2); } - | '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); } - | '&' expr %prec ADDRESSOF { $$ = make_expr1(EXPR_ADDRESSOF, $2); } - | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } + | expr[cond] '?' expr[true] ':' expr[false] + { $$ = expr_op( EXPR_COND, $cond, $true, $false ); } + | expr[op1] LOGICALOR expr[op2] { $$ = expr_op( EXPR_LOGOR, $op1, $op2, NULL ); } + | expr[op1] LOGICALAND expr[op2] { $$ = expr_op( EXPR_LOGAND, $op1, $op2, NULL ); } + | expr[op1] '|' expr[op2] { $$ = expr_op( EXPR_OR , $op1, $op2, NULL ); } + | expr[op1] '^' expr[op2] { $$ = expr_op( EXPR_XOR, $op1, $op2, NULL ); } + | expr[op1] '&' expr[op2] { $$ = expr_op( EXPR_AND, $op1, $op2, NULL ); } + | expr[op1] EQUALITY expr[op2] { $$ = expr_op( EXPR_EQUALITY, $op1, $op2, NULL ); } + | expr[op1] INEQUALITY expr[op2] { $$ = expr_op( EXPR_INEQUALITY, $op1, $op2, NULL ); } + | expr[op1] '>' expr[op2] { $$ = expr_op( EXPR_GTR, $op1, $op2, NULL ); } + | expr[op1] '<' expr[op2] { $$ = expr_op( EXPR_LESS, $op1, $op2, NULL ); } + | expr[op1] GREATEREQUAL expr[op2] { $$ = expr_op( EXPR_GTREQL, $op1, $op2, NULL ); } + | expr[op1] LESSEQUAL expr[op2] { $$ = expr_op( EXPR_LESSEQL, $op1, $op2, NULL ); } + | expr[op1] SHL expr[op2] { $$ = expr_op( EXPR_SHL, $op1, $op2, NULL ); } + | expr[op1] SHR expr[op2] { $$ = expr_op( EXPR_SHR, $op1, $op2, NULL ); } + | expr[op1] '+' expr[op2] { $$ = expr_op( EXPR_ADD, $op1, $op2, NULL ); } + | expr[op1] '-' expr[op2] { $$ = expr_op( EXPR_SUB, $op1, $op2, NULL ); } + | expr[op1] '%' expr[op2] { $$ = expr_op( EXPR_MOD, $op1, $op2, NULL ); } + | expr[op1] '*' expr[op2] { $$ = expr_op( EXPR_MUL, $op1, $op2, NULL ); } + | expr[op1] '/' expr[op2] { $$ = expr_op( EXPR_DIV, $op1, $op2, NULL ); } + | '!' expr[op] { $$ = expr_op( EXPR_LOGNOT, $op, NULL, NULL ); } + | '~' expr[op] { $$ = expr_op( EXPR_NOT, $op, NULL, NULL ); } + | '+' expr[op] %prec POS { $$ = expr_op( EXPR_POS, $op, NULL, NULL ); } + | '-' expr[op] %prec NEG { $$ = expr_op( EXPR_NEG, $op, NULL, NULL ); } + | '&' expr[op] %prec ADDRESSOF { $$ = expr_op( EXPR_ADDRESSOF, $op, NULL, NULL ); } + | '*' expr[op] %prec PPTR { $$ = expr_op( EXPR_PPTR, $op, NULL, NULL ); } | expr[obj] MEMBERPTR aIDENTIFIER { expr_t *member = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); - $$ = make_expr2( EXPR_MEMBER, make_expr1( EXPR_PPTR, $obj ), member ); + expr_t *deref = expr_op( EXPR_PPTR, $obj, NULL, NULL ); + $$ = expr_op( EXPR_MEMBER, deref, member, NULL ); } | expr[obj] '.' aIDENTIFIER { expr_t *member = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); - $$ = make_expr2( EXPR_MEMBER, $obj, member ); + $$ = expr_op( EXPR_MEMBER, $obj, member, NULL ); } | '(' unqualified_decl_spec m_abstract_declarator ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, declare_var(NULL, $2, $3, 0), $5); free($2); free($3); } | tSIZEOF '(' unqualified_decl_spec m_abstract_declarator ')' { $$ = make_exprt(EXPR_SIZEOF, declare_var(NULL, $3, $4, 0), NULL); free($3); free($4); } - | expr '[' expr ']' { $$ = make_expr2(EXPR_ARRAY, $1, $3); } - | '(' expr ')' { $$ = $2; } - ; + | expr[array] '[' expr[index] ']' { $$ = expr_op( EXPR_ARRAY, $array, $index, NULL ); } + | '(' expr ')' { $$ = $2; } + ;
expr_list_int_const: expr_int_const { $$ = append_expr( NULL, $1 ); } | expr_list_int_const ',' expr_int_const { $$ = append_expr( $1, $3 ); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 9d1d5a6ec11..d79fb78f301 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -1618,34 +1618,34 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, switch (subexpr->type) { case EXPR_PPTR: - subexpr = subexpr->ref; + subexpr = subexpr->u.args[0]; operator_type = FC_DEREFERENCE; break; case EXPR_DIV: - if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2)) + if (subexpr->u.args[1]->is_const && (subexpr->u.args[1]->cval == 2)) { - subexpr = subexpr->ref; + subexpr = subexpr->u.args[0]; operator_type = FC_DIV_2; } break; case EXPR_MUL: - if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2)) + if (subexpr->u.args[1]->is_const && (subexpr->u.args[1]->cval == 2)) { - subexpr = subexpr->ref; + subexpr = subexpr->u.args[0]; operator_type = FC_MULT_2; } break; case EXPR_SUB: - if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1)) + if (subexpr->u.args[1]->is_const && (subexpr->u.args[1]->cval == 1)) { - subexpr = subexpr->ref; + subexpr = subexpr->u.args[0]; operator_type = FC_SUB_1; } break; case EXPR_ADD: - if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1)) + if (subexpr->u.args[1]->is_const && (subexpr->u.args[1]->cval == 1)) { - subexpr = subexpr->ref; + subexpr = subexpr->u.args[0]; operator_type = FC_ADD_1; } break; diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 6efb15a85ba..2bd2d1b8a9d 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -144,9 +144,7 @@ extern expr_t *expr_int( int val, const char *text ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); -extern expr_t *make_expr1( enum expr_type type, expr_t *expr ); -extern expr_t *make_expr2( enum expr_type type, expr_t *exp1, expr_t *exp2 ); -extern expr_t *make_expr3( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3 ); +extern expr_t *expr_op( enum expr_type type, expr_t *arg0, expr_t *arg1, expr_t *arg2 );
extern const type_t *expr_resolve_type( const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr ); extern int compare_expr( const expr_t *a, const expr_t *b ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 544461740de..322c6084f26 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -348,15 +348,13 @@ struct _attr_t {
struct _expr_t { enum expr_type type; - const expr_t *ref; union { int lval; double dval; const char *sval; - const expr_t *ext; - decl_spec_t tref; + const expr_t *args[3]; } u; - const expr_t *ext2; + decl_spec_t tref; int is_const; int cval; /* parser-internal */
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 40 +++++++++++++++++++---------- tools/widl/header.c | 8 +++--- tools/widl/parser.y | 58 ++++++++++++++++++++++++++++-------------- tools/widl/widl.h | 3 ++- tools/widl/widltypes.h | 3 ++- 5 files changed, 74 insertions(+), 38 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 8ea7f932771..36f5d769d1a 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -116,6 +116,16 @@ expr_t *expr_void(void) return e; }
+expr_t *expr_decl( decl_spec_t *decl ) +{ + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); + e->type = EXPR_DECL; + e->u.decl = decl; + e->is_const = TRUE; + return e; +} + expr_t *expr_int( int val, const char *text ) { expr_t *e = xmalloc( sizeof(expr_t) ); @@ -177,21 +187,21 @@ expr_t *expr_str( enum expr_type type, char *val ) return e; }
-expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) +expr_t *make_exprt(enum expr_type type, expr_t *decl, expr_t *expr) { expr_t *e; type_t *tref;
- if (var->declspec.stgclass != STG_NONE && var->declspec.stgclass != STG_REGISTER) + if (decl->u.decl->stgclass != STG_NONE && decl->u.decl->stgclass != STG_REGISTER) error_loc("invalid storage class for type expression\n");
- tref = var->declspec.type; + tref = decl->u.decl->type;
e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); e->type = type; - e->u.args[0] = expr; - e->tref = var->declspec; + e->u.args[0] = decl; + e->u.args[1] = expr; if (type == EXPR_SIZEOF) { /* only do this for types that should be the same on all platforms */ @@ -232,7 +242,7 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) e->cval = expr->cval; } } - free(var); + return e; }
@@ -462,6 +472,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc switch (e->type) { case EXPR_VOID: + case EXPR_DECL: break; case EXPR_INT: result.is_temporary = FALSE; @@ -533,8 +544,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); break; case EXPR_CAST: - result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); - result.type = e->tref.type; + result = resolve_expression( expr_loc, cont_type, e->u.args[1] ); + result.type = e->u.args[0]->u.decl->type; break; case EXPR_SIZEOF: result.is_temporary = FALSE; @@ -637,6 +648,7 @@ void write_expr(FILE *h, const expr_t *e, int brackets, switch (e->type) { case EXPR_VOID: + case EXPR_DECL: break; case EXPR_INT: fprintf(h, "%s", e->text); @@ -692,13 +704,13 @@ void write_expr(FILE *h, const expr_t *e, int brackets, break; case EXPR_CAST: fprintf(h, "("); - write_type_decl( h, &e->tref, NULL ); + write_type_decl( h, e->u.args[0]->u.decl, NULL ); fprintf(h, ")"); - write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); + write_expr( h, e->u.args[1], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type_decl( h, &e->tref, NULL ); + write_type_decl( h, e->u.args[0]->u.decl, NULL ); fprintf(h, ")"); break; case EXPR_SHL: @@ -848,7 +860,7 @@ int compare_expr(const expr_t *a, const expr_t *b) return ret; return compare_expr( a->u.args[1], b->u.args[1] ); case EXPR_CAST: - ret = compare_type( a->tref.type, b->tref.type ); + ret = compare_type( a->u.args[0]->u.decl->type, b->u.args[0]->u.decl->type ); if (ret != 0) return ret; /* Fall through. */ @@ -860,7 +872,9 @@ int compare_expr(const expr_t *a, const expr_t *b) case EXPR_POS: return compare_expr( a->u.args[0], b->u.args[0] ); case EXPR_SIZEOF: - return compare_type( a->tref.type, b->tref.type ); + return compare_type( a->u.args[0]->u.decl->type, b->u.args[0]->u.decl->type ); + case EXPR_DECL: + return compare_type( a->u.decl->type, b->u.decl->type ); case EXPR_VOID: return 0; } diff --git a/tools/widl/header.c b/tools/widl/header.c index 006e5a274a0..bd7dddca862 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1581,8 +1581,8 @@ static void write_apicontract_guard_start(FILE *header, const expr_t *expr) char *name; int ver; if (!winrt_mode) return; - type = expr->tref.type; - ver = expr->u.args[0]->u.lval; + type = expr->u.args[0]->u.decl->type; + ver = expr->u.args[1]->u.lval; name = format_apicontract_macro(type); fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); free(name); @@ -1594,8 +1594,8 @@ static void write_apicontract_guard_end(FILE *header, const expr_t *expr) char *name; int ver; if (!winrt_mode) return; - type = expr->tref.type; - ver = expr->u.args[0]->u.lval; + type = expr->u.args[0]->u.decl->type; + ver = expr->u.args[1]->u.lval; name = format_apicontract_macro(type); fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); free(name); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 9805e33d33d..edaa27a3e43 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -305,6 +305,7 @@ void pop_import( PARSER_LTYPE *yylloc ); %type <type_qualifier> type_qualifier m_type_qual_list %type <function_specifier> function_specifier %type <declspec> decl_spec unqualified_decl_spec decl_spec_no_type m_decl_spec_no_type +%type <declspec> cast_decl_spec %type <type> inherit interface interfacedef %type <type> interfaceref %type <type> dispinterfaceref @@ -597,26 +598,31 @@ contract_ver: contract_req : decl_spec ',' contract_ver { expr_t *contract = expr_int( $3, strmake( "%u", $3 ) ); + expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_APICONTRACT) error_loc( "type %s is not an apicontract\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_GTREQL, declare_var( NULL, $decl_spec, make_declarator( NULL ), 0 ), contract ); + $$ = make_exprt( EXPR_GTREQL, decl, contract ); } ;
static_attr - : decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) - error_loc("type %s is not an interface\n", $1->type->name); - $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); - } - ; + : decl_spec ',' contract_req { + expr_t *decl = expr_decl( $decl_spec ); + if ($decl_spec->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + } + ;
activatable_attr: - decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) - error_loc("type %s is not an interface\n", $1->type->name); - $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); - } - | contract_req { $$ = $1; } /* activatable on the default activation factory */ - ; + decl_spec ',' contract_req { + expr_t *decl = expr_decl( $decl_spec ); + if ($decl_spec->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + } + | contract_req { $$ = $contract_req; } /* activatable on the default activation factory */ + ;
access_attr : tPUBLIC { $$ = attr_int( @$, ATTR_PUBLIC, 0 ); } @@ -625,9 +631,11 @@ access_attr
composable_attr : decl_spec ',' access_attr ',' contract_req - { if ($1->type->type_type != TYPE_INTERFACE) - error_loc( "type %s is not an interface\n", $1->type->name ); - $$ = make_exprt( EXPR_MEMBER, declare_var( append_attr( NULL, $3 ), $1, make_declarator( NULL ), 0 ), $5 ); + { + expr_t *decl = expr_decl( $decl_spec ); + if ($decl_spec->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); } ;
@@ -884,10 +892,15 @@ expr: aNUM { $$ = expr_int( $aNUM, strmake( expr_t *member = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); $$ = expr_op( EXPR_MEMBER, $obj, member, NULL ); } - | '(' unqualified_decl_spec m_abstract_declarator ')' expr %prec CAST - { $$ = make_exprt(EXPR_CAST, declare_var(NULL, $2, $3, 0), $5); free($2); free($3); } - | tSIZEOF '(' unqualified_decl_spec m_abstract_declarator ')' - { $$ = make_exprt(EXPR_SIZEOF, declare_var(NULL, $3, $4, 0), NULL); free($3); free($4); } + | '(' cast_decl_spec ')' expr[value] %prec CAST + { + expr_t *decl = expr_decl( $cast_decl_spec ); + $$ = make_exprt( EXPR_CAST, decl, $value ); + } + | tSIZEOF '(' cast_decl_spec ')' { + expr_t *decl = expr_decl( $cast_decl_spec ); + $$ = make_exprt( EXPR_SIZEOF, decl, NULL ); + } | expr[array] '[' expr[index] ']' { $$ = expr_op( EXPR_ARRAY, $array, $index, NULL ); } | '(' expr ')' { $$ = $2; } ; @@ -1204,6 +1217,13 @@ unqualified_decl_spec: unqualified_type m_decl_spec_no_type { $$ = make_decl_spec($2, $1, $3, STG_NONE, 0, 0); } ;
+cast_decl_spec: unqualified_decl_spec m_abstract_declarator + { + append_chain_type( $m_abstract_declarator, $unqualified_decl_spec->type, $unqualified_decl_spec->qualifier ); + $$ = make_decl_spec( $m_abstract_declarator->type, $unqualified_decl_spec, NULL, STG_NONE, 0, 0 ); + } + ; + m_decl_spec_no_type : %empty { $$ = NULL; } | decl_spec_no_type diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 2bd2d1b8a9d..506d9e39809 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -140,10 +140,11 @@ struct expr_loc };
extern expr_t *expr_void(void); +extern expr_t *expr_decl( decl_spec_t *decl ); extern expr_t *expr_int( int val, const char *text ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); -extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); +extern expr_t *make_exprt( enum expr_type type, expr_t *decl, expr_t *expr ); extern expr_t *expr_op( enum expr_type type, expr_t *arg0, expr_t *arg1, expr_t *arg2 );
extern const type_t *expr_resolve_type( const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 322c6084f26..ba4fecdbede 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -189,6 +189,7 @@ enum attr_type enum expr_type { EXPR_VOID, + EXPR_DECL, EXPR_INT, EXPR_DOUBLE, EXPR_IDENTIFIER, @@ -352,9 +353,9 @@ struct _expr_t { int lval; double dval; const char *sval; + decl_spec_t *decl; const expr_t *args[3]; } u; - decl_spec_t tref; int is_const; int cval; /* parser-internal */
From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 92 ++++++++++++++++----------------------------- tools/widl/parser.y | 12 +++--- tools/widl/widl.h | 1 - 3 files changed, 39 insertions(+), 66 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 36f5d769d1a..b25ec5ee769 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -187,65 +187,6 @@ expr_t *expr_str( enum expr_type type, char *val ) return e; }
-expr_t *make_exprt(enum expr_type type, expr_t *decl, expr_t *expr) -{ - expr_t *e; - type_t *tref; - - if (decl->u.decl->stgclass != STG_NONE && decl->u.decl->stgclass != STG_REGISTER) - error_loc("invalid storage class for type expression\n"); - - tref = decl->u.decl->type; - - e = xmalloc( sizeof(expr_t) ); - memset( e, 0, sizeof(*e) ); - e->type = type; - e->u.args[0] = decl; - e->u.args[1] = expr; - if (type == EXPR_SIZEOF) - { - /* only do this for types that should be the same on all platforms */ - if (is_integer_type(tref) || is_float_type(tref)) - { - e->is_const = TRUE; - e->cval = type_memsize(tref); - } - } - /* check for cast of constant expression */ - if (type == EXPR_CAST && expr->is_const) - { - if (is_integer_type(tref)) - { - unsigned int cast_type_bits = type_memsize(tref) * 8; - unsigned int cast_mask; - - e->is_const = TRUE; - if (is_signed_integer_type(tref)) - { - cast_mask = (1u << (cast_type_bits - 1)) - 1; - if (expr->cval & (1u << (cast_type_bits - 1))) - e->cval = -((-expr->cval) & cast_mask); - else - e->cval = expr->cval & cast_mask; - } - else - { - /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */ - cast_mask = ((1u << (cast_type_bits - 1)) - 1) | - 1u << (cast_type_bits - 1); - e->cval = expr->cval & cast_mask; - } - } - else - { - e->is_const = TRUE; - e->cval = expr->cval; - } - } - - return e; -} - expr_t *expr_op( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3 ) { expr_t *e = xmalloc( sizeof(expr_t) ); @@ -346,6 +287,39 @@ expr_t *expr_op( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr case EXPR_COND: e->cval = expr1->cval ? expr2->cval : expr3->cval; break; + case EXPR_SIZEOF: + /* only do this for types that should be the same on all platforms */ + if (!is_integer_type( expr1->u.decl->type ) && !is_float_type( expr1->u.decl->type )) + e->is_const = FALSE; + else + e->cval = type_memsize( expr1->u.decl->type ); + break; + + case EXPR_CAST: + /* check for cast of constant expression */ + if (!is_integer_type( expr1->u.decl->type )) + e->cval = expr2->cval; + else + { + unsigned int cast_type_bits = type_memsize( expr1->u.decl->type ) * 8; + unsigned int cast_mask; + + if (is_signed_integer_type( expr1->u.decl->type )) + { + cast_mask = (1u << (cast_type_bits - 1)) - 1; + if (expr2->cval & (1u << (cast_type_bits - 1))) + e->cval = -((-expr2->cval) & cast_mask); + else + e->cval = expr2->cval & cast_mask; + } + else + { + /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */ + cast_mask = ((1u << (cast_type_bits - 1)) - 1) | 1u << (cast_type_bits - 1); + e->cval = expr2->cval & cast_mask; + } + } + break; default: e->is_const = FALSE; break; diff --git a/tools/widl/parser.y b/tools/widl/parser.y index edaa27a3e43..c4bf480a765 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -601,7 +601,7 @@ contract_req expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_APICONTRACT) error_loc( "type %s is not an apicontract\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_GTREQL, decl, contract ); + $$ = expr_op( EXPR_GTREQL, decl, contract, NULL ); } ;
@@ -610,7 +610,7 @@ static_attr expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + $$ = expr_op( EXPR_MEMBER, decl, $contract_req, NULL ); } ;
@@ -619,7 +619,7 @@ activatable_attr: expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + $$ = expr_op( EXPR_MEMBER, decl, $contract_req, NULL ); } | contract_req { $$ = $contract_req; } /* activatable on the default activation factory */ ; @@ -635,7 +635,7 @@ composable_attr expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + $$ = expr_op( EXPR_MEMBER, decl, $contract_req, NULL ); } ;
@@ -895,11 +895,11 @@ expr: aNUM { $$ = expr_int( $aNUM, strmake( | '(' cast_decl_spec ')' expr[value] %prec CAST { expr_t *decl = expr_decl( $cast_decl_spec ); - $$ = make_exprt( EXPR_CAST, decl, $value ); + $$ = expr_op( EXPR_CAST, decl, $value, NULL ); } | tSIZEOF '(' cast_decl_spec ')' { expr_t *decl = expr_decl( $cast_decl_spec ); - $$ = make_exprt( EXPR_SIZEOF, decl, NULL ); + $$ = expr_op( EXPR_SIZEOF, decl, NULL, NULL ); } | expr[array] '[' expr[index] ']' { $$ = expr_op( EXPR_ARRAY, $array, $index, NULL ); } | '(' expr ')' { $$ = $2; } diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 506d9e39809..aa0f75a70f0 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -144,7 +144,6 @@ extern expr_t *expr_decl( decl_spec_t *decl ); extern expr_t *expr_int( int val, const char *text ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); -extern expr_t *make_exprt( enum expr_type type, expr_t *decl, expr_t *expr ); extern expr_t *expr_op( enum expr_type type, expr_t *arg0, expr_t *arg1, expr_t *arg2 );
extern const type_t *expr_resolve_type( const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr );
Jacek Caban (@jacek) commented about tools/widl/parser.y:
enum_list: enum {
if (!$enum->eval) $enum->eval = expr_int( EXPR_NUM, 0 /* default for first enum entry */ );
if (!$enum->eval) $enum->eval = expr_int( 0, "0" ); $$ = append_var( NULL, $enum ); } | enum_list[list] ',' enum { if (!$enum->eval) {
var_t *last = LIST_ENTRY( list_tail( $list ), var_t, entry );
enum expr_type type = EXPR_NUM;
if (last->eval->type == EXPR_HEXNUM) type = EXPR_HEXNUM;
if (last->eval->cval + 1 < 0) type = EXPR_HEXNUM;
$enum->eval = expr_int( type, last->eval->cval + 1 );
expr_t *last = LIST_ENTRY( list_tail( $list ), var_t, entry )->eval;
const char *fmt = last->cval + 1 < 0 ? "0x%x" : "%u";
if (last->text && last->text[1] == 'x') fmt = "0x%x";
You're missing the case where text[1] == 'X' here. More generally, I'm not convinced that storing the string inside int expressions is an improvement, it seems fragile.
On Sun Oct 29 17:26:43 2023 +0000, Jacek Caban wrote:
You're missing the case where text[1] == 'X' here. More generally, I'm not convinced that storing the string inside int expressions is an improvement, it seems fragile.
I don't think 'X' can happen, we format the strings ourselves below and hex always use lower case.
Anyway, what about just getting rid of custom formats and always use decimal numbers? This is only going to end up in generated files after all, I'm not sure it's critical to have hex/NULL/TRUE/FALSE?
On Mon Oct 30 17:11:52 2023 +0000, Rémi Bernon wrote:
I don't think 'X' can happen, we format the strings ourselves below and hex always use lower case. Anyway, what about just getting rid of custom formats and always use decimal numbers? This is only going to end up in generated files after all, I'm not sure it's critical to have hex/NULL/TRUE/FALSE?
Oh, right, 'X' is not a problem here. Still, I feel that interpreting the string is not really elegant. Preserving hex format makes generated headers nicer to read and that's what midl does. I can see the argument that it's of minor importance in generated files, but to be honest current solution of separated types is easy enough that I don't really see why we need to change it.
Jacek Caban (@jacek) commented about tools/widl/widltypes.h:
enum expr_type { EXPR_VOID,
- EXPR_DECL,
Type declaration is not an expression removing that distinction in its representation seems questionable to me.
On Tue Oct 31 15:22:43 2023 +0000, Jacek Caban wrote:
Type declaration is not an expression removing that distinction in its representation seems questionable to me.
I used "decl" here as a name because the expression member is a "decl_spec", but it could have been "type" if that matters. Do you mean that an expression cannot be a "type" expression? Why not, as we can very well have `sizeof(expression)` as well as `sizeof(type)`?
On Tue Oct 31 15:31:45 2023 +0000, Rémi Bernon wrote:
I used "decl" here as a name because the expression member is a "decl_spec", but it could have been "type" if that matters. Do you mean that an expression cannot be a "type" expression? Why not, as we can very well have `sizeof(expression)` as well as `sizeof(type)`?
Can it be `sizeof(expression)` in IDLs? Quick check with midl doesn't confirm that and our parser expects a type as well. It's allowed in C, but I think its argument is specified as "type or expression". You also can't use `(expression)expression` for a cast just like you can't do `0 + (type)`.
On Tue Oct 31 15:49:08 2023 +0000, Jacek Caban wrote:
Can it be `sizeof(expression)` in IDLs? Quick check with midl doesn't confirm that and our parser expects a type as well. It's allowed in C, but I think its argument is specified as "type or expression". You also can't use `(expression)expression` for a cast just like you can't do `0
- (type)`.
Right, but that's IMO something that the grammar doesn't allow. I don't see why it would have to be modeled as distinct widl types (which only makes expressions combination more complicated), rather than distinct widl expr enum.
On Tue Oct 31 16:07:35 2023 +0000, Rémi Bernon wrote:
Right, but that's IMO something that the grammar doesn't allow. I don't see why it would have to be modeled as distinct widl types (which only makes expressions combination more complicated), rather than distinct widl expr enum.
Fwiw I would also be fine with modelling expression kind into the type system, as that could be more readable than an abstract "args", but I think that the in between solution that is currently used, with type arguments stored separately feels awkward.
On Tue Oct 31 16:32:10 2023 +0000, Rémi Bernon wrote:
Fwiw I would also be fine with modelling expression kind into the type system, as that could be more readable than an abstract "args", but I think that the in between solution that is currently used, with type arguments stored separately feels awkward.
[Expressions](https://en.wikipedia.org/wiki/Expression_(computer_science)) have their meaning and are a different things than types, it's more generic distinction than just a specific gramma rule. Sure, it's possible to pretend that types are expressions in data structures, but I think it adds more confusion and complexity. I don't see how accessing the type by something like `expr->u.args[0]->u.type` is cleaner than `expr->u.type`. You assume that `args[0]` is an expression carrying a type anyway, and take an extra step to construct an extra expr_t. Isn't it better to adjust `expr_t` to be explicit about that?
And I'm not sure what you mean by type arguments being stored separately. Is it about the fact that it's not part of the union? That's only because you change it in an earlier patch in this series.
On Tue Oct 31 23:40:13 2023 +0000, Jacek Caban wrote:
[Expressions](https://en.wikipedia.org/wiki/Expression_(computer_science)) have their meaning and are a different things than types, it's more generic distinction than just a specific gramma rule. Sure, it's possible to pretend that types are expressions in data structures, but I think it adds more confusion and complexity. I don't see how accessing the type by something like `expr->u.args[0]->u.type` is cleaner than `expr->u.type`. You assume that `args[0]` is an expression carrying a type anyway, and take an extra step to construct an extra expr_t. Isn't it better to adjust `expr_t` to be explicit about that? And I'm not sure what you mean by type arguments being stored separately. Is it about the fact that it's not part of the union? That's only because you change it in an earlier patch in this series.
Expressions are just a sequence of tokens that can be evaluated to compute a resulting value. The result type may be a basic langage type, or it can be a type itself, in which case it's often called a "type expression". You can very well see declspecs as type expressions, with operators modifying the type values.
Anyway, I will make each expression kind its own struct, so that would solve the question.
This merge request was closed by Rémi Bernon.