Sync ACPICA with Intel's version 20150515.
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / prscan.c
1 /******************************************************************************
2  *
3  * Module Name: prscan - Preprocessor start-up and file scan module
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, 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 static void
89 PrDoIncludeBuffer (
90     char                    *Pathname,
91     char                    *BufferName);
92
93 static void
94 PrDoIncludeFile (
95     char                    *Pathname);
96
97
98 /*
99  * Supported preprocessor directives
100  * Each entry is of the form "Name, ArgumentCount"
101  */
102 static const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
103 {
104     {"define",          1},
105     {"elif",            0}, /* Converted to #else..#if internally */
106     {"else",            0},
107     {"endif",           0},
108     {"error",           1},
109     {"if",              1},
110     {"ifdef",           1},
111     {"ifndef",          1},
112     {"include",         0}, /* Argument is not standard format, so just use 0 here */
113     {"includebuffer",   0}, /* Argument is not standard format, so just use 0 here */
114     {"line",            1},
115     {"loadbuffer",      0},
116     {"pragma",          1},
117     {"undef",           1},
118     {"warning",         1},
119     {NULL,              0}
120 };
121
122 /* This table must match ordering of above table exactly */
123
124 enum Gbl_DirectiveIndexes
125 {
126     PR_DIRECTIVE_DEFINE = 0,
127     PR_DIRECTIVE_ELIF,
128     PR_DIRECTIVE_ELSE,
129     PR_DIRECTIVE_ENDIF,
130     PR_DIRECTIVE_ERROR,
131     PR_DIRECTIVE_IF,
132     PR_DIRECTIVE_IFDEF,
133     PR_DIRECTIVE_IFNDEF,
134     PR_DIRECTIVE_INCLUDE,
135     PR_DIRECTIVE_INCLUDEBUFFER,
136     PR_DIRECTIVE_LINE,
137     PR_DIRECTIVE_PRAGMA,
138     PR_DIRECTIVE_UNDEF,
139     PR_DIRECTIVE_WARNING,
140 };
141
142 #define ASL_DIRECTIVE_NOT_FOUND     -1
143
144
145 /*******************************************************************************
146  *
147  * FUNCTION:    PrInitializePreprocessor
148  *
149  * PARAMETERS:  None
150  *
151  * RETURN:      None
152  *
153  * DESCRIPTION: Startup initialization for the Preprocessor.
154  *
155  ******************************************************************************/
156
157 void
158 PrInitializePreprocessor (
159     void)
160 {
161     /* Init globals and the list of #defines */
162
163     PrInitializeGlobals ();
164     Gbl_DefineList = NULL;
165 }
166
167
168 /*******************************************************************************
169  *
170  * FUNCTION:    PrInitializeGlobals
171  *
172  * PARAMETERS:  None
173  *
174  * RETURN:      None
175  *
176  * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
177  *              initialization and re-initialization between compiles during
178  *              a multiple source file compile.
179  *
180  ******************************************************************************/
181
182 void
183 PrInitializeGlobals (
184     void)
185 {
186     /* Init globals */
187
188     Gbl_InputFileList = NULL;
189     Gbl_CurrentLineNumber = 0;
190     Gbl_PreprocessorLineNumber = 1;
191     Gbl_PreprocessorError = FALSE;
192
193     /* These are used to track #if/#else blocks (possibly nested) */
194
195     Gbl_IfDepth = 0;
196     Gbl_IgnoringThisCodeBlock = FALSE;
197     Gbl_DirectiveStack = NULL;
198 }
199
200
201 /*******************************************************************************
202  *
203  * FUNCTION:    PrTerminatePreprocessor
204  *
205  * PARAMETERS:  None
206  *
207  * RETURN:      None
208  *
209  * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
210  *              defines that were specified on the command line, in order to
211  *              support multiple compiles with a single compiler invocation.
212  *
213  ******************************************************************************/
214
215 void
216 PrTerminatePreprocessor (
217     void)
218 {
219     PR_DEFINE_INFO          *DefineInfo;
220
221
222     /*
223      * The persistent defines (created on the command line) are always at the
224      * end of the list. We save them.
225      */
226     while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
227     {
228         DefineInfo = Gbl_DefineList;
229         Gbl_DefineList = DefineInfo->Next;
230
231         ACPI_FREE (DefineInfo->Replacement);
232         ACPI_FREE (DefineInfo->Identifier);
233         ACPI_FREE (DefineInfo);
234     }
235 }
236
237
238 /*******************************************************************************
239  *
240  * FUNCTION:    PrDoPreprocess
241  *
242  * PARAMETERS:  None
243  *
244  * RETURN:      None
245  *
246  * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
247  *              be already open. Handles multiple input files via the
248  *              #include directive.
249  *
250  ******************************************************************************/
251
252 void
253 PrDoPreprocess (
254     void)
255 {
256     BOOLEAN                 MoreInputFiles;
257
258
259     DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
260
261
262     FlSeekFile (ASL_FILE_INPUT, 0);
263     PrDumpPredefinedNames ();
264
265     /* Main preprocessor loop, handles include files */
266
267     do
268     {
269         PrPreprocessInputFile ();
270         MoreInputFiles = PrPopInputFileStack ();
271
272     } while (MoreInputFiles);
273
274     /* Point compiler input to the new preprocessor output file (.i) */
275
276     FlCloseFile (ASL_FILE_INPUT);
277     Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
278     AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
279
280     /* Reset globals to allow compiler to run */
281
282     FlSeekFile (ASL_FILE_INPUT, 0);
283     Gbl_CurrentLineNumber = 1;
284
285     DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
286 }
287
288
289 /*******************************************************************************
290  *
291  * FUNCTION:    PrPreprocessInputFile
292  *
293  * PARAMETERS:  None
294  *
295  * RETURN:      None
296  *
297  * DESCRIPTION: Preprocess one entire file, line-by-line.
298  *
299  * Input:  Raw user ASL from ASL_FILE_INPUT
300  * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
301  *
302  ******************************************************************************/
303
304 static void
305 PrPreprocessInputFile (
306     void)
307 {
308     UINT32                  Offset;
309     char                    *Token;
310     char                    *ReplaceString;
311     PR_DEFINE_INFO          *DefineInfo;
312     ACPI_SIZE               TokenOffset;
313     char                    *Next;
314     int                     OffsetAdjust;
315
316
317     /* Scan line-by-line. Comments and blank lines are skipped by this function */
318
319     while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
320     {
321         /* Need a copy of the input line for strok() */
322
323         strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
324         Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
325         OffsetAdjust = 0;
326
327         /* All preprocessor directives must begin with '#' */
328
329         if (Token && (*Token == '#'))
330         {
331             if (strlen (Token) == 1)
332             {
333                 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
334             }
335             else
336             {
337                 Token++;    /* Skip leading # */
338             }
339
340             /* Execute the directive, do not write line to output file */
341
342             PrDoDirective (Token, &Next);
343             continue;
344         }
345
346         /*
347          * If we are currently within the part of an IF/ELSE block that is
348          * FALSE, ignore the line and do not write it to the output file.
349          * This continues until an #else or #endif is encountered.
350          */
351         if (Gbl_IgnoringThisCodeBlock)
352         {
353             continue;
354         }
355
356         /* Match and replace all #defined names within this source line */
357
358         while (Token)
359         {
360             DefineInfo = PrMatchDefine (Token);
361             if (DefineInfo)
362             {
363                 if (DefineInfo->Body)
364                 {
365                     /* This is a macro */
366
367                     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
368                         "Matched Macro: %s->%s\n",
369                         Gbl_CurrentLineNumber, DefineInfo->Identifier,
370                         DefineInfo->Replacement);
371
372                     PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
373                         DefineInfo, &Next);
374                 }
375                 else
376                 {
377                     ReplaceString = DefineInfo->Replacement;
378
379                     /* Replace the name in the original line buffer */
380
381                     TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
382                     PrReplaceData (
383                         &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
384                         ReplaceString, strlen (ReplaceString));
385
386                     /* Adjust for length difference between old and new name length */
387
388                     OffsetAdjust += strlen (ReplaceString) - strlen (Token);
389
390                     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
391                         "Matched #define: %s->%s\n",
392                         Gbl_CurrentLineNumber, Token,
393                         *ReplaceString ? ReplaceString : "(NULL STRING)");
394                 }
395             }
396
397             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
398         }
399
400         /*
401          * Emit a #line directive if necessary, to keep the line numbers in
402          * the (.i) file synchronized with the original source code file, so
403          * that the correct line number appears in any error messages
404          * generated by the actual compiler.
405          */
406         if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1))
407         {
408             FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n",
409                 Gbl_CurrentLineNumber);
410         }
411
412         Gbl_PreviousLineNumber = Gbl_CurrentLineNumber;
413         Gbl_PreprocessorLineNumber++;
414
415         /*
416          * Now we can write the possibly modified source line to the
417          * preprocessor (.i) file
418          */
419         FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
420             strlen (Gbl_CurrentLineBuffer));
421     }
422 }
423
424
425 /*******************************************************************************
426  *
427  * FUNCTION:    PrDoDirective
428  *
429  * PARAMETERS:  Directive               - Pointer to directive name token
430  *              Next                    - "Next" buffer from GetNextToken
431  *
432  * RETURN:      None.
433  *
434  * DESCRIPTION: Main processing for all preprocessor directives
435  *
436  ******************************************************************************/
437
438 static void
439 PrDoDirective (
440     char                    *DirectiveToken,
441     char                    **Next)
442 {
443     char                    *Token = Gbl_MainTokenBuffer;
444     char                    *Token2 = NULL;
445     char                    *End;
446     UINT64                  Value;
447     ACPI_SIZE               TokenOffset;
448     int                     Directive;
449     ACPI_STATUS             Status;
450
451
452     if (!DirectiveToken)
453     {
454         goto SyntaxError;
455     }
456
457     Directive = PrMatchDirective (DirectiveToken);
458     if (Directive == ASL_DIRECTIVE_NOT_FOUND)
459     {
460         PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
461             THIS_TOKEN_OFFSET (DirectiveToken));
462
463         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
464             "#%s: Unknown directive\n",
465             Gbl_CurrentLineNumber, DirectiveToken);
466         return;
467     }
468
469     /*
470      * If we are currently ignoring this block and we encounter a #else or
471      * #elif, we must ignore their blocks also if the parent block is also
472      * being ignored.
473      */
474     if (Gbl_IgnoringThisCodeBlock)
475     {
476         switch (Directive)
477         {
478         case PR_DIRECTIVE_ELSE:
479         case PR_DIRECTIVE_ELIF:
480
481             if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock)
482             {
483                 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
484                 return;
485             }
486             break;
487
488         default:
489             break;
490         }
491     }
492
493     /*
494      * Need to always check for #else, #elif, #endif regardless of
495      * whether we are ignoring the current code block, since these
496      * are conditional code block terminators.
497      */
498     switch (Directive)
499     {
500     case PR_DIRECTIVE_ELSE:
501
502         Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
503         PrDbgPrint ("Executing", "else block");
504         return;
505
506     case PR_DIRECTIVE_ELIF:
507
508         Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
509         Directive = PR_DIRECTIVE_IF;
510
511         if (Gbl_IgnoringThisCodeBlock == TRUE)
512         {
513             /* Not executing the ELSE part -- all done here */
514             PrDbgPrint ("Ignoring", "elif block");
515             return;
516         }
517
518         /*
519          * After this, we will execute the IF part further below.
520          * First, however, pop off the original #if directive.
521          */
522         if (ACPI_FAILURE (PrPopDirective ()))
523         {
524             PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
525                 THIS_TOKEN_OFFSET (DirectiveToken));
526         }
527
528         PrDbgPrint ("Executing", "elif block");
529         break;
530
531     case PR_DIRECTIVE_ENDIF:
532
533         PrDbgPrint ("Executing", "endif");
534
535         /* Pop the owning #if/#ifdef/#ifndef */
536
537         if (ACPI_FAILURE (PrPopDirective ()))
538         {
539             PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
540                 THIS_TOKEN_OFFSET (DirectiveToken));
541         }
542         return;
543
544     default:
545         break;
546     }
547
548     /* Most directives have at least one argument */
549
550     if (Gbl_DirectiveInfo[Directive].ArgCount >= 1)
551     {
552         Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
553         if (!Token)
554         {
555             goto SyntaxError;
556         }
557     }
558
559     if (Gbl_DirectiveInfo[Directive].ArgCount >= 2)
560     {
561         Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
562         if (!Token2)
563         {
564             goto SyntaxError;
565         }
566     }
567
568     /*
569      * At this point, if we are ignoring the current code block,
570      * do not process any more directives (i.e., ignore them also.)
571      * For "if" style directives, open/push a new block anyway. We
572      * must do this to keep track of #endif directives
573      */
574     if (Gbl_IgnoringThisCodeBlock)
575     {
576         switch (Directive)
577         {
578         case PR_DIRECTIVE_IF:
579         case PR_DIRECTIVE_IFDEF:
580         case PR_DIRECTIVE_IFNDEF:
581
582             PrPushDirective (Directive, Token);
583             PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
584             break;
585
586         default:
587             break;
588         }
589
590         return;
591     }
592
593     /*
594      * Execute the directive
595      */
596     PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name);
597
598     switch (Directive)
599     {
600     case PR_DIRECTIVE_IF:
601
602         TokenOffset = Token - Gbl_MainTokenBuffer;
603
604         /* Need to expand #define macros in the expression string first */
605
606         Status = PrResolveIntegerExpression (
607             &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
608         if (ACPI_FAILURE (Status))
609         {
610             return;
611         }
612
613         PrPushDirective (Directive, Token);
614         if (!Value)
615         {
616             Gbl_IgnoringThisCodeBlock = TRUE;
617         }
618
619         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
620             "Resolved #if: %8.8X%8.8X %s\n",
621             Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
622             Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
623         break;
624
625     case PR_DIRECTIVE_IFDEF:
626
627         PrPushDirective (Directive, Token);
628         if (!PrMatchDefine (Token))
629         {
630             Gbl_IgnoringThisCodeBlock = TRUE;
631         }
632
633         PrDbgPrint ("Evaluated", "ifdef");
634         break;
635
636     case PR_DIRECTIVE_IFNDEF:
637
638         PrPushDirective (Directive, Token);
639         if (PrMatchDefine (Token))
640         {
641             Gbl_IgnoringThisCodeBlock = TRUE;
642         }
643
644         PrDbgPrint ("Evaluated", "ifndef");
645         break;
646
647     case PR_DIRECTIVE_DEFINE:
648         /*
649          * By definition, if first char after the name is a paren,
650          * this is a function macro.
651          */
652         TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
653         if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
654         {
655 #ifndef MACROS_SUPPORTED
656             AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n",
657                 Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber);
658             exit(1);
659 #else
660             PrAddMacro (Token, Next);
661 #endif
662         }
663         else
664         {
665             /* Use the remainder of the line for the #define */
666
667             Token2 = *Next;
668             if (Token2)
669             {
670                 while ((*Token2 == ' ') || (*Token2 == '\t'))
671                 {
672                     Token2++;
673                 }
674                 End = Token2;
675                 while (*End != '\n')
676                 {
677                     End++;
678                 }
679                 *End = 0;
680             }
681             else
682             {
683                 Token2 = "";
684             }
685 #if 0
686             Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
687             if (!Token2)
688             {
689                 Token2 = "";
690             }
691 #endif
692             DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
693                 "New #define: %s->%s\n",
694                 Gbl_CurrentLineNumber, Token, Token2);
695
696             PrAddDefine (Token, Token2, FALSE);
697         }
698         break;
699
700     case PR_DIRECTIVE_ERROR:
701
702         /* Note: No macro expansion */
703
704         PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
705             THIS_TOKEN_OFFSET (Token));
706
707         Gbl_SourceLine = 0;
708         Gbl_NextError = Gbl_ErrorLog;
709         CmCleanupAndExit ();
710         exit(1);
711
712     case PR_DIRECTIVE_INCLUDE:
713
714         Token = PrGetNextToken (NULL, " \"<>", Next);
715         if (!Token)
716         {
717             goto SyntaxError;
718         }
719
720         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
721             "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
722             Token, Gbl_CurrentLineNumber);
723
724         PrDoIncludeFile (Token);
725         break;
726
727     case PR_DIRECTIVE_INCLUDEBUFFER:
728
729         Token = PrGetNextToken (NULL, " \"<>", Next);
730         if (!Token)
731         {
732             goto SyntaxError;
733         }
734
735         Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
736         if (!Token2)
737         {
738             goto SyntaxError;
739         }
740
741         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
742             "Start #includebuffer input from file \"%s\", buffer name %s\n",
743             Gbl_CurrentLineNumber, Token, Token2);
744
745         PrDoIncludeBuffer (Token, Token2);
746         break;
747
748     case PR_DIRECTIVE_LINE:
749
750         TokenOffset = Token - Gbl_MainTokenBuffer;
751
752         Status = PrResolveIntegerExpression (
753             &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
754         if (ACPI_FAILURE (Status))
755         {
756             return;
757         }
758
759         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
760             "User #line invocation %s\n", Gbl_CurrentLineNumber,
761             Token);
762
763         /* Update local line numbers */
764
765         Gbl_CurrentLineNumber = (UINT32) Value;
766         Gbl_PreviousLineNumber = 0;
767
768         /* Emit #line into the preprocessor file */
769
770         FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
771             Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
772         break;
773
774     case PR_DIRECTIVE_PRAGMA:
775
776         if (!strcmp (Token, "disable"))
777         {
778             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
779             if (!Token)
780             {
781                 goto SyntaxError;
782             }
783
784             TokenOffset = Token - Gbl_MainTokenBuffer;
785             AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
786         }
787         else if (!strcmp (Token, "message"))
788         {
789             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
790             if (!Token)
791             {
792                 goto SyntaxError;
793             }
794
795             TokenOffset = Token - Gbl_MainTokenBuffer;
796             AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
797         }
798         else
799         {
800             PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
801                 THIS_TOKEN_OFFSET (Token));
802             return;
803         }
804
805         break;
806
807     case PR_DIRECTIVE_UNDEF:
808
809         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
810             "#undef: %s\n", Gbl_CurrentLineNumber, Token);
811
812         PrRemoveDefine (Token);
813         break;
814
815     case PR_DIRECTIVE_WARNING:
816
817         PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
818             THIS_TOKEN_OFFSET (Token));
819         break;
820
821     default:
822
823         /* Should never get here */
824         DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
825             "Unrecognized directive: %u\n",
826             Gbl_CurrentLineNumber, Directive);
827         break;
828     }
829
830     return;
831
832 SyntaxError:
833
834     PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
835         THIS_TOKEN_OFFSET (DirectiveToken));
836     return;
837 }
838
839
840 /*******************************************************************************
841  *
842  * FUNCTION:    PrMatchDirective
843  *
844  * PARAMETERS:  Directive           - Pointer to directive name token
845  *
846  * RETURN:      Index into command array, -1 if not found
847  *
848  * DESCRIPTION: Lookup the incoming directive in the known directives table.
849  *
850  ******************************************************************************/
851
852 static int
853 PrMatchDirective (
854     char                    *Directive)
855 {
856     int                     i;
857
858
859     if (!Directive || Directive[0] == 0)
860     {
861         return (ASL_DIRECTIVE_NOT_FOUND);
862     }
863
864     for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
865     {
866         if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
867         {
868             return (i);
869         }
870     }
871
872     return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
873 }
874
875
876 /*******************************************************************************
877  *
878  * FUNCTION:    PrPushDirective
879  *
880  * PARAMETERS:  Directive           - Encoded directive ID
881  *              Argument            - String containing argument to the
882  *                                    directive
883  *
884  * RETURN:      None
885  *
886  * DESCRIPTION: Push an item onto the directive stack. Used for processing
887  *              nested #if/#else type conditional compilation directives.
888  *              Specifically: Used on detection of #if/#ifdef/#ifndef to open
889  *              a block.
890  *
891  ******************************************************************************/
892
893 static void
894 PrPushDirective (
895     int                     Directive,
896     char                    *Argument)
897 {
898     DIRECTIVE_INFO          *Info;
899
900
901     /* Allocate and populate a stack info item */
902
903     Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO));
904
905     Info->Next = Gbl_DirectiveStack;
906     Info->Directive = Directive;
907     Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock;
908     strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
909
910     DbgPrint (ASL_DEBUG_OUTPUT,
911         "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
912         Gbl_CurrentLineNumber, Gbl_IfDepth,
913         Gbl_IgnoringThisCodeBlock ? "I" : "E",
914         Gbl_IfDepth * 4, " ",
915         Gbl_DirectiveInfo[Directive].Name,
916         Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
917
918     /* Push new item */
919
920     Gbl_DirectiveStack = Info;
921     Gbl_IfDepth++;
922 }
923
924
925 /*******************************************************************************
926  *
927  * FUNCTION:    PrPopDirective
928  *
929  * PARAMETERS:  None
930  *
931  * RETURN:      Status. Error if the stack is empty.
932  *
933  * DESCRIPTION: Pop an item off the directive stack. Used for processing
934  *              nested #if/#else type conditional compilation directives.
935  *              Specifically: Used on detection of #elif and #endif to remove
936  *              the original #if/#ifdef/#ifndef from the stack and close
937  *              the block.
938  *
939  ******************************************************************************/
940
941 static ACPI_STATUS
942 PrPopDirective (
943     void)
944 {
945     DIRECTIVE_INFO          *Info;
946
947
948     /* Check for empty stack */
949
950     Info = Gbl_DirectiveStack;
951     if (!Info)
952     {
953         return (AE_ERROR);
954     }
955
956     /* Pop one item, keep globals up-to-date */
957
958     Gbl_IfDepth--;
959     Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
960     Gbl_DirectiveStack = Info->Next;
961
962     DbgPrint (ASL_DEBUG_OUTPUT,
963         "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
964         Gbl_CurrentLineNumber, Gbl_IfDepth,
965         Gbl_IgnoringThisCodeBlock ? "I" : "E",
966         Gbl_IfDepth * 4, " ",
967         Gbl_DirectiveInfo[Info->Directive].Name,
968         Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
969
970     ACPI_FREE (Info);
971     return (AE_OK);
972 }
973
974
975 /*******************************************************************************
976  *
977  * FUNCTION:    PrDbgPrint
978  *
979  * PARAMETERS:  Action              - Action being performed
980  *              DirectiveName       - Directive being processed
981  *
982  * RETURN:      None
983  *
984  * DESCRIPTION: Special debug print for directive processing.
985  *
986  ******************************************************************************/
987
988 static void
989 PrDbgPrint (
990     char                    *Action,
991     char                    *DirectiveName)
992 {
993
994     DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
995         "%*s %s #%s, IfDepth %u\n",
996         Gbl_CurrentLineNumber, Gbl_IfDepth,
997         Gbl_IgnoringThisCodeBlock ? "I" : "E",
998         Gbl_IfDepth * 4, " ",
999         Action, DirectiveName, Gbl_IfDepth);
1000 }
1001
1002
1003 /*******************************************************************************
1004  *
1005  * FUNCTION:    PrDoIncludeFile
1006  *
1007  * PARAMETERS:  Pathname                - Name of the input file
1008  *
1009  * RETURN:      None.
1010  *
1011  * DESCRIPTION: Open an include file, from #include.
1012  *
1013  ******************************************************************************/
1014
1015 static void
1016 PrDoIncludeFile (
1017     char                    *Pathname)
1018 {
1019     char                    *FullPathname;
1020
1021
1022     (void) PrOpenIncludeFile (Pathname, "r", &FullPathname);
1023 }
1024
1025
1026 /*******************************************************************************
1027  *
1028  * FUNCTION:    PrDoIncludeBuffer
1029  *
1030  * PARAMETERS:  Pathname                - Name of the input binary file
1031  *              BufferName              - ACPI namepath of the buffer
1032  *
1033  * RETURN:      None.
1034  *
1035  * DESCRIPTION: Create an ACPI buffer object from a binary file. The contents
1036  *              of the file are emitted into the buffer object as ascii
1037  *              hex data. From #includebuffer.
1038  *
1039  ******************************************************************************/
1040
1041 static void
1042 PrDoIncludeBuffer (
1043     char                    *Pathname,
1044     char                    *BufferName)
1045 {
1046     char                    *FullPathname;
1047     FILE                    *BinaryBufferFile;
1048     UINT32                  i = 0;
1049     UINT8                   c;
1050
1051
1052     BinaryBufferFile = PrOpenIncludeFile (Pathname, "rb", &FullPathname);
1053     if (!BinaryBufferFile)
1054     {
1055         return;
1056     }
1057
1058     /* Emit "Name (XXXX, Buffer() {" header */
1059
1060     FlPrintFile (ASL_FILE_PREPROCESSOR, "Name (%s, Buffer()\n{", BufferName);
1061
1062     /* Dump the entire file in ascii hex format */
1063
1064     while (fread (&c, 1, 1, BinaryBufferFile))
1065     {
1066         if (!(i % 8))
1067         {
1068             FlPrintFile (ASL_FILE_PREPROCESSOR, "\n   ", c);
1069         }
1070
1071         FlPrintFile (ASL_FILE_PREPROCESSOR, " 0x%2.2X,", c);
1072         i++;
1073     }
1074
1075     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
1076         "#includebuffer: read %u bytes from %s\n",
1077         Gbl_CurrentLineNumber, i, FullPathname);
1078
1079     /* Close the Name() operator */
1080
1081     FlPrintFile (ASL_FILE_PREPROCESSOR, "\n})\n", BufferName);
1082     fclose (BinaryBufferFile);
1083 }