Parse the NOT operator, the [idempotent] attribute, and the handle_t

and error_status_t types. Improved some parsing rules to get rid of
the LINK_LAST and LINK_SAFE macros. Enclose generated .h file within
an extern "C" (for C++). Output function prototypes for regular RPC
interfaces.  Fixed a couple of bugs.
This commit is contained in:
Ove Kaaven 2002-12-03 19:12:07 +00:00 committed by Alexandre Julliard
parent 2ec8b71bae
commit e30a96776a
8 changed files with 194 additions and 70 deletions

View File

@ -185,7 +185,7 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n)
break;
case RPC_FC_HYPER:
if (t->ref) fprintf(h, t->ref->name);
else fprintf(h, "__int64");
else fprintf(h, "hyper");
break;
case RPC_FC_FLOAT:
fprintf(h, "float");
@ -206,6 +206,14 @@ void write_type(FILE *h, type_t *t, var_t *v, char *n)
}
else fprintf(h, "enum %s", t->name);
break;
case RPC_FC_ERROR_STATUS_T:
if (t->ref) fprintf(h, t->ref->name);
else fprintf(h, "error_status_t");
break;
case RPC_FC_BIND_PRIMITIVE:
if (t->ref) fprintf(h, t->ref->name);
else fprintf(h, "handle_t");
break;
case RPC_FC_STRUCT:
case RPC_FC_ENCAPSULATED_UNION:
if (t->defined && !t->written) {
@ -283,6 +291,10 @@ static void do_write_expr(FILE *h, expr_t *e, int p)
fprintf(h, "-");
do_write_expr(h, e->ref, 1);
break;
case EXPR_NOT:
fprintf(h, "~");
do_write_expr(h, e->ref, 1);
break;
case EXPR_PPTR:
fprintf(h, "*");
do_write_expr(h, e->ref, 1);
@ -350,40 +362,46 @@ void write_externdef(var_t *v)
/********** INTERFACES **********/
uuid_t *get_uuid(attr_t *a)
int is_attr(attr_t *a, enum attr_type t)
{
while (a) {
if (a->type == ATTR_UUID) return a->u.pval;
if (a->type == t) return 1;
a = NEXT_LINK(a);
}
return 0;
}
void *get_attrp(attr_t *a, enum attr_type t)
{
while (a) {
if (a->type == t) return a->u.pval;
a = NEXT_LINK(a);
}
return NULL;
}
DWORD get_attrv(attr_t *a, enum attr_type t)
{
while (a) {
if (a->type == t) return a->u.ival;
a = NEXT_LINK(a);
}
return 0;
}
int is_object(attr_t *a)
{
while (a) {
if (a->type == ATTR_OBJECT) return 1;
a = NEXT_LINK(a);
}
return 0;
return is_attr(a, ATTR_OBJECT);
}
int is_local(attr_t *a)
{
while (a) {
if (a->type == ATTR_LOCAL) return 1;
a = NEXT_LINK(a);
}
return 0;
return is_attr(a, ATTR_LOCAL);
}
var_t *is_callas(attr_t *a)
{
while (a) {
if (a->type == ATTR_CALLAS) return a->u.pval;
a = NEXT_LINK(a);
}
return NULL;
return get_attrp(a, ATTR_CALLAS);
}
static void write_method_def(type_t *iface)
@ -476,19 +494,25 @@ static int write_method_macro(type_t *iface, char *name)
return idx;
}
void write_method_args(FILE *h, var_t *arg, char *name)
void write_args(FILE *h, var_t *arg, char *name, int method)
{
int count = 0;
if (arg) {
while (NEXT_LINK(arg))
arg = NEXT_LINK(arg);
}
if (method) {
fprintf(h, " %s* This", name);
count++;
}
else fprintf(h, " ");
while (arg) {
fprintf(h, ",\n ");
if (count) fprintf(h, ",\n ");
write_type(h, arg->type, arg, arg->tname);
fprintf(h, " ");
write_name(h,arg);
arg = PREV_LINK(arg);
count++;
}
}
@ -503,9 +527,9 @@ static void write_method_proto(type_t *iface)
/* proxy prototype */
write_type(header, def->type, def, def->tname);
fprintf(header, " CALLBACK %s_", iface->name);
write_name(header,def);
write_name(header, def);
fprintf(header, "_Proxy(\n");
write_method_args(header, cur->args, iface->name);
write_args(header, cur->args, iface->name, 1);
fprintf(header, ");\n");
/* stub prototype */
fprintf(header, "void __RPC_STUB %s_", iface->name);
@ -527,14 +551,14 @@ static void write_method_proto(type_t *iface)
fprintf(header, " CALLBACK %s_", iface->name);
write_name(header, mdef);
fprintf(header, "_Proxy(\n");
write_method_args(header, m->args, iface->name);
write_args(header, m->args, iface->name, 1);
fprintf(header, ");\n");
/* stub prototype - use remotable prototype */
write_type(header, def->type, def, def->tname);
fprintf(header, " __RPC_STUB %s_", iface->name);
write_name(header, mdef);
fprintf(header, "_Stub(\n");
write_method_args(header, cur->args, iface->name);
write_args(header, cur->args, iface->name, 1);
fprintf(header, ");\n");
}
else {
@ -546,6 +570,24 @@ static void write_method_proto(type_t *iface)
}
}
static void write_function_proto(type_t *iface)
{
func_t *cur = iface->funcs;
while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
while (cur) {
var_t *def = cur->def;
/* FIXME: do we need to handle call_as? */
write_type(header, def->type, def, def->tname);
fprintf(header, " ");
write_name(header, def);
fprintf(header, "(\n");
write_args(header, cur->args, iface->name, 0);
fprintf(header, ");\n");
cur = PREV_LINK(cur);
}
}
void write_forward(type_t *iface)
{
/* C/C++ forwards should only be written for object interfaces, so if we
@ -561,21 +603,15 @@ void write_forward(type_t *iface)
void write_guid(type_t *iface)
{
uuid_t *uuid = get_uuid(iface->attrs);
uuid_t *uuid = get_attrp(iface->attrs, ATTR_UUID);
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)
void write_com_interface(type_t *iface)
{
if (!is_object(iface->attrs)) {
if (!iface->funcs) return;
yywarning("RPC interfaces not supported yet\n");
return;
}
if (!iface->funcs) {
yywarning("%s has no methods", iface->name);
return;
@ -606,3 +642,29 @@ void write_interface(type_t *iface)
if (!is_local(iface->attrs))
write_proxy(iface);
}
void write_rpc_interface(type_t *iface)
{
DWORD ver = get_attrv(iface->attrs, ATTR_VERSION);
if (!iface->funcs) return;
fprintf(header, "/*****************************************************************************\n");
fprintf(header, " * %s interface (v%d.%d)\n", iface->name, LOWORD(ver), HIWORD(ver));
fprintf(header, " */\n");
write_guid(iface);
fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_c_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_s_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
write_function_proto(iface);
fprintf(header, "\n");
/* FIXME: server/client code */
}
void write_interface(type_t *iface)
{
if (is_object(iface->attrs))
write_com_interface(iface);
else
write_rpc_interface(iface);
}

