[SPEC2DEF] Refactor to avoid parsing multiple times

This commit is contained in:
Timo Kreuzer 2019-08-18 15:32:22 +02:00
parent 9cff65970f
commit e8ab2736e7

View file

@ -28,8 +28,29 @@ typedef struct
int anArgs[30];
unsigned int uFlags;
int nNumber;
unsigned nStartVersion;
unsigned nEndVersion;
int bVersionIncluded;
} EXPORT;
#if 0 // Debug helper function
void
PrintExport(EXPORT *pexp)
{
fprintf(stderr, "strName='%.*s'\n", pexp->strName.len, pexp->strName.buf);
fprintf(stderr, "strName='%.*s'\n", pexp->strTarget.len, pexp->strTarget.buf);
fprintf(stderr, "nCallingConvention=%u\n", pexp->nCallingConvention);
fprintf(stderr, "nOrdinal=%u\n", pexp->nOrdinal);
fprintf(stderr, "nStackBytes=%u\n", pexp->nStackBytes);
fprintf(stderr, "nArgCount=%u\n", pexp->nArgCount);
fprintf(stderr, "uFlags=0x%x\n", pexp->uFlags);
fprintf(stderr, "nNumber=%u\n", pexp->nNumber);
fprintf(stderr, "nStartVersion=%u\n", pexp->nStartVersion);
fprintf(stderr, "nEndVersion=%u\n", pexp->nEndVersion);
fprintf(stderr, "bVersionIncluded=%u\n", pexp->bVersionIncluded);
}
#endif
enum _ARCH
{
ARCH_X86,
@ -509,7 +530,7 @@ PrintName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco)
const char *pcName = pstr->buf;
int nNameLength = pstr->len;
const char* pcDot, *pcAt;
char namebuffer[16];
char namebuffer[19];
if ((nNameLength == 1) && (pcName[0] == '@'))
{
@ -803,17 +824,34 @@ Fatal(
va_end(argptr);
}
int
ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
EXPORT *
ParseFile(char* pcStart, FILE *fileDest, unsigned *cExports)
{
EXPORT *pexports;
const char *pc, *pcLine;
int nLine;
int cLines, nLine;
EXPORT exp;
int included, version_included;
int included;
unsigned int i;
*cExports = 0;
//fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
/* Count the lines */
for (cLines = 1, pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), cLines++)
{
/* Nothing */
}
/* Allocate an array of EXPORT structures */
pexports = malloc(cLines * sizeof(EXPORT));
if (pexports == NULL)
{
fprintf(stderr, "ERROR: %s: failed to allocate EXPORT array of %u elements\n", pszSourceFileName, cLines);
return NULL;
}
/* Loop all lines */
nLine = 1;
exp.nNumber = 0;
@ -821,16 +859,32 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
{
pc = pcLine;
exp.strName.buf = NULL;
exp.strName.len = 0;
exp.strTarget.buf = NULL;
exp.strTarget.len = 0;
exp.nArgCount = 0;
exp.uFlags = 0;
exp.nNumber++;
exp.nStartVersion = 0;
exp.nEndVersion = 0xFFFFFFFF;
exp.bVersionIncluded = 1;
/* Skip white spaces */
while (*pc == ' ' || *pc == '\t') pc++;
/* Skip empty lines, stop at EOF */
if (*pc == ';' || *pc <= '#') continue;
if (*pc == 0) return 0;
/* Check for line break or comment */
if ((*pc == '\r') || (*pc == '\n') ||
(*pc == ';') || (*pc == '#'))
{
continue;
}
/* On EOF we are done */
if (*pc == 0)
{
return pexports;
}
/* Now we should get either an ordinal or @ */
if (*pc == '@')
@ -909,7 +963,6 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
/* Handle options */
included = 1;
version_included = 1;
while (*pc == '-')
{
if (CompareToken(pc, "-arch="))
@ -941,7 +994,7 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
const char *pcVersionStart = pc + 9;
/* Default to not included */
version_included = 0;
exp.bVersionIncluded = 0;
pc += 8;
/* Look if we are included */
@ -981,11 +1034,14 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
"Invalid version range");
}
exp.nStartVersion = version;
exp.nEndVersion = endversion;
/* Now compare the range with our version */
if ((guOsVersion >= version) &&
(guOsVersion <= endversion))
{
version_included = 1;
exp.bVersionIncluded = 1;
}
/* Skip to next arch or end */
@ -1042,7 +1098,7 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
//fprintf(stderr, "info: Name:'%.10s'\n", pc);
/* If arch didn't match ours, skip this entry */
if (!included || !version_included) continue;
if (!included) continue;
/* Get name */
exp.strName.buf = pc;
@ -1235,11 +1291,12 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
}
}
OutputLine(fileDest, &exp);
pexports[*cExports] = exp;
(*cExports)++;
gbDebug = 0;
}
return 0;
return pexports;
}
void usage(void)
@ -1265,7 +1322,8 @@ int main(int argc, char *argv[])
const char* pszVersionOption = "--version=0x";
char achDllName[40];
FILE *file;
int result = 0, i;
unsigned cExports = 0, i;
EXPORT *pexports;
if (argc < 2)
{
@ -1274,7 +1332,7 @@ int main(int argc, char *argv[])
}
/* Read options */
for (i = 1; i < argc && *argv[i] == '-'; i++)
for (i = 1; i < (unsigned)argc && *argv[i] == '-'; i++)
{
if ((strcasecmp(argv[i], "--help") == 0) ||
(strcasecmp(argv[i], "-h") == 0))
@ -1404,6 +1462,13 @@ int main(int argc, char *argv[])
/* Zero terminate the source */
pszSource[nFileSize] = '\0';
pexports = ParseFile(pszSource, file, &cExports);
if (pexports == NULL)
{
fprintf(stderr, "Failed to allocate memory for export data!\n");
return -1;
}
if (pszDefFileName)
{
/* Open output file */
@ -1415,7 +1480,13 @@ int main(int argc, char *argv[])
}
OutputHeader_def(file, pszDllName);
result = ParseFile(pszSource, file, OutputLine_def);
for (i = 0; i < cExports; i++)
{
if (pexports[i].bVersionIncluded)
OutputLine_def(file, &pexports[i]);
}
fclose(file);
}
@ -1430,7 +1501,13 @@ int main(int argc, char *argv[])
}
OutputHeader_stub(file);
result = ParseFile(pszSource, file, OutputLine_stub);
for (i = 0; i < cExports; i++)
{
if (pexports[i].bVersionIncluded)
OutputLine_stub(file, &pexports[i]);
}
fclose(file);
}
@ -1445,10 +1522,18 @@ int main(int argc, char *argv[])
}
OutputHeader_asmstub(file, pszDllName);
result = ParseFile(pszSource, file, OutputLine_asmstub);
for (i = 0; i < cExports; i++)
{
if (pexports[i].bVersionIncluded)
OutputLine_asmstub(file, &pexports[i]);
}
fprintf(file, "\n END\n");
fclose(file);
}
return result;
free(pexports);
return 0;
}