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