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