prscan.c revision 1.1 1 /******************************************************************************
2 *
3 * Module Name: prscan - Preprocessor start-up and file scan module
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #define _DECLARE_PR_GLOBALS
45
46 #include "aslcompiler.h"
47 #include "dtcompiler.h"
48
49 /*
50 * TBDs:
51 *
52 * No nested macros, maybe never
53 * Implement ASL "Include" as well as "#include" here?
54 */
55 #define _COMPONENT ASL_PREPROCESSOR
56 ACPI_MODULE_NAME ("prscan")
57
58
59 /* Local prototypes */
60
61 static void
62 PrPreprocessInputFile (
63 void);
64
65 static void
66 PrDoDirective (
67 char *DirectiveToken,
68 char **Next);
69
70 static int
71 PrMatchDirective (
72 char *Directive);
73
74 static void
75 PrPushDirective (
76 int Directive,
77 char *Argument);
78
79 static ACPI_STATUS
80 PrPopDirective (
81 void);
82
83 static void
84 PrDbgPrint (
85 char *Action,
86 char *DirectiveName);
87
88
89 /*
90 * Supported preprocessor directives
91 */
92 static const PR_DIRECTIVE_INFO Gbl_DirectiveInfo[] =
93 {
94 {"define", 1},
95 {"elif", 0}, /* Converted to #else..#if internally */
96 {"else", 0},
97 {"endif", 0},
98 {"error", 1},
99 {"if", 1},
100 {"ifdef", 1},
101 {"ifndef", 1},
102 {"include", 0}, /* Argument is not standard format, so 0 */
103 {"line", 1},
104 {"pragma", 1},
105 {"undef", 1},
106 {"warning", 1},
107 {NULL, 0}
108 };
109
110 enum Gbl_DirectiveIndexes
111 {
112 PR_DIRECTIVE_DEFINE = 0,
113 PR_DIRECTIVE_ELIF,
114 PR_DIRECTIVE_ELSE,
115 PR_DIRECTIVE_ENDIF,
116 PR_DIRECTIVE_ERROR,
117 PR_DIRECTIVE_IF,
118 PR_DIRECTIVE_IFDEF,
119 PR_DIRECTIVE_IFNDEF,
120 PR_DIRECTIVE_INCLUDE,
121 PR_DIRECTIVE_LINE,
122 PR_DIRECTIVE_PRAGMA,
123 PR_DIRECTIVE_UNDEF,
124 PR_DIRECTIVE_WARNING,
125 };
126
127 #define ASL_DIRECTIVE_NOT_FOUND -1
128
129
130 /*******************************************************************************
131 *
132 * FUNCTION: PrInitializePreprocessor
133 *
134 * PARAMETERS: None
135 *
136 * RETURN: None
137 *
138 * DESCRIPTION: Startup initialization for the Preprocessor.
139 *
140 ******************************************************************************/
141
142 void
143 PrInitializePreprocessor (
144 void)
145 {
146 /* Init globals and the list of #defines */
147
148 PrInitializeGlobals ();
149 Gbl_DefineList = NULL;
150 }
151
152
153 /*******************************************************************************
154 *
155 * FUNCTION: PrInitializeGlobals
156 *
157 * PARAMETERS: None
158 *
159 * RETURN: None
160 *
161 * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
162 * initialization and re-initialization between compiles during
163 * a multiple source file compile.
164 *
165 ******************************************************************************/
166
167 void
168 PrInitializeGlobals (
169 void)
170 {
171 /* Init globals */
172
173 Gbl_InputFileList = NULL;
174 Gbl_CurrentLineNumber = 0;
175 Gbl_PreprocessorLineNumber = 1;
176 Gbl_PreprocessorError = FALSE;
177
178 /* These are used to track #if/#else blocks (possibly nested) */
179
180 Gbl_IfDepth = 0;
181 Gbl_IgnoringThisCodeBlock = FALSE;
182 Gbl_DirectiveStack = NULL;
183 }
184
185
186 /*******************************************************************************
187 *
188 * FUNCTION: PrTerminatePreprocessor
189 *
190 * PARAMETERS: None
191 *
192 * RETURN: None
193 *
194 * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
195 * defines that were specified on the command line, in order to
196 * support multiple compiles with a single compiler invocation.
197 *
198 ******************************************************************************/
199
200 void
201 PrTerminatePreprocessor (
202 void)
203 {
204 PR_DEFINE_INFO *DefineInfo;
205
206
207 /*
208 * The persistent defines (created on the command line) are always at the
209 * end of the list. We save them.
210 */
211 while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
212 {
213 DefineInfo = Gbl_DefineList;
214 Gbl_DefineList = DefineInfo->Next;
215
216 ACPI_FREE (DefineInfo->Replacement);
217 ACPI_FREE (DefineInfo->Identifier);
218 ACPI_FREE (DefineInfo);
219 }
220 }
221
222
223 /*******************************************************************************
224 *
225 * FUNCTION: PrDoPreprocess
226 *
227 * PARAMETERS: None
228 *
229 * RETURN: None
230 *
231 * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
232 * be already open. Handles multiple input files via the
233 * #include directive.
234 *
235 ******************************************************************************/
236
237 void
238 PrDoPreprocess (
239 void)
240 {
241 BOOLEAN MoreInputFiles;
242
243
244 DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
245
246
247 FlSeekFile (ASL_FILE_INPUT, 0);
248 PrDumpPredefinedNames ();
249
250 /* Main preprocessor loop, handles include files */
251
252 do
253 {
254 PrPreprocessInputFile ();
255 MoreInputFiles = PrPopInputFileStack ();
256
257 } while (MoreInputFiles);
258
259 /* Point compiler input to the new preprocessor output file (.i) */
260
261 FlCloseFile (ASL_FILE_INPUT);
262 Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
263 AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
264
265 /* Reset globals to allow compiler to run */
266
267 FlSeekFile (ASL_FILE_INPUT, 0);
268 Gbl_CurrentLineNumber = 1;
269
270 DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
271 }
272
273
274 /*******************************************************************************
275 *
276 * FUNCTION: PrPreprocessInputFile
277 *
278 * PARAMETERS: None
279 *
280 * RETURN: None
281 *
282 * DESCRIPTION: Preprocess one entire file, line-by-line.
283 *
284 * Input: Raw user ASL from ASL_FILE_INPUT
285 * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
286 *
287 ******************************************************************************/
288
289 static void
290 PrPreprocessInputFile (
291 void)
292 {
293 UINT32 Offset;
294 char *Token;
295 char *ReplaceString;
296 PR_DEFINE_INFO *DefineInfo;
297 ACPI_SIZE TokenOffset;
298 char *Next;
299 int OffsetAdjust;
300
301
302 /* Scan line-by-line. Comments and blank lines are skipped by this function */
303
304 while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
305 {
306 /* Need a copy of the input line for strok() */
307
308 strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
309 Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
310 OffsetAdjust = 0;
311
312 /* All preprocessor directives must begin with '#' */
313
314 if (Token && (*Token == '#'))
315 {
316 if (strlen (Token) == 1)
317 {
318 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
319 }
320 else
321 {
322 Token++; /* Skip leading # */
323 }
324
325 /* Execute the directive, do not write line to output file */
326
327 PrDoDirective (Token, &Next);
328 continue;
329 }
330
331 /*
332 * If we are currently within the part of an IF/ELSE block that is
333 * FALSE, ignore the line and do not write it to the output file.
334 * This continues until an #else or #endif is encountered.
335 */
336 if (Gbl_IgnoringThisCodeBlock)
337 {
338 continue;
339 }
340
341 /* Match and replace all #defined names within this source line */
342
343 while (Token)
344 {
345 DefineInfo = PrMatchDefine (Token);
346 if (DefineInfo)
347 {
348 if (DefineInfo->Body)
349 {
350 /* This is a macro */
351
352 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
353 "Matched Macro: %s->%s\n",
354 Gbl_CurrentLineNumber, DefineInfo->Identifier,
355 DefineInfo->Replacement);
356
357 PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
358 DefineInfo, &Next);
359 }
360 else
361 {
362 ReplaceString = DefineInfo->Replacement;
363
364 /* Replace the name in the original line buffer */
365
366 TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
367 PrReplaceData (
368 &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
369 ReplaceString, strlen (ReplaceString));
370
371 /* Adjust for length difference between old and new name length */
372
373 OffsetAdjust += strlen (ReplaceString) - strlen (Token);
374
375 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
376 "Matched #define: %s->%s\n",
377 Gbl_CurrentLineNumber, Token,
378 *ReplaceString ? ReplaceString : "(NULL STRING)");
379 }
380 }
381
382 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
383 }
384
385 #if 0
386 /* Line prefix */
387 FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s %.5u i:%.5u */ ",
388 Gbl_Files[ASL_FILE_INPUT].Filename,
389 Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
390 #endif
391
392 /*
393 * Emit a #line directive if necessary, to keep the line numbers in
394 * the (.i) file synchronized with the original source code file, so
395 * that the correct line number appears in any error messages
396 * generated by the actual compiler.
397 */
398 if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1))
399 {
400 FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n",
401 Gbl_CurrentLineNumber);
402 }
403
404 Gbl_PreviousLineNumber = Gbl_CurrentLineNumber;
405 Gbl_PreprocessorLineNumber++;
406
407 /*
408 * Now we can write the possibly modified source line to the
409 * preprocessor (.i) file
410 */
411 FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
412 strlen (Gbl_CurrentLineBuffer));
413 }
414 }
415
416
417 /*******************************************************************************
418 *
419 * FUNCTION: PrDoDirective
420 *
421 * PARAMETERS: Directive - Pointer to directive name token
422 * Next - "Next" buffer from GetNextToken
423 *
424 * RETURN: None.
425 *
426 * DESCRIPTION: Main processing for all preprocessor directives
427 *
428 ******************************************************************************/
429
430 static void
431 PrDoDirective (
432 char *DirectiveToken,
433 char **Next)
434 {
435 char *Token = Gbl_MainTokenBuffer;
436 char *Token2;
437 char *End;
438 UINT64 Value;
439 ACPI_SIZE TokenOffset;
440 int Directive;
441 ACPI_STATUS Status;
442
443
444 if (!DirectiveToken)
445 {
446 goto SyntaxError;
447 }
448
449 Directive = PrMatchDirective (DirectiveToken);
450 if (Directive == ASL_DIRECTIVE_NOT_FOUND)
451 {
452 PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
453 THIS_TOKEN_OFFSET (DirectiveToken));
454
455 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
456 "#%s: Unknown directive\n",
457 Gbl_CurrentLineNumber, DirectiveToken);
458 return;
459 }
460
461 /*
462 * If we are currently ignoring this block and we encounter a #else or
463 * #elif, we must ignore their blocks also if the parent block is also
464 * being ignored.
465 */
466 if (Gbl_IgnoringThisCodeBlock)
467 {
468 switch (Directive)
469 {
470 case PR_DIRECTIVE_ELSE:
471 case PR_DIRECTIVE_ELIF:
472
473 if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock)
474 {
475 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
476 return;
477 }
478 break;
479
480 default:
481 break;
482 }
483 }
484
485 /*
486 * Need to always check for #else, #elif, #endif regardless of
487 * whether we are ignoring the current code block, since these
488 * are conditional code block terminators.
489 */
490 switch (Directive)
491 {
492 case PR_DIRECTIVE_ELSE:
493
494 Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
495 PrDbgPrint ("Executing", "else block");
496 return;
497
498 case PR_DIRECTIVE_ELIF:
499
500 Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
501 Directive = PR_DIRECTIVE_IF;
502
503 if (Gbl_IgnoringThisCodeBlock == TRUE)
504 {
505 /* Not executing the ELSE part -- all done here */
506 PrDbgPrint ("Ignoring", "elif block");
507 return;
508 }
509
510 /*
511 * After this, we will execute the IF part further below.
512 * First, however, pop off the original #if directive.
513 */
514 if (ACPI_FAILURE (PrPopDirective ()))
515 {
516 PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
517 THIS_TOKEN_OFFSET (DirectiveToken));
518 }
519
520 PrDbgPrint ("Executing", "elif block");
521 break;
522
523 case PR_DIRECTIVE_ENDIF:
524
525 PrDbgPrint ("Executing", "endif");
526
527 /* Pop the owning #if/#ifdef/#ifndef */
528
529 if (ACPI_FAILURE (PrPopDirective ()))
530 {
531 PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
532 THIS_TOKEN_OFFSET (DirectiveToken));
533 }
534 return;
535
536 default:
537 break;
538 }
539
540 /* Most directives have at least one argument */
541
542 if (Gbl_DirectiveInfo[Directive].ArgCount == 1)
543 {
544 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
545 if (!Token)
546 {
547 goto SyntaxError;
548 }
549 }
550
551 /*
552 * At this point, if we are ignoring the current code block,
553 * do not process any more directives (i.e., ignore them also.)
554 * For "if" style directives, open/push a new block anyway. We
555 * must do this to keep track of #endif directives
556 */
557 if (Gbl_IgnoringThisCodeBlock)
558 {
559 switch (Directive)
560 {
561 case PR_DIRECTIVE_IF:
562 case PR_DIRECTIVE_IFDEF:
563 case PR_DIRECTIVE_IFNDEF:
564
565 PrPushDirective (Directive, Token);
566 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
567 break;
568
569 default:
570 break;
571 }
572
573 return;
574 }
575
576 /*
577 * Execute the directive
578 */
579 PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name);
580
581 switch (Directive)
582 {
583 case PR_DIRECTIVE_IF:
584
585 TokenOffset = Token - Gbl_MainTokenBuffer;
586
587 /* Need to expand #define macros in the expression string first */
588
589 Status = PrResolveIntegerExpression (
590 &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
591 if (ACPI_FAILURE (Status))
592 {
593 return;
594 }
595
596 PrPushDirective (Directive, Token);
597 if (!Value)
598 {
599 Gbl_IgnoringThisCodeBlock = TRUE;
600 }
601
602 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
603 "Resolved #if: %8.8X%8.8X %s\n",
604 Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
605 Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
606 break;
607
608 case PR_DIRECTIVE_IFDEF:
609
610 PrPushDirective (Directive, Token);
611 if (!PrMatchDefine (Token))
612 {
613 Gbl_IgnoringThisCodeBlock = TRUE;
614 }
615
616 PrDbgPrint ("Evaluated", "ifdef");
617 break;
618
619 case PR_DIRECTIVE_IFNDEF:
620
621 PrPushDirective (Directive, Token);
622 if (PrMatchDefine (Token))
623 {
624 Gbl_IgnoringThisCodeBlock = TRUE;
625 }
626
627 PrDbgPrint ("Evaluated", "ifndef");
628 break;
629
630 case PR_DIRECTIVE_DEFINE:
631 /*
632 * By definition, if first char after the name is a paren,
633 * this is a function macro.
634 */
635 TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
636 if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
637 {
638 #ifndef MACROS_SUPPORTED
639 AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n",
640 Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber);
641 exit(1);
642 #else
643 PrAddMacro (Token, Next);
644 #endif
645 }
646 else
647 {
648 /* Use the remainder of the line for the #define */
649
650 Token2 = *Next;
651 if (Token2)
652 {
653 while ((*Token2 == ' ') || (*Token2 == '\t'))
654 {
655 Token2++;
656 }
657 End = Token2;
658 while (*End != '\n')
659 {
660 End++;
661 }
662 *End = 0;
663 }
664 else
665 {
666 Token2 = "";
667 }
668 #if 0
669 Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
670 if (!Token2)
671 {
672 Token2 = "";
673 }
674 #endif
675 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
676 "New #define: %s->%s\n",
677 Gbl_CurrentLineNumber, Token, Token2);
678
679 PrAddDefine (Token, Token2, FALSE);
680 }
681 break;
682
683 case PR_DIRECTIVE_ERROR:
684
685 /* Note: No macro expansion */
686
687 PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
688 THIS_TOKEN_OFFSET (Token));
689
690 Gbl_SourceLine = 0;
691 Gbl_NextError = Gbl_ErrorLog;
692 CmCleanupAndExit ();
693 exit(1);
694
695 case PR_DIRECTIVE_INCLUDE:
696
697 Token = PrGetNextToken (NULL, " \"<>", Next);
698 if (!Token)
699 {
700 goto SyntaxError;
701 }
702
703 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
704 "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
705 Token, Gbl_CurrentLineNumber);
706
707 PrOpenIncludeFile (Token);
708 break;
709
710 case PR_DIRECTIVE_LINE:
711
712 TokenOffset = Token - Gbl_MainTokenBuffer;
713
714 Status = PrResolveIntegerExpression (
715 &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
716 if (ACPI_FAILURE (Status))
717 {
718 return;
719 }
720
721 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
722 "User #line invocation %s\n", Gbl_CurrentLineNumber,
723 Token);
724
725 /* Update local line numbers */
726
727 Gbl_CurrentLineNumber = (UINT32) Value;
728 Gbl_PreviousLineNumber = 0;
729
730 /* Emit #line into the preprocessor file */
731
732 FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
733 Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
734 break;
735
736 case PR_DIRECTIVE_PRAGMA:
737
738 if (!strcmp (Token, "disable"))
739 {
740 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
741 if (!Token)
742 {
743 goto SyntaxError;
744 }
745
746 TokenOffset = Token - Gbl_MainTokenBuffer;
747 AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
748 }
749 else if (!strcmp (Token, "message"))
750 {
751 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
752 if (!Token)
753 {
754 goto SyntaxError;
755 }
756
757 TokenOffset = Token - Gbl_MainTokenBuffer;
758 AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
759 }
760 else
761 {
762 PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
763 THIS_TOKEN_OFFSET (Token));
764 return;
765 }
766
767 break;
768
769 case PR_DIRECTIVE_UNDEF:
770
771 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
772 "#undef: %s\n", Gbl_CurrentLineNumber, Token);
773
774 PrRemoveDefine (Token);
775 break;
776
777 case PR_DIRECTIVE_WARNING:
778
779 PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
780 THIS_TOKEN_OFFSET (Token));
781 break;
782
783 default:
784
785 /* Should never get here */
786 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
787 "Unrecognized directive: %u\n",
788 Gbl_CurrentLineNumber, Directive);
789 break;
790 }
791
792 return;
793
794 SyntaxError:
795
796 PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
797 THIS_TOKEN_OFFSET (DirectiveToken));
798 return;
799 }
800
801
802 /*******************************************************************************
803 *
804 * FUNCTION: PrMatchDirective
805 *
806 * PARAMETERS: Directive - Pointer to directive name token
807 *
808 * RETURN: Index into command array, -1 if not found
809 *
810 * DESCRIPTION: Lookup the incoming directive in the known directives table.
811 *
812 ******************************************************************************/
813
814 static int
815 PrMatchDirective (
816 char *Directive)
817 {
818 int i;
819
820
821 if (!Directive || Directive[0] == 0)
822 {
823 return (ASL_DIRECTIVE_NOT_FOUND);
824 }
825
826 for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
827 {
828 if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
829 {
830 return (i);
831 }
832 }
833
834 return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */
835 }
836
837
838 /*******************************************************************************
839 *
840 * FUNCTION: PrPushDirective
841 *
842 * PARAMETERS: Directive - Encoded directive ID
843 * Argument - String containing argument to the
844 * directive
845 *
846 * RETURN: None
847 *
848 * DESCRIPTION: Push an item onto the directive stack. Used for processing
849 * nested #if/#else type conditional compilation directives.
850 * Specifically: Used on detection of #if/#ifdef/#ifndef to open
851 * a block.
852 *
853 ******************************************************************************/
854
855 static void
856 PrPushDirective (
857 int Directive,
858 char *Argument)
859 {
860 DIRECTIVE_INFO *Info;
861
862
863 /* Allocate and populate a stack info item */
864
865 Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO));
866
867 Info->Next = Gbl_DirectiveStack;
868 Info->Directive = Directive;
869 Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock;
870 strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
871
872 DbgPrint (ASL_DEBUG_OUTPUT,
873 "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
874 Gbl_CurrentLineNumber, Gbl_IfDepth,
875 Gbl_IgnoringThisCodeBlock ? "I" : "E",
876 Gbl_IfDepth * 4, " ",
877 Gbl_DirectiveInfo[Directive].Name,
878 Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
879
880 /* Push new item */
881
882 Gbl_DirectiveStack = Info;
883 Gbl_IfDepth++;
884 }
885
886
887 /*******************************************************************************
888 *
889 * FUNCTION: PrPopDirective
890 *
891 * PARAMETERS: None
892 *
893 * RETURN: Status. Error if the stack is empty.
894 *
895 * DESCRIPTION: Pop an item off the directive stack. Used for processing
896 * nested #if/#else type conditional compilation directives.
897 * Specifically: Used on detection of #elif and #endif to remove
898 * the original #if/#ifdef/#ifndef from the stack and close
899 * the block.
900 *
901 ******************************************************************************/
902
903 static ACPI_STATUS
904 PrPopDirective (
905 void)
906 {
907 DIRECTIVE_INFO *Info;
908
909
910 /* Check for empty stack */
911
912 Info = Gbl_DirectiveStack;
913 if (!Info)
914 {
915 return (AE_ERROR);
916 }
917
918 /* Pop one item, keep globals up-to-date */
919
920 Gbl_IfDepth--;
921 Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
922 Gbl_DirectiveStack = Info->Next;
923
924 DbgPrint (ASL_DEBUG_OUTPUT,
925 "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
926 Gbl_CurrentLineNumber, Gbl_IfDepth,
927 Gbl_IgnoringThisCodeBlock ? "I" : "E",
928 Gbl_IfDepth * 4, " ",
929 Gbl_DirectiveInfo[Info->Directive].Name,
930 Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
931
932 ACPI_FREE (Info);
933 return (AE_OK);
934 }
935
936
937 /*******************************************************************************
938 *
939 * FUNCTION: PrDbgPrint
940 *
941 * PARAMETERS: Action - Action being performed
942 * DirectiveName - Directive being processed
943 *
944 * RETURN: None
945 *
946 * DESCRIPTION: Special debug print for directive processing.
947 *
948 ******************************************************************************/
949
950 static void
951 PrDbgPrint (
952 char *Action,
953 char *DirectiveName)
954 {
955
956 DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
957 "%*s %s #%s, Depth %u\n",
958 Gbl_CurrentLineNumber, Gbl_IfDepth,
959 Gbl_IgnoringThisCodeBlock ? "I" : "E",
960 Gbl_IfDepth * 4, " ",
961 Action, DirectiveName, Gbl_IfDepth);
962 }
963