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