Fixed compatibility of output.
[AROS.git] / arch / all-pc / acpica / source / compiler / aslsupport.l
blobe7d2b1fac893a407d3f4d29a81b656de6891b106
1 /******************************************************************************
2  *
3  * Module Name: aslsupport.l - Flex/lex scanner C support routines.
4  *              NOTE: Included into aslcompile.l, not compiled by itself.
5  *
6  *****************************************************************************/
8 /*
9  * Copyright (C) 2000 - 2013, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
46 /* Configuration */
48 #define ASL_SPACES_PER_TAB      4
50 #define ASL_NORMAL_CHAR         0
51 #define ASL_ESCAPE_SEQUENCE     1
52 #define ASL_OCTAL_CONSTANT      2
53 #define ASL_HEX_CONSTANT        3
56 /* File node - used for "Include" operator file stack */
58 typedef struct asl_file_node
60     FILE                    *File;
61     UINT32                  CurrentLineNumber;
62     YY_BUFFER_STATE         State;
63     char                    *Filename;
64     struct asl_file_node    *Next;
66 } ASL_FILE_NODE;
68 /* File stack for the "Include" operator (NOT #include operator) */
70 ASL_FILE_NODE               *Gbl_IncludeFileStack = NULL;
73 /*******************************************************************************
74  *
75  * FUNCTION:    AslDoLineDirective
76  *
77  * PARAMETERS:  None. Uses input() to access current source code line
78  *
79  * RETURN:      Updates global line number and filename
80  *
81  * DESCRIPTION: Handle #line directives emitted by the preprocessor.
82  *
83  * The #line directive is emitted by the preprocesser, and is used to
84  * pass through line numbers from the original source code file to the
85  * preprocessor output file (.i). This allows any compiler-generated
86  * error messages to be displayed with the correct line number.
87  *
88  ******************************************************************************/
90 static void
91 AslDoLineDirective (
92     void)
94     int                     c;
95     char                    *Token;
96     UINT32                  LineNumber;
97     char                    *Filename;
98     UINT32                  i;
101     /* Eat the entire line that contains the #line directive */
103     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
105     while ((c = input()) != '\n' && c != EOF)
106     {
107         *Gbl_LineBufPtr = c;
108         Gbl_LineBufPtr++;
109     }
110     *Gbl_LineBufPtr = 0;
112     /* First argument is the actual line number */
114     Token = strtok (Gbl_CurrentLineBuffer, " ");
115     if (!Token)
116     {
117         goto ResetAndExit;
118     }
120     /* First argument is the line number */
122     LineNumber = (UINT32) UtDoConstant (Token);
124     /* Emit the appropriate number of newlines */
126     Gbl_CurrentColumn = 0;
127     if (LineNumber > Gbl_CurrentLineNumber)
128     {
129         for (i = 0; i < (LineNumber - Gbl_CurrentLineNumber); i++)
130         {
131             FlWriteFile (ASL_FILE_SOURCE_OUTPUT, "\n", 1);
132             Gbl_CurrentColumn++;
133         }
134     }
136     FlSetLineNumber (LineNumber);
138     /* Second argument is the optional filename (in double quotes) */
140     Token = strtok (NULL, " \"");
141     if (Token)
142     {
143         Filename = ACPI_ALLOCATE_ZEROED (strlen (Token) + 1);
144         strcpy (Filename, Token);
145         FlSetFilename (Filename);
146     }
148     /* Third argument is not supported at this time */
150 ResetAndExit:
152     /* Reset globals for a new line */
154     Gbl_CurrentLineOffset += Gbl_CurrentColumn;
155     Gbl_CurrentColumn = 0;
156     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
160 /*******************************************************************************
162  * FUNCTION:    AslPopInputFileStack
164  * PARAMETERS:  None
166  * RETURN:      0 if a node was popped, -1 otherwise
168  * DESCRIPTION: Pop the top of the input file stack and point the parser to
169  *              the saved parse buffer contained in the fnode. Also, set the
170  *              global line counters to the saved values. This function is
171  *              called when an include file reaches EOF.
173  ******************************************************************************/
176 AslPopInputFileStack (
177     void)
179     ASL_FILE_NODE           *Fnode;
182     Fnode = Gbl_IncludeFileStack;
183     DbgPrint (ASL_PARSE_OUTPUT, "\nPop InputFile Stack, Fnode %p\n\n", Fnode);
185     if (!Fnode)
186     {
187         return (-1);
188     }
190     /* Close the current include file */
192     fclose (yyin);
194     /* Update the top-of-stack */
196     Gbl_IncludeFileStack = Fnode->Next;
198     /* Reset global line counter and filename */
200     Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
201     Gbl_CurrentLineNumber = Fnode->CurrentLineNumber;
203     /* Point the parser to the popped file */
205     yy_delete_buffer (YY_CURRENT_BUFFER);
206     yy_switch_to_buffer (Fnode->State);
208     /* All done with this node */
210     ACPI_FREE (Fnode);
211     return (0);
215 /*******************************************************************************
217  * FUNCTION:    AslPushInputFileStack
219  * PARAMETERS:  InputFile           - Open file pointer
220  *              Filename            - Name of the file
222  * RETURN:      None
224  * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
225  *              to this file. Called when an include file is successfully
226  *              opened.
228  ******************************************************************************/
230 void
231 AslPushInputFileStack (
232     FILE                    *InputFile,
233     char                    *Filename)
235     ASL_FILE_NODE           *Fnode;
236     YY_BUFFER_STATE         State;
239     /* Save the current state in an Fnode */
241     Fnode = UtLocalCalloc (sizeof (ASL_FILE_NODE));
243     Fnode->File                 = yyin;
244     Fnode->Next                 = Gbl_IncludeFileStack;
245     Fnode->State                = YY_CURRENT_BUFFER;
246     Fnode->CurrentLineNumber    = Gbl_CurrentLineNumber;
247     Fnode->Filename             = Gbl_Files[ASL_FILE_INPUT].Filename;
249     /* Push it on the stack */
251     Gbl_IncludeFileStack = Fnode;
253     /* Point the parser to this file */
255     State = yy_create_buffer (InputFile, YY_BUF_SIZE);
256     yy_switch_to_buffer (State);
258     DbgPrint (ASL_PARSE_OUTPUT, "\nPush InputFile Stack, returning %p\n\n", InputFile);
260     /* Reset the global line count and filename */
262     Gbl_Files[ASL_FILE_INPUT].Filename = Filename;
263     Gbl_CurrentLineNumber = 1;
264     yyin = InputFile;
268 /*******************************************************************************
270  * FUNCTION:    AslResetCurrentLineBuffer
272  * PARAMETERS:  None
274  * RETURN:      None
276  * DESCRIPTION: Reset the Line Buffer to zero, increment global line numbers.
278  ******************************************************************************/
280 void
281 AslResetCurrentLineBuffer (
282     void)
285     if (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle)
286     {
287         FlWriteFile (ASL_FILE_SOURCE_OUTPUT, Gbl_CurrentLineBuffer,
288             Gbl_LineBufPtr - Gbl_CurrentLineBuffer);
289     }
291     Gbl_CurrentLineOffset += Gbl_CurrentColumn;
292     Gbl_CurrentColumn = 0;
294     Gbl_CurrentLineNumber++;
295     Gbl_LogicalLineNumber++;
296     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
300 /*******************************************************************************
302  * FUNCTION:    AslInsertLineBuffer
304  * PARAMETERS:  SourceChar      - One char from the input ASL source file
306  * RETURN:      None
308  * DESCRIPTION: Put one character of the source file into the temp line buffer
310  ******************************************************************************/
312 void
313 AslInsertLineBuffer (
314     int                     SourceChar)
316     UINT32                  i;
317     UINT32                  Count = 1;
320     if (SourceChar == EOF)
321     {
322         return;
323     }
325     Gbl_InputByteCount++;
327     /* Handle tabs. Convert to spaces */
329     if (SourceChar == '\t')
330     {
331         SourceChar = ' ';
332         Count = ASL_SPACES_PER_TAB -
333                     (Gbl_CurrentColumn & (ASL_SPACES_PER_TAB-1));
334     }
336     for (i = 0; i < Count; i++)
337     {
338         Gbl_CurrentColumn++;
340         /* Insert the character into the line buffer */
342         *Gbl_LineBufPtr = (UINT8) SourceChar;
343         Gbl_LineBufPtr++;
345         if (Gbl_LineBufPtr > (Gbl_CurrentLineBuffer + (Gbl_LineBufferSize - 1)))
346         {
347 #if 0
348             /*
349              * Warning if we have split a long source line.
350              * <Probably overkill>
351              */
352             sprintf (MsgBuffer, "Max %u", Gbl_LineBufferSize);
353             AslCommonError (ASL_WARNING, ASL_MSG_LONG_LINE,
354                             Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
355                             Gbl_CurrentLineOffset, Gbl_CurrentColumn,
356                             Gbl_Files[ASL_FILE_INPUT].Filename, MsgBuffer);
357 #endif
359             AslResetCurrentLineBuffer ();
360         }
361         else if (SourceChar == '\n')
362         {
363             /* End of line */
365             AslResetCurrentLineBuffer ();
366         }
367     }
371 /*******************************************************************************
373  * FUNCTION:    count
375  * PARAMETERS:  yytext      - Contains the matched keyword.
376  *              Type        - Keyword/Character type:
377  *                             0 = anything except a keyword
378  *                             1 = pseudo-keywords
379  *                             2 = non-executable ASL keywords
380  *                             3 = executable ASL keywords
382  * RETURN:      None
384  * DESCRIPTION: Count keywords and put them into the line buffer
386  ******************************************************************************/
388 static void
389 count (
390     int                 Type)
392     int                 i;
395     switch (Type)
396     {
397     case 2:
399         TotalKeywords++;
400         TotalNamedObjects++;
401         break;
403     case 3:
405         TotalKeywords++;
406         TotalExecutableOpcodes++;
407         break;
409     default:
411         break;
412     }
414     for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++)
415     {
416         AslInsertLineBuffer (yytext[i]);
417         *Gbl_LineBufPtr = 0;
418     }
422 /*******************************************************************************
424  * FUNCTION:    AslDoComment
426  * PARAMETERS:  none
428  * RETURN:      none
430  * DESCRIPTION: Process a standard comment.
432  ******************************************************************************/
434 static char
435 AslDoComment (
436     void)
438     int                 c;
439     int                 c1 = 0;
442     AslInsertLineBuffer ('/');
443     AslInsertLineBuffer ('*');
445 loop:
447     /* Eat chars until end-of-comment */
449     while ((c = input()) != '*' && c != EOF)
450     {
451         AslInsertLineBuffer (c);
452         c1 = c;
453     }
455     if (c == EOF)
456     {
457         goto EarlyEOF;
458     }
460     /*
461      * Check for nested comment -- can help catch cases where a previous
462      * comment was accidently left unterminated
463      */
464     if ((c1 == '/') && (c == '*'))
465     {
466         AslCommonError (ASL_WARNING, ASL_MSG_NESTED_COMMENT,
467                         Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
468                         Gbl_InputByteCount, Gbl_CurrentColumn,
469                         Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
470     }
472     /* Comment is closed only if the NEXT character is a slash */
474     AslInsertLineBuffer (c);
476     if ((c1 = input()) != '/' && c1 != EOF)
477     {
478         unput(c1);
479         goto loop;
480     }
482     if (c1 == EOF)
483     {
484         goto EarlyEOF;
485     }
487     AslInsertLineBuffer (c1);
488     return (TRUE);
491 EarlyEOF:
492     /*
493      * Premature End-Of-File
494      */
495     AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF,
496                     Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
497                     Gbl_CurrentLineOffset, Gbl_CurrentColumn,
498                     Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
499     return (FALSE);
503 /*******************************************************************************
505  * FUNCTION:    AslDoCommentType2
507  * PARAMETERS:  none
509  * RETURN:      none
511  * DESCRIPTION: Process a new "//" comment.
513  ******************************************************************************/
515 static char
516 AslDoCommentType2 (
517     void)
519     int                 c;
522     AslInsertLineBuffer ('/');
523     AslInsertLineBuffer ('/');
525     while ((c = input()) != '\n' && c != EOF)
526     {
527         AslInsertLineBuffer (c);
528     }
530     if (c == EOF)
531     {
532         /* End of file is OK, change to newline. Let parser detect EOF later */
534         c = '\n';
535     }
537     AslInsertLineBuffer (c);
538     return (TRUE);
542 /*******************************************************************************
544  * FUNCTION:    AslDoStringLiteral
546  * PARAMETERS:  none
548  * RETURN:      none
550  * DESCRIPTION: Process a string literal (surrounded by quotes)
552  ******************************************************************************/
554 static char
555 AslDoStringLiteral (
556     void)
558     char                *StringBuffer = MsgBuffer;
559     char                *EndBuffer = MsgBuffer + ASL_MSG_BUFFER_SIZE;
560     char                *CleanString;
561     int                 StringChar;
562     UINT32              State = ASL_NORMAL_CHAR;
563     UINT32              i = 0;
564     UINT8               Digit;
565     char                ConvertBuffer[4];
568     /*
569      * Eat chars until end-of-literal.
570      * NOTE:  Put back the original surrounding quotes into the
571      * source line buffer.
572      */
573     AslInsertLineBuffer ('\"');
574     while ((StringChar = input()) != EOF)
575     {
576         AslInsertLineBuffer (StringChar);
578 DoCharacter:
579         switch (State)
580         {
581         case ASL_NORMAL_CHAR:
583             switch (StringChar)
584             {
585             case '\\':
586                 /*
587                  * Special handling for backslash-escape sequence. We will
588                  * toss the backslash and translate the escape char(s).
589                  */
590                 State = ASL_ESCAPE_SEQUENCE;
591                 continue;
593             case '\"':
595                 /* String terminator */
597                 goto CompletedString;
599             default:
601                 break;
602             }
603             break;
606         case ASL_ESCAPE_SEQUENCE:
608             State = ASL_NORMAL_CHAR;
609             switch (StringChar)
610             {
611             case 'a':
613                 StringChar = 0x07;      /* BELL */
614                 break;
616             case 'b':
618                 StringChar = 0x08;      /* BACKSPACE */
619                 break;
621             case 'f':
623                 StringChar = 0x0C;      /* FORMFEED */
624                 break;
626             case 'n':
628                 StringChar = 0x0A;      /* LINEFEED */
629                 break;
631             case 'r':
633                 StringChar = 0x0D;      /* CARRIAGE RETURN*/
634                 break;
636             case 't':
638                 StringChar = 0x09;      /* HORIZONTAL TAB */
639                 break;
641             case 'v':
643                 StringChar = 0x0B;      /* VERTICAL TAB */
644                 break;
646             case 'x':
648                 State = ASL_HEX_CONSTANT;
649                 i = 0;
650                 continue;
652             case '\'':                  /* Single Quote */
653             case '\"':                  /* Double Quote */
654             case '\\':                  /* Backslash */
656                 break;
658             default:
660                 /* Check for an octal digit (0-7) */
662                 if (ACPI_IS_OCTAL_DIGIT (StringChar))
663                 {
664                     State = ASL_OCTAL_CONSTANT;
665                     ConvertBuffer[0] = StringChar;
666                     i = 1;
667                     continue;
668                 }
670                 /* Unknown escape sequence issue warning, but use the character */
672                 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_ESCAPE,
673                                 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
674                                 Gbl_CurrentLineOffset, Gbl_CurrentColumn,
675                                 Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
676                 break;
677             }
678             break;
681         case ASL_OCTAL_CONSTANT:
683             /* Up to three octal digits allowed */
685             if (!ACPI_IS_OCTAL_DIGIT (StringChar) ||
686                 (i > 2))
687             {
688                 /*
689                  * Reached end of the constant. Convert the assembled ASCII
690                  * string and resume processing of the next character
691                  */
692                 ConvertBuffer[i] = 0;
693                 Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 8);
695                 /* Check for NULL or non-ascii character (ignore if so) */
697                 if ((Digit == 0) || (Digit > ACPI_ASCII_MAX))
698                 {
699                     AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING,
700                                     Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
701                                     Gbl_CurrentLineOffset, Gbl_CurrentColumn,
702                                     Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
703                 }
704                 else
705                 {
706                     *StringBuffer = (char) Digit;
707                     StringBuffer++;
708                     if (StringBuffer >= EndBuffer)
709                     {
710                         goto BufferOverflow;
711                     }
712                 }
714                 State = ASL_NORMAL_CHAR;
715                 goto DoCharacter;
716                 break;
717             }
719             /* Append another digit of the constant */
721             ConvertBuffer[i] = StringChar;
722             i++;
723             continue;
725         case ASL_HEX_CONSTANT:
727             /* Up to two hex digits allowed */
729             if (!ACPI_IS_XDIGIT (StringChar) ||
730                 (i > 1))
731             {
732                 /*
733                  * Reached end of the constant. Convert the assembled ASCII
734                  * string and resume processing of the next character
735                  */
736                 ConvertBuffer[i] = 0;
737                 Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 16);
739                 /* Check for NULL or non-ascii character (ignore if so) */
741                 if ((Digit == 0) || (Digit > ACPI_ASCII_MAX))
742                 {
743                     AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING,
744                                     Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
745                                     Gbl_CurrentLineOffset, Gbl_CurrentColumn,
746                                     Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
747                 }
748                 else
749                 {
750                     *StringBuffer = (char) Digit;
751                     StringBuffer++;
752                     if (StringBuffer >= EndBuffer)
753                     {
754                         goto BufferOverflow;
755                     }
756                 }
758                 State = ASL_NORMAL_CHAR;
759                 goto DoCharacter;
760                 break;
761             }
763             /* Append another digit of the constant */
765             ConvertBuffer[i] = StringChar;
766             i++;
767             continue;
769         default:
771             break;
772         }
774         /* Save the finished character */
776         *StringBuffer = StringChar;
777         StringBuffer++;
778         if (StringBuffer >= EndBuffer)
779         {
780             goto BufferOverflow;
781         }
782     }
784     /*
785      * Premature End-Of-File
786      */
787     AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF,
788                     Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
789                     Gbl_CurrentLineOffset, Gbl_CurrentColumn,
790                     Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
791     return (FALSE);
794 CompletedString:
795     /*
796      * Null terminate the input string and copy string to a new buffer
797      */
798     *StringBuffer = 0;
800     CleanString = UtGetStringBuffer (strlen (MsgBuffer) + 1);
801     if (!CleanString)
802     {
803         AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION,
804                         Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
805                         Gbl_CurrentLineOffset, Gbl_CurrentColumn,
806                         Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
807         return (FALSE);
808     }
810     ACPI_STRCPY (CleanString, MsgBuffer);
811     AslCompilerlval.s = CleanString;
812     return (TRUE);
815 BufferOverflow:
817     /* Literal was too long */
819     AslCommonError (ASL_ERROR, ASL_MSG_STRING_LENGTH,
820                     Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
821                     Gbl_CurrentLineOffset, Gbl_CurrentColumn,
822                     Gbl_Files[ASL_FILE_INPUT].Filename, "Max length 4096");
823     return (FALSE);