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