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