xref: /freebsd/sys/contrib/dev/acpica/compiler/prscan.c (revision 595e514d0df2bac5b813d35f83e32875dbf16a83)
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 <contrib/dev/acpica/compiler/aslcompiler.h>
47 #include <contrib/dev/acpica/compiler/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     BOOLEAN                 *IgnoringThisCodeBlock);
70 
71 static int
72 PrMatchDirective (
73     char                    *Directive);
74 
75 /*
76  * Supported preprocessor directives
77  */
78 static const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
79 {
80     {"define",  1},
81     {"elif",    0}, /* Converted to #else..#if internally */
82     {"else",    0},
83     {"endif",   0},
84     {"error",   1},
85     {"if",      1},
86     {"ifdef",   1},
87     {"ifndef",  1},
88     {"include", 0}, /* Argument is not standard format, so 0 */
89     {"line",    1},
90     {"pragma",  1},
91     {"undef",   1},
92     {"warning", 1},
93     {NULL,      0}
94 };
95 
96 enum Gbl_DirectiveIndexes
97 {
98     PR_DIRECTIVE_DEFINE = 0,
99     PR_DIRECTIVE_ELIF,
100     PR_DIRECTIVE_ELSE,
101     PR_DIRECTIVE_ENDIF,
102     PR_DIRECTIVE_ERROR,
103     PR_DIRECTIVE_IF,
104     PR_DIRECTIVE_IFDEF,
105     PR_DIRECTIVE_IFNDEF,
106     PR_DIRECTIVE_INCLUDE,
107     PR_DIRECTIVE_LINE,
108     PR_DIRECTIVE_PRAGMA,
109     PR_DIRECTIVE_UNDEF,
110     PR_DIRECTIVE_WARNING,
111 };
112 
113 #define ASL_DIRECTIVE_NOT_FOUND     -1
114 
115 
116 /*******************************************************************************
117  *
118  * FUNCTION:    PrInitializePreprocessor
119  *
120  * PARAMETERS:  None
121  *
122  * RETURN:      None
123  *
124  * DESCRIPTION: Startup initialization for the Preprocessor.
125  *
126  ******************************************************************************/
127 
128 void
129 PrInitializePreprocessor (
130     void)
131 {
132     /* Init globals and the list of #defines */
133 
134     PrInitializeGlobals ();
135     Gbl_DefineList = NULL;
136 }
137 
138 
139 /*******************************************************************************
140  *
141  * FUNCTION:    PrInitializeGlobals
142  *
143  * PARAMETERS:  None
144  *
145  * RETURN:      None
146  *
147  * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
148  *              initialization and re-initialization between compiles during
149  *              a multiple source file compile.
150  *
151  ******************************************************************************/
152 
153 void
154 PrInitializeGlobals (
155     void)
156 {
157     /* Init globals */
158 
159     Gbl_IfDepth = 0;
160     Gbl_InputFileList = NULL;
161     Gbl_CurrentLineNumber = 0;
162     Gbl_PreprocessorLineNumber = 1;
163     Gbl_PreprocessorError = FALSE;
164 }
165 
166 
167 /*******************************************************************************
168  *
169  * FUNCTION:    PrTerminatePreprocessor
170  *
171  * PARAMETERS:  None
172  *
173  * RETURN:      None
174  *
175  * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
176  *              defines that were specified on the command line, in order to
177  *              support multiple compiles with a single compiler invocation.
178  *
179  ******************************************************************************/
180 
181 void
182 PrTerminatePreprocessor (
183     void)
184 {
185     PR_DEFINE_INFO          *DefineInfo;
186 
187 
188     /*
189      * The persistent defines (created on the command line) are always at the
190      * end of the list. We save them.
191      */
192     while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
193     {
194         DefineInfo = Gbl_DefineList;
195         Gbl_DefineList = DefineInfo->Next;
196 
197         ACPI_FREE (DefineInfo->Replacement);
198         ACPI_FREE (DefineInfo->Identifier);
199         ACPI_FREE (DefineInfo);
200     }
201 }
202 
203 
204 /*******************************************************************************
205  *
206  * FUNCTION:    PrDoPreprocess
207  *
208  * PARAMETERS:  None
209  *
210  * RETURN:      Error Status. TRUE if error, FALSE if OK.
211  *
212  * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
213  *              be already open. Handles multiple input files via the
214  *              #include directive.
215  *
216  ******************************************************************************/
217 
218 BOOLEAN
219 PrDoPreprocess (
220     void)
221 {
222     BOOLEAN                 MoreInputFiles;
223 
224 
225     DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
226 
227 
228     FlSeekFile (ASL_FILE_INPUT, 0);
229     PrDumpPredefinedNames ();
230 
231     /* Main preprocessor loop, handles include files */
232 
233     do
234     {
235         PrPreprocessInputFile ();
236         MoreInputFiles = PrPopInputFileStack ();
237 
238     } while (MoreInputFiles);
239 
240 
241     /*
242      * TBD: is this necessary? (Do we abort on any preprocessing errors?)
243      */
244     if (Gbl_PreprocessorError)
245     {
246         /* TBD: can't use source_output file for preprocessor error reporting */
247 
248         Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle = NULL;
249         PrTerminatePreprocessor ();
250         return (TRUE);
251     }
252 
253     /* Point compiler input to the new preprocessor file (.i) */
254 
255     FlCloseFile (ASL_FILE_INPUT);
256     Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
257     AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
258 
259     /* Reset globals to allow compiler to run */
260 
261     FlSeekFile (ASL_FILE_INPUT, 0);
262     Gbl_CurrentLineNumber = 1;
263 
264     DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
265     return (FALSE);
266 }
267 
268 
269 /*******************************************************************************
270  *
271  * FUNCTION:    PrPreprocessInputFile
272  *
273  * PARAMETERS:  None
274  *
275  * RETURN:      None
276  *
277  * DESCRIPTION: Preprocess one entire file, line-by-line.
278  *
279  * Input:  Raw user ASL from ASL_FILE_INPUT
280  * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
281  *
282  ******************************************************************************/
283 
284 static void
285 PrPreprocessInputFile (
286     void)
287 {
288     UINT32                  Offset;
289     char                    *Token;
290     char                    *ReplaceString;
291     PR_DEFINE_INFO          *DefineInfo;
292     ACPI_SIZE               TokenOffset;
293     BOOLEAN                 IgnoringThisCodeBlock = FALSE;
294     char                    *Next;
295     int                     OffsetAdjust;
296 
297 
298     /* Scan line-by-line. Comments and blank lines are skipped by this function */
299 
300     while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
301     {
302         /* Need a copy of the input line for strok() */
303 
304         strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
305         Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
306         OffsetAdjust = 0;
307 
308         /* All preprocessor directives must begin with '#' */
309 
310         if (Token && (*Token == '#'))
311         {
312             if (strlen (Token) == 1)
313             {
314                 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
315             }
316             else
317             {
318                 Token++;    /* Skip leading # */
319             }
320 
321             /* Execute the directive, do not write line to output file */
322 
323             PrDoDirective (Token, &Next, &IgnoringThisCodeBlock);
324             continue;
325         }
326 
327         /*
328          * If we are currently within the part of an IF/ELSE block that is
329          * FALSE, ignore the line and do not write it to the output file.
330          * This continues until an #else or #endif is encountered.
331          */
332         if (IgnoringThisCodeBlock == TRUE)
333         {
334             continue;
335         }
336 
337         /* Match and replace all #defined names within this source line */
338 
339         while (Token)
340         {
341             DefineInfo = PrMatchDefine (Token);
342             if (DefineInfo)
343             {
344                 if (DefineInfo->Body)
345                 {
346                     /* This is a macro */
347 
348                     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
349                         "Matched Macro: %s->%s\n",
350                         Gbl_CurrentLineNumber, DefineInfo->Identifier,
351                         DefineInfo->Replacement);
352 
353                     PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
354                         DefineInfo, &Next);
355                 }
356                 else
357                 {
358                     ReplaceString = DefineInfo->Replacement;
359 
360                     /* Replace the name in the original line buffer */
361 
362                     TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
363                     PrReplaceData (
364                         &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
365                         ReplaceString, strlen (ReplaceString));
366 
367                     /* Adjust for length difference between old and new name length */
368 
369                     OffsetAdjust += strlen (ReplaceString) - strlen (Token);
370 
371                     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
372                         "Matched #define: %s->%s\n",
373                         Gbl_CurrentLineNumber, Token,
374                         *ReplaceString ? ReplaceString : "(NULL STRING)");
375                 }
376             }
377 
378             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
379         }
380 
381 #if 0
382 /* Line prefix */
383         FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s  %.5u  i:%.5u */ ",
384             Gbl_Files[ASL_FILE_INPUT].Filename,
385             Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
386 #endif
387 
388         /*
389          * Emit a #line directive if necessary, to keep the line numbers in
390          * the (.i) file synchronized with the original source code file, so
391          * that the correct line number appears in any error messages
392          * generated by the actual compiler.
393          */
394         if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1))
395         {
396             FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n",
397                 Gbl_CurrentLineNumber);
398         }
399 
400         Gbl_PreviousLineNumber = Gbl_CurrentLineNumber;
401         Gbl_PreprocessorLineNumber++;
402 
403         /*
404          * Now we can write the possibly modified source line to the
405          * preprocessor (.i) file
406          */
407         FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
408             strlen (Gbl_CurrentLineBuffer));
409     }
410 }
411 
412 
413 /*******************************************************************************
414  *
415  * FUNCTION:    PrDoDirective
416  *
417  * PARAMETERS:  Directive               - Pointer to directive name token
418  *              Next                    - "Next" buffer from GetNextToken
419  *              IgnoringThisCodeBlock   - Where the "ignore code" flag is
420  *                                        returned.
421  *
422  * RETURN:      IgnoringThisCodeBlock: Set to TRUE if we are skipping the FALSE
423  *              part of an #if or #else block. Set to FALSE when the
424  *              corresponding #else or #endif is encountered.
425  *
426  * DESCRIPTION: Main processing for all preprocessor directives
427  *
428  ******************************************************************************/
429 
430 static void
431 PrDoDirective (
432     char                    *DirectiveToken,
433     char                    **Next,
434     BOOLEAN                 *IgnoringThisCodeBlock)
435 {
436     char                    *Token = Gbl_MainTokenBuffer;
437     char                    *Token2;
438     char                    *End;
439     UINT64                  Value;
440     ACPI_SIZE               TokenOffset;
441     int                     Directive;
442     ACPI_STATUS             Status;
443 
444 
445     if (!DirectiveToken)
446     {
447         goto SyntaxError;
448     }
449 
450     Directive = PrMatchDirective (DirectiveToken);
451     if (Directive == ASL_DIRECTIVE_NOT_FOUND)
452     {
453         PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
454             THIS_TOKEN_OFFSET (DirectiveToken));
455 
456         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
457             "#%s: Unknown directive\n",
458             Gbl_CurrentLineNumber, DirectiveToken);
459         return;
460     }
461 
462     /* TBD: Need a faster way to do this: */
463 
464     if ((Directive == PR_DIRECTIVE_ELIF) ||
465         (Directive == PR_DIRECTIVE_ELSE) ||
466         (Directive == PR_DIRECTIVE_ENDIF))
467     {
468         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n",
469             Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name);
470     }
471 
472     /*
473      * Need to always check for #else, #elif, #endif regardless of
474      * whether we are ignoring the current code block, since these
475      * are conditional code block terminators.
476      */
477     switch (Directive)
478     {
479     case PR_DIRECTIVE_ELIF:
480 
481         *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock);
482         if (*IgnoringThisCodeBlock == TRUE)
483         {
484             /* Not executing the ELSE part -- all done here */
485             return;
486         }
487 
488         /* Will execute the ELSE..IF part */
489 
490         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
491             "#elif - Executing else block\n",
492             Gbl_CurrentLineNumber);
493         Directive = PR_DIRECTIVE_IF;
494         break;
495 
496     case PR_DIRECTIVE_ELSE:
497 
498         *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock);
499         return;
500 
501     case PR_DIRECTIVE_ENDIF:
502 
503         *IgnoringThisCodeBlock = FALSE;
504         Gbl_IfDepth--;
505         if (Gbl_IfDepth < 0)
506         {
507             PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
508                 THIS_TOKEN_OFFSET (DirectiveToken));
509             Gbl_IfDepth = 0;
510         }
511         return;
512 
513     default:
514 
515         break;
516     }
517 
518     /*
519      * At this point, if we are ignoring the current code block,
520      * do not process any more directives (i.e., ignore them also.)
521      */
522     if (*IgnoringThisCodeBlock == TRUE)
523     {
524         return;
525     }
526 
527     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n",
528         Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name);
529 
530     /* Most directives have at least one argument */
531 
532     if (Gbl_DirectiveInfo[Directive].ArgCount == 1)
533     {
534         Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
535         if (!Token)
536         {
537             goto SyntaxError;
538         }
539     }
540 
541     switch (Directive)
542     {
543     case PR_DIRECTIVE_DEFINE:
544         /*
545          * By definition, if first char after the name is a paren,
546          * this is a function macro.
547          */
548         TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
549         if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
550         {
551 #ifndef MACROS_SUPPORTED
552             AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n",
553                 Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber);
554             exit(1);
555 #else
556             PrAddMacro (Token, Next);
557 #endif
558         }
559         else
560         {
561             /* Use the remainder of the line for the #define */
562 
563             Token2 = *Next;
564             if (Token2)
565             {
566                 while ((*Token2 == ' ') || (*Token2 == '\t'))
567                 {
568                     Token2++;
569                 }
570                 End = Token2;
571                 while (*End != '\n')
572                 {
573                     End++;
574                 }
575                 *End = 0;
576             }
577             else
578             {
579                 Token2 = "";
580             }
581 #if 0
582             Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
583             if (!Token2)
584             {
585                 Token2 = "";
586             }
587 #endif
588             DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
589                 "New #define: %s->%s\n",
590                 Gbl_CurrentLineNumber, Token, Token2);
591 
592             PrAddDefine (Token, Token2, FALSE);
593         }
594         break;
595 
596     case PR_DIRECTIVE_ERROR:
597 
598         /* TBD compiler should abort */
599         /* Note: No macro expansion */
600 
601         PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
602             THIS_TOKEN_OFFSET (Token));
603         break;
604 
605     case PR_DIRECTIVE_IF:
606 
607         TokenOffset = Token - Gbl_MainTokenBuffer;
608 
609         /* Need to expand #define macros in the expression string first */
610 
611         Status = PrResolveIntegerExpression (
612             &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
613         if (ACPI_FAILURE (Status))
614         {
615             return;
616         }
617 
618         if (!Value)
619         {
620             *IgnoringThisCodeBlock = TRUE;
621         }
622 
623         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
624             "Resolved #if: %8.8X%8.8X %s\n",
625             Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
626             *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
627 
628         Gbl_IfDepth++;
629         break;
630 
631     case PR_DIRECTIVE_IFDEF:
632 
633         if (!PrMatchDefine (Token))
634         {
635             *IgnoringThisCodeBlock = TRUE;
636         }
637 
638         Gbl_IfDepth++;
639         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
640             "Start #ifdef %s\n", Gbl_CurrentLineNumber,
641             *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
642         break;
643 
644     case PR_DIRECTIVE_IFNDEF:
645 
646         if (PrMatchDefine (Token))
647         {
648             *IgnoringThisCodeBlock = TRUE;
649         }
650 
651         Gbl_IfDepth++;
652         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
653             "Start #ifndef %2.2X\n", Gbl_CurrentLineNumber,
654             *IgnoringThisCodeBlock, Gbl_CurrentLineNumber);
655         break;
656 
657     case PR_DIRECTIVE_INCLUDE:
658 
659         Token = PrGetNextToken (NULL, " \"<>", Next);
660         if (!Token)
661         {
662             goto SyntaxError;
663         }
664 
665         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
666             "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
667             Token, Gbl_CurrentLineNumber);
668 
669         PrOpenIncludeFile (Token);
670         break;
671 
672     case PR_DIRECTIVE_LINE:
673 
674         TokenOffset = Token - Gbl_MainTokenBuffer;
675 
676         Status = PrResolveIntegerExpression (
677             &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
678         if (ACPI_FAILURE (Status))
679         {
680             return;
681         }
682 
683         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
684             "User #line invocation %s\n", Gbl_CurrentLineNumber,
685             Token);
686 
687         /* Update local line numbers */
688 
689         Gbl_CurrentLineNumber = (UINT32) Value;
690         Gbl_PreviousLineNumber = 0;
691 
692         /* Emit #line into the preprocessor file */
693 
694         FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
695             Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
696         break;
697 
698     case PR_DIRECTIVE_PRAGMA:
699 
700         if (!strcmp (Token, "disable"))
701         {
702             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
703             if (!Token)
704             {
705                 goto SyntaxError;
706             }
707 
708             TokenOffset = Token - Gbl_MainTokenBuffer;
709             AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
710         }
711         else if (!strcmp (Token, "message"))
712         {
713             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
714             if (!Token)
715             {
716                 goto SyntaxError;
717             }
718 
719             TokenOffset = Token - Gbl_MainTokenBuffer;
720             AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
721         }
722         else
723         {
724             PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
725                 THIS_TOKEN_OFFSET (Token));
726             return;
727         }
728 
729         break;
730 
731     case PR_DIRECTIVE_UNDEF:
732 
733         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
734             "#undef: %s\n", Gbl_CurrentLineNumber, Token);
735 
736         PrRemoveDefine (Token);
737         break;
738 
739     case PR_DIRECTIVE_WARNING:
740 
741         PrError (ASL_WARNING, ASL_MSG_ERROR_DIRECTIVE,
742             THIS_TOKEN_OFFSET (Token));
743         break;
744 
745     default:
746 
747         /* Should never get here */
748         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
749             "Unrecognized directive: %u\n",
750             Gbl_CurrentLineNumber, Directive);
751         break;
752     }
753 
754     return;
755 
756 
757 SyntaxError:
758 
759     PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
760         THIS_TOKEN_OFFSET (DirectiveToken));
761     return;
762 }
763 
764 
765 /*******************************************************************************
766  *
767  * FUNCTION:    PrMatchDirective
768  *
769  * PARAMETERS:  Directive           - Pointer to directive name token
770  *
771  * RETURN:      Index into command array, -1 if not found
772  *
773  * DESCRIPTION: Lookup the incoming directive in the known directives table.
774  *
775  ******************************************************************************/
776 
777 static int
778 PrMatchDirective (
779     char                    *Directive)
780 {
781     int                     i;
782 
783 
784     if (!Directive || Directive[0] == 0)
785     {
786         return (ASL_DIRECTIVE_NOT_FOUND);
787     }
788 
789     for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
790     {
791         if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
792         {
793             return (i);
794         }
795     }
796 
797     return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
798 }
799