char *name;
unsigned int is_array:1;
unsigned int is_ptr:1;
+ unsigned int is_struct:1; // split for args
};
struct parsed_proto_arg {
unsigned int is_vararg:1;
unsigned int is_fptr:1;
unsigned int is_noreturn:1;
+ unsigned int has_structarg:1;
};
static const char *hdrfn;
static int hdrfline = 0;
+static void pp_copy_arg(struct parsed_proto_arg *d,
+ const struct parsed_proto_arg *s);
+
static int b_pp_c_handler(char *proto, const char *fname);
static int do_protostrs(FILE *fhdr, const char *fname)
"unsigned",
"struct",
"enum",
+ "CONST",
};
static const char *known_ptr_types[] = {
"HBITMAP",
"HCURSOR",
"HDC",
+ "HFONT",
"HGDIOBJ",
"HGLOBAL",
"HINSTANCE",
+ "HIMC",
"HMODULE",
"HRGN",
"HRSRC",
"HKEY",
"HMENU",
"HWND",
- "PLONG",
+ "PCRITICAL_SECTION",
"PDWORD",
+ "PHKEY",
+ "PLONG",
+ "PMEMORY_BASIC_INFORMATION",
+ "PUINT",
"PVOID",
"PCVOID",
"DLGPROC",
+ "TIMERPROC",
+ "WNDENUMPROC",
"va_list",
"__VALIST",
};
break;
}
- if (n[0] == 'L' && n[1] == 'P')
+ if (n[0] == 'L' && n[1] == 'P' && strncmp(n, "LPARAM", 6))
type->is_ptr = 1;
// assume single word
ret = n1 - name;
type->name = strndup(name, ret);
+ if (IS(type->name, "VOID"))
+ memcpy(type->name, "void", 4);
+
return ret;
}
return reg;
}
+static int check_struct_arg(struct parsed_proto_arg *arg)
+{
+ if (IS(arg->type.name, "POINT"))
+ return 2 - 1;
+
+ return 0;
+}
+
static int parse_protostr(char *protostr, struct parsed_proto *pp)
{
struct parsed_proto_arg *arg;
p++;
break;
}
- if (*p == ',')
+ if (xarg > 0) {
+ if (*p != ',') {
+ printf("%s:%d:%zd: ',' expected\n",
+ hdrfn, hdrfline, (p - protostr) + 1);
+ return -1;
+ }
p = sskip(p + 1);
+ }
if (!strncmp(p, "...", 3)) {
pp->is_vararg = 1;
return -1;
}
// we'll treat it as void * for non-calls
- arg->type.name = "void *";
+ arg->type.name = strdup("void *");
arg->type.is_ptr = 1;
p = p1 + ret;
arg->reg = strdup(map_reg(regparm));
}
+
+ ret = check_struct_arg(arg);
+ if (ret > 0) {
+ pp->has_structarg = 1;
+ arg->type.is_struct = 1;
+ free(arg->type.name);
+ arg->type.name = strdup("int");
+ for (l = 0; l < ret; l++) {
+ pp_copy_arg(&pp->arg[xarg], arg);
+ xarg++;
+ }
+ }
}
if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) {
return pp_ret;
}
+static void pp_copy_arg(struct parsed_proto_arg *d,
+ const struct parsed_proto_arg *s)
+{
+ memcpy(d, s, sizeof(*d));
+
+ if (s->reg != NULL) {
+ d->reg = strdup(s->reg);
+ my_assert_not(d->reg, NULL);
+ }
+ if (s->type.name != NULL) {
+ d->type.name = strdup(s->type.name);
+ my_assert_not(d->type.name, NULL);
+ }
+ if (s->fptr != NULL) {
+ d->fptr = malloc(sizeof(*d->fptr));
+ my_assert_not(d->fptr, NULL);
+ memcpy(d->fptr, s->fptr, sizeof(*d->fptr));
+ }
+}
+
struct parsed_proto *proto_clone(const struct parsed_proto *pp_c)
{
struct parsed_proto *pp;
memcpy(pp, pp_c, sizeof(*pp)); // lazy..
// do the actual deep copy..
- for (i = 0; i < pp_c->argc; i++) {
- if (pp_c->arg[i].reg != NULL) {
- pp->arg[i].reg = strdup(pp_c->arg[i].reg);
- my_assert_not(pp->arg[i].reg, NULL);
- }
- if (pp_c->arg[i].type.name != NULL) {
- pp->arg[i].type.name = strdup(pp_c->arg[i].type.name);
- my_assert_not(pp->arg[i].type.name, NULL);
- }
- if (pp_c->arg[i].fptr != NULL) {
- pp->arg[i].fptr = malloc(sizeof(*pp->arg[i].fptr));
- my_assert_not(pp->arg[i].fptr, NULL);
- memcpy(pp->arg[i].fptr, pp_c->arg[i].fptr,
- sizeof(*pp->arg[i].fptr));
- }
- }
+ for (i = 0; i < pp_c->argc; i++)
+ pp_copy_arg(&pp->arg[i], &pp_c->arg[i]);
if (pp_c->ret_type.name != NULL)
pp->ret_type.name = strdup(pp_c->ret_type.name);