SimpleFileParsing.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429
  1. /** @file
  2. Generic but simple file parsing routines.
  3. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. --*/
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include "CommonLib.h"
  11. #include "EfiUtilityMsgs.h"
  12. #include "SimpleFileParsing.h"
  13. #ifndef MAX_PATH
  14. #define MAX_PATH 255
  15. #endif
  16. //
  17. // just in case we get in an endless loop.
  18. //
  19. #define MAX_NEST_DEPTH 20
  20. //
  21. // number of wchars
  22. //
  23. #define MAX_STRING_IDENTIFIER_NAME 100
  24. #define T_CHAR_SPACE ' '
  25. #define T_CHAR_NULL 0
  26. #define T_CHAR_CR '\r'
  27. #define T_CHAR_TAB '\t'
  28. #define T_CHAR_LF '\n'
  29. #define T_CHAR_SLASH '/'
  30. #define T_CHAR_BACKSLASH '\\'
  31. #define T_CHAR_DOUBLE_QUOTE '"'
  32. #define T_CHAR_LC_X 'x'
  33. #define T_CHAR_0 '0'
  34. #define T_CHAR_STAR '*'
  35. //
  36. // We keep a linked list of these for the source files we process
  37. //
  38. typedef struct _SOURCE_FILE {
  39. FILE *Fptr;
  40. CHAR8 *FileBuffer;
  41. CHAR8 *FileBufferPtr;
  42. UINTN FileSize;
  43. CHAR8 FileName[MAX_PATH];
  44. UINTN LineNum;
  45. BOOLEAN EndOfFile;
  46. BOOLEAN SkipToHash;
  47. struct _SOURCE_FILE *Previous;
  48. struct _SOURCE_FILE *Next;
  49. CHAR8 ControlCharacter;
  50. } SOURCE_FILE;
  51. typedef struct {
  52. CHAR8 *FileBufferPtr;
  53. } FILE_POSITION;
  54. //
  55. // Keep all our module globals in this structure
  56. //
  57. STATIC struct {
  58. SOURCE_FILE SourceFile;
  59. BOOLEAN VerboseFile;
  60. BOOLEAN VerboseToken;
  61. } mGlobals;
  62. STATIC
  63. UINTN
  64. t_strcmp (
  65. CHAR8 *Buffer,
  66. CHAR8 *Str
  67. );
  68. STATIC
  69. UINTN
  70. t_strncmp (
  71. CHAR8 *Str1,
  72. CHAR8 *Str2,
  73. INTN Len
  74. );
  75. STATIC
  76. UINTN
  77. t_strlen (
  78. CHAR8 *Str
  79. );
  80. STATIC
  81. VOID
  82. RewindFile (
  83. SOURCE_FILE *SourceFile
  84. );
  85. STATIC
  86. BOOLEAN
  87. IsWhiteSpace (
  88. SOURCE_FILE *SourceFile
  89. );
  90. STATIC
  91. UINTN
  92. SkipWhiteSpace (
  93. SOURCE_FILE *SourceFile
  94. );
  95. STATIC
  96. BOOLEAN
  97. EndOfFile (
  98. SOURCE_FILE *SourceFile
  99. );
  100. STATIC
  101. VOID
  102. PreprocessFile (
  103. SOURCE_FILE *SourceFile
  104. );
  105. STATIC
  106. CHAR8 *
  107. t_strcpy (
  108. CHAR8 *Dest,
  109. CHAR8 *Src
  110. );
  111. STATIC
  112. STATUS
  113. ProcessIncludeFile (
  114. SOURCE_FILE *SourceFile,
  115. SOURCE_FILE *ParentSourceFile
  116. );
  117. STATIC
  118. STATUS
  119. ProcessFile (
  120. SOURCE_FILE *SourceFile
  121. );
  122. STATIC
  123. STATUS
  124. GetFilePosition (
  125. FILE_POSITION *Fpos
  126. );
  127. STATIC
  128. STATUS
  129. SetFilePosition (
  130. FILE_POSITION *Fpos
  131. );
  132. STATUS
  133. SFPInit (
  134. VOID
  135. )
  136. /*++
  137. Routine Description:
  138. Arguments:
  139. None.
  140. Returns:
  141. STATUS_SUCCESS always
  142. --*/
  143. {
  144. memset ((VOID *) &mGlobals, 0, sizeof (mGlobals));
  145. return STATUS_SUCCESS;
  146. }
  147. UINTN
  148. SFPGetLineNumber (
  149. VOID
  150. )
  151. /*++
  152. Routine Description:
  153. Return the line number of the file we're parsing. Used
  154. for error reporting purposes.
  155. Arguments:
  156. None.
  157. Returns:
  158. The line number, or 0 if no file is being processed
  159. --*/
  160. {
  161. return mGlobals.SourceFile.LineNum;
  162. }
  163. CHAR8 *
  164. SFPGetFileName (
  165. VOID
  166. )
  167. /*++
  168. Routine Description:
  169. Return the name of the file we're parsing. Used
  170. for error reporting purposes.
  171. Arguments:
  172. None.
  173. Returns:
  174. A pointer to the file name. Null if no file is being
  175. processed.
  176. --*/
  177. {
  178. if (mGlobals.SourceFile.FileName[0]) {
  179. return mGlobals.SourceFile.FileName;
  180. }
  181. return NULL;
  182. }
  183. STATUS
  184. SFPOpenFile (
  185. CHAR8 *FileName
  186. )
  187. /*++
  188. Routine Description:
  189. Open a file for parsing.
  190. Arguments:
  191. FileName - name of the file to parse
  192. Returns:
  193. --*/
  194. {
  195. STATUS Status;
  196. t_strcpy (mGlobals.SourceFile.FileName, FileName);
  197. Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
  198. return Status;
  199. }
  200. BOOLEAN
  201. SFPIsToken (
  202. CHAR8 *Str
  203. )
  204. /*++
  205. Routine Description:
  206. Check to see if the specified token is found at
  207. the current position in the input file.
  208. Arguments:
  209. Str - the token to look for
  210. Returns:
  211. TRUE - the token is next
  212. FALSE - the token is not next
  213. Notes:
  214. We do a simple string comparison on this function. It is
  215. the responsibility of the caller to ensure that the token
  216. is not a subset of some other token.
  217. The file pointer is advanced past the token in the input file.
  218. --*/
  219. {
  220. UINTN Len;
  221. SkipWhiteSpace (&mGlobals.SourceFile);
  222. if (EndOfFile (&mGlobals.SourceFile)) {
  223. return FALSE;
  224. }
  225. if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
  226. mGlobals.SourceFile.FileBufferPtr += Len;
  227. if (mGlobals.VerboseToken) {
  228. printf ("Token: '%s'\n", Str);
  229. }
  230. return TRUE;
  231. }
  232. return FALSE;
  233. }
  234. BOOLEAN
  235. SFPIsKeyword (
  236. CHAR8 *Str
  237. )
  238. /*++
  239. Routine Description:
  240. Check to see if the specified keyword is found at
  241. the current position in the input file.
  242. Arguments:
  243. Str - keyword to look for
  244. Returns:
  245. TRUE - the keyword is next
  246. FALSE - the keyword is not next
  247. Notes:
  248. A keyword is defined as a "special" string that has a non-alphanumeric
  249. character following it.
  250. --*/
  251. {
  252. UINTN Len;
  253. SkipWhiteSpace (&mGlobals.SourceFile);
  254. if (EndOfFile (&mGlobals.SourceFile)) {
  255. return FALSE;
  256. }
  257. if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
  258. if (isalnum ((int)mGlobals.SourceFile.FileBufferPtr[Len])) {
  259. return FALSE;
  260. }
  261. mGlobals.SourceFile.FileBufferPtr += Len;
  262. if (mGlobals.VerboseToken) {
  263. printf ("Token: '%s'\n", Str);
  264. }
  265. return TRUE;
  266. }
  267. return FALSE;
  268. }
  269. BOOLEAN
  270. SFPGetNextToken (
  271. CHAR8 *Str,
  272. UINTN Len
  273. )
  274. /*++
  275. Routine Description:
  276. Get the next token from the input stream.
  277. Arguments:
  278. Str - pointer to a copy of the next token
  279. Len - size of buffer pointed to by Str
  280. Returns:
  281. TRUE - next token successfully returned
  282. FALSE - otherwise
  283. Notes:
  284. Preceding white space is ignored.
  285. The parser's buffer pointer is advanced past the end of the
  286. token.
  287. --*/
  288. {
  289. UINTN Index;
  290. CHAR8 TempChar;
  291. SkipWhiteSpace (&mGlobals.SourceFile);
  292. if (EndOfFile (&mGlobals.SourceFile)) {
  293. return FALSE;
  294. }
  295. //
  296. // Have to have enough string for at least one char and a null-terminator
  297. //
  298. if (Len < 2) {
  299. return FALSE;
  300. }
  301. //
  302. // Look at the first character. If it's an identifier, then treat it
  303. // as such
  304. //
  305. TempChar = mGlobals.SourceFile.FileBufferPtr[0];
  306. if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) {
  307. Str[0] = TempChar;
  308. mGlobals.SourceFile.FileBufferPtr++;
  309. Index = 1;
  310. while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
  311. TempChar = mGlobals.SourceFile.FileBufferPtr[0];
  312. if (((TempChar >= 'a') && (TempChar <= 'z')) ||
  313. ((TempChar >= 'A') && (TempChar <= 'Z')) ||
  314. ((TempChar >= '0') && (TempChar <= '9')) ||
  315. (TempChar == '_')
  316. ) {
  317. Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
  318. mGlobals.SourceFile.FileBufferPtr++;
  319. Index++;
  320. } else {
  321. //
  322. // Invalid character for symbol name, so break out
  323. //
  324. break;
  325. }
  326. }
  327. //
  328. // Null terminate and return success
  329. //
  330. Str[Index] = 0;
  331. return TRUE;
  332. } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) {
  333. Str[0] = mGlobals.SourceFile.FileBufferPtr[0];
  334. mGlobals.SourceFile.FileBufferPtr++;
  335. Str[1] = 0;
  336. return TRUE;
  337. } else {
  338. //
  339. // Everything else is white-space (or EOF) separated
  340. //
  341. Index = 0;
  342. while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
  343. if (IsWhiteSpace (&mGlobals.SourceFile)) {
  344. if (Index > 0) {
  345. Str[Index] = 0;
  346. return TRUE;
  347. }
  348. return FALSE;
  349. } else {
  350. Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
  351. mGlobals.SourceFile.FileBufferPtr++;
  352. Index++;
  353. }
  354. }
  355. //
  356. // See if we just ran out of file contents, but did find a token
  357. //
  358. if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) {
  359. Str[Index] = 0;
  360. return TRUE;
  361. }
  362. }
  363. return FALSE;
  364. }
  365. BOOLEAN
  366. SFPGetGuidToken (
  367. CHAR8 *Str,
  368. UINT32 Len
  369. )
  370. /*++
  371. Routine Description:
  372. Parse a GUID from the input stream. Stop when you discover white space.
  373. Arguments:
  374. Str - pointer to a copy of the next token
  375. Len - size of buffer pointed to by Str
  376. Returns:
  377. TRUE - GUID string returned successfully
  378. FALSE - otherwise
  379. --*/
  380. {
  381. UINT32 Index;
  382. SkipWhiteSpace (&mGlobals.SourceFile);
  383. if (EndOfFile (&mGlobals.SourceFile)) {
  384. return FALSE;
  385. }
  386. Index = 0;
  387. while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
  388. if (IsWhiteSpace (&mGlobals.SourceFile)) {
  389. if (Index > 0) {
  390. Str[Index] = 0;
  391. return TRUE;
  392. }
  393. return FALSE;
  394. } else {
  395. Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
  396. mGlobals.SourceFile.FileBufferPtr++;
  397. Index++;
  398. }
  399. }
  400. return FALSE;
  401. }
  402. BOOLEAN
  403. SFPSkipToToken (
  404. CHAR8 *Str
  405. )
  406. {
  407. UINTN Len;
  408. CHAR8 *SavePos;
  409. Len = t_strlen (Str);
  410. SavePos = mGlobals.SourceFile.FileBufferPtr;
  411. SkipWhiteSpace (&mGlobals.SourceFile);
  412. while (!EndOfFile (&mGlobals.SourceFile)) {
  413. if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {
  414. mGlobals.SourceFile.FileBufferPtr += Len;
  415. return TRUE;
  416. }
  417. mGlobals.SourceFile.FileBufferPtr++;
  418. SkipWhiteSpace (&mGlobals.SourceFile);
  419. }
  420. mGlobals.SourceFile.FileBufferPtr = SavePos;
  421. return FALSE;
  422. }
  423. BOOLEAN
  424. SFPGetNumber (
  425. UINTN *Value
  426. )
  427. /*++
  428. Routine Description:
  429. Check the token at the current file position for a numeric value.
  430. May be either decimal or hex.
  431. Arguments:
  432. Value - pointer where to store the value
  433. Returns:
  434. FALSE - current token is not a number
  435. TRUE - current token is a number
  436. --*/
  437. {
  438. int Val;
  439. SkipWhiteSpace (&mGlobals.SourceFile);
  440. if (EndOfFile (&mGlobals.SourceFile)) {
  441. return FALSE;
  442. }
  443. if (isdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
  444. //
  445. // Check for hex value
  446. //
  447. if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {
  448. if (!isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[2])) {
  449. return FALSE;
  450. }
  451. mGlobals.SourceFile.FileBufferPtr += 2;
  452. sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", &Val);
  453. *Value = (UINT32) Val;
  454. while (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
  455. mGlobals.SourceFile.FileBufferPtr++;
  456. }
  457. return TRUE;
  458. } else {
  459. *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
  460. while (isdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
  461. mGlobals.SourceFile.FileBufferPtr++;
  462. }
  463. return TRUE;
  464. }
  465. } else {
  466. return FALSE;
  467. }
  468. }
  469. STATUS
  470. SFPCloseFile (
  471. VOID
  472. )
  473. /*++
  474. Routine Description:
  475. Close the file being parsed.
  476. Arguments:
  477. None.
  478. Returns:
  479. STATUS_SUCCESS - the file was closed
  480. STATUS_ERROR - no file is currently open
  481. --*/
  482. {
  483. if (mGlobals.SourceFile.FileBuffer != NULL) {
  484. free (mGlobals.SourceFile.FileBuffer);
  485. memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
  486. return STATUS_SUCCESS;
  487. }
  488. return STATUS_ERROR;
  489. }
  490. STATIC
  491. STATUS
  492. ProcessIncludeFile (
  493. SOURCE_FILE *SourceFile,
  494. SOURCE_FILE *ParentSourceFile
  495. )
  496. /*++
  497. Routine Description:
  498. Given a source file, open the file and parse it
  499. Arguments:
  500. SourceFile - name of file to parse
  501. ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
  502. Returns:
  503. Standard status.
  504. --*/
  505. {
  506. STATIC UINTN NestDepth = 0;
  507. CHAR8 FoundFileName[MAX_PATH];
  508. STATUS Status;
  509. Status = STATUS_SUCCESS;
  510. NestDepth++;
  511. //
  512. // Print the file being processed. Indent so you can tell the include nesting
  513. // depth.
  514. //
  515. if (mGlobals.VerboseFile) {
  516. fprintf (stdout, "%*cProcessing file '%s'\n", (int)NestDepth * 2, ' ', SourceFile->FileName);
  517. fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile->FileName);
  518. }
  519. //
  520. // Make sure we didn't exceed our maximum nesting depth
  521. //
  522. if (NestDepth > MAX_NEST_DEPTH) {
  523. Error (NULL, 0, 3001, "Not Supported", "%s exceeds max nesting depth (%u)", SourceFile->FileName, (unsigned) NestDepth);
  524. Status = STATUS_ERROR;
  525. goto Finish;
  526. }
  527. //
  528. // Try to open the file locally, and if that fails try along our include paths.
  529. //
  530. strcpy (FoundFileName, SourceFile->FileName);
  531. if ((SourceFile->Fptr = fopen (LongFilePath (FoundFileName), "rb")) == NULL) {
  532. return STATUS_ERROR;
  533. }
  534. //
  535. // Process the file found
  536. //
  537. ProcessFile (SourceFile);
  538. Finish:
  539. //
  540. // Close open files and return status
  541. //
  542. if (SourceFile->Fptr != NULL) {
  543. fclose (SourceFile->Fptr);
  544. SourceFile->Fptr = NULL;
  545. }
  546. return Status;
  547. }
  548. STATIC
  549. STATUS
  550. ProcessFile (
  551. SOURCE_FILE *SourceFile
  552. )
  553. /*++
  554. Routine Description:
  555. Given a source file that's been opened, read the contents into an internal
  556. buffer and pre-process it to remove comments.
  557. Arguments:
  558. SourceFile - structure containing info on the file to process
  559. Returns:
  560. Standard status.
  561. --*/
  562. {
  563. //
  564. // Get the file size, and then read the entire thing into memory.
  565. // Allocate extra space for a terminator character.
  566. //
  567. fseek (SourceFile->Fptr, 0, SEEK_END);
  568. SourceFile->FileSize = ftell (SourceFile->Fptr);
  569. if (mGlobals.VerboseFile) {
  570. printf ("FileSize = %u (0x%X)\n", (unsigned) SourceFile->FileSize, (unsigned) SourceFile->FileSize);
  571. }
  572. fseek (SourceFile->Fptr, 0, SEEK_SET);
  573. SourceFile->FileBuffer = (CHAR8 *) malloc (SourceFile->FileSize + sizeof (CHAR8 ));
  574. if (SourceFile->FileBuffer == NULL) {
  575. Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL);
  576. return STATUS_ERROR;
  577. }
  578. fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
  579. SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (CHAR8 ))] = T_CHAR_NULL;
  580. //
  581. // Pre-process the file to replace comments with spaces
  582. //
  583. PreprocessFile (SourceFile);
  584. SourceFile->LineNum = 1;
  585. return STATUS_SUCCESS;
  586. }
  587. STATIC
  588. VOID
  589. PreprocessFile (
  590. SOURCE_FILE *SourceFile
  591. )
  592. /*++
  593. Routine Description:
  594. Preprocess a file to replace all carriage returns with NULLs so
  595. we can print lines (as part of error messages) from the file to the screen.
  596. Arguments:
  597. SourceFile - structure that we use to keep track of an input file.
  598. Returns:
  599. Nothing.
  600. --*/
  601. {
  602. BOOLEAN InComment;
  603. BOOLEAN SlashSlashComment;
  604. int LineNum;
  605. RewindFile (SourceFile);
  606. InComment = FALSE;
  607. SlashSlashComment = FALSE;
  608. while (!EndOfFile (SourceFile)) {
  609. //
  610. // If a line-feed, then no longer in a comment if we're in a // comment
  611. //
  612. if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
  613. SourceFile->FileBufferPtr++;
  614. SourceFile->LineNum++;
  615. if (InComment && SlashSlashComment) {
  616. InComment = FALSE;
  617. SlashSlashComment = FALSE;
  618. }
  619. } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
  620. //
  621. // Replace all carriage returns with a NULL so we can print stuff
  622. //
  623. SourceFile->FileBufferPtr[0] = 0;
  624. SourceFile->FileBufferPtr++;
  625. //
  626. // Check for */ comment end
  627. //
  628. } else if (InComment &&
  629. !SlashSlashComment &&
  630. (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) &&
  631. (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)
  632. ) {
  633. SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
  634. SourceFile->FileBufferPtr++;
  635. SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
  636. SourceFile->FileBufferPtr++;
  637. InComment = FALSE;
  638. } else if (InComment) {
  639. SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
  640. SourceFile->FileBufferPtr++;
  641. //
  642. // Check for // comments
  643. //
  644. } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
  645. InComment = TRUE;
  646. SlashSlashComment = TRUE;
  647. //
  648. // Check for /* comment start
  649. //
  650. } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) {
  651. SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
  652. SourceFile->FileBufferPtr++;
  653. SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
  654. SourceFile->FileBufferPtr++;
  655. SlashSlashComment = FALSE;
  656. InComment = TRUE;
  657. } else {
  658. SourceFile->FileBufferPtr++;
  659. }
  660. }
  661. //
  662. // Could check for end-of-file and still in a comment, but
  663. // should not be necessary. So just restore the file pointers.
  664. //
  665. RewindFile (SourceFile);
  666. //
  667. // Dump the reformatted file if verbose mode
  668. //
  669. if (mGlobals.VerboseFile) {
  670. LineNum = 1;
  671. printf ("%04d: ", LineNum);
  672. while (!EndOfFile (SourceFile)) {
  673. if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
  674. printf ("'\n%04d: '", ++LineNum);
  675. } else {
  676. printf ("%c", SourceFile->FileBufferPtr[0]);
  677. }
  678. SourceFile->FileBufferPtr++;
  679. }
  680. printf ("'\n");
  681. printf ("FileSize = %u (0x%X)\n", (unsigned)SourceFile->FileSize, (unsigned)SourceFile->FileSize);
  682. RewindFile (SourceFile);
  683. }
  684. }
  685. BOOLEAN
  686. SFPGetQuotedString (
  687. CHAR8 *Str,
  688. INTN Length
  689. )
  690. /*++
  691. Routine Description:
  692. Retrieve a quoted-string from the input file.
  693. Arguments:
  694. Str - pointer to a copy of the quoted string parsed
  695. Length - size of buffer pointed to by Str
  696. Returns:
  697. TRUE - next token in input stream was a quoted string, and
  698. the string value was returned in Str
  699. FALSE - otherwise
  700. --*/
  701. {
  702. SkipWhiteSpace (&mGlobals.SourceFile);
  703. if (EndOfFile (&mGlobals.SourceFile)) {
  704. return FALSE;
  705. }
  706. if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
  707. mGlobals.SourceFile.FileBufferPtr++;
  708. while (Length > 0) {
  709. if (EndOfFile (&mGlobals.SourceFile)) {
  710. return FALSE;
  711. }
  712. //
  713. // Check for closing quote
  714. //
  715. if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
  716. mGlobals.SourceFile.FileBufferPtr++;
  717. *Str = 0;
  718. return TRUE;
  719. }
  720. *Str = mGlobals.SourceFile.FileBufferPtr[0];
  721. Str++;
  722. Length--;
  723. mGlobals.SourceFile.FileBufferPtr++;
  724. }
  725. }
  726. //
  727. // First character was not a quote, or the input string length was
  728. // insufficient to contain the quoted string, so return failure code.
  729. //
  730. return FALSE;
  731. }
  732. BOOLEAN
  733. SFPIsEOF (
  734. VOID
  735. )
  736. /*++
  737. Routine Description:
  738. Return TRUE of FALSE to indicate whether or not we've reached the end of the
  739. file we're parsing.
  740. Arguments:
  741. NA
  742. Returns:
  743. TRUE - EOF reached
  744. FALSE - otherwise
  745. --*/
  746. {
  747. SkipWhiteSpace (&mGlobals.SourceFile);
  748. return EndOfFile (&mGlobals.SourceFile);
  749. }
  750. #if 0
  751. STATIC
  752. CHAR8 *
  753. GetQuotedString (
  754. SOURCE_FILE *SourceFile,
  755. BOOLEAN Optional
  756. )
  757. {
  758. CHAR8 *String;
  759. CHAR8 *Start;
  760. CHAR8 *Ptr;
  761. UINTN Len;
  762. BOOLEAN PreviousBackslash;
  763. if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
  764. if (Optional == FALSE) {
  765. Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
  766. }
  767. return NULL;
  768. }
  769. Len = 0;
  770. SourceFile->FileBufferPtr++;
  771. Start = Ptr = SourceFile->FileBufferPtr;
  772. PreviousBackslash = FALSE;
  773. while (!EndOfFile (SourceFile)) {
  774. if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) {
  775. break;
  776. } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
  777. Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
  778. PreviousBackslash = FALSE;
  779. } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {
  780. PreviousBackslash = TRUE;
  781. } else {
  782. PreviousBackslash = FALSE;
  783. }
  784. SourceFile->FileBufferPtr++;
  785. Len++;
  786. }
  787. if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
  788. Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
  789. } else {
  790. SourceFile->FileBufferPtr++;
  791. }
  792. //
  793. // Now allocate memory for the string and save it off
  794. //
  795. String = (CHAR8 *) malloc ((Len + 1) * sizeof (CHAR8 ));
  796. if (String == NULL) {
  797. Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL);
  798. return NULL;
  799. }
  800. //
  801. // Copy the string from the file buffer to the local copy.
  802. // We do no reformatting of it whatsoever at this point.
  803. //
  804. Ptr = String;
  805. while (Len > 0) {
  806. *Ptr = *Start;
  807. Start++;
  808. Ptr++;
  809. Len--;
  810. }
  811. *Ptr = 0;
  812. return String;
  813. }
  814. #endif
  815. STATIC
  816. BOOLEAN
  817. EndOfFile (
  818. SOURCE_FILE *SourceFile
  819. )
  820. {
  821. //
  822. // The file buffer pointer will typically get updated before the End-of-file flag in the
  823. // source file structure, so check it first.
  824. //
  825. if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (CHAR8 )) {
  826. SourceFile->EndOfFile = TRUE;
  827. return TRUE;
  828. }
  829. if (SourceFile->EndOfFile) {
  830. return TRUE;
  831. }
  832. return FALSE;
  833. }
  834. #if 0
  835. STATIC
  836. VOID
  837. ProcessTokenInclude (
  838. SOURCE_FILE *SourceFile
  839. )
  840. {
  841. CHAR8 IncludeFileName[MAX_PATH];
  842. CHAR8 *To;
  843. UINTN Len;
  844. BOOLEAN ReportedError;
  845. SOURCE_FILE IncludedSourceFile;
  846. ReportedError = FALSE;
  847. if (SkipWhiteSpace (SourceFile) == 0) {
  848. Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
  849. }
  850. //
  851. // Should be quoted file name
  852. //
  853. if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
  854. Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
  855. goto FailDone;
  856. }
  857. SourceFile->FileBufferPtr++;
  858. //
  859. // Copy the filename as ascii to our local string
  860. //
  861. To = IncludeFileName;
  862. Len = 0;
  863. while (!EndOfFile (SourceFile)) {
  864. if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {
  865. Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
  866. goto FailDone;
  867. }
  868. if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
  869. SourceFile->FileBufferPtr++;
  870. break;
  871. }
  872. //
  873. // If too long, then report the error once and process until the closing quote
  874. //
  875. Len++;
  876. if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
  877. Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
  878. ReportedError = TRUE;
  879. }
  880. if (!ReportedError) {
  881. *To = (CHAR8 ) SourceFile->FileBufferPtr[0];
  882. To++;
  883. }
  884. SourceFile->FileBufferPtr++;
  885. }
  886. if (!ReportedError) {
  887. *To = 0;
  888. memset ((CHAR8 *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
  889. strcpy (IncludedSourceFile.FileName, IncludeFileName);
  890. ProcessIncludeFile (&IncludedSourceFile, SourceFile);
  891. }
  892. return ;
  893. FailDone:
  894. //
  895. // Error recovery -- skip to next #
  896. //
  897. SourceFile->SkipToHash = TRUE;
  898. }
  899. #endif
  900. STATIC
  901. BOOLEAN
  902. IsWhiteSpace (
  903. SOURCE_FILE *SourceFile
  904. )
  905. {
  906. switch (*SourceFile->FileBufferPtr) {
  907. case T_CHAR_NULL:
  908. case T_CHAR_CR:
  909. case T_CHAR_SPACE:
  910. case T_CHAR_TAB:
  911. case T_CHAR_LF:
  912. return TRUE;
  913. default:
  914. return FALSE;
  915. }
  916. }
  917. UINTN
  918. SkipWhiteSpace (
  919. SOURCE_FILE *SourceFile
  920. )
  921. {
  922. UINTN Count;
  923. Count = 0;
  924. while (!EndOfFile (SourceFile)) {
  925. Count++;
  926. switch (*SourceFile->FileBufferPtr) {
  927. case T_CHAR_NULL:
  928. case T_CHAR_CR:
  929. case T_CHAR_SPACE:
  930. case T_CHAR_TAB:
  931. SourceFile->FileBufferPtr++;
  932. break;
  933. case T_CHAR_LF:
  934. SourceFile->FileBufferPtr++;
  935. SourceFile->LineNum++;
  936. break;
  937. default:
  938. return Count - 1;
  939. }
  940. }
  941. //
  942. // Some tokens require trailing whitespace. If we're at the end of the
  943. // file, then we count that as well.
  944. //
  945. if ((Count == 0) && (EndOfFile (SourceFile))) {
  946. Count++;
  947. }
  948. return Count;
  949. }
  950. STATIC
  951. UINTN
  952. t_strcmp (
  953. CHAR8 *Buffer,
  954. CHAR8 *Str
  955. )
  956. /*++
  957. Routine Description:
  958. Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,
  959. so only compare up to the length of Str.
  960. Arguments:
  961. Buffer - pointer to first (possibly not null-terminated) string
  962. Str - pointer to null-terminated string to compare to Buffer
  963. Returns:
  964. Number of bytes matched if exact match
  965. 0 if Buffer does not start with Str
  966. --*/
  967. {
  968. UINTN Len;
  969. Len = 0;
  970. while (*Str && (*Str == *Buffer)) {
  971. Buffer++;
  972. Str++;
  973. Len++;
  974. }
  975. if (*Str) {
  976. return 0;
  977. }
  978. return Len;
  979. }
  980. STATIC
  981. UINTN
  982. t_strlen (
  983. CHAR8 *Str
  984. )
  985. {
  986. UINTN Len;
  987. Len = 0;
  988. while (*Str) {
  989. Len++;
  990. Str++;
  991. }
  992. return Len;
  993. }
  994. STATIC
  995. UINTN
  996. t_strncmp (
  997. CHAR8 *Str1,
  998. CHAR8 *Str2,
  999. INTN Len
  1000. )
  1001. {
  1002. while (Len > 0) {
  1003. if (*Str1 != *Str2) {
  1004. return Len;
  1005. }
  1006. Len--;
  1007. Str1++;
  1008. Str2++;
  1009. }
  1010. return 0;
  1011. }
  1012. STATIC
  1013. CHAR8 *
  1014. t_strcpy (
  1015. CHAR8 *Dest,
  1016. CHAR8 *Src
  1017. )
  1018. {
  1019. CHAR8 *SaveDest;
  1020. SaveDest = Dest;
  1021. while (*Src) {
  1022. *Dest = *Src;
  1023. Dest++;
  1024. Src++;
  1025. }
  1026. *Dest = 0;
  1027. return SaveDest;
  1028. }
  1029. STATIC
  1030. VOID
  1031. RewindFile (
  1032. SOURCE_FILE *SourceFile
  1033. )
  1034. {
  1035. SourceFile->LineNum = 1;
  1036. SourceFile->FileBufferPtr = SourceFile->FileBuffer;
  1037. SourceFile->EndOfFile = 0;
  1038. }
  1039. STATIC
  1040. UINT32
  1041. GetHexChars (
  1042. CHAR8 *Buffer,
  1043. UINT32 BufferLen
  1044. )
  1045. {
  1046. UINT32 Len;
  1047. Len = 0;
  1048. while (!EndOfFile (&mGlobals.SourceFile) && (Len < BufferLen)) {
  1049. if (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
  1050. Buffer[Len] = mGlobals.SourceFile.FileBufferPtr[0];
  1051. Len++;
  1052. mGlobals.SourceFile.FileBufferPtr++;
  1053. } else {
  1054. break;
  1055. }
  1056. }
  1057. //
  1058. // Null terminate if we can
  1059. //
  1060. if ((Len > 0) && (Len < BufferLen)) {
  1061. Buffer[Len] = 0;
  1062. }
  1063. return Len;
  1064. }
  1065. BOOLEAN
  1066. SFPGetGuid (
  1067. INTN GuidStyle,
  1068. EFI_GUID *Value
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. Parse a GUID from the input stream. Stop when you discover white space.
  1073. Arguments:
  1074. GuidStyle - Style of the following GUID token
  1075. Value - pointer to EFI_GUID struct for output
  1076. Returns:
  1077. TRUE - GUID string parsed successfully
  1078. FALSE - otherwise
  1079. GUID styles
  1080. Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
  1081. --*/
  1082. {
  1083. INT32 Value32;
  1084. UINT32 Index;
  1085. FILE_POSITION FPos;
  1086. CHAR8 TempString[20];
  1087. CHAR8 TempString2[3];
  1088. CHAR8 *From;
  1089. CHAR8 *To;
  1090. UINT32 Len;
  1091. BOOLEAN Status;
  1092. Status = FALSE;
  1093. //
  1094. // Skip white space, then start parsing
  1095. //
  1096. SkipWhiteSpace (&mGlobals.SourceFile);
  1097. GetFilePosition (&FPos);
  1098. if (EndOfFile (&mGlobals.SourceFile)) {
  1099. return FALSE;
  1100. }
  1101. if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) {
  1102. //
  1103. // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
  1104. //
  1105. Len = GetHexChars (TempString, sizeof (TempString));
  1106. if ((Len == 0) || (Len > 8)) {
  1107. goto Done;
  1108. }
  1109. sscanf (TempString, "%x", &Value32);
  1110. Value->Data1 = Value32;
  1111. //
  1112. // Next two UINT16 fields
  1113. //
  1114. if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
  1115. goto Done;
  1116. }
  1117. mGlobals.SourceFile.FileBufferPtr++;
  1118. Len = GetHexChars (TempString, sizeof (TempString));
  1119. if ((Len == 0) || (Len > 4)) {
  1120. goto Done;
  1121. }
  1122. sscanf (TempString, "%x", &Value32);
  1123. Value->Data2 = (UINT16) Value32;
  1124. if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
  1125. goto Done;
  1126. }
  1127. mGlobals.SourceFile.FileBufferPtr++;
  1128. Len = GetHexChars (TempString, sizeof (TempString));
  1129. if ((Len == 0) || (Len > 4)) {
  1130. goto Done;
  1131. }
  1132. sscanf (TempString, "%x", &Value32);
  1133. Value->Data3 = (UINT16) Value32;
  1134. //
  1135. // Parse the "AAAA" as two bytes
  1136. //
  1137. if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
  1138. goto Done;
  1139. }
  1140. mGlobals.SourceFile.FileBufferPtr++;
  1141. Len = GetHexChars (TempString, sizeof (TempString));
  1142. if ((Len == 0) || (Len > 4)) {
  1143. goto Done;
  1144. }
  1145. sscanf (TempString, "%x", &Value32);
  1146. Value->Data4[0] = (UINT8) (Value32 >> 8);
  1147. Value->Data4[1] = (UINT8) Value32;
  1148. if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
  1149. goto Done;
  1150. }
  1151. mGlobals.SourceFile.FileBufferPtr++;
  1152. //
  1153. // Read the last 6 bytes of the GUID
  1154. //
  1155. //
  1156. Len = GetHexChars (TempString, sizeof (TempString));
  1157. if ((Len == 0) || (Len > 12)) {
  1158. goto Done;
  1159. }
  1160. //
  1161. // Insert leading 0's to make life easier
  1162. //
  1163. if (Len != 12) {
  1164. From = TempString + Len - 1;
  1165. To = TempString + 11;
  1166. TempString[12] = 0;
  1167. while (From >= TempString) {
  1168. *To = *From;
  1169. To--;
  1170. From--;
  1171. }
  1172. while (To >= TempString) {
  1173. *To = '0';
  1174. To--;
  1175. }
  1176. }
  1177. //
  1178. // Now parse each byte
  1179. //
  1180. TempString2[2] = 0;
  1181. for (Index = 0; Index < 6; Index++) {
  1182. //
  1183. // Copy the two characters from the input string to something
  1184. // we can parse.
  1185. //
  1186. TempString2[0] = TempString[Index * 2];
  1187. TempString2[1] = TempString[Index * 2 + 1];
  1188. sscanf (TempString2, "%x", &Value32);
  1189. Value->Data4[Index + 2] = (UINT8) Value32;
  1190. }
  1191. Status = TRUE;
  1192. } else {
  1193. //
  1194. // Unsupported GUID style
  1195. //
  1196. return FALSE;
  1197. }
  1198. Done:
  1199. if (Status == FALSE) {
  1200. SetFilePosition (&FPos);
  1201. }
  1202. return Status;
  1203. }
  1204. STATIC
  1205. STATUS
  1206. GetFilePosition (
  1207. FILE_POSITION *Fpos
  1208. )
  1209. {
  1210. Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr;
  1211. return STATUS_SUCCESS;
  1212. }
  1213. STATIC
  1214. STATUS
  1215. SetFilePosition (
  1216. FILE_POSITION *Fpos
  1217. )
  1218. {
  1219. //
  1220. // Should check range of pointer
  1221. //
  1222. mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr;
  1223. return STATUS_SUCCESS;
  1224. }