sub_401000 compiles
[ia32rtools.git] / tools / protoparse.h
CommitLineData
c36e914d 1
2struct parsed_proto {
3 struct {
4 char *reg;
5 const char *type;
91977a1c 6 void *datap;
c36e914d 7 } arg[16];
8 const char *ret_type;
9 int is_stdcall;
10 int argc;
11 int argc_stack;
12 int argc_reg;
13};
14
15static const char *hdrfn;
16static int hdrfline = 0;
17
18static int find_protostr(char *dst, size_t dlen, FILE *fhdr, const char *sym)
19{
20 int line = 0;
21 char *p;
22
23 rewind(fhdr);
24
25 while (fgets(dst, dlen, fhdr))
26 {
27 line++;
28 if (strstr(dst, sym) != NULL)
29 break;
30 }
31 hdrfline = line;
32
33 if (feof(fhdr))
34 return -1;
35
36 p = dst + strlen(dst);
37 for (p--; p > dst && my_isblank(*p); --p)
38 *p = 0;
39
40 return 0;
41}
42
43static int get_regparm(char *dst, size_t dlen, char *p)
44{
45 int i, o;
46
47 if (*p != '<')
48 return 0;
49
50 for (o = 0, i = 1; o < dlen; i++) {
51 if (p[i] == 0)
52 return 0;
53 if (p[i] == '>')
54 break;
55 dst[o++] = p[i];
56 }
57 dst[o] = 0;
58 return i + 1;
59}
60
61// hmh..
62static const char *known_types[] = {
63 "const void *",
64 "void *",
65 "char *",
66 "FILE *",
67 "unsigned __int8",
68 "unsigned __int16",
69 "unsigned int",
70 "signed int",
71 "char",
72 "__int8",
73 "__int16",
74 "int",
75 "bool",
76 "void",
77 "BYTE",
78 "WORD",
79 "DWORD",
91977a1c 80 "_DWORD",
c36e914d 81 "HMODULE",
82 "HANDLE",
83 "HWND",
84 "LPCSTR",
85 "size_t",
86};
87
88static const char *check_type(const char *name)
89{
90 int i, l;
91
92 for (i = 0; i < ARRAY_SIZE(known_types); i++) {
93 l = strlen(known_types[i]);
94 if (strncmp(known_types[i], name, l) == 0)
95 return known_types[i];
96 }
97
98 return NULL;
99}
100
101/* args are always expanded to 32bit */
102static const char *map_reg(const char *reg)
103{
104 const char *regs_f[] = { "eax", "ebx", "ecx", "edx", "esi", "edi" };
105 const char *regs_w[] = { "ax", "bx", "cx", "dx", "si", "di" };
106 const char *regs_b[] = { "al", "bl", "cl", "dl" };
107 int i;
108
109 for (i = 0; i < ARRAY_SIZE(regs_w); i++)
110 if (IS(reg, regs_w[i]))
111 return regs_f[i];
112
113 for (i = 0; i < ARRAY_SIZE(regs_b); i++)
114 if (IS(reg, regs_b[i]))
115 return regs_f[i];
116
117 return reg;
118}
119
120static int parse_protostr(char *protostr, struct parsed_proto *pp)
121{
122 char regparm[16];
123 char buf[256];
124 char cconv[32];
125 const char *kt;
126 int xarg = 0;
127 int ret;
128 char *p;
129 int i;
130
131 p = protostr;
132 if (p[0] == '/' && p[1] == '/') {
133 //printf("warning: decl for sym '%s' is commented out\n", sym);
134 p = sskip(p + 2);
135 }
136
137 kt = check_type(p);
138 if (kt == NULL) {
139 printf("%s:%d:%ld: unhandled return in '%s'\n",
140 hdrfn, hdrfline, (p - protostr) + 1, protostr);
141 return 1;
142 }
143 pp->ret_type = kt;
144 p += strlen(kt);
145 p = sskip(p);
146
147 p = next_word(cconv, sizeof(cconv), p);
148 p = sskip(p);
149 if (cconv[0] == 0) {
150 printf("%s:%d:%ld: cconv missing\n",
151 hdrfn, hdrfline, (p - protostr) + 1);
152 return 1;
153 }
154 if (IS(cconv, "__cdecl"))
155 pp->is_stdcall = 0;
156 else if (IS(cconv, "__stdcall"))
157 pp->is_stdcall = 1;
158 else if (IS(cconv, "__fastcall"))
159 pp->is_stdcall = 1;
160 else if (IS(cconv, "__thiscall"))
161 pp->is_stdcall = 1;
162 else if (IS(cconv, "__userpurge"))
163 pp->is_stdcall = 1; // in all cases seen..
164 else if (IS(cconv, "__usercall"))
165 pp->is_stdcall = 0; // ..or is it?
166 else {
167 printf("%s:%d:%ld: unhandled cconv: '%s'\n",
168 hdrfn, hdrfline, (p - protostr) + 1, cconv);
169 return 1;
170 }
171
172 p = next_idt(buf, sizeof(buf), p);
173 p = sskip(p);
174 if (buf[0] == 0) {
175 printf("%s:%d:%ld: func name missing\n",
176 hdrfn, hdrfline, (p - protostr) + 1);
177 return 1;
178 }
179
180 ret = get_regparm(regparm, sizeof(regparm), p);
181 if (ret > 0) {
182 if (!IS(regparm, "eax") && !IS(regparm, "ax")
183 && !IS(regparm, "al"))
184 {
185 printf("%s:%d:%ld: bad regparm: %s\n",
186 hdrfn, hdrfline, (p - protostr) + 1, regparm);
187 return 1;
188 }
189 p += ret;
190 p = sskip(p);
191 }
192
193 if (*p != '(') {
194 printf("%s:%d:%ld: '(' expected, got '%c'\n",
195 hdrfn, hdrfline, (p - protostr) + 1, *p);
196 return 1;
197 }
198 p++;
199
200 while (1) {
201 p = sskip(p);
202 if (*p == ')')
203 break;
204 if (*p == ',')
205 p = sskip(p + 1);
206
207 xarg++;
208
209 kt = check_type(p);
210 if (kt == NULL) {
211 printf("%s:%d:%ld: unhandled type for arg%d\n",
212 hdrfn, hdrfline, (p - protostr) + 1, xarg);
213 return 1;
214 }
215 pp->arg[xarg - 1].type = kt;
216 p += strlen(kt);
217 p = sskip(p);
218
219 p = next_idt(buf, sizeof(buf), p);
220 p = sskip(p);
221#if 0
222 if (buf[0] == 0) {
223 printf("%s:%d:%ld: idt missing for arg%d\n",
224 hdrfn, hdrfline, (p - protostr) + 1, xarg);
225 return 1;
226 }
227#endif
228 pp->arg[xarg - 1].reg = NULL;
229
230 ret = get_regparm(regparm, sizeof(regparm), p);
231 if (ret > 0) {
232 p += ret;
233 p = sskip(p);
234
235 pp->arg[xarg - 1].reg = strdup(map_reg(regparm));
236 }
237 }
238
239 if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) {
240 if (pp->arg[0].reg != NULL) {
241 printf("%s:%d: %s with arg1 spec %s?\n",
242 hdrfn, hdrfline, cconv, pp->arg[0].reg);
243 }
244 pp->arg[0].reg = strdup("ecx");
245 }
246
247 if (xarg > 1 && IS(cconv, "__fastcall")) {
248 if (pp->arg[1].reg != NULL) {
249 printf("%s:%d: %s with arg2 spec %s?\n",
250 hdrfn, hdrfline, cconv, pp->arg[1].reg);
251 }
252 pp->arg[1].reg = strdup("edx");
253 }
254
255 pp->argc = xarg;
256
257 for (i = 0; i < pp->argc; i++) {
258 if (pp->arg[i].reg == NULL)
259 pp->argc_stack++;
260 else
261 pp->argc_reg++;
262 }
263
264 return 0;
265}
266
267static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp)
268{
269 char protostr[256];
270 int ret;
271
272 memset(pp, 0, sizeof(*pp));
273
274 ret = find_protostr(protostr, sizeof(protostr), fhdr, sym);
275 if (ret != 0) {
276 printf("%s: sym '%s' is missing\n", hdrfn, sym);
277 return ret;
278 }
279
280 return parse_protostr(protostr, pp);
281}
282
283static void proto_release(struct parsed_proto *pp)
284{
285 int i;
286
287 for (i = 0; i < pp->argc; i++) {
288 if (pp->arg[i].reg == NULL)
289 free(pp->arg[i].reg);
290 }
291}