1 /******************************************************************************
3 * Module Name: aslsupport.l - Flex/lex scanner C support routines.
4 * NOTE: Included into aslcompile.l, not compiled by itself.
6 *****************************************************************************/
9 * Copyright (C) 2000 - 2013, Intel Corp.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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.
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.
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
61 UINT32 CurrentLineNumber;
62 YY_BUFFER_STATE State;
64 struct asl_file_node *Next;
68 /* File stack for the "Include" operator (NOT #include operator) */
70 ASL_FILE_NODE *Gbl_IncludeFileStack = NULL;
73 /*******************************************************************************
75 * FUNCTION: AslDoLineDirective
77 * PARAMETERS: None. Uses input() to access current source code line
79 * RETURN: Updates global line number and filename
81 * DESCRIPTION: Handle #line directives emitted by the preprocessor.
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.
88 ******************************************************************************/
101 /* Eat the entire line that contains the #line directive */
103 Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
105 while ((c = input()) != '\n' && c != EOF)
112 /* First argument is the actual line number */
114 Token = strtok (Gbl_CurrentLineBuffer, " ");
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)
129 for (i = 0; i < (LineNumber - Gbl_CurrentLineNumber); i++)
131 FlWriteFile (ASL_FILE_SOURCE_OUTPUT, "\n", 1);
136 FlSetLineNumber (LineNumber);
138 /* Second argument is the optional filename (in double quotes) */
140 Token = strtok (NULL, " \"");
143 Filename = ACPI_ALLOCATE_ZEROED (strlen (Token) + 1);
144 strcpy (Filename, Token);
145 FlSetFilename (Filename);
148 /* Third argument is not supported at this time */
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
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 (
179 ASL_FILE_NODE *Fnode;
182 Fnode = Gbl_IncludeFileStack;
183 DbgPrint (ASL_PARSE_OUTPUT, "\nPop InputFile Stack, Fnode %p\n\n", Fnode);
190 /* Close the current include file */
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 */
215 /*******************************************************************************
217 * FUNCTION: AslPushInputFileStack
219 * PARAMETERS: InputFile - Open file pointer
220 * Filename - Name of the file
224 * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
225 * to this file. Called when an include file is successfully
228 ******************************************************************************/
231 AslPushInputFileStack (
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));
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;
268 /*******************************************************************************
270 * FUNCTION: AslResetCurrentLineBuffer
276 * DESCRIPTION: Reset the Line Buffer to zero, increment global line numbers.
278 ******************************************************************************/
281 AslResetCurrentLineBuffer (
285 if (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle)
287 FlWriteFile (ASL_FILE_SOURCE_OUTPUT, Gbl_CurrentLineBuffer,
288 Gbl_LineBufPtr - Gbl_CurrentLineBuffer);
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
308 * DESCRIPTION: Put one character of the source file into the temp line buffer
310 ******************************************************************************/
313 AslInsertLineBuffer (
320 if (SourceChar == EOF)
325 Gbl_InputByteCount++;
327 /* Handle tabs. Convert to spaces */
329 if (SourceChar == '\t')
332 Count = ASL_SPACES_PER_TAB -
333 (Gbl_CurrentColumn & (ASL_SPACES_PER_TAB-1));
336 for (i = 0; i < Count; i++)
340 /* Insert the character into the line buffer */
342 *Gbl_LineBufPtr = (UINT8) SourceChar;
345 if (Gbl_LineBufPtr > (Gbl_CurrentLineBuffer + (Gbl_LineBufferSize - 1)))
349 * Warning if we have split a long source line.
350 * <Probably overkill>
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);
359 AslResetCurrentLineBuffer ();
361 else if (SourceChar == '\n')
365 AslResetCurrentLineBuffer ();
371 /*******************************************************************************
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
384 * DESCRIPTION: Count keywords and put them into the line buffer
386 ******************************************************************************/
406 TotalExecutableOpcodes++;
414 for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++)
416 AslInsertLineBuffer (yytext[i]);
422 /*******************************************************************************
424 * FUNCTION: AslDoComment
430 * DESCRIPTION: Process a standard comment.
432 ******************************************************************************/
442 AslInsertLineBuffer ('/');
443 AslInsertLineBuffer ('*');
447 /* Eat chars until end-of-comment */
449 while ((c = input()) != '*' && c != EOF)
451 AslInsertLineBuffer (c);
461 * Check for nested comment -- can help catch cases where a previous
462 * comment was accidently left unterminated
464 if ((c1 == '/') && (c == '*'))
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);
472 /* Comment is closed only if the NEXT character is a slash */
474 AslInsertLineBuffer (c);
476 if ((c1 = input()) != '/' && c1 != EOF)
487 AslInsertLineBuffer (c1);
493 * Premature End-Of-File
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);
503 /*******************************************************************************
505 * FUNCTION: AslDoCommentType2
511 * DESCRIPTION: Process a new "//" comment.
513 ******************************************************************************/
522 AslInsertLineBuffer ('/');
523 AslInsertLineBuffer ('/');
525 while ((c = input()) != '\n' && c != EOF)
527 AslInsertLineBuffer (c);
532 /* End of file is OK, change to newline. Let parser detect EOF later */
537 AslInsertLineBuffer (c);
542 /*******************************************************************************
544 * FUNCTION: AslDoStringLiteral
550 * DESCRIPTION: Process a string literal (surrounded by quotes)
552 ******************************************************************************/
558 char *StringBuffer = MsgBuffer;
559 char *EndBuffer = MsgBuffer + ASL_MSG_BUFFER_SIZE;
562 UINT32 State = ASL_NORMAL_CHAR;
565 char ConvertBuffer[4];
569 * Eat chars until end-of-literal.
570 * NOTE: Put back the original surrounding quotes into the
571 * source line buffer.
573 AslInsertLineBuffer ('\"');
574 while ((StringChar = input()) != EOF)
576 AslInsertLineBuffer (StringChar);
581 case ASL_NORMAL_CHAR:
587 * Special handling for backslash-escape sequence. We will
588 * toss the backslash and translate the escape char(s).
590 State = ASL_ESCAPE_SEQUENCE;
595 /* String terminator */
597 goto CompletedString;
606 case ASL_ESCAPE_SEQUENCE:
608 State = ASL_NORMAL_CHAR;
613 StringChar = 0x07; /* BELL */
618 StringChar = 0x08; /* BACKSPACE */
623 StringChar = 0x0C; /* FORMFEED */
628 StringChar = 0x0A; /* LINEFEED */
633 StringChar = 0x0D; /* CARRIAGE RETURN*/
638 StringChar = 0x09; /* HORIZONTAL TAB */
643 StringChar = 0x0B; /* VERTICAL TAB */
648 State = ASL_HEX_CONSTANT;
652 case '\'': /* Single Quote */
653 case '\"': /* Double Quote */
654 case '\\': /* Backslash */
660 /* Check for an octal digit (0-7) */
662 if (ACPI_IS_OCTAL_DIGIT (StringChar))
664 State = ASL_OCTAL_CONSTANT;
665 ConvertBuffer[0] = StringChar;
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);
681 case ASL_OCTAL_CONSTANT:
683 /* Up to three octal digits allowed */
685 if (!ACPI_IS_OCTAL_DIGIT (StringChar) ||
689 * Reached end of the constant. Convert the assembled ASCII
690 * string and resume processing of the next character
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))
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);
706 *StringBuffer = (char) Digit;
708 if (StringBuffer >= EndBuffer)
714 State = ASL_NORMAL_CHAR;
719 /* Append another digit of the constant */
721 ConvertBuffer[i] = StringChar;
725 case ASL_HEX_CONSTANT:
727 /* Up to two hex digits allowed */
729 if (!ACPI_IS_XDIGIT (StringChar) ||
733 * Reached end of the constant. Convert the assembled ASCII
734 * string and resume processing of the next character
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))
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);
750 *StringBuffer = (char) Digit;
752 if (StringBuffer >= EndBuffer)
758 State = ASL_NORMAL_CHAR;
763 /* Append another digit of the constant */
765 ConvertBuffer[i] = StringChar;
774 /* Save the finished character */
776 *StringBuffer = StringChar;
778 if (StringBuffer >= EndBuffer)
785 * Premature End-Of-File
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);
796 * Null terminate the input string and copy string to a new buffer
800 CleanString = UtGetStringBuffer (strlen (MsgBuffer) + 1);
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);
810 ACPI_STRCPY (CleanString, MsgBuffer);
811 AslCompilerlval.s = CleanString;
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");