Commit 319a7a10 authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

widl: Implement a more abstract way of representing basic types.

parent 0be9d259
......@@ -434,22 +434,22 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
case EXPR_TRUEFALSE:
result.is_variable = FALSE;
result.is_temporary = FALSE;
result.type = find_type("int", 0);
result.type = type_new_int(TYPE_BASIC_INT, 0);
break;
case EXPR_STRLIT:
result.is_variable = FALSE;
result.is_temporary = TRUE;
result.type = make_type(RPC_FC_RP, find_type("char", 0));
result.type = type_new_pointer(type_new_int(TYPE_BASIC_CHAR, 0), NULL);
break;
case EXPR_WSTRLIT:
result.is_variable = FALSE;
result.is_temporary = TRUE;
result.type = make_type(RPC_FC_RP, find_type("wchar_t", 0));
result.type = type_new_pointer(type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
break;
case EXPR_DOUBLE:
result.is_variable = FALSE;
result.is_temporary = FALSE;
result.type = find_type("double", 0);
result.is_temporary = TRUE;
result.type = type_new_basic(TYPE_BASIC_DOUBLE);
break;
case EXPR_IDENTIFIER:
{
......@@ -470,7 +470,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
check_scalar_type(expr_loc, cont_type, result.type);
result.is_variable = FALSE;
result.is_temporary = FALSE;
result.type = find_type("int", 0);
result.type = type_new_int(TYPE_BASIC_INT, 0);
break;
case EXPR_NOT:
result = resolve_expression(expr_loc, cont_type, e->ref);
......@@ -491,7 +491,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
expr_loc->attr ? expr_loc->attr : "");
result.is_variable = FALSE;
result.is_temporary = TRUE;
result.type = make_type(RPC_FC_RP, result.type);
result.type = type_new_pointer(result.type, NULL);
break;
case EXPR_PPTR:
result = resolve_expression(expr_loc, cont_type, e->ref);
......@@ -512,7 +512,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
case EXPR_SIZEOF:
result.is_variable = FALSE;
result.is_temporary = FALSE;
result.type = find_type("int", 0);
result.type = type_new_int(TYPE_BASIC_INT, 0);
break;
case EXPR_SHL:
case EXPR_SHR:
......@@ -550,7 +550,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
check_scalar_type(expr_loc, cont_type, result_right.type);
result.is_variable = FALSE;
result.is_temporary = FALSE;
result.type = find_type("int", 0);
result.type = type_new_int(TYPE_BASIC_INT, 0);
break;
}
case EXPR_MEMBER:
......
......@@ -253,15 +253,41 @@ void write_type_left(FILE *h, type_t *t, int declonly)
}
break;
case TYPE_BASIC:
if (t->sign > 0) fprintf(h, "signed ");
else if (t->sign < 0) fprintf(h, "unsigned ");
/* fall through */
if (type_basic_get_type(t) != TYPE_BASIC_HYPER)
{
if (type_basic_get_sign(t) < 0) fprintf(h, "signed ");
else if (type_basic_get_sign(t) > 0) fprintf(h, "unsigned ");
}
switch (type_basic_get_type(t))
{
case TYPE_BASIC_INT8: fprintf(h, "small"); break;
case TYPE_BASIC_INT16: fprintf(h, "short"); break;
case TYPE_BASIC_INT32: fprintf(h, "long"); break;
case TYPE_BASIC_INT: fprintf(h, "int"); break;
case TYPE_BASIC_INT64: fprintf(h, "__int64"); break;
case TYPE_BASIC_BYTE: fprintf(h, "byte"); break;
case TYPE_BASIC_CHAR: fprintf(h, "char"); break;
case TYPE_BASIC_WCHAR: fprintf(h, "wchar_t"); break;
case TYPE_BASIC_FLOAT: fprintf(h, "float"); break;
case TYPE_BASIC_DOUBLE: fprintf(h, "double"); break;
case TYPE_BASIC_ERROR_STATUS_T: fprintf(h, "error_status_t"); break;
case TYPE_BASIC_HANDLE: fprintf(h, "handle_t"); break;
case TYPE_BASIC_HYPER:
if (type_basic_get_sign(t) > 0)
fprintf(h, "MIDL_uhyper");
else
fprintf(h, "hyper");
break;
}
break;
case TYPE_INTERFACE:
case TYPE_MODULE:
case TYPE_COCLASS:
case TYPE_VOID:
fprintf(h, "%s", t->name);
break;
case TYPE_VOID:
fprintf(h, "void");
break;
case TYPE_ALIAS:
case TYPE_FUNCTION:
/* handled elsewhere */
......
......@@ -115,8 +115,6 @@ static func_list_t *append_func(func_list_t *list, func_t *func);
static func_t *make_func(var_t *def);
static type_t *make_class(char *name);
static type_t *make_safearray(type_t *type);
static type_t *make_builtin(char *name);
static type_t *make_int(int sign);
static typelib_t *make_library(const char *name, const attr_list_t *attrs);
static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type);
......@@ -611,10 +609,10 @@ enum_list: enum { if (!$1->eval)
enum: ident '=' expr_int_const { $$ = reg_const($1);
$$->eval = $3;
$$->type = make_int(0);
$$->type = type_new_int(TYPE_BASIC_INT, 0);
}
| ident { $$ = reg_const($1);
$$->type = make_int(0);
$$->type = type_new_int(TYPE_BASIC_INT, 0);
}
;
......@@ -769,46 +767,31 @@ ident: aIDENTIFIER { $$ = make_var($1); }
| aKNOWNTYPE { $$ = make_var($<str>1); }
;
base_type: tBYTE { $$ = make_builtin($<str>1); }
| tWCHAR { $$ = make_builtin($<str>1); }
base_type: tBYTE { $$ = find_type_or_error($<str>1, 0); }
| tWCHAR { $$ = find_type_or_error($<str>1, 0); }
| int_std
| tSIGNED int_std { $$ = $2; $$->sign = 1; }
| tUNSIGNED int_std { $$ = $2; $$->sign = -1;
switch ($$->type) {
case RPC_FC_CHAR: break;
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 ($$->name[0] == 'h') /* hyper, as opposed to __int64 */
{
$$ = type_new_alias($$, "MIDL_uhyper");
$$->sign = 0;
}
break;
default: break;
}
}
| tUNSIGNED { $$ = make_int(-1); }
| tFLOAT { $$ = make_builtin($<str>1); }
| tSIGNED int_std { $$ = type_new_int(type_basic_get_type($2), -1); }
| tUNSIGNED int_std { $$ = type_new_int(type_basic_get_type($2), 1); }
| tUNSIGNED { $$ = type_new_int(TYPE_BASIC_INT, 1); }
| tFLOAT { $$ = find_type_or_error($<str>1, 0); }
| tSINGLE { $$ = find_type("float", 0); }
| tDOUBLE { $$ = make_builtin($<str>1); }
| tBOOLEAN { $$ = make_builtin($<str>1); }
| tERRORSTATUST { $$ = make_builtin($<str>1); }
| tHANDLET { $$ = make_builtin($<str>1); }
| tDOUBLE { $$ = find_type_or_error($<str>1, 0); }
| tBOOLEAN { $$ = find_type_or_error($<str>1, 0); }
| tERRORSTATUST { $$ = find_type_or_error($<str>1, 0); }
| tHANDLET { $$ = find_type_or_error($<str>1, 0); }
;
m_int:
| tINT
;
int_std: tINT { $$ = make_builtin($<str>1); }
| tSHORT m_int { $$ = make_builtin($<str>1); }
| tSMALL { $$ = make_builtin($<str>1); }
| tLONG m_int { $$ = make_builtin($<str>1); }
| tHYPER m_int { $$ = make_builtin($<str>1); }
| tINT64 { $$ = make_builtin($<str>1); }
| tCHAR { $$ = make_builtin($<str>1); }
int_std: tINT { $$ = type_new_int(TYPE_BASIC_INT, 0); }
| tSHORT m_int { $$ = type_new_int(TYPE_BASIC_INT16, 0); }
| tSMALL { $$ = type_new_int(TYPE_BASIC_INT8, 0); }
| tLONG m_int { $$ = type_new_int(TYPE_BASIC_INT32, 0); }
| tHYPER m_int { $$ = type_new_int(TYPE_BASIC_HYPER, 0); }
| tINT64 { $$ = type_new_int(TYPE_BASIC_INT64, 0); }
| tCHAR { $$ = type_new_int(TYPE_BASIC_CHAR, 0); }
;
coclass: tCOCLASS aIDENTIFIER { $$ = make_class($2); }
......@@ -996,7 +979,7 @@ pointer_type:
structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, TRUE, $4); }
;
type: tVOID { $$ = find_type_or_error("void", 0); }
type: tVOID { $$ = type_new_void(); }
| aKNOWNTYPE { $$ = find_type_or_error($1, 0); }
| base_type { $$ = $1; }
| enumdef { $$ = $1; }
......@@ -1028,49 +1011,26 @@ version:
%%
static void decl_builtin(const char *name, unsigned char type)
static void decl_builtin_basic(const char *name, enum type_basic_type type)
{
type_t *t = make_type(type, NULL);
t->name = xstrdup(name);
type_t *t = type_new_basic(type);
reg_type(t, name, 0);
}
static type_t *make_builtin(char *name)
{
/* NAME is strdup'd in the lexer */
type_t *t = duptype(find_type_or_error(name, 0), 0);
t->name = name;
return t;
}
static type_t *make_int(int sign)
static void decl_builtin_alias(const char *name, type_t *t)
{
type_t *t = duptype(find_type_or_error("int", 0), 1);
t->sign = sign;
if (sign < 0)
t->type = t->type == RPC_FC_LONG ? RPC_FC_ULONG : RPC_FC_USHORT;
return t;
reg_type(type_new_alias(t, name), name, 0);
}
void init_types(void)
{
decl_builtin("void", 0);
decl_builtin("byte", RPC_FC_BYTE);
decl_builtin("wchar_t", RPC_FC_WCHAR);
decl_builtin("int", RPC_FC_LONG); /* win32 */
decl_builtin("short", RPC_FC_SHORT);
decl_builtin("small", RPC_FC_SMALL);
decl_builtin("long", RPC_FC_LONG);
decl_builtin("hyper", RPC_FC_HYPER);
decl_builtin("__int64", RPC_FC_HYPER);
decl_builtin("char", RPC_FC_CHAR);
decl_builtin("float", RPC_FC_FLOAT);
decl_builtin("double", RPC_FC_DOUBLE);
decl_builtin("boolean", RPC_FC_BYTE);
decl_builtin("error_status_t", RPC_FC_ERROR_STATUS_T);
decl_builtin("handle_t", RPC_FC_BIND_PRIMITIVE);
decl_builtin_basic("byte", TYPE_BASIC_BYTE);
decl_builtin_basic("wchar_t", TYPE_BASIC_WCHAR);
decl_builtin_basic("float", TYPE_BASIC_FLOAT);
decl_builtin_basic("double", TYPE_BASIC_DOUBLE);
decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T);
decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE);
decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE));
}
static str_list_t *append_str(str_list_t *list, char *str)
......@@ -1295,7 +1255,6 @@ type_t *make_type(unsigned char type, type_t *ref)
t->typestring_offset = 0;
t->ptrdesc = 0;
t->ignore = (parse_only != 0);
t->sign = 0;
t->defined = FALSE;
t->written = FALSE;
t->user_types_registered = FALSE;
......
......@@ -148,35 +148,45 @@ unsigned short get_type_vt(type_t *t)
switch (type_get_type(t)) {
case TYPE_BASIC:
switch (type_basic_get_fc(t)) {
case RPC_FC_BYTE:
case RPC_FC_USMALL:
switch (type_basic_get_type(t)) {
case TYPE_BASIC_BYTE:
return VT_UI1;
case RPC_FC_CHAR:
case RPC_FC_SMALL:
case TYPE_BASIC_CHAR:
case TYPE_BASIC_INT8:
if (type_basic_get_sign(t) > 0)
return VT_UI1;
else
return VT_I1;
case RPC_FC_WCHAR:
case TYPE_BASIC_WCHAR:
return VT_I2; /* mktyplib seems to parse wchar_t as short */
case RPC_FC_SHORT:
return VT_I2;
case RPC_FC_USHORT:
case TYPE_BASIC_INT16:
if (type_basic_get_sign(t) > 0)
return VT_UI2;
case RPC_FC_LONG:
if (match(t->name, "int")) return VT_INT;
return VT_I4;
case RPC_FC_ULONG:
if (match(t->name, "int")) return VT_UINT;
else
return VT_I2;
case TYPE_BASIC_INT:
if (type_basic_get_sign(t) > 0)
return VT_UINT;
else
return VT_INT;
case TYPE_BASIC_INT32:
case TYPE_BASIC_ERROR_STATUS_T:
if (type_basic_get_sign(t) > 0)
return VT_UI4;
case RPC_FC_HYPER:
if (t->sign < 0) return VT_UI8;
if (match(t->name, "MIDL_uhyper")) return VT_UI8;
else
return VT_I4;
case TYPE_BASIC_INT64:
case TYPE_BASIC_HYPER:
if (type_basic_get_sign(t) > 0)
return VT_UI8;
else
return VT_I8;
case RPC_FC_FLOAT:
case TYPE_BASIC_FLOAT:
return VT_R4;
case RPC_FC_DOUBLE:
case TYPE_BASIC_DOUBLE:
return VT_R8;
default:
error("get_type_vt: unknown basic type: 0x%02x\n", type_basic_get_fc(t));
case TYPE_BASIC_HANDLE:
error("handles can't be used in typelibs\n");
}
break;
......
......@@ -92,6 +92,37 @@ type_t *type_new_array(const char *name, type_t *element, int declptr,
return t;
}
type_t *type_new_basic(enum type_basic_type basic_type)
{
type_t *t = make_type(TYPE_BASIC, NULL);
t->details.basic.type = basic_type;
t->details.basic.sign = 0;
return t;
}
type_t *type_new_int(enum type_basic_type basic_type, int sign)
{
static type_t *int_types[TYPE_BASIC_INT_MAX+1][3];
assert(basic_type <= TYPE_BASIC_INT_MAX);
/* map sign { -1, 0, 1 } -> { 0, 1, 2 } */
if (!int_types[basic_type][sign + 1])
{
int_types[basic_type][sign + 1] = type_new_basic(basic_type);
int_types[basic_type][sign + 1]->details.basic.sign = sign;
}
return int_types[basic_type][sign + 1];
}
type_t *type_new_void(void)
{
static type_t *void_type = NULL;
if (!void_type)
void_type = make_type(0, NULL);
return void_type;
}
static int compute_method_indexes(type_t *iface)
{
int idx;
......
......@@ -30,6 +30,9 @@ type_t *type_new_alias(type_t *t, const char *name);
type_t *type_new_module(char *name);
type_t *type_new_array(const char *name, type_t *element, int declptr,
unsigned int dim, expr_t *size_is, expr_t *length_is);
type_t *type_new_basic(enum type_basic_type basic_type);
type_t *type_new_int(enum type_basic_type basic_type, int sign);
type_t *type_new_void(void);
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts);
void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods);
void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface);
......@@ -56,9 +59,41 @@ static inline enum type_type type_get_type(const type_t *type)
static inline unsigned char type_basic_get_fc(const type_t *type)
{
int sign;
type = type_get_real_type(type);
assert(type_get_type(type) == TYPE_BASIC);
return type->type;
sign = type->details.basic.sign;
switch (type->details.basic.type)
{
case TYPE_BASIC_INT8: return (sign <= 0 ? RPC_FC_SMALL : RPC_FC_USMALL);
case TYPE_BASIC_INT16: return (sign <= 0 ? RPC_FC_SHORT : RPC_FC_USHORT);
case TYPE_BASIC_INT32: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG);
case TYPE_BASIC_INT64: return RPC_FC_HYPER;
case TYPE_BASIC_INT: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG);
case TYPE_BASIC_BYTE: return RPC_FC_BYTE;
case TYPE_BASIC_CHAR: return RPC_FC_CHAR;
case TYPE_BASIC_WCHAR: return RPC_FC_WCHAR;
case TYPE_BASIC_HYPER: return RPC_FC_HYPER;
case TYPE_BASIC_FLOAT: return RPC_FC_FLOAT;
case TYPE_BASIC_DOUBLE: return RPC_FC_DOUBLE;
case TYPE_BASIC_ERROR_STATUS_T: return RPC_FC_ERROR_STATUS_T;
case TYPE_BASIC_HANDLE: return RPC_FC_BIND_PRIMITIVE;
default: return 0;
}
}
static inline enum type_basic_type type_basic_get_type(const type_t *type)
{
type = type_get_real_type(type);
assert(type_get_type(type) == TYPE_BASIC);
return type->details.basic.type;
}
static inline int type_basic_get_sign(const type_t *type)
{
type = type_get_real_type(type);
assert(type_get_type(type) == TYPE_BASIC);
return type->details.basic.sign;
}
static inline var_list_t *type_struct_get_fields(const type_t *type)
......
......@@ -221,6 +221,27 @@ enum statement_type
STMT_CPPQUOTE
};
enum type_basic_type
{
TYPE_BASIC_INT8 = 1,
TYPE_BASIC_INT16,
TYPE_BASIC_INT32,
TYPE_BASIC_INT64,
TYPE_BASIC_INT,
TYPE_BASIC_CHAR,
TYPE_BASIC_HYPER,
TYPE_BASIC_BYTE,
TYPE_BASIC_WCHAR,
TYPE_BASIC_FLOAT,
TYPE_BASIC_DOUBLE,
TYPE_BASIC_ERROR_STATUS_T,
TYPE_BASIC_HANDLE,
};
#define TYPE_BASIC_MAX TYPE_BASIC_HANDLE
#define TYPE_BASIC_INT_MIN TYPE_BASIC_INT8
#define TYPE_BASIC_INT_MAX TYPE_BASIC_HYPER
struct _loc_info_t
{
const char *input_name;
......@@ -303,6 +324,12 @@ struct coclass_details
ifref_list_t *ifaces;
};
struct basic_details
{
enum type_basic_type type;
int sign;
};
enum type_type
{
TYPE_VOID,
......@@ -334,6 +361,7 @@ struct _type_t {
struct module_details *module;
struct array_details array;
struct coclass_details coclass;
struct basic_details basic;
} details;
type_t *orig; /* dup'd types */
unsigned int typestring_offset;
......@@ -347,7 +375,6 @@ struct _type_t {
unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */
unsigned int checked : 1;
unsigned int is_alias : 1; /* is the type an alias? */
int sign : 2;
};
struct _var_t {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment