Fix for Ecc failing on empty files

This commit is contained in:
Robert MacGregor 2016-03-12 15:41:56 -05:00
parent c9fe415f2c
commit cfefaf581a
2 changed files with 121 additions and 11 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2002-2012 Croteam Ltd. /* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation the Free Software Foundation
@ -63,7 +63,7 @@ char *LineDirective(int i)
return strdup(str); return strdup(str);
} }
SType SType::operator+(const SType &other) SType SType::operator+(const SType &other)
{ {
SType sum; SType sum;
sum.strString = stradd(strString, other.strString); sum.strString = stradd(strString, other.strString);
@ -116,7 +116,7 @@ FILE *FOpen(const char *strFileName, char *strMode)
/* /*
* Print a header to an output file. * Print a header to an output file.
*/ */
static void PrintHeader(FILE *f) static void PrintHeader(FILE *f)
{ {
fprintf(f, "/*\n"); fprintf(f, "/*\n");
fprintf(f, " * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98\n"); fprintf(f, " * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98\n");
@ -174,13 +174,13 @@ void ReplaceFileRL(const char *strOld, const char *strNew)
{ {
continue; continue;
} }
// process each charachter // process each charachter
for(int ich=0;ich<ctch;ich++) for(int ich=0;ich<ctch;ich++)
{ {
char *pchOld = &strOldBuff[iOldch]; char *pchOld = &strOldBuff[iOldch];
char *pchNew = &strNewBuff[ich]; char *pchNew = &strNewBuff[ich];
if((*pchNew == '{') || (*pchNew == '}') || *pchNew == ';') if((*pchNew == '{') || (*pchNew == '}') || *pchNew == ';')
{ {
if((!bComment) && (!bQuotes) && (*(pchNew+1) != 13)) if((!bComment) && (!bQuotes) && (*(pchNew+1) != 13))
@ -193,7 +193,7 @@ void ReplaceFileRL(const char *strOld, const char *strNew)
} }
if(*pchNew == '"') if(*pchNew == '"')
{ {
// if this is quote // if this is quote
if((ich>0) && (*(pchNew-1)=='\\')) { } if((ich>0) && (*(pchNew-1)=='\\')) { }
else bQuotes = !bQuotes; else bQuotes = !bQuotes;
} }
@ -227,8 +227,106 @@ void ReplaceFile(const char *strOld, const char *strNew)
remove(strOld); remove(strOld);
rename(strNew, strOld); rename(strNew, strOld);
} }
enum ESStatus
{
/* Appears to be non-empty, ready to parse. */
Good,
/* Appears to be empty, ignore it. */
Empty,
/* Error occured during status check. */
Error,
};
/* Determine whether or not our target ES file is indeed valid input. */
ESStatus GetESStatus(char *filename)
{
ESStatus result = ESStatus::Good;
// Read a temporary buffer of the entire file contents
fseek(_fInput, 0, SEEK_END);
size_t length = ftell(_fInput);
char* temporaryBuffer = (char*)malloc(length);
fseek(_fInput, 0, SEEK_SET);
fread(temporaryBuffer, length, 1, _fInput);
fclose(_fInput);
// First, let's remove line comments
char *commentBegin = NULL;
while (commentBegin = strstr(temporaryBuffer, "//"))
{
size_t commentLength = length;
char* lineEnding = strstr(commentBegin, "\n");
if (lineEnding)
commentLength = (size_t)(lineEnding) - (size_t)commentBegin;
memset(commentBegin, 0x20, commentLength);
}
// Then block comments
commentBegin = NULL;
while (commentBegin = strstr(temporaryBuffer, "/*"))
{
size_t commentLength = length;
char* commentEnd = strstr(commentBegin, "*/");
if (commentEnd)
commentLength = (size_t)(commentEnd + 3) - (size_t)commentBegin;
else
{
result = ESStatus::Error;
break;
}
memset(commentBegin, 0x20, commentLength);
}
// If we return here, it was because of unbalanced block comments
if (result != ESStatus::Good)
{
free(temporaryBuffer);
return result;
}
// Now we just loop through the buffer until we find something that's not 0x20 or \n
result = ESStatus::Empty;
for (size_t iteration = 0; iteration < length; iteration++)
if (temporaryBuffer[iteration] != 0x20 && temporaryBuffer[iteration] != '\n')
{
size_t checkLength = length;
char* checkStart = &temporaryBuffer[iteration];
char* lineEnding = strstr(checkStart, "\n");
if (lineEnding)
checkLength = (size_t)(lineEnding) - (size_t)checkStart;
// Loop through and use isdigit to check all the digits
checkStart[checkLength + 1] = 0x00;
for (int digit = 0; digit < strlen(checkStart); digit++)
if (checkStart[digit] != 0x20 && checkStart[digit] != '\n' && isdigit(checkStart[digit]))
result = ESStatus::Good;
else if (checkStart[digit] != 0x20 && checkStart[digit] != '\n')
{
// If this occurs, then the first non-whitespace line we read wasn't a number.
result = ESStatus::Error;
break;
}
break;
}
free(temporaryBuffer);
if (result == ESStatus::Good)
_fInput = FOpen(filename, "r");
return result;
}
/* Replace a file with a new file if they are different. /* Replace a file with a new file if they are different.
* Used to keep .h files from constantly changing when you change the implementation. * Used to keep .h files from constantly changing when you change the implementation.
*/ */
void ReplaceIfChanged(const char *strOld, const char *strNew) void ReplaceIfChanged(const char *strOld, const char *strNew)
{ {
@ -240,7 +338,7 @@ void ReplaceIfChanged(const char *strOld, const char *strNew)
while (!feof(fOld)) { while (!feof(fOld)) {
char strOldLine[4096] = "#l"; char strOldLine[4096] = "#l";
char strNewLine[4096] = "#l"; char strNewLine[4096] = "#l";
// skip #line directives // skip #line directives
while(strNewLine[0]=='#' && strNewLine[1]=='l' && !feof(fNew)) { while(strNewLine[0]=='#' && strNewLine[1]=='l' && !feof(fNew)) {
fgets(strNewLine, sizeof(strNewLine)-1, fNew); fgets(strNewLine, sizeof(strNewLine)-1, fNew);
@ -283,6 +381,18 @@ int main(int argc, char *argv[])
} }
// open the input file // open the input file
_fInput = FOpen(argv[1], "r"); _fInput = FOpen(argv[1], "r");
// Make sure we're loading a valid ES file
ESStatus status = GetESStatus(argv[1]);
switch (status)
{
case ESStatus::Empty:
return EXIT_SUCCESS;
case ESStatus::Error:
return EXIT_FAILURE;
}
//printf("%s\n", argv[1]); //printf("%s\n", argv[1]);
// open all the output files // open all the output files
char *strImplementation = ChangeFileNameExtension(argv[1], ".cpp_tmp"); char *strImplementation = ChangeFileNameExtension(argv[1], ".cpp_tmp");
@ -333,7 +443,7 @@ int main(int argc, char *argv[])
ReplaceFile(strImplementationOld, strImplementation); ReplaceFile(strImplementationOld, strImplementation);
ReplaceIfChanged(strDeclarationOld, strDeclaration); ReplaceIfChanged(strDeclarationOld, strDeclaration);
ReplaceIfChanged(strTablesOld, strTables); ReplaceIfChanged(strTablesOld, strTables);
return EXIT_SUCCESS; return EXIT_SUCCESS;
// if there were errors // if there were errors
} else { } else {

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2002-2012 Croteam Ltd. /* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation the Free Software Foundation
@ -13,6 +13,7 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include <ctype.h>
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -27,4 +28,3 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <unistd.h> #include <unistd.h>
#define _fullpath(x, y, z) realpath(y, x) #define _fullpath(x, y, z) realpath(y, x)
#endif #endif