15 static const char *hdrfn;
16 static int hdrfline = 0;
18 static int find_protostr(char *dst, size_t dlen, FILE *fhdr, const char *sym)
25 while (fgets(dst, dlen, fhdr))
28 if (strstr(dst, sym) != NULL)
36 p = dst + strlen(dst);
37 for (p--; p > dst && my_isblank(*p); --p)
43 static int get_regparm(char *dst, size_t dlen, char *p)
50 for (o = 0, i = 1; o < dlen; i++) {
62 static const char *known_types[] = {
88 static const char *check_type(const char *name)
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];
101 /* args are always expanded to 32bit */
102 static const char *map_reg(const char *reg)
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" };
109 for (i = 0; i < ARRAY_SIZE(regs_w); i++)
110 if (IS(reg, regs_w[i]))
113 for (i = 0; i < ARRAY_SIZE(regs_b); i++)
114 if (IS(reg, regs_b[i]))
120 static int parse_protostr(char *protostr, struct parsed_proto *pp)
132 if (p[0] == '/' && p[1] == '/') {
133 //printf("warning: decl for sym '%s' is commented out\n", sym);
139 printf("%s:%d:%ld: unhandled return in '%s'\n",
140 hdrfn, hdrfline, (p - protostr) + 1, protostr);
147 p = next_word(cconv, sizeof(cconv), p);
150 printf("%s:%d:%ld: cconv missing\n",
151 hdrfn, hdrfline, (p - protostr) + 1);
154 if (IS(cconv, "__cdecl"))
156 else if (IS(cconv, "__stdcall"))
158 else if (IS(cconv, "__fastcall"))
160 else if (IS(cconv, "__thiscall"))
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?
167 printf("%s:%d:%ld: unhandled cconv: '%s'\n",
168 hdrfn, hdrfline, (p - protostr) + 1, cconv);
172 p = next_idt(buf, sizeof(buf), p);
175 printf("%s:%d:%ld: func name missing\n",
176 hdrfn, hdrfline, (p - protostr) + 1);
180 ret = get_regparm(regparm, sizeof(regparm), p);
182 if (!IS(regparm, "eax") && !IS(regparm, "ax")
183 && !IS(regparm, "al"))
185 printf("%s:%d:%ld: bad regparm: %s\n",
186 hdrfn, hdrfline, (p - protostr) + 1, regparm);
194 printf("%s:%d:%ld: '(' expected, got '%c'\n",
195 hdrfn, hdrfline, (p - protostr) + 1, *p);
211 printf("%s:%d:%ld: unhandled type for arg%d\n",
212 hdrfn, hdrfline, (p - protostr) + 1, xarg);
215 pp->arg[xarg - 1].type = kt;
219 p = next_idt(buf, sizeof(buf), p);
223 printf("%s:%d:%ld: idt missing for arg%d\n",
224 hdrfn, hdrfline, (p - protostr) + 1, xarg);
228 pp->arg[xarg - 1].reg = NULL;
230 ret = get_regparm(regparm, sizeof(regparm), p);
235 pp->arg[xarg - 1].reg = strdup(map_reg(regparm));
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);
244 pp->arg[0].reg = strdup("ecx");
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);
252 pp->arg[1].reg = strdup("edx");
257 for (i = 0; i < pp->argc; i++) {
258 if (pp->arg[i].reg == NULL)
267 static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp)
272 memset(pp, 0, sizeof(*pp));
274 ret = find_protostr(protostr, sizeof(protostr), fhdr, sym);
276 printf("%s: sym '%s' is missing\n", hdrfn, sym);
280 return parse_protostr(protostr, pp);
283 static void proto_release(struct parsed_proto *pp)
287 for (i = 0; i < pp->argc; i++) {
288 if (pp->arg[i].reg == NULL)
289 free(pp->arg[i].reg);