SimpleFileParsing.c 31 KB

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