Main.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "StdH.h"
  13. #include "Main.h"
  14. FILE *_fInput;
  15. int _iLinesCt = 1;
  16. char *_strInputFileName;
  17. int _bTrackLineInformation=0; // this is set if #line should be inserted in tokens
  18. bool _bRemoveLineDirective = 0;
  19. FILE *_fImplementation;
  20. FILE *_fDeclaration;
  21. FILE *_fTables;
  22. FILE *_fExports;
  23. char *_strFileNameBase;
  24. char *_strFileNameBaseIdentifier;
  25. extern FILE *yyin;
  26. extern "C" int yywrap(void)
  27. {
  28. return 1;
  29. }
  30. int ctErrors = 0;
  31. char *stradd(char *str1, char *str2)
  32. {
  33. char *strResult;
  34. strResult = (char*)malloc(strlen(str1)+strlen(str2)+1);
  35. strcpy(strResult, str1);
  36. strcat(strResult, str2);
  37. return strResult;
  38. }
  39. char *stradd(char *str1, char *str2, char *str3)
  40. {
  41. char *strResult;
  42. strResult = (char*)malloc(strlen(str1)+strlen(str2)+strlen(str3)+1);
  43. strcpy(strResult, str1);
  44. strcat(strResult, str2);
  45. strcat(strResult, str3);
  46. return strResult;
  47. }
  48. char *LineDirective(int i)
  49. {
  50. char str[256];
  51. sprintf(str, "\n#line %d %s\n", i, _strInputFileName);
  52. return strdup(str);
  53. }
  54. SType SType::operator+(const SType &other)
  55. {
  56. SType sum;
  57. sum.strString = stradd(strString, other.strString);
  58. sum.iLine = -1;
  59. sum.bCrossesStates = bCrossesStates||other.bCrossesStates;
  60. return sum;
  61. };
  62. /*
  63. * Function used for reporting errors.
  64. */
  65. void yyerror(char *s)
  66. {
  67. fprintf( stderr, "%s(%d): Error: %s\n", _strInputFileName, _iLinesCt, s);
  68. ctErrors++;
  69. }
  70. /*
  71. * Change the extension of the filename.
  72. */
  73. char *ChangeFileNameExtension(char *strFileName, char *strNewExtension)
  74. {
  75. char *strChanged = (char*)malloc(strlen(strFileName)+strlen(strNewExtension)+2);
  76. strcpy(strChanged, strFileName);
  77. char *pchDot = strrchr(strChanged, '.');
  78. if (pchDot==NULL) {
  79. pchDot = strChanged+strlen(strChanged);
  80. }
  81. strcpy(pchDot, strNewExtension);
  82. return strChanged;
  83. }
  84. /*
  85. * Open a file and report an error if failed.
  86. */
  87. FILE *FOpen(const char *strFileName, char *strMode)
  88. {
  89. // open the input file
  90. FILE *f = fopen(strFileName, strMode);
  91. // if not successful
  92. if (f==NULL) {
  93. // report error
  94. fprintf(stderr, "Can't open file '%s': %s\n", strFileName, strerror(errno));
  95. //quit
  96. exit(EXIT_FAILURE);
  97. }
  98. return f;
  99. }
  100. /*
  101. * Print a header to an output file.
  102. */
  103. static void PrintHeader(FILE *f)
  104. {
  105. fprintf(f, "/*\n");
  106. fprintf(f, " * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98\n");
  107. fprintf(f, " */\n");
  108. fprintf(f, "\n");
  109. }
  110. void TranslateBackSlashes(char *str)
  111. {
  112. char *strNextSlash = str;
  113. while((strNextSlash = strchr(strNextSlash, '\\'))!=NULL) {
  114. *strNextSlash = '/';
  115. }
  116. }
  117. #define READSIZE 1024
  118. /* Relpace File and remove #line directive from file */
  119. void ReplaceFileRL(const char *strOld, const char *strNew)
  120. {
  121. char strOldBuff[READSIZE*3+1];
  122. char strNewBuff[READSIZE+1];
  123. int iOldch=0;
  124. FILE *pfNew = NULL;
  125. FILE *pfOld = NULL;
  126. bool bQuotes = 0;
  127. bool bComment = 0;
  128. // open files
  129. pfNew = fopen(strNew,"rb");
  130. if(!pfNew) goto Error;
  131. pfOld = fopen(strOld,"wb");
  132. if(!pfOld) goto Error;
  133. // until eof
  134. while(!feof(pfNew))
  135. {
  136. // clear buffers
  137. memset(&strOldBuff,0,sizeof(strOldBuff));
  138. memset(&strNewBuff,0,sizeof(strNewBuff));
  139. iOldch = 0;
  140. bQuotes = 0;
  141. bComment = 0;
  142. // read one line from file
  143. int iRead = fread(strNewBuff,1,READSIZE,pfNew);
  144. char *chLineEnd = strchr(strNewBuff,13);
  145. if(chLineEnd) *(chLineEnd+2) = 0;
  146. // get line length
  147. int ctch = strlen(strNewBuff);
  148. int iSeek = -iRead+ctch;
  149. // seek file for extra characters read
  150. if(iSeek!=0) fseek(pfNew,iSeek ,SEEK_CUR);
  151. if(strncmp(strNewBuff,"#line",5)==0)
  152. {
  153. continue;
  154. }
  155. // process each charachter
  156. for(int ich=0;ich<ctch;ich++)
  157. {
  158. char *pchOld = &strOldBuff[iOldch];
  159. char *pchNew = &strNewBuff[ich];
  160. if((*pchNew == '{') || (*pchNew == '}') || *pchNew == ';')
  161. {
  162. if((!bComment) && (!bQuotes) && (*(pchNew+1) != 13))
  163. {
  164. strOldBuff[iOldch++] = strNewBuff[ich];
  165. strOldBuff[iOldch++] = 13;
  166. strOldBuff[iOldch++] = 10;
  167. continue;
  168. }
  169. }
  170. if(*pchNew == '"')
  171. {
  172. // if this is quote
  173. if((ich>0) && (*(pchNew-1)=='\\')) { }
  174. else bQuotes = !bQuotes;
  175. }
  176. else if((*pchNew == '/') && (*(pchNew+1) == '/'))
  177. {
  178. // if this is comment
  179. bComment = 1;
  180. }
  181. strOldBuff[iOldch++] = strNewBuff[ich];
  182. }
  183. fwrite(&strOldBuff,1,iOldch,pfOld);
  184. }
  185. if(pfNew) fclose(pfNew);
  186. if(pfOld) fclose(pfOld);
  187. remove(strNew);
  188. return;
  189. Error:
  190. if(pfNew) fclose(pfNew);
  191. if(pfOld) fclose(pfOld);
  192. }
  193. /* Replace a file with a new file. */
  194. void ReplaceFile(const char *strOld, const char *strNew)
  195. {
  196. if(_bRemoveLineDirective)
  197. {
  198. ReplaceFileRL(strOld,strNew);
  199. return;
  200. }
  201. remove(strOld);
  202. rename(strNew, strOld);
  203. }
  204. /* Replace a file with a new file if they are different.
  205. * Used to keep .h files from constantly changing when you change the implementation.
  206. */
  207. void ReplaceIfChanged(const char *strOld, const char *strNew)
  208. {
  209. int iChanged = 1;
  210. FILE *fOld = fopen(strOld, "r");
  211. if (fOld!=NULL) {
  212. iChanged = 0;
  213. FILE *fNew = FOpen(strNew, "r");
  214. while (!feof(fOld)) {
  215. char strOldLine[4096] = "#l";
  216. char strNewLine[4096] = "#l";
  217. // skip #line directives
  218. while(strNewLine[0]=='#' && strNewLine[1]=='l' && !feof(fNew)) {
  219. fgets(strNewLine, sizeof(strNewLine)-1, fNew);
  220. }
  221. while(strOldLine[0]=='#' && strOldLine[1]=='l' && !feof(fOld)) {
  222. fgets(strOldLine, sizeof(strOldLine)-1, fOld);
  223. }
  224. if (strcmp(strNewLine, strOldLine)!=0) {
  225. iChanged = 1;
  226. break;
  227. }
  228. }
  229. fclose(fNew);
  230. fclose(fOld);
  231. }
  232. if (iChanged) {
  233. remove(strOld);
  234. rename(strNew, strOld);
  235. } else {
  236. remove(strNew);
  237. }
  238. }
  239. int main(int argc, char *argv[])
  240. {
  241. // if there is not one argument on the command line
  242. if (argc<1+1) {
  243. // print usage
  244. printf("Usage: Ecc <es_file_name>\n -line\n");
  245. //quit
  246. return EXIT_FAILURE;
  247. }
  248. if(argc>2)
  249. {
  250. if(strcmp(argv[2],"-line")==0)
  251. {
  252. _bRemoveLineDirective=1;
  253. }
  254. }
  255. // open the input file
  256. _fInput = FOpen(argv[1], "r");
  257. //printf("%s\n", argv[1]);
  258. // open all the output files
  259. char *strImplementation = ChangeFileNameExtension(argv[1], ".cpp_tmp");
  260. char *strImplementationOld = ChangeFileNameExtension(argv[1], ".cpp");
  261. char *strDeclaration = ChangeFileNameExtension(argv[1], ".h_tmp");
  262. char *strDeclarationOld = ChangeFileNameExtension(argv[1], ".h");
  263. char *strTables = ChangeFileNameExtension(argv[1], "_tables.h_tmp");
  264. char *strTablesOld = ChangeFileNameExtension(argv[1], "_tables.h");
  265. _fImplementation = FOpen(strImplementation, "w");
  266. _fDeclaration = FOpen(strDeclaration , "w");
  267. _fTables = FOpen(strTables , "w");
  268. // get the filename as preprocessor usable identifier
  269. _strFileNameBase = ChangeFileNameExtension(argv[1], "");
  270. _strFileNameBaseIdentifier = strdup(_strFileNameBase);
  271. {char *strNextSlash = _strFileNameBaseIdentifier;
  272. while((strNextSlash = strchr(strNextSlash, '/'))!=NULL) {
  273. *strNextSlash = '_';
  274. }}
  275. {char *strNextSlash = _strFileNameBaseIdentifier;
  276. while((strNextSlash = strchr(strNextSlash, '\\'))!=NULL) {
  277. *strNextSlash = '_';
  278. }}
  279. // print their headers
  280. PrintHeader(_fImplementation );
  281. PrintHeader(_fDeclaration );
  282. PrintHeader(_fTables );
  283. // remember input filename
  284. char strFullInputName[MAXPATHLEN];
  285. _fullpath(strFullInputName, argv[1], MAXPATHLEN);
  286. _strInputFileName = strFullInputName;
  287. TranslateBackSlashes(_strInputFileName);
  288. // make lex use the input file
  289. yyin = _fInput;
  290. // parse input file and generate the output files
  291. yyparse();
  292. // close all files
  293. fclose(_fImplementation);
  294. fclose(_fDeclaration);
  295. fclose(_fTables);
  296. // if there were no errors
  297. if (ctErrors==0) {
  298. // update the files that have changed
  299. ReplaceFile(strImplementationOld, strImplementation);
  300. ReplaceIfChanged(strDeclarationOld, strDeclaration);
  301. ReplaceIfChanged(strTablesOld, strTables);
  302. return EXIT_SUCCESS;
  303. // if there were errors
  304. } else {
  305. // delete all files (the old declaration file is left intact!)
  306. remove(strImplementation);
  307. remove(strDeclaration );
  308. remove(strTables );
  309. return EXIT_FAILURE;
  310. }
  311. }