int ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine) { char *pc, *pcLine; int nLine; EXPORT exp; int included; //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart); /* Loop all lines */ nLine = 1; exp.nNumber = 0; for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++) { pc = pcLine; exp.nArgCount = 0; exp.uFlags = 0; exp.nNumber++; //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n", // nLine, TokenLength(pcLine), pcLine); /* Skip white spaces */ while (*pc == ' ' || *pc == '\t') pc++; /* Skip empty lines, stop at EOF */ if (*pc == ';' || *pc <= '#') continue; if (*pc == 0) return 0; //fprintf(stderr, "info: line %d, token:'%.*s'\n", // nLine, TokenLength(pc), pc); /* Now we should get either an ordinal or @ */ if (*pc == '@') exp.nOrdinal = -1; else exp.nOrdinal = atol(pc); /* Go to next token (type) */ if (!(pc = NextToken(pc))) { fprintf(stderr, "error: line %d, unexpected end of line\n", nLine); return -10; } //fprintf(stderr, "info: Token:'%.10s'\n", pc); /* Now we should get the type */ if (CompareToken(pc, "stdcall")) { exp.nCallingConvention = CC_STDCALL; } else if (CompareToken(pc, "cdecl") || CompareToken(pc, "varargs")) { exp.nCallingConvention = CC_CDECL; } else if (CompareToken(pc, "fastcall")) { exp.nCallingConvention = CC_FASTCALL; } else if (CompareToken(pc, "thiscall")) { exp.nCallingConvention = CC_THISCALL; } else if (CompareToken(pc, "extern")) { exp.nCallingConvention = CC_EXTERN; } else if (CompareToken(pc, "stub")) { exp.nCallingConvention = CC_STUB; } else { fprintf(stderr, "error: line %d, expected type, got '%.*s' %d\n", nLine, TokenLength(pc), pc, *pc); return -11; } //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention); /* Go to next token (options or name) */ if (!(pc = NextToken(pc))) { fprintf(stderr, "fail2\n"); return -12; } /* Handle options */ included = 1; while (*pc == '-') { if (CompareToken(pc, "-arch")) { /* Default to not included */ included = 0; pc += 5; /* Look if we are included */ while (*pc == '=' || *pc == ',') { pc++; if (CompareToken(pc, pszArchString) || CompareToken(pc, pszArchString2)) { included = 1; } /* Skip to next arch or end */ while (*pc > ',') pc++; } } else if (CompareToken(pc, "-i386")) { if (giArch != ARCH_X86) included = 0; } else if (CompareToken(pc, "-private")) { exp.uFlags |= FL_PRIVATE; } else if (CompareToken(pc, "-noname") || CompareToken(pc, "-ordinal")) { exp.uFlags |= FL_NONAME; } else if (CompareToken(pc, "-stub")) { exp.uFlags |= FL_STUB; } else if (CompareToken(pc, "-norelay") || CompareToken(pc, "-register") || CompareToken(pc, "-ret64")) { /* silently ignore these */ } else { fprintf(stderr, "info: ignored option: '%.*s'\n", TokenLength(pc), pc); } /* Go to next token */ pc = NextToken(pc); } //fprintf(stderr, "info: Name:'%.10s'\n", pc); /* If arch didn't match ours, skip this entry */ if (!included) continue; /* Get name */ exp.pcName = pc; exp.nNameLength = TokenLength(pc); /* Handle parameters */ exp.nStackBytes = 0; if (exp.nCallingConvention != CC_EXTERN && exp.nCallingConvention != CC_STUB) { //fprintf(stderr, "info: options:'%.10s'\n", pc); /* Go to next token */ if (!(pc = NextToken(pc))) { fprintf(stderr, "fail4\n"); return -13; } /* Verify syntax */ if (*pc++ != '(') { fprintf(stderr, "error: line %d, expected '('\n", nLine); return -14; } /* Skip whitespaces */ while (*pc == ' ' || *pc == '\t') pc++; exp.nStackBytes = 0; while (*pc >= '0') { if (CompareToken(pc, "long")) { exp.nStackBytes += 4; exp.anArgs[exp.nArgCount] = ARG_LONG; } else if (CompareToken(pc, "double")) { exp.nStackBytes += 8; exp.anArgs[exp.nArgCount] = ARG_DBL; } else if (CompareToken(pc, "ptr") || CompareToken(pc, "str") || CompareToken(pc, "wstr")) { exp.nStackBytes += 4; // sizeof(void*) on x86 exp.anArgs[exp.nArgCount] = ARG_PTR; // FIXME: handle strings } else if (CompareToken(pc, "int64")) { exp.nStackBytes += 8; exp.anArgs[exp.nArgCount] = ARG_INT64; } else if (CompareToken(pc, "int128")) { exp.nStackBytes += 16; exp.anArgs[exp.nArgCount] = ARG_INT128; } else if (CompareToken(pc, "float")) { exp.nStackBytes += 4; exp.anArgs[exp.nArgCount] = ARG_FLOAT; } else fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc); exp.nArgCount++; /* Go to next parameter */ if (!(pc = NextToken(pc))) { fprintf(stderr, "fail5\n"); return -15; } } /* Check syntax */ if (*pc++ != ')') { fprintf(stderr, "error: line %d, expected ')'\n", nLine); return -16; } } /* Handle special stub cases */ if (exp.nCallingConvention == CC_STUB) { /* Check for c++ mangled name */ if (pc[0] == '?') { //printf("Found c++ mangled name...\n"); // } else { /* Check for stdcall name */ char *p = strchr(pc, '@'); if (p && ((size_t)(p - pc) < exp.nNameLength)) { int i; exp.nNameLength = p - pc; if (exp.nNameLength < 1) { fprintf(stderr, "error, @ in line %d\n", nLine); return -1; } exp.nStackBytes = atoi(p + 1); exp.nArgCount = exp.nStackBytes / 4; exp.nCallingConvention = CC_STDCALL; exp.uFlags |= FL_STUB; for (i = 0; i < exp.nArgCount; i++) exp.anArgs[i] = ARG_LONG; } } } /* Get optional redirection */ if ((pc = NextToken(pc))) { exp.pcRedirection = pc; exp.nRedirectionLength = TokenLength(pc); /* Check syntax (end of line) */ if (NextToken(pc)) { fprintf(stderr, "error: line %d, additional tokens after ')'\n", nLine); return -17; } } else { exp.pcRedirection = 0; exp.nRedirectionLength = 0; } OutputLine(fileDest, &exp); } return 0; }
int ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine) { char *pc, *pcLine; int nLine; EXPORT exp; int included; char namebuffer[16]; //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart); /* Loop all lines */ nLine = 1; exp.nNumber = 0; for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++) { pc = pcLine; exp.nArgCount = 0; exp.uFlags = 0; exp.nNumber++; //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28)) // gbDebug = 1; //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n", // nLine, TokenLength(pcLine), pcLine); /* Skip white spaces */ while (*pc == ' ' || *pc == '\t') pc++; /* Skip empty lines, stop at EOF */ if (*pc == ';' || *pc <= '#') continue; if (*pc == 0) return 0; //fprintf(stderr, "info: line %d, token:'%.*s'\n", // nLine, TokenLength(pc), pc); /* Now we should get either an ordinal or @ */ if (*pc == '@') exp.nOrdinal = -1; else { exp.nOrdinal = atol(pc); /* The import lib should contain the ordinal only if -ordinal was specified */ if (!gbImportLib) exp.uFlags |= FL_ORDINAL; } /* Go to next token (type) */ if (!(pc = NextToken(pc))) { fprintf(stderr, "error: line %d, unexpected end of line\n", nLine); return -10; } //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc); /* Now we should get the type */ if (CompareToken(pc, "stdcall")) { exp.nCallingConvention = CC_STDCALL; } else if (CompareToken(pc, "cdecl") || CompareToken(pc, "varargs")) { exp.nCallingConvention = CC_CDECL; } else if (CompareToken(pc, "fastcall")) { exp.nCallingConvention = CC_FASTCALL; } else if (CompareToken(pc, "thiscall")) { exp.nCallingConvention = CC_THISCALL; } else if (CompareToken(pc, "extern")) { exp.nCallingConvention = CC_EXTERN; } else if (CompareToken(pc, "stub")) { exp.nCallingConvention = CC_STUB; } else { fprintf(stderr, "error: line %d, expected callconv, got '%.*s' %d\n", nLine, TokenLength(pc), pc, *pc); return -11; } //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention); /* Go to next token (options or name) */ if (!(pc = NextToken(pc))) { fprintf(stderr, "fail2\n"); return -12; } /* Handle options */ included = 1; while (*pc == '-') { if (CompareToken(pc, "-arch")) { /* Default to not included */ included = 0; pc += 5; /* Look if we are included */ while (*pc == '=' || *pc == ',') { pc++; if (CompareToken(pc, pszArchString) || CompareToken(pc, pszArchString2)) { included = 1; } /* Skip to next arch or end */ while (*pc > ',') pc++; } } else if (CompareToken(pc, "-i386")) { if (giArch != ARCH_X86) included = 0; } else if (CompareToken(pc, "-private")) { exp.uFlags |= FL_PRIVATE; } else if (CompareToken(pc, "-noname")) { exp.uFlags |= FL_ORDINAL | FL_NONAME; } else if (CompareToken(pc, "-ordinal")) { exp.uFlags |= FL_ORDINAL; /* GCC doesn't automatically import by ordinal if an ordinal * is found in the def file. Force it. */ if (gbImportLib && !gbMSComp) exp.uFlags |= FL_NONAME; } else if (CompareToken(pc, "-stub")) { exp.uFlags |= FL_STUB; } else if (CompareToken(pc, "-norelay")) { exp.uFlags |= FL_NORELAY; } else if (CompareToken(pc, "-ret64")) { exp.uFlags |= FL_RET64; } else if (CompareToken(pc, "-register")) { exp.uFlags |= FL_REGISTER; } else { fprintf(stderr, "info: ignored option: '%.*s'\n", TokenLength(pc), pc); } /* Go to next token */ pc = NextToken(pc); } //fprintf(stderr, "info: Name:'%.10s'\n", pc); /* If arch didn't match ours, skip this entry */ if (!included) continue; /* Get name */ exp.strName.buf = pc; exp.strName.len = TokenLength(pc); DbgPrint("Got name: '%.*s'\n", exp.strName.len, exp.strName.buf); /* Check for autoname */ if ((exp.strName.len == 1) && (exp.strName.buf[0] == '@')) { sprintf(namebuffer, "ordinal%d", exp.nOrdinal); exp.strName.len = strlen(namebuffer); exp.strName.buf = namebuffer; exp.uFlags |= FL_ORDINAL | FL_NONAME; } /* Handle parameters */ exp.nStackBytes = 0; if (exp.nCallingConvention != CC_EXTERN && exp.nCallingConvention != CC_STUB) { /* Go to next token */ if (!(pc = NextToken(pc))) { fprintf(stderr, "fail4\n"); return -13; } /* Verify syntax */ if (*pc++ != '(') { fprintf(stderr, "error: line %d, expected '('\n", nLine); return -14; } /* Skip whitespaces */ while (*pc == ' ' || *pc == '\t') pc++; exp.nStackBytes = 0; while (*pc >= '0') { if (CompareToken(pc, "long")) { exp.nStackBytes += 4; exp.anArgs[exp.nArgCount] = ARG_LONG; } else if (CompareToken(pc, "double")) { exp.nStackBytes += 8; exp.anArgs[exp.nArgCount] = ARG_DBL; } else if (CompareToken(pc, "ptr")) { exp.nStackBytes += 4; // sizeof(void*) on x86 exp.anArgs[exp.nArgCount] = ARG_PTR; } else if (CompareToken(pc, "str")) { exp.nStackBytes += 4; // sizeof(void*) on x86 exp.anArgs[exp.nArgCount] = ARG_STR; } else if (CompareToken(pc, "wstr")) { exp.nStackBytes += 4; // sizeof(void*) on x86 exp.anArgs[exp.nArgCount] = ARG_WSTR; } else if (CompareToken(pc, "int64")) { exp.nStackBytes += 8; exp.anArgs[exp.nArgCount] = ARG_INT64; } else if (CompareToken(pc, "int128")) { exp.nStackBytes += 16; exp.anArgs[exp.nArgCount] = ARG_INT128; } else if (CompareToken(pc, "float")) { exp.nStackBytes += 4; exp.anArgs[exp.nArgCount] = ARG_FLOAT; } else fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc); exp.nArgCount++; /* Go to next parameter */ if (!(pc = NextToken(pc))) { fprintf(stderr, "fail5\n"); return -15; } } /* Check syntax */ if (*pc++ != ')') { fprintf(stderr, "error: line %d, expected ')'\n", nLine); return -16; } } /* Handle special stub cases */ if (exp.nCallingConvention == CC_STUB) { /* Check for c++ mangled name */ if (pc[0] == '?') { //printf("Found c++ mangled name...\n"); // } else { /* Check for stdcall name */ const char *p = ScanToken(pc, '@'); if (p && (p - pc < exp.strName.len)) { int i; /* Truncate the name to before the @ */ exp.strName.len = (int)(p - pc); if (exp.strName.len < 1) { fprintf(stderr, "error, @ in line %d\n", nLine); return -1; } exp.nStackBytes = atoi(p + 1); exp.nArgCount = exp.nStackBytes / 4; exp.nCallingConvention = CC_STDCALL; exp.uFlags |= FL_STUB; for (i = 0; i < exp.nArgCount; i++) exp.anArgs[i] = ARG_LONG; } } } /* Get optional redirection */ pc = NextToken(pc); if (pc) { exp.strTarget.buf = pc; exp.strTarget.len = TokenLength(pc); /* Check syntax (end of line) */ if (NextToken(pc)) { fprintf(stderr, "error: line %d, additional tokens after ')'\n", nLine); return -17; } /* Don't relay-trace forwarded functions */ exp.uFlags |= FL_NORELAY; } else { exp.strTarget.buf = 0; exp.strTarget.len = 0; } /* Check for no-name without ordinal */ if ((exp.uFlags & FL_ORDINAL) && (exp.nOrdinal == -1)) { fprintf(stderr, "error: line %d, ordinal export without ordinal!\n", nLine); return -1; } OutputLine(fileDest, &exp); gbDebug = 0; } return 0; }