widl: Use type_get_type to determine the types of types during parsing and checking.
[wine] / tools / widl / typetree.c
1 /*
2  * IDL Type Tree
3  *
4  * Copyright 2008 Robert Shearman
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "widl.h"
28 #include "utils.h"
29 #include "parser.h"
30 #include "typetree.h"
31 #include "header.h"
32
33 type_t *duptype(type_t *t, int dupname)
34 {
35   type_t *d = alloc_type();
36
37   *d = *t;
38   if (dupname && t->name)
39     d->name = xstrdup(t->name);
40
41   return d;
42 }
43
44 type_t *type_new_function(var_list_t *args)
45 {
46     type_t *t = make_type(RPC_FC_FUNCTION, NULL);
47     t->details.function = xmalloc(sizeof(*t->details.function));
48     t->details.function->args = args;
49     t->details.function->idx = -1;
50     return t;
51 }
52
53 type_t *type_new_pointer(type_t *ref, attr_list_t *attrs)
54 {
55     type_t *t = make_type(pointer_default, ref);
56     t->attrs = attrs;
57     return t;
58 }
59
60 type_t *type_new_alias(type_t *t, const char *name)
61 {
62     type_t *a = duptype(t, 0);
63
64     a->name = xstrdup(name);
65     a->attrs = NULL;
66     a->declarray = FALSE;
67     a->orig = t;
68     a->is_alias = TRUE;
69     init_loc_info(&a->loc_info);
70
71     return a;
72 }
73
74 type_t *type_new_module(char *name)
75 {
76     type_t *type = make_type(RPC_FC_MODULE, NULL);
77     type->name = name;
78     /* FIXME: register type to detect multiple definitions */
79     return type;
80 }
81
82 type_t *type_new_array(const char *name, type_t *element, int declarray,
83                        unsigned int dim, expr_t *size_is, expr_t *length_is)
84 {
85     type_t *t = make_type(RPC_FC_LGFARRAY, element);
86     if (name) t->name = xstrdup(name);
87     t->declarray = declarray;
88     t->details.array.length_is = length_is;
89     if (size_is)
90         t->details.array.size_is = size_is;
91     else
92         t->details.array.dim = dim;
93     return t;
94 }
95
96 static int compute_method_indexes(type_t *iface)
97 {
98     int idx;
99     statement_t *stmt;
100
101     if (!iface->details.iface)
102         return 0;
103
104     if (type_iface_get_inherit(iface))
105         idx = compute_method_indexes(type_iface_get_inherit(iface));
106     else
107         idx = 0;
108
109     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
110     {
111         var_t *func = stmt->u.var;
112         if (!is_callas(func->attrs))
113             func->type->details.function->idx = idx++;
114     }
115
116     return idx;
117 }
118
119 void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts)
120 {
121     iface->ref = inherit;
122     iface->details.iface = xmalloc(sizeof(*iface->details.iface));
123     iface->details.iface->disp_props = NULL;
124     iface->details.iface->disp_methods = NULL;
125     iface->details.iface->stmts = stmts;
126     iface->defined = TRUE;
127     compute_method_indexes(iface);
128 }
129
130 void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods)
131 {
132     iface->ref = find_type("IDispatch", 0);
133     if (!iface->ref) error_loc("IDispatch is undefined\n");
134     iface->details.iface = xmalloc(sizeof(*iface->details.iface));
135     iface->details.iface->disp_props = props;
136     iface->details.iface->disp_methods = methods;
137     iface->details.iface->stmts = NULL;
138     iface->defined = TRUE;
139     compute_method_indexes(iface);
140 }
141
142 void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface)
143 {
144     type_dispinterface_define(dispiface, iface->details.iface->disp_props,
145                               iface->details.iface->disp_methods);
146 }
147
148 void type_module_define(type_t *module, statement_list_t *stmts)
149 {
150     if (module->details.module) error_loc("multiple definition error\n");
151     module->details.module = xmalloc(sizeof(*module->details.module));
152     module->details.module->stmts = stmts;
153     module->defined = TRUE;
154 }
155
156 type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces)
157 {
158     coclass->details.coclass.ifaces = ifaces;
159     coclass->defined = TRUE;
160     return coclass;
161 }
162
163 int type_is_equal(const type_t *type1, const type_t *type2)
164 {
165     if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2))
166         return FALSE;
167
168     if (type1->name && type2->name)
169         return !strcmp(type1->name, type2->name);
170     else if ((!type1->name && type2->name) || (type1->name && !type2->name))
171         return FALSE;
172
173     /* FIXME: do deep inspection of types to determine if they are equal */
174
175     return FALSE;
176 }