View File

@ -28,7 +28,7 @@ extern void write_type(FILE *h, type_t *t, var_t *v, char *n);
extern int is_object(attr_t *a);
extern int is_local(attr_t *a);
extern var_t *is_callas(attr_t *a);
extern void write_method_args(FILE *h, var_t *arg, char *name);
extern void write_args(FILE *h, var_t *arg, char *name, int obj);
extern void write_forward(type_t *iface);
extern void write_interface(type_t *iface);
extern void write_typedef(type_t *type, var_t *names);

View File

@ -80,18 +80,18 @@ static uuid_t* parse_uuid(const char*u)
uuid_t* uuid = xmalloc(sizeof(uuid_t));
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);
uuid->Data1 = strtoul(u, NULL, 16);
uuid->Data2 = strtoul(u+9, NULL, 16);
uuid->Data3 = strtoul(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);
memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16);
memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16);
memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16);
memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16);
memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16);
memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16);
memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16);
memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16);
return uuid;
}
@ -188,12 +188,17 @@ static struct keyword {
{"double", tDOUBLE},
/* ... */
{"enum", tENUM},
{"error_status_t", tERRORSTATUST},
/* ... */
{"extern", tEXTERN},
/* ... */
{"float", tFLOAT},
/* ... */
{"handle_t", tHANDLET},
/* ... */
{"hyper", tHYPER},
/* ... */
{"idempotent", tIDEMPOTENT},
/* ... */
{"iid_is", tIIDIS},
/* ... */
@ -271,7 +276,10 @@ static int kw_token(const char *kw)
}
}
#endif
if (kwp) return kwp->token;
if (kwp) {
yylval.str = (char*)kwp->kw;
return kwp->token;
}
yylval.str = xstrdup(kw);
return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
}

