]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CodeTools/TianoTools/GenFfsFile/SimpleFileParsing.c
Restructuring for better separation of Tool packages.
[mirror_edk2.git] / Tools / CodeTools / TianoTools / GenFfsFile / 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
ce53a8c3 27#include <Common/UefiBaseTypes.h>\r
28\r
878ddf1f 29#include "EfiUtilityMsgs.h"\r
30#include "SimpleFileParsing.h"\r
31\r
32#define MAX_PATH 255\r
33#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop.\r
34#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars\r
35#define MAX_LINE_LEN 400\r
36\r
37#define T_CHAR_SPACE ' '\r
38#define T_CHAR_NULL 0\r
39#define T_CHAR_CR '\r'\r
40#define T_CHAR_TAB '\t'\r
41#define T_CHAR_LF '\n'\r
42#define T_CHAR_SLASH '/'\r
43#define T_CHAR_BACKSLASH '\\'\r
44#define T_CHAR_DOUBLE_QUOTE '"'\r
45#define T_CHAR_LC_X 'x'\r
46#define T_CHAR_0 '0'\r
47\r
48//\r
49// We keep a linked list of these for the source files we process\r
50//\r
51typedef struct _SOURCE_FILE {\r
52 FILE *Fptr;\r
53 T_CHAR *FileBuffer;\r
54 T_CHAR *FileBufferPtr;\r
55 UINT32 FileSize;\r
56 INT8 FileName[MAX_PATH];\r
57 UINT32 LineNum;\r
58 BOOLEAN EndOfFile;\r
59 BOOLEAN SkipToHash;\r
60 struct _SOURCE_FILE *Previous;\r
61 struct _SOURCE_FILE *Next;\r
62 T_CHAR ControlCharacter;\r
63} SOURCE_FILE;\r
64\r
65//\r
66// Here's all our module globals.\r
67//\r
68static struct {\r
69 SOURCE_FILE SourceFile;\r
70 BOOLEAN Verbose;\r
71} mGlobals;\r
72\r
73static\r
74UINT32\r
75t_strcmp (\r
76 T_CHAR *Buffer,\r
77 T_CHAR *Str\r
78 );\r
79\r
80static\r
81UINT32\r
82t_strncmp (\r
83 T_CHAR *Str1,\r
84 T_CHAR *Str2,\r
85 UINT32 Len\r
86 );\r
87\r
88static\r
89UINT32\r
90t_strlen (\r
91 T_CHAR *Str\r
92 );\r
93\r
94static\r
95void\r
96RewindFile (\r
97 SOURCE_FILE *SourceFile\r
98 );\r
99\r
100static\r
101BOOLEAN\r
102SkipTo (\r
103 SOURCE_FILE *SourceFile,\r
104 T_CHAR TChar,\r
105 BOOLEAN StopAfterNewline\r
106 );\r
107\r
108static\r
109BOOLEAN\r
110IsWhiteSpace (\r
111 SOURCE_FILE *SourceFile\r
112 );\r
113\r
114static\r
115UINT32\r
116SkipWhiteSpace (\r
117 SOURCE_FILE *SourceFile\r
118 );\r
119\r
120static\r
121BOOLEAN\r
122EndOfFile (\r
123 SOURCE_FILE *SourceFile\r
124 );\r
125\r
126static\r
127void\r
128PreprocessFile (\r
129 SOURCE_FILE *SourceFile\r
130 );\r
131\r
132//\r
133// static\r
134// T_CHAR *\r
135// GetQuotedString (\r
136// SOURCE_FILE *SourceFile,\r
137// BOOLEAN Optional\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 IN INT8 *FileName,\r
164 OUT INT8 *FoundFileName,\r
165 IN UINT32 FoundFileNameLen\r
166 );\r
167\r
168static\r
169STATUS\r
170ProcessFile (\r
171 SOURCE_FILE *SourceFile\r
172 );\r
173\r
174STATUS\r
175SFPInit (\r
176 VOID\r
177 )\r
178{\r
179 memset ((void *) &mGlobals, 0, sizeof (mGlobals));\r
180 return STATUS_SUCCESS;\r
181}\r
182\r
183UINT32\r
184SFPGetLineNumber (\r
185 VOID\r
186 )\r
187{\r
188 return mGlobals.SourceFile.LineNum;\r
189}\r
190\r
191/*++\r
192\r
193Routine Description:\r
194 Return the line number of the file we're parsing. Used\r
195 for error reporting purposes.\r
196\r
197Arguments:\r
198 None.\r
199\r
200Returns:\r
201 The line number, or 0 if no file is being processed\r
202\r
203--*/\r
204T_CHAR *\r
205SFPGetFileName (\r
206 VOID\r
207 )\r
208/*++\r
209\r
210Routine Description:\r
211 Return the name 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 A pointer to the file name. Null if no file is being\r
219 processed.\r
220\r
221--*/\r
222{\r
223 if (mGlobals.SourceFile.FileName[0]) {\r
224 return mGlobals.SourceFile.FileName;\r
225 }\r
226\r
227 return NULL;\r
228}\r
229\r
230STATUS\r
231SFPOpenFile (\r
232 IN INT8 *FileName\r
233 )\r
234/*++\r
235\r
236Routine Description:\r
237 Open a file for parsing.\r
238\r
239Arguments:\r
240 FileName - name of the file to parse\r
241\r
242Returns:\r
243 \r
244\r
245--*/\r
246{\r
247 STATUS Status;\r
248 t_strcpy (mGlobals.SourceFile.FileName, FileName);\r
249 Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);\r
250 return Status;\r
251}\r
252\r
253BOOLEAN\r
254SFPIsToken (\r
255 T_CHAR *Str\r
256 )\r
257/*++\r
258\r
259Routine Description:\r
260 Check to see if the specified token is found at\r
261 the current position in the input file.\r
262\r
263Arguments:\r
264 Str - the token to look for\r
265\r
266Returns:\r
267 TRUE - the token is next\r
268 FALSE - the token is not next\r
269\r
270Notes:\r
271 We do a simple string comparison on this function. It is\r
272 the responsibility of the caller to ensure that the token\r
273 is not a subset of some other token.\r
274\r
275 The file pointer is advanced past the token in the input file.\r
276\r
277--*/\r
278{\r
279 UINT32 Len;\r
280 SkipWhiteSpace (&mGlobals.SourceFile);\r
281\r
282 if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {\r
283 mGlobals.SourceFile.FileBufferPtr += Len;\r
284 return TRUE;\r
285 }\r
286\r
287 return FALSE;\r
288\r
289}\r
290\r
291BOOLEAN\r
292SFPGetNextToken (\r
293 T_CHAR *Str,\r
294 UINT32 Len\r
295 )\r
296{\r
297 UINT32 Index;\r
298 SkipWhiteSpace (&mGlobals.SourceFile);\r
299 Index = 0;\r
300 while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {\r
301 if (IsWhiteSpace (&mGlobals.SourceFile)) {\r
302 if (Index > 0) {\r
303 Str[Index] = 0;\r
304 return TRUE;\r
305 }\r
306\r
307 return FALSE;\r
308 } else {\r
309 Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];\r
310 mGlobals.SourceFile.FileBufferPtr++;\r
311 Index++;\r
312 }\r
313 }\r
314\r
315 return FALSE;\r
316}\r
317\r
318BOOLEAN\r
319SFPSkipToToken (\r
320 T_CHAR *Str\r
321 )\r
322{\r
323 UINT32 Len;\r
324 T_CHAR *SavePos;\r
325 Len = t_strlen (Str);\r
326 SavePos = mGlobals.SourceFile.FileBufferPtr;\r
327 SkipWhiteSpace (&mGlobals.SourceFile);\r
328 while (!EndOfFile (&mGlobals.SourceFile)) {\r
329 if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {\r
330 mGlobals.SourceFile.FileBufferPtr += Len;\r
331 return TRUE;\r
332 }\r
333\r
334 mGlobals.SourceFile.FileBufferPtr++;\r
335 SkipWhiteSpace (&mGlobals.SourceFile);\r
336 }\r
337\r
338 mGlobals.SourceFile.FileBufferPtr = SavePos;\r
339 return FALSE;\r
340}\r
341\r
342BOOLEAN\r
343SFPGetNumber (\r
344 UINT32 *Value\r
345 )\r
346/*++\r
347\r
348Routine Description:\r
349 Check the token at the current file position for a numeric value.\r
350 May be either decimal or hex.\r
351\r
352Arguments:\r
353 Value - pointer where to store the value\r
354\r
355Returns:\r
356 FALSE - current token is not a number\r
357 TRUE - current token is a number\r
358\r
359--*/\r
360{\r
361 //\r
362 // UINT32 Len;\r
363 //\r
364 SkipWhiteSpace (&mGlobals.SourceFile);\r
365 if (EndOfFile (&mGlobals.SourceFile)) {\r
366 return FALSE;\r
367 }\r
368\r
369 if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
370 //\r
371 // Check for hex value\r
372 //\r
373 if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {\r
374 if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {\r
375 return FALSE;\r
376 }\r
377\r
378 mGlobals.SourceFile.FileBufferPtr += 2;\r
379 sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);\r
380 while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
381 mGlobals.SourceFile.FileBufferPtr++;\r
382 }\r
383\r
384 return TRUE;\r
385 } else {\r
386 *Value = atoi (mGlobals.SourceFile.FileBufferPtr);\r
387 while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
388 mGlobals.SourceFile.FileBufferPtr++;\r
389 }\r
390\r
391 return TRUE;\r
392 }\r
393 } else {\r
394 return FALSE;\r
395 }\r
396}\r
397\r
398STATUS\r
399SFPCloseFile (\r
400 VOID\r
401 )\r
402/*++\r
403\r
404Routine Description:\r
405 Close the file being parsed.\r
406\r
407Arguments:\r
408 None.\r
409\r
410Returns:\r
411 STATUS_SUCCESS - the file was closed \r
412 STATUS_ERROR - no file is currently open\r
413\r
414--*/\r
415{\r
416 if (mGlobals.SourceFile.FileBuffer != NULL) {\r
417 free (mGlobals.SourceFile.FileBuffer);\r
418 memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));\r
419 return STATUS_SUCCESS;\r
420 }\r
421\r
422 return STATUS_ERROR;\r
423}\r
424\r
425static\r
426STATUS\r
427ProcessIncludeFile (\r
428 SOURCE_FILE *SourceFile,\r
429 SOURCE_FILE *ParentSourceFile\r
430 )\r
431/*++\r
432\r
433Routine Description:\r
434\r
435 Given a source file, open the file and parse it\r
436 \r
437Arguments:\r
438\r
439 SourceFile - name of file to parse\r
440 ParentSourceFile - for error reporting purposes, the file that #included SourceFile.\r
441\r
442Returns:\r
443\r
444 Standard status.\r
445 \r
446--*/\r
447{\r
448 static UINT32 NestDepth = 0;\r
449 INT8 FoundFileName[MAX_PATH];\r
450 STATUS Status;\r
451\r
452 Status = STATUS_SUCCESS;\r
453 NestDepth++;\r
454 //\r
455 // Print the file being processed. Indent so you can tell the include nesting\r
456 // depth.\r
457 //\r
458 if (mGlobals.Verbose) {\r
459 fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);\r
460 }\r
461\r
462 //\r
463 // Make sure we didn't exceed our maximum nesting depth\r
464 //\r
465 if (NestDepth > MAX_NEST_DEPTH) {\r
466 Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);\r
467 Status = STATUS_ERROR;\r
468 goto Finish;\r
469 }\r
470 //\r
471 // Try to open the file locally, and if that fails try along our include paths.\r
472 //\r
473 strcpy (FoundFileName, SourceFile->FileName);\r
474 if ((SourceFile->Fptr = fopen (FoundFileName, "r")) == NULL) {\r
475 //\r
476 // Try to find it among the paths if it has a parent (that is, it is included\r
477 // by someone else).\r
478 //\r
479 Error (NULL, 0, 0, SourceFile->FileName, "file not found");\r
480 return STATUS_ERROR;\r
481 }\r
482 //\r
483 // Process the file found\r
484 //\r
485 ProcessFile (SourceFile);\r
486Finish:\r
487 //\r
488 // Close open files and return status\r
489 //\r
490 if (SourceFile->Fptr != NULL) {\r
491 fclose (SourceFile->Fptr);\r
492 SourceFile->Fptr = NULL;\r
493 }\r
494\r
495 return Status;\r
496}\r
497\r
498static\r
499STATUS\r
500ProcessFile (\r
501 SOURCE_FILE *SourceFile\r
502 )\r
503{\r
504 //\r
505 // Get the file size, and then read the entire thing into memory.\r
506 // Allocate space for a terminator character.\r
507 //\r
508 fseek (SourceFile->Fptr, 0, SEEK_END);\r
509 SourceFile->FileSize = ftell (SourceFile->Fptr);\r
510 fseek (SourceFile->Fptr, 0, SEEK_SET);\r
511 SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));\r
512 if (SourceFile->FileBuffer == NULL) {\r
513 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
514 return STATUS_ERROR;\r
515 }\r
516\r
517 fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);\r
518 SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;\r
519 //\r
520 // Pre-process the file to replace comments with spaces\r
521 //\r
522 PreprocessFile (SourceFile);\r
523 SourceFile->LineNum = 1;\r
524 return STATUS_SUCCESS;\r
525}\r
526\r
527static\r
528void\r
529PreprocessFile (\r
530 SOURCE_FILE *SourceFile\r
531 )\r
532/*++\r
533\r
534Routine Description:\r
535 Preprocess a file to replace all carriage returns with NULLs so\r
536 we can print lines from the file to the screen.\r
537 \r
538Arguments:\r
539 SourceFile - structure that we use to keep track of an input file.\r
540\r
541Returns:\r
542 Nothing.\r
543 \r
544--*/\r
545{\r
546 BOOLEAN InComment;\r
547\r
548 RewindFile (SourceFile);\r
549 InComment = FALSE;\r
550 while (!EndOfFile (SourceFile)) {\r
551 //\r
552 // If a line-feed, then no longer in a comment\r
553 //\r
554 if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {\r
555 SourceFile->FileBufferPtr++;\r
556 SourceFile->LineNum++;\r
557 InComment = 0;\r
558 } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {\r
559 //\r
560 // Replace all carriage returns with a NULL so we can print stuff\r
561 //\r
562 SourceFile->FileBufferPtr[0] = 0;\r
563 SourceFile->FileBufferPtr++;\r
564 } else if (InComment) {\r
565 SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;\r
566 SourceFile->FileBufferPtr++;\r
567 } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {\r
568 SourceFile->FileBufferPtr += 2;\r
569 InComment = TRUE;\r
570 } else {\r
571 SourceFile->FileBufferPtr++;\r
572 }\r
573 }\r
574 //\r
575 // Could check for end-of-file and still in a comment, but\r
576 // should not be necessary. So just restore the file pointers.\r
577 //\r
578 RewindFile (SourceFile);\r
579}\r
580\r
581#if 0\r
582static\r
583T_CHAR *\r
584GetQuotedString (\r
585 SOURCE_FILE *SourceFile,\r
586 BOOLEAN Optional\r
587 )\r
588{\r
589 T_CHAR *String;\r
590 T_CHAR *Start;\r
591 T_CHAR *Ptr;\r
592 UINT32 Len;\r
593 BOOLEAN PreviousBackslash;\r
594\r
595 if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {\r
596 if (!Optional) {\r
597 Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);\r
598 }\r
599\r
600 return NULL;\r
601 }\r
602\r
603 Len = 0;\r
604 SourceFile->FileBufferPtr++;\r
605 Start = Ptr = SourceFile->FileBufferPtr;\r
606 PreviousBackslash = FALSE;\r
607 while (!EndOfFile (SourceFile)) {\r
608 if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (!PreviousBackslash)) {\r
609 break;\r
610 } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {\r
611 Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);\r
612 PreviousBackslash = FALSE;\r
613 } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {\r
614 PreviousBackslash = TRUE;\r
615 } else {\r
616 PreviousBackslash = FALSE;\r
617 }\r
618\r
619 SourceFile->FileBufferPtr++;\r
620 Len++;\r
621 }\r
622\r
623 if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {\r
624 Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);\r
625 } else {\r
626 SourceFile->FileBufferPtr++;\r
627 }\r
628 //\r
629 // Now allocate memory for the string and save it off\r
630 //\r
631 String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));\r
632 if (String == NULL) {\r
633 Error (NULL, 0, 0, "memory allocation failed", NULL);\r
634 return NULL;\r
635 }\r
636 //\r
637 // Copy the string from the file buffer to the local copy.\r
638 // We do no reformatting of it whatsoever at this point.\r
639 //\r
640 Ptr = String;\r
641 while (Len > 0) {\r
642 *Ptr = *Start;\r
643 Start++;\r
644 Ptr++;\r
645 Len--;\r
646 }\r
647\r
648 *Ptr = 0;\r
649 return String;\r
650}\r
651#endif\r
652static\r
653BOOLEAN\r
654EndOfFile (\r
655 SOURCE_FILE *SourceFile\r
656 )\r
657{\r
658 //\r
659 // The file buffer pointer will typically get updated before the End-of-file flag in the\r
660 // source file structure, so check it first.\r
661 //\r
662 if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {\r
663 SourceFile->EndOfFile = TRUE;\r
664 return TRUE;\r
665 }\r
666\r
667 if (SourceFile->EndOfFile) {\r
668 return TRUE;\r
669 }\r
670\r
671 return FALSE;\r
672}\r
673\r
674#if 0\r
675static\r
676void\r
677ProcessTokenInclude (\r
678 SOURCE_FILE *SourceFile\r
679 )\r
680{\r
681 INT8 IncludeFileName[MAX_PATH];\r
682 INT8 *To;\r
683 UINT32 Len;\r
684 BOOLEAN ReportedError;\r
685 SOURCE_FILE IncludedSourceFile;\r
686\r
687 ReportedError = FALSE;\r
688 if (SkipWhiteSpace (SourceFile) == 0) {\r
689 Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);\r
690 }\r
691 //\r
692 // Should be quoted file name\r
693 //\r
694 if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {\r
695 Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);\r
696 goto FailDone;\r
697 }\r
698\r
699 SourceFile->FileBufferPtr++;\r
700 //\r
701 // Copy the filename as ascii to our local string\r
702 //\r
703 To = IncludeFileName;\r
704 Len = 0;\r
705 while (!EndOfFile (SourceFile)) {\r
706 if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {\r
707 Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);\r
708 goto FailDone;\r
709 }\r
710\r
711 if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {\r
712 SourceFile->FileBufferPtr++;\r
713 break;\r
714 }\r
715 //\r
716 // If too long, then report the error once and process until the closing quote\r
717 //\r
718 Len++;\r
719 if (!ReportedError && (Len >= sizeof (IncludeFileName))) {\r
720 Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);\r
721 ReportedError = TRUE;\r
722 }\r
723\r
724 if (!ReportedError) {\r
725 //\r
726 // *To = UNICODE_TO_ASCII(SourceFile->FileBufferPtr[0]);\r
727 //\r
728 *To = (T_CHAR) SourceFile->FileBufferPtr[0];\r
729 To++;\r
730 }\r
731\r
732 SourceFile->FileBufferPtr++;\r
733 }\r
734\r
735 if (!ReportedError) {\r
736 *To = 0;\r
737 memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));\r
738 strcpy (IncludedSourceFile.FileName, IncludeFileName);\r
739 //\r
740 // IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;\r
741 //\r
742 ProcessIncludeFile (&IncludedSourceFile, SourceFile);\r
743 //\r
744 // printf ("including file '%s'\n", IncludeFileName);\r
745 //\r
746 }\r
747\r
748 return ;\r
749FailDone:\r
750 //\r
751 // Error recovery -- skip to next #\r
752 //\r
753 SourceFile->SkipToHash = TRUE;\r
754}\r
755#endif\r
756static\r
757BOOLEAN\r
758IsWhiteSpace (\r
759 SOURCE_FILE *SourceFile\r
760 )\r
761{\r
762 switch (*SourceFile->FileBufferPtr) {\r
763 case T_CHAR_NULL:\r
764 case T_CHAR_CR:\r
765 case T_CHAR_SPACE:\r
766 case T_CHAR_TAB:\r
767 case T_CHAR_LF:\r
768 return TRUE;\r
769\r
770 default:\r
771 return FALSE;\r
772 }\r
773}\r
774\r
775UINT32\r
776SkipWhiteSpace (\r
777 SOURCE_FILE *SourceFile\r
778 )\r
779{\r
780 UINT32 Count;\r
781\r
782 Count = 0;\r
783 while (!EndOfFile (SourceFile)) {\r
784 Count++;\r
785 switch (*SourceFile->FileBufferPtr) {\r
786 case T_CHAR_NULL:\r
787 case T_CHAR_CR:\r
788 case T_CHAR_SPACE:\r
789 case T_CHAR_TAB:\r
790 SourceFile->FileBufferPtr++;\r
791 break;\r
792\r
793 case T_CHAR_LF:\r
794 SourceFile->FileBufferPtr++;\r
795 SourceFile->LineNum++;\r
796 if (mGlobals.Verbose) {\r
797 printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);\r
798 }\r
799 break;\r
800\r
801 default:\r
802 return Count - 1;\r
803 }\r
804 }\r
805 //\r
806 // Some tokens require trailing whitespace. If we're at the end of the\r
807 // file, then we count that as well.\r
808 //\r
809 if ((Count == 0) && (EndOfFile (SourceFile))) {\r
810 Count++;\r
811 }\r
812\r
813 return Count;\r
814}\r
815\r
816static\r
817UINT32\r
818t_strcmp (\r
819 T_CHAR *Buffer,\r
820 T_CHAR *Str\r
821 )\r
822{\r
823 UINT32 Len;\r
824\r
825 Len = 0;\r
826 while (*Str == *Buffer) {\r
827 Buffer++;\r
828 Str++;\r
829 Len++;\r
830 }\r
831\r
832 if (*Str) {\r
833 return 0;\r
834 }\r
835\r
836 return Len;\r
837}\r
838\r
839static\r
840UINT32\r
841t_strlen (\r
842 T_CHAR *Str\r
843 )\r
844{\r
845 UINT32 Len;\r
846 Len = 0;\r
847 while (*Str) {\r
848 Len++;\r
849 Str++;\r
850 }\r
851\r
852 return Len;\r
853}\r
854\r
855static\r
856UINT32\r
857t_strncmp (\r
858 T_CHAR *Str1,\r
859 T_CHAR *Str2,\r
860 UINT32 Len\r
861 )\r
862{\r
863 while (Len > 0) {\r
864 if (*Str1 != *Str2) {\r
865 return Len;\r
866 }\r
867\r
868 Len--;\r
869 Str1++;\r
870 Str2++;\r
871 }\r
872\r
873 return 0;\r
874}\r
875\r
876static\r
877T_CHAR *\r
878t_strcpy (\r
879 T_CHAR *Dest,\r
880 T_CHAR *Src\r
881 )\r
882{\r
883 T_CHAR *SaveDest;\r
884 SaveDest = Dest;\r
885 while (*Src) {\r
886 *Dest = *Src;\r
887 Dest++;\r
888 Src++;\r
889 }\r
890\r
891 *Dest = 0;\r
892 return SaveDest;\r
893}\r
894\r
895#if 0\r
896static\r
897BOOLEAN\r
898IsValidIdentifierChar (\r
899 INT8 Char,\r
900 BOOLEAN FirstChar\r
901 )\r
902{\r
903 //\r
904 // If it's the first character of an identifier, then\r
905 // it must be one of [A-Za-z_].\r
906 //\r
907 if (FirstChar) {\r
908 if (isalpha (Char) || (Char == '_')) {\r
909 return TRUE;\r
910 }\r
911 } else {\r
912 //\r
913 // If it's not the first character, then it can\r
914 // be one of [A-Za-z_0-9]\r
915 //\r
916 if (isalnum (Char) || (Char == '_')) {\r
917 return TRUE;\r
918 }\r
919 }\r
920\r
921 return FALSE;\r
922}\r
923#endif\r
924static\r
925void\r
926RewindFile (\r
927 SOURCE_FILE *SourceFile\r
928 )\r
929{\r
930 SourceFile->LineNum = 1;\r
931 SourceFile->FileBufferPtr = SourceFile->FileBuffer;\r
932 SourceFile->EndOfFile = 0;\r
933}\r
934\r
935#if 0\r
936static\r
937BOOLEAN\r
938SkipTo (\r
939 SOURCE_FILE *SourceFile,\r
940 T_CHAR TChar,\r
941 BOOLEAN StopAfterNewline\r
942 )\r
943{\r
944 while (!EndOfFile (SourceFile)) {\r
945 //\r
946 // Check for the character of interest\r
947 //\r
948 if (SourceFile->FileBufferPtr[0] == TChar) {\r
949 return TRUE;\r
950 } else {\r
951 if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {\r
952 SourceFile->LineNum++;\r
953 if (StopAfterNewline) {\r
954 SourceFile->FileBufferPtr++;\r
955 if (SourceFile->FileBufferPtr[0] == 0) {\r
956 SourceFile->FileBufferPtr++;\r
957 }\r
958\r
959 return FALSE;\r
960 }\r
961 }\r
962\r
963 SourceFile->FileBufferPtr++;\r
964 }\r
965 }\r
966\r
967 return FALSE;\r
968}\r
969#endif\r