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