View File

@ -94,6 +94,8 @@ static var_t *find_const(char *name, int f);
static type_t std_bool = { "boolean" };
static type_t std_int = { "int" };
static type_t std_int64 = { "__int64" };
static type_t std_uhyper = { "MIDL_uhyper" };
%}
%union {
@ -122,10 +124,12 @@ static type_t std_int = { "int" };
%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
%token tDEFAULT
%token tDOUBLE
%token tENUM
%token tENUM tERRORSTATUST
%token tEXTERN
%token tFLOAT
%token tHANDLET
%token tHYPER
%token tIDEMPOTENT
%token tIIDIS
%token tIMPORT tIMPORTLIB
%token tIN tINCLUDE tINLINE
@ -158,7 +162,8 @@ static type_t std_int = { "int" };
%token tPOINTERTYPE
%type <attr> m_attributes attributes attrib_list attribute
%type <expr> exprs expr_list expr array expr_const
%type <expr> m_exprs /* exprs expr_list */ m_expr expr expr_list_const expr_const
%type <expr> array array_list
%type <type> inherit interface interfacehdr interfacedef lib_statements
%type <type> base_type int_std
%type <type> enumdef structdef typedef uniondef
@ -167,7 +172,7 @@ static type_t std_int = { "int" };
%type <var> fields field s_field cases case enums enum_list enum constdef externdef
%type <var> m_ident t_ident ident p_ident pident pident_list
%type <func> funcdef int_statements
%type <num> pointer_type
%type <num> pointer_type version
%left ','
%left '|'
@ -175,6 +180,7 @@ static type_t std_int = { "int" };
%left '-' '+'
%left '*' '/'
%left SHL SHR
%right '~'
%right CAST
%right PPTR
%right NEG
@ -240,45 +246,52 @@ arg: attributes type pident array { $$ = $3;
;
array: { $$ = NULL; }
| '[' exprs ']' { $$ = $2; }
| '[' array_list ']' { $$ = $2; }
| '[' '*' ']' { $$ = make_expr(EXPR_VOID); }
;
array_list: m_expr /* size of first dimension is optional */
| array_list ',' expr { LINK($3, $1); $$ = $3; }
| array_list ']' '[' expr { LINK($4, $1); $$ = $4; }
;
m_attributes: { $$ = NULL; }
| attributes
;
attributes:
m_attributes '[' attrib_list ']' { LINK_LAST($3, $1); $$ = $3; }
'[' attrib_list ']' { $$ = $2; }
;
attrib_list: attribute
| attrib_list ',' attribute { LINK_SAFE($3, $1); $$ = $3; /* FIXME: don't use SAFE */ }
| attrib_list ',' attribute { LINK($3, $1); $$ = $3; }
| attrib_list ']' '[' attribute { LINK($4, $1); $$ = $4; }
;
attribute:
tASYNC { $$ = make_attr(ATTR_ASYNC); }
| tCALLAS '(' ident ')' { $$ = make_attrp(ATTR_CALLAS, $3); }
| tCASE '(' expr_list ')' { $$ = NULL; }
| tCONTEXTHANDLE { $$ = NULL; }
| tCONTEXTHANDLENOSERIALIZE { $$ = NULL; }
| tCONTEXTHANDLESERIALIZE { $$ = NULL; }
| tCASE '(' expr_list_const ')' { $$ = make_attrp(ATTR_CASE, $3); }
| tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
| tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
| tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
| tDEFAULT { $$ = make_attr(ATTR_DEFAULT); }
| tIDEMPOTENT { $$ = make_attr(ATTR_IDEMPOTENT); }
| tIIDIS '(' ident ')' { $$ = make_attrp(ATTR_IIDIS, $3); }
| tIN { $$ = make_attr(ATTR_IN); }
| tLENGTHIS '(' exprs ')' { $$ = NULL; }
| tLENGTHIS '(' m_exprs ')' { $$ = make_attrp(ATTR_LENGTHIS, $3); }
| tLOCAL { $$ = make_attr(ATTR_LOCAL); }
| tOBJECT { $$ = make_attr(ATTR_OBJECT); }
| tOLEAUTOMATION { $$ = make_attr(ATTR_OLEAUTOMATION); }
| tOUT { $$ = make_attr(ATTR_OUT); }
| tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
| tSIZEIS '(' exprs ')' { $$ = NULL; }
| tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); }
| tSTRING { $$ = make_attr(ATTR_STRING); }
| tSWITCHIS '(' expr ')' { $$ = NULL; }
| tSWITCHTYPE '(' type ')' { $$ = NULL; }
| tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); }
| tSWITCHTYPE '(' type ')' { $$ = make_attrp(ATTR_SWITCHTYPE, type_ref($3)); }
| tUUID '(' aUUID ')' { $$ = make_attrp(ATTR_UUID, $3); }
| tV1ENUM { $$ = make_attr(ATTR_V1ENUM); }
| tVERSION '(' version ')' { $$ = NULL; }
| tVERSION '(' version ')' { $$ = make_attrv(ATTR_VERSION, $3); }
| tWIREMARSHAL '(' type ')' { $$ = make_attrp(ATTR_WIREMARSHAL, type_ref($3)); }
| pointer_type { $$ = make_attrv(ATTR_POINTERTYPE, $1); }
;
@ -293,9 +306,9 @@ cases: { $$ = NULL; }
}
;
case: tCASE expr ':' field { /* attr_t *a = NULL; */ /* FIXME */
case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, $2);
$$ = $4; if (!$$) $$ = make_var(NULL);
/* LINK(a, $$->attrs); $$->attrs = a; */
LINK(a, $$->attrs); $$->attrs = a;
}
| tDEFAULT ':' field { attr_t *a = make_attr(ATTR_DEFAULT);
$$ = $3; if (!$$) $$ = make_var(NULL);
@ -337,6 +350,11 @@ enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM
}
;
m_exprs: m_expr
| m_exprs ',' m_expr { LINK($3, $1); $$ = $3; }
;
/*
exprs: { $$ = make_expr(EXPR_VOID); }
| expr_list
;
@ -344,6 +362,11 @@ exprs: { $$ = make_expr(EXPR_VOID); }
expr_list: expr
| expr_list ',' expr { LINK($3, $1); $$ = $3; }
;
*/
m_expr: { $$ = make_expr(EXPR_VOID); }
| expr
;
expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); }
| aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); }
@ -356,6 +379,7 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); }
| expr '/' expr { $$ = make_expr2(EXPR_DIV, $1, $3); }
| expr SHL expr { $$ = make_expr2(EXPR_SHL, $1, $3); }
| expr SHR expr { $$ = make_expr2(EXPR_SHR, $1, $3); }
| '~' expr { $$ = make_expr1(EXPR_NOT, $2); }
| '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); }
| '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); }
| '(' type ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, $2, $4); }
@ -363,6 +387,10 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); }
| '(' expr ')' { $$ = $2; }
;
expr_list_const: expr_const
| expr_list_const ',' expr_const { LINK($3, $1); $$ = $3; }
;
expr_const: expr { $$ = $1;
if (!$$->is_const) yyerror("expression is not constant\n");
}
@ -406,6 +434,8 @@ t_ident: { $$ = NULL; }
;
ident: aIDENTIFIER { $$ = make_var($1); }
/* some "reserved words" used in attributes are also used as field names in some MS IDL files */
| tVERSION { $$ = make_var($<str>1); }
;
base_type: tBYTE { $$ = make_type(RPC_FC_BYTE, NULL); }
@ -417,12 +447,17 @@ base_type: tBYTE { $$ = make_type(RPC_FC_BYTE, NULL); }
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;
case RPC_FC_HYPER:
if (!$$->ref) { $$->ref = &std_uhyper; $$->sign = 0; }
break;
default: break;
}
}
| tFLOAT { $$ = make_type(RPC_FC_FLOAT, NULL); }
| tDOUBLE { $$ = make_type(RPC_FC_DOUBLE, NULL); }
| tBOOLEAN { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ }
| tERRORSTATUST { $$ = make_type(RPC_FC_ERROR_STATUS_T, NULL); }
| tHANDLET { $$ = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ }
;
m_int:
@ -433,7 +468,7 @@ int_std: tINT { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
| tSHORT m_int { $$ = make_type(RPC_FC_SHORT, NULL); }
| 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); }
| tINT64 { $$ = make_type(RPC_FC_HYPER, &std_int64); }
| tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); }
;
@ -535,8 +570,8 @@ uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATE
;
version:
aNUM {}
| aNUM '.' aNUM {}
aNUM { $$ = MAKELONG($1, 0); }
| aNUM '.' aNUM { $$ = MAKELONG($1, $3); }
;
%%
@ -650,6 +685,9 @@ static expr_t *make_expr1(enum expr_type type, expr_t *expr)
case EXPR_NEG:
e->cval = -expr->cval;
break;
case EXPR_NOT:
e->cval = ~expr->cval;
break;
default:
e->is_const = FALSE;
break;

