PropertyFieldClass::PropertyFieldClass(PropertyGroup * group, IObject * obj, const Property * prop) : PropertyFieldComboBox(group, obj, prop) { const char * str = prop->editorName; String temp, baseClass; str = str_substring(temp.c_str(), 128, str); str = str_substring(baseClass.c_str(), 128, str); d_assert (temp == "PT_Class" && baseClass != ""); Root::ENUM_OBJECT_FACTORY(mClassNames, baseClass.c_str(), true); for (int i = 0; i < mClassNames.Size(); ++i) { mComboBox->Append(mClassNames[i].c_wstr()); } FixedString32 myClass = mProperty->AsFixedString(mObject->GetPropertyData(mProperty)); for (int i = 0; i < mClassNames.Size(); ++i) { if (mClassNames[i] == myClass) { mComboBox->SetSelectIndex(i); break; } } mComboBox->E_SelectChanged += new cListener2<PropertyFieldClass, const MGUI::Event *, int>(this, &PropertyFieldClass::OnSelChanged); }
static inline const char* strip_ext (const char *str) { int len = strlen(str); if (len>4 && strcmp(str+len-4,".dll") == 0) return str_substring (str, str+len-4); else return strdup (str); }
void mafBlock_subAlign(MafBlock *block, int start, int end) { int i, j, oldSeqlen = block->seqlen; MafSubBlock *sub; String *str; if (start > end || start <= 0 || start > oldSeqlen || end <= 0 || end > oldSeqlen) die("ERROR: mafBlock_subAlign got start=%i, end=%i, seqlen=%i\n", start, end, oldSeqlen); if (end==oldSeqlen && start==1) return; //nothing to do start--; //convert to zero-based coords block->seqlen = end-start; for (i=0; i<lst_size(block->data); i++) { sub = (MafSubBlock*)lst_get_ptr(block->data, i); if (sub->lineType[0]=='e') continue; //e-lines remain unchanged if (sub->lineType[0] != 's') die("ERROR mafBlock_sub_align: expected lineType 's', got %c\n", sub->lineType[0]); for (j=0; j<start; j++) if (sub->seq->chars[j]!='-') sub->start++; sub->size = 0; for (j=start; j<end; j++) if (sub->seq->chars[j] != '-') sub->size++; mafSubBlock_strip_iLine(sub); //get rid of i-line if exists mafSubBlock_strip_iLine(sub); //trim seq and quality scores str = str_new(end-start); str_substring(str, sub->seq, start, end-start); str_free(sub->seq); sub->seq = str; if (sub->quality != NULL) { str = str_new(end-start); str_substring(str, sub->quality, start, end-start); str_free(sub->quality); sub->quality = str; } } }
/******************************************************************* * demangle_symbol * * Demangle a C++ linker symbol into a C prototype */ int symbol_demangle (parsed_symbol *sym) { compound_type ct; int is_static = 0, is_const = 0; char *function_name = NULL; char *class_name = NULL; char *name; const char *const_status; static unsigned int hash = 0; /* In case of overloaded functions */ unsigned int data_flags = 0; assert (globals.do_code); assert (sym && sym->symbol); hash++; /* MS mangled names always begin with '?' */ name = sym->symbol; if (*name++ != '?') return -1; if (VERBOSE) puts ("Attempting to demangle symbol"); /* Then function name or operator code */ if (*name == '?') { /* C++ operator code (one character, or two if the first is '_') */ switch (*++name) { case '0': function_name = strdup ("ctor"); break; case '1': function_name = strdup ("dtor"); break; case '2': function_name = strdup ("operator_new"); break; case '3': function_name = strdup ("operator_delete"); break; case '4': function_name = strdup ("operator_equals"); break; case '5': function_name = strdup ("operator_shiftright"); break; case '6': function_name = strdup ("operator_shiftleft"); break; case '7': function_name = strdup ("operator_not"); break; case '8': function_name = strdup ("operator_equalsequals"); break; case '9': function_name = strdup ("operator_notequals"); break; case 'A': function_name = strdup ("operator_array"); break; case 'C': function_name = strdup ("operator_dereference"); break; case 'D': function_name = strdup ("operator_multiply"); break; case 'E': function_name = strdup ("operator_plusplus"); break; case 'F': function_name = strdup ("operator_minusminus"); break; case 'G': function_name = strdup ("operator_minus"); break; case 'H': function_name = strdup ("operator_plus"); break; case 'I': function_name = strdup ("operator_address"); break; case 'J': function_name = strdup ("operator_dereferencememberptr"); break; case 'K': function_name = strdup ("operator_divide"); break; case 'L': function_name = strdup ("operator_modulo"); break; case 'M': function_name = strdup ("operator_lessthan"); break; case 'N': function_name = strdup ("operator_lessthanequal"); break; case 'O': function_name = strdup ("operator_greaterthan"); break; case 'P': function_name = strdup ("operator_greaterthanequal"); break; case 'Q': function_name = strdup ("operator_comma"); break; case 'R': function_name = strdup ("operator_functioncall"); break; case 'S': function_name = strdup ("operator_complement"); break; case 'T': function_name = strdup ("operator_xor"); break; case 'U': function_name = strdup ("operator_logicalor"); break; case 'V': function_name = strdup ("operator_logicaland"); break; case 'W': function_name = strdup ("operator_or"); break; case 'X': function_name = strdup ("operator_multiplyequals"); break; case 'Y': function_name = strdup ("operator_plusequals"); break; case 'Z': function_name = strdup ("operator_minusequals"); break; case '_': switch (*++name) { case '0': function_name = strdup ("operator_divideequals"); break; case '1': function_name = strdup ("operator_moduloequals"); break; case '2': function_name = strdup ("operator_shiftrightequals"); break; case '3': function_name = strdup ("operator_shiftleftequals"); break; case '4': function_name = strdup ("operator_andequals"); break; case '5': function_name = strdup ("operator_orequals"); break; case '6': function_name = strdup ("operator_xorequals"); break; case '7': function_name = strdup ("vftable"); data_flags = DATA_VTABLE; break; case '8': function_name = strdup ("vbtable"); data_flags = DATA_VTABLE; break; case '9': function_name = strdup ("vcall"); data_flags = DATA_VTABLE; break; case 'A': function_name = strdup ("typeof"); data_flags = DATA_VTABLE; break; case 'B': function_name = strdup ("local_static_guard"); data_flags = DATA_VTABLE; break; case 'C': function_name = strdup ("string"); data_flags = DATA_VTABLE; break; case 'D': function_name = strdup ("vbase_dtor"); data_flags = DATA_VTABLE; break; case 'E': function_name = strdup ("vector_dtor"); break; case 'G': function_name = strdup ("scalar_dtor"); break; case 'H': function_name = strdup ("vector_ctor_iter"); break; case 'I': function_name = strdup ("vector_dtor_iter"); break; case 'J': function_name = strdup ("vector_vbase_ctor_iter"); break; case 'L': function_name = strdup ("eh_vector_ctor_iter"); break; case 'M': function_name = strdup ("eh_vector_dtor_iter"); break; case 'N': function_name = strdup ("eh_vector_vbase_ctor_iter"); break; case 'O': function_name = strdup ("copy_ctor_closure"); break; case 'S': function_name = strdup ("local_vftable"); data_flags = DATA_VTABLE; break; case 'T': function_name = strdup ("local_vftable_ctor_closure"); break; case 'U': function_name = strdup ("operator_new_vector"); break; case 'V': function_name = strdup ("operator_delete_vector"); break; case 'X': function_name = strdup ("placement_new_closure"); break; case 'Y': function_name = strdup ("placement_delete_closure"); break; default: return -1; } break; default: /* FIXME: Other operators */ return -1; } name++; } else { /* Type or function name terminated by '@' */ function_name = name; while (*name && *name++ != '@') ; if (!*name) return -1; function_name = str_substring (function_name, name - 1); } /* Either a class name, or '@' if the symbol is not a class member */ if (*name == '@') { class_name = strdup ("global"); /* Non member function (or a datatype) */ name++; } else { /* Class the function is associated with, terminated by '@@' */ class_name = name; while (*name && *name++ != '@') ; if (*name++ != '@') { free (function_name); return -1; } class_name = str_substring (class_name, name - 2); /* Allocates a new string */ } /* Function/Data type and access level */ /* FIXME: why 2 possible letters for each option? */ switch(*name++) { /* Data */ case '0' : /* private static */ case '1' : /* protected static */ case '2' : /* public static */ is_static = 1; /* Fall through */ case '3' : /* non static */ case '4' : /* non static */ /* Data members need to be implemented: report */ INIT_CT (ct); if (!demangle_datatype (&name, &ct, sym)) { if (VERBOSE) printf ("/*FIXME: %s: unknown data*/\n", sym->symbol); free (function_name); free (class_name); return -1; } sym->flags |= SYM_DATA; sym->argc = 1; sym->arg_name[0] = str_create (5, OUTPUT_UC_DLL_NAME, "_", class_name, is_static ? "static_" : "_", function_name); sym->arg_text[0] = str_create (3, ct.expression, " ", sym->arg_name[0]); FREE_CT (ct); free (function_name); free (class_name); return 0; case '6' : /* compiler generated static */ case '7' : /* compiler generated static */ if (data_flags & DATA_VTABLE) { sym->flags |= SYM_DATA; sym->argc = 1; sym->arg_name[0] = str_create (5, OUTPUT_UC_DLL_NAME, "_", class_name, "_", function_name); sym->arg_text[0] = str_create (2, "void *", sym->arg_name[0]); if (VERBOSE) puts ("Demangled symbol OK [vtable]"); free (function_name); free (class_name); return 0; } free (function_name); free (class_name); return -1; /* Functions */ case 'E' : /* private virtual */ case 'F' : /* private virtual */ case 'M' : /* protected virtual */ case 'N' : /* protected virtual */ case 'U' : /* public virtual */ case 'V' : /* public virtual */ /* Virtual functions need to be added to the exported vtable: report */ if (VERBOSE) printf ("/*FIXME %s: %s::%s is virtual-add to vftable*/\n", sym->symbol, class_name, function_name); /* Fall through */ case 'A' : /* private */ case 'B' : /* private */ case 'I' : /* protected */ case 'J' : /* protected */ case 'Q' : /* public */ case 'R' : /* public */ /* Implicit 'this' pointer */ sym->arg_text [sym->argc] = str_create (3, "struct ", class_name, " *"); sym->arg_type [sym->argc] = ARG_POINTER; sym->arg_flag [sym->argc] = 0; sym->arg_name [sym->argc++] = strdup ("_this"); /* New struct definitions can be 'grep'ed out for making a fixup header */ if (VERBOSE) printf ("struct %s { void **vtable; /*FIXME: class definition */ };\n", class_name); break; case 'C' : /* private: static */ case 'D' : /* private: static */ case 'K' : /* protected: static */ case 'L' : /* protected: static */ case 'S' : /* public: static */ case 'T' : /* public: static */ is_static = 1; /* No implicit this pointer */ break; case 'Y' : case 'Z' : break; /* FIXME: G,H / O,P / W,X are private / protected / public thunks */ default: free (function_name); free (class_name); return -1; } /* If there is an implicit this pointer, const status follows */ if (sym->argc) { switch (*name++) { case 'A': break; /* non-const */ case 'B': is_const = CT_CONST; break; case 'C': is_const = CT_VOLATILE; break; case 'D': is_const = (CT_CONST | CT_VOLATILE); break; default: free (function_name); free (class_name); return -1; } } /* Next is the calling convention */ switch (*name++) { case 'A': /* __cdecl */ case 'B': /* __cdecl __declspec(dllexport) */ if (!sym->argc) { sym->flags |= SYM_CDECL; break; } /* Else fall through */ case 'C': /* __pascal */ case 'D': /* __pascal __declspec(dllexport) */ case 'E': /* __thiscall */ case 'F': /* __thiscall __declspec(dllexport) */ case 'G': /* __stdcall */ case 'H': /* __stdcall __declspec(dllexport) */ case 'I': /* __fastcall */ case 'J': /* __fastcall __declspec(dllexport)*/ case 'K': /* default (none given) */ if (sym->argc) sym->flags |= SYM_THISCALL; else sym->flags |= SYM_STDCALL; break; default: free (function_name); free (class_name); return -1; } /* Return type, or @ if 'void' */ if (*name == '@') { sym->return_text = strdup ("void"); sym->return_type = ARG_VOID; name++; } else { INIT_CT (ct); if (!demangle_datatype (&name, &ct, sym)) { free (function_name); free (class_name); return -1; } sym->return_text = ct.expression; sym->return_type = get_type_constant(ct.dest_type, ct.flags); ct.expression = NULL; FREE_CT (ct); } /* Now come the function arguments */ while (*name && *name != 'Z') { /* Decode each data type and append it to the argument list */ if (*name != '@') { INIT_CT (ct); if (!demangle_datatype(&name, &ct, sym)) { free (function_name); free (class_name); return -1; } if (strcmp (ct.expression, "void")) { sym->arg_text [sym->argc] = ct.expression; ct.expression = NULL; sym->arg_type [sym->argc] = get_type_constant (ct.dest_type, ct.flags); sym->arg_flag [sym->argc] = ct.flags; sym->arg_name[sym->argc] = str_create_num (1, sym->argc, "arg"); sym->argc++; } else break; /* 'void' terminates an argument list */ FREE_CT (ct); } else name++; } while (*name == '@') name++; /* Functions are always terminated by 'Z'. If we made it this far and * Don't find it, we have incorrectly identified a data type. */ if (*name != 'Z') { free (function_name); free (class_name); return -1; } /* Note: '()' after 'Z' means 'throws', but we don't care here */ /* Create the function name. Include a unique number because otherwise * overloaded functions could have the same c signature. */ switch (is_const) { case (CT_CONST | CT_VOLATILE): const_status = "_const_volatile"; break; case CT_CONST: const_status = "_const"; break; case CT_VOLATILE: const_status = "_volatile"; break; default: const_status = "_"; break; } sym->function_name = str_create_num (4, hash, class_name, "_", function_name, is_static ? "_static" : const_status); assert (sym->return_text); assert (sym->flags); assert (sym->function_name); free (class_name); free (function_name); if (VERBOSE) puts ("Demangled symbol OK"); return 0; }
/******************************************************************* * demangle_datatype * * Attempt to demangle a C++ data type, which may be compound. * a compound type is made up of a number of simple types. e.g: * char** = (pointer to (pointer to (char))) * * Uses a simple recursive descent algorithm that is broken * and/or incomplete, without a doubt ;-) */ static char *demangle_datatype (char **str, compound_type *ct, parsed_symbol* sym) { char *iter; assert (str && *str); assert (ct); iter = *str; if (!get_constraints_convention_1 (&iter, ct)) return NULL; if (*iter == '_') { /* MS type: __int8,__int16 etc */ ct->flags |= CT_EXTENDED; iter++; } switch (*iter) { case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'M': case 'N': case 'O': case 'X': case 'Z': /* Simple data types */ ct->dest_type = *iter++; if (!get_constraints_convention_2 (&iter, ct)) return NULL; ct->expression = get_type_string (ct->dest_type, ct->flags); break; case 'U': case 'V': /* Class/struct/union */ ct->dest_type = *iter++; if (*iter == '0' || *iter == '1') { /* Referring to class type (implicit 'this') */ char *stripped; if (!sym->argc) return NULL; iter++; /* Apply our constraints to the base type (struct xxx *) */ stripped = strdup (sym->arg_text [0]); if (!stripped) fatal ("Out of Memory"); /* If we're a reference, re-use the pointer already in the type */ if (!(ct->flags & CT_BY_REFERENCE)) stripped[ strlen (stripped) - 2] = '\0'; /* otherwise, strip it */ ct->expression = str_create (2, ct->flags & CT_CONST ? "const " : ct->flags & CT_VOLATILE ? "volatile " : "", stripped); free (stripped); } else if (*iter != '@') { /* The name of the class/struct, followed by '@@' */ char *struct_name = iter; while (*iter && *iter++ != '@') ; if (*iter++ != '@') return NULL; struct_name = str_substring (struct_name, iter - 2); ct->expression = str_create (4, ct->flags & CT_CONST ? "const " : ct->flags & CT_VOLATILE ? "volatile " : "", "struct ", struct_name, ct->flags & CT_BY_REFERENCE ? " *" : ""); free (struct_name); } break; case 'Q': /* FIXME: Array Just treated as pointer currently */ case 'P': /* Pointer */ { compound_type sub_ct; INIT_CT (sub_ct); ct->dest_type = *iter++; if (!get_constraints_convention_2 (&iter, ct)) return NULL; /* FIXME: P6 = Function pointer, others who knows.. */ if (isdigit (*iter)) { if (*iter == '6') { int sub_expressions = 0; /* FIXME: there are a tons of memory leaks here */ /* FIXME: this is still broken in some cases and it has to be * merged with the function prototype parsing above... */ iter += iter[1] == 'A' ? 2 : 3; /* FIXME */ if (!demangle_datatype (&iter, &sub_ct, sym)) return NULL; ct->expression = str_create(2, sub_ct.expression, " (*)("); if (*iter != '@') { while (*iter != 'Z') { FREE_CT (sub_ct); INIT_CT (sub_ct); if (!demangle_datatype (&iter, &sub_ct, sym)) return NULL; if (sub_expressions) ct->expression = str_create(3, ct->expression, ", ", sub_ct.expression); else ct->expression = str_create(2, ct->expression, sub_ct.expression); while (*iter == '@') iter++; sub_expressions++; } } else while (*iter == '@') iter++; iter++; ct->expression = str_create(2, ct->expression, ")"); } else return NULL; } else { /* Recurse to get the pointed-to type */ if (!demangle_datatype (&iter, &sub_ct, sym)) return NULL; ct->expression = get_pointer_type_string (ct, sub_ct.expression); } FREE_CT (sub_ct); } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Referring back to previously parsed type */ if (sym->argc >= (size_t)('0' - *iter)) return NULL; ct->dest_type = sym->arg_type ['0' - *iter]; ct->expression = strdup (sym->arg_text ['0' - *iter]); iter++; break; default : return NULL; } if (!ct->expression) return NULL; return (char *)(*str = iter); }
LocalPwAlignment *la_read_lav(FILE *F, int read_seqs) { String *line = str_new(STR_MED_LEN); int line_no=0; LocalPwAlignment *lpwa = la_new(); List *fields = lst_new_ptr(6); Regex *stanza_start_re = str_re_new("^([dshaxm])[[:space:]]*{"); AlignmentBlock *aln_block = NULL; char stanza_type = '\0'; int i; int done_with[256]; done_with[(int)'d'] = done_with[(int)'s'] = done_with[(int)'h'] = done_with[(int)'x'] = done_with[(int)'m'] = 0; while (str_readline(line, F) != EOF) { str_trim(line); if (line->length == 0) continue; checkInterruptN(line_no, 1000); line_no++; if (line_no == 1) { if (!str_equals_charstr(line, "#:lav")) { die("ERROR: lav file missing header.\n"); } } else if (str_re_match(line, stanza_start_re, fields, 1) >= 0) { String *tmpstr = lst_get_ptr(fields, 1); stanza_type = tmpstr->chars[0]; str_free(tmpstr); str_free(lst_get_ptr(fields, 0)); if (stanza_type != 'a' && done_with[(int)stanza_type]) { die("ERROR: multiple '%c' stanzas in lav file.\n", stanza_type); } if (stanza_type == 'a') { aln_block = la_new_alignment_block(-1, -1, -1, -1, -1, NULL); lst_push_ptr(lpwa->alignment_blocks, aln_block); } } /* end current stanza */ else if (str_equals_charstr(line, "}")) { if (stanza_type == '\0') { die("ERROR: end stanza without matching begin.\n"); } done_with[(int)stanza_type] = 1; stanza_type = '\0'; } else if (stanza_type == 'd') { ; /* do nothing for now */ } else if (stanza_type == 's') { int beg, end; String *tmpstr, *fname, *seq=NULL; FILE *F2; str_double_trim(line); str_split(line, NULL, fields); if (lst_size(fields) != 3 || str_as_int(lst_get_ptr(fields, 1), &beg) != 0 || str_as_int(lst_get_ptr(fields, 2), &end) != 0) { die("ERROR: bad line in 's' stanza in lav file.\n"); } tmpstr = lst_get_ptr(fields, 0); fname = str_new(tmpstr->length-2); /* remove quotes */ str_substring(fname, tmpstr, 1, tmpstr->length-2); if (read_seqs) { F2 = phast_fopen(fname->chars, "r"); seq = msa_read_seq_fasta(F2); phast_fclose(F2); } for (i = 0; i < lst_size(fields); i++) str_free(lst_get_ptr(fields, i)); if (beg != 1) { die("ERROR: unexpected begin index in 's' stanza of lav file (begin index currently must be 1).\n"); } if (lpwa->query_len == -1) { lpwa->query_len = end; if (read_seqs) lpwa->query_seq = seq; } else if (lpwa->target_len == -1) { lpwa->target_len = end; if (read_seqs) lpwa->target_seq = seq; } else { die("ERROR: too many sequences listed in 's' stanza of lav file.\n"); } str_free(fname); } else if (stanza_type == 'h') { String *name; str_double_trim(line); name = str_new(line->length-3); /* get rid of quotes and leading '>' */ str_substring(name, line, 2, line->length-3); if (lpwa->query_name == NULL) lpwa->query_name = name; else if (lpwa->target_name == NULL) lpwa->target_name = name; else { die("ERROR: too many entries in 'h' stanza of lav file.\n"); } } else if (stanza_type == 'a') { String *type; int val[6]; if (!done_with[(int)'s'] || !done_with[(int)'d'] || !done_with[(int)'h']) { die("ERROR: 'a' stanza appears in lav file before 'd', 's', or 'h' stanza.\n"); } str_double_trim(line); str_split(line, NULL, fields); type = lst_get_ptr(fields, 0); if (lst_size(fields) > 6) { die("ERROR: illegal line in 'a' stanza.\n"); } for (i = 1; i < lst_size(fields); i++) { str_as_int(lst_get_ptr(fields, i), &val[i]); str_free(lst_get_ptr(fields, i)); } if (type->chars[0] == 's') aln_block->score = val[1]; else if (type->chars[0] == 'b') { aln_block->query_beg = val[1]; aln_block->target_beg = val[2]; } else if (type->chars[0] == 'e') { aln_block->query_end = val[1]; aln_block->target_end = val[2]; } else if (type->chars[0] == 'l') lst_push_ptr(aln_block->gapless_alns, la_new_gapless_aln(val[1], val[3], val[2], val[4])); str_free(type); } } str_free(line); lst_free(fields); str_re_free(stanza_start_re); return lpwa; }
/******************************************************************* * get_type * * Read a type from a prototype */ static const char *get_type (parsed_symbol *sym, const char *proto, int arg) { int is_const, is_volatile, is_struct, is_signed, is_unsigned, ptrs = 0; const char *iter, *type_str, *base_type, *catch_unsigned; char dest_type; assert (sym && sym->symbol); assert (proto && *proto); assert (arg < 0 || (unsigned)arg == sym->argc); type_str = proto; proto = str_match (proto, "const", &is_const); proto = str_match (proto, "volatile", &is_volatile); proto = str_match (proto, "struct", &is_struct); if (!is_struct) proto = str_match (proto, "union", &is_struct); catch_unsigned = proto; proto = str_match (proto, "unsigned", &is_unsigned); proto = str_match (proto, "signed", &is_signed); /* Can have 'unsigned const' or 'const unsigned' etc */ if (!is_const) proto = str_match (proto, "const", &is_const); if (!is_volatile) proto = str_match (proto, "volatile", &is_volatile); base_type = proto; iter = str_find_set (proto, " ,*)"); if (!iter) return NULL; if (arg < 0 && (is_signed || is_unsigned)) { /* Prevent calling convention from being swallowed by 'un/signed' alone */ if (strncmp (base_type, "int", 3) && strncmp (base_type, "long", 4) && strncmp (base_type, "short", 5) && strncmp (base_type, "char", 4)) { iter = proto; base_type = catch_unsigned; } else catch_unsigned = NULL; } else catch_unsigned = NULL; /* FIXME: skip const/volatile here too */ for (proto = iter; *proto; proto++) if (*proto == '*') ptrs++; else if (*proto != ' ') break; if (!*proto) return NULL; type_str = str_substring (type_str, proto); if (iter == base_type || catch_unsigned) { /* 'unsigned' with no type */ char *tmp = str_create (2, type_str, " int"); free ((char*)type_str); type_str = tmp; } symbol_clean_string (type_str); dest_type = symbol_get_type (type_str); if (arg < 0) { sym->return_text = (char*)type_str; sym->return_type = dest_type; } else { sym->arg_type [arg] = dest_type; sym->arg_flag [arg] = is_const ? CT_CONST : is_volatile ? CT_VOLATILE : 0; if (*proto == ',' || *proto == ')') sym->arg_name [arg] = str_create_num (1, arg, "arg"); else { iter = str_find_set (proto, " ,)"); if (!iter) { free ((char*)type_str); return NULL; } sym->arg_name [arg] = str_substring (proto, iter); proto = iter; } sym->arg_text [arg] = (char*)type_str; } return proto; }
/******************************************************************* * symbol_from_prototype * * Convert a C prototype into a symbol */ static int symbol_from_prototype (parsed_symbol *sym, const char *proto) { const char *iter; int found; proto = get_type (sym, proto, -1); /* Get return type */ if (!proto) return -1; iter = str_match (proto, sym->symbol, &found); if (!found) { char *call; /* Calling Convention */ iter = strchr (iter, ' '); if (!iter) return -1; call = str_substring (proto, iter); if (!strcasecmp (call, "cdecl") || !strcasecmp (call, "__cdecl")) sym->flags |= SYM_CDECL; else sym->flags |= SYM_STDCALL; free (call); iter = str_match (iter, sym->symbol, &found); if (!found) return -1; if (VERBOSE) printf ("Using %s calling convention\n", sym->flags & SYM_CDECL ? "cdecl" : "stdcall"); } else sym->flags = CALLING_CONVENTION; sym->function_name = strdup (sym->symbol); proto = iter; /* Now should be the arguments */ if (*proto++ != '(') return -1; for (; *proto == ' '; proto++); if (!strncmp (proto, "void", 4)) return 0; do { /* Process next argument */ str_match (proto, "...", &sym->varargs); if (sym->varargs) return 0; if (!(proto = get_type (sym, proto, sym->argc))) return -1; sym->argc++; if (*proto == ',') proto++; else if (*proto != ')') return -1; } while (*proto != ')'); return 0; }