double __cdecl atof (const char*);
int __cdecl atoi (const char*);
long __cdecl atol (const char*);
-
size_t __cdecl strlen (const char*) ;
char* __cdecl strncat (char*, const char*, size_t);
int __cdecl strncmp (const char*, const char*, size_t) ;
char* __cdecl strtok (char*, const char*);
size_t __cdecl strxfrm (char*, const char*, size_t);
+char* __cdecl _strerror (const char *);
+void* __cdecl _memccpy (void*, const void*, int, size_t);
+int __cdecl _memicmp (const void*, const void*, size_t);
+char* __cdecl _strdup (const char*);
+int __cdecl _strcmpi (const char*, const char*);
+int __cdecl _stricmp (const char*, const char*);
+int __cdecl _stricoll (const char*, const char*);
+char* __cdecl _strlwr (char*);
+int __cdecl _strnicmp (const char*, const char*, size_t);
+char* __cdecl _strnset (char*, int, size_t);
+char* __cdecl _strrev (char*);
+char* __cdecl _strset (char*, int);
+char* __cdecl _strupr (char*);
+void __cdecl _swab (const char*, char*, size_t);
+
int __cdecl isalnum(int);
int __cdecl isalpha(int);
int __cdecl iscntrl(int);
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)
"HBITMAP",
"HCURSOR",
"HDC",
+ "HFONT",
"HGDIOBJ",
"HGLOBAL",
"HINSTANCE",
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
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;
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);
if (tmplmod < opr->lmod)
opr->size_lt = 1;
}
+ opr->is_ptr = pp->type.is_ptr;
}
- opr->is_ptr = pp->type.is_ptr;
opr->is_array = pp->type.is_array;
}
static int collect_call_args(struct parsed_op *po, int i,
struct parsed_proto *pp, int *save_arg_vars, int arg,
- int need_op_saving, int branched)
+ int need_op_saving, int may_reuse)
{
struct parsed_proto *pp_tmp;
struct label_ref *lr;
for (j = i; j >= 0 && arg < pp->argc; )
{
if (g_labels[j][0] != 0) {
- branched = 1;
lr = &g_label_refs[j];
if (lr->next != NULL)
need_op_saving = 1;
- for (; lr->next; lr = lr->next)
+ for (; lr->next; lr = lr->next) {
+ if ((ops[lr->i].flags & (OPF_JMP|OPF_CC)) != OPF_JMP)
+ may_reuse = 1;
ret |= collect_call_args(po, lr->i, pp, save_arg_vars,
- arg, need_op_saving, branched);
+ arg, need_op_saving, may_reuse);
+ }
+ if ((ops[lr->i].flags & (OPF_JMP|OPF_CC)) != OPF_JMP)
+ may_reuse = 1;
if (j > 0 && LAST_OP(j - 1)) {
// follow last branch in reverse
j = lr->i;
}
need_op_saving = 1;
ret |= collect_call_args(po, lr->i, pp, save_arg_vars,
- arg, need_op_saving, branched);
+ arg, need_op_saving, may_reuse);
}
j--;
pp_tmp = ops[j].datap;
if (pp_tmp == NULL)
ferr(po, "arg collect hit unparsed call\n");
- if (branched && pp_tmp->argc_stack > 0)
+ if (may_reuse && pp_tmp->argc_stack > 0)
ferr(po, "arg collect %d/%d hit '%s' with %d stack args\n",
arg, pp->argc, opr_name(&ops[j], 0), pp_tmp->argc_stack);
}
else if (ops[j].op == OP_POP) {
ferr(po, "arg collect %d/%d hit pop\n", arg, pp->argc);
}
- else if (LAST_OP(j)) {
- break;
- }
else if ((ops[j].flags & (OPF_JMP|OPF_CC)) == (OPF_JMP|OPF_CC))
{
- branched = 1;
+ may_reuse = 1;
}
else if (ops[j].op == OP_PUSH && !(ops[j].flags & OPF_FARG))
{
else if (ops[j].argnum == 0)
ops[j].flags |= OPF_RMD;
- // some PUSHes are reused by calls on multiple branches,
+ // some PUSHes are reused by different calls on other branches,
// but that can't happen if we didn't branch, so they
// can be removed from future searches (handles nested calls)
- if (!branched)
+ if (!may_reuse)
ops[j].flags |= OPF_FARG;
// next arg
lr_new = calloc(1, sizeof(*lr_new));
lr_new->i = op_i;
+ lr_new->next = lr->next;
lr->next = lr_new;
}
else {
if (pp->name[0] == 0)
ferr(po, "missing pp->name\n");
- fprintf(fout, "%s(", pp->name);
+ fprintf(fout, "%s%s(", pp->name,
+ pp->has_structarg ? "_sa" : "");
}
for (arg = 0; arg < pp->argc; arg++) {