View File

@ -69,7 +69,7 @@ static void gen_proxy(type_t *iface, func_t *cur, int idx)
fprintf(proxy, " CALLBACK %s_", iface->name);
write_name(proxy, def);
fprintf(proxy, "_Proxy(\n");
write_method_args(proxy, cur->args, iface->name);
write_args(proxy, cur->args, iface->name, 1);
fprintf(proxy, ")\n");
fprintf(proxy, "{\n");
/* local variables */
@ -304,7 +304,7 @@ void finish_proxy(void)
{
if_list *lcur = if_first;
if_list *cur;
char *file_id = "XXX";
char *file_id = proxy_token;
int c;
if (!lcur) return;

View File

@ -74,6 +74,7 @@ char *input_name;
char *header_name;
char *header_token;
char *proxy_name;
char *proxy_token;
char *temp_name;
int line_number = 1;
@ -179,6 +180,7 @@ int main(int argc,char *argv[])
if (!proxy_name) {
proxy_name = dup_basename(input_name, ".idl");
proxy_token = xstrdup(proxy_name);
strcat(proxy_name, "_p.c");
}
@ -218,10 +220,16 @@ int main(int argc,char *argv[])
fprintf(header, "#include \"rpcndr.h\"\n\n" );
fprintf(header, "#ifndef __WIDL_%s\n", header_token);
fprintf(header, "#define __WIDL_%s\n", header_token);
fprintf(header, "#ifdef __cplusplus\n");
fprintf(header, "extern \"C\" {\n");
fprintf(header, "#endif\n");
ret = yyparse();
finish_proxy();
fprintf(header, "#ifdef __cplusplus\n");
fprintf(header, "}\n");
fprintf(header, "#endif\n");
fprintf(header, "#endif /* __WIDL_%s */\n", header_token);
fclose(header);
fclose(yyin);

View File

@ -43,6 +43,7 @@ extern int header_only;
extern char *input_name;
extern char *header_name;
extern char *proxy_name;
extern char *proxy_token;
extern time_t now;
extern int line_number;

View File

@ -37,8 +37,6 @@ typedef struct _uuid_t uuid_t;
type *l_prev;
#define LINK(x,y) do { x->l_next = y; if (y) y->l_prev = x; } while (0)
#define LINK_LAST(x,y) do { if (y) { attr_t *_c = x; while (_c->l_next) _c = _c->l_next; LINK(_c, y); } } while (0)
#define LINK_SAFE(x,y) do { if (x) LINK_LAST(x,y); else { x = y; } } while (0)
#define INIT_LINK(x) do { x->l_next = NULL; x->l_prev = NULL; } while (0)
#define NEXT_LINK(x) ((x)->l_next)
@ -48,18 +46,26 @@ enum attr_type
{
ATTR_ASYNC,
ATTR_CALLAS,
ATTR_CASE,
ATTR_CONTEXTHANDLE,
ATTR_DEFAULT,
ATTR_IDEMPOTENT,
ATTR_IIDIS,
ATTR_IN,
ATTR_LENGTHIS,
ATTR_LOCAL,
ATTR_OBJECT,
ATTR_OLEAUTOMATION,
ATTR_OUT,
ATTR_POINTERDEFAULT,
ATTR_POINTERTYPE,
ATTR_SIZEIS,
ATTR_STRING,
ATTR_SWITCHIS,
ATTR_SWITCHTYPE,
ATTR_UUID,
ATTR_V1ENUM,
ATTR_VERSION,
ATTR_WIREMARSHAL,
};
@ -70,6 +76,7 @@ enum expr_type
EXPR_HEXNUM,
EXPR_IDENTIFIER,
EXPR_NEG,
EXPR_NOT,
EXPR_PPTR,
EXPR_CAST,
EXPR_SIZEOF,