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