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