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