aslsupport.l revision 1.1 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 *****************************************************************************/
7
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 */
44
45
46 /* Configuration */
47
48 #define ASL_SPACES_PER_TAB 4
49
50 #define ASL_NORMAL_CHAR 0
51 #define ASL_ESCAPE_SEQUENCE 1
52 #define ASL_OCTAL_CONSTANT 2
53 #define ASL_HEX_CONSTANT 3
54
55
56 /* File node - used for "Include" operator file stack */
57
58 typedef struct asl_file_node
59 {
60 FILE *File;
61 UINT32 CurrentLineNumber;
62 YY_BUFFER_STATE State;
63 char *Filename;
64 struct asl_file_node *Next;
65
66 } ASL_FILE_NODE;
67
68 /* File stack for the "Include" operator (NOT #include operator) */
69
70 ASL_FILE_NODE *Gbl_IncludeFileStack = NULL;
71
72
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 ******************************************************************************/
89
90 static void
91 AslDoLineDirective (
92 void)
93 {
94 int c;
95 char *Token;
96 UINT32 LineNumber;
97 char *Filename;
98 UINT32 i;
99
100
101 /* Eat the entire line that contains the #line directive */
102
103 Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
104
105 while ((c = input()) != '\n' && c != EOF)
106 {
107 *Gbl_LineBufPtr = c;
108 Gbl_LineBufPtr++;
109 }
110 *Gbl_LineBufPtr = 0;
111
112 /* First argument is the actual line number */
113
114 Token = strtok (Gbl_CurrentLineBuffer, " ");
115 if (!Token)
116 {
117 goto ResetAndExit;
118 }
119
120 /* First argument is the line number */
121
122 LineNumber = (UINT32) UtDoConstant (Token);
123
124 /* Emit the appropriate number of newlines */
125
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 }
135
136 FlSetLineNumber (LineNumber);
137
138 /* Second argument is the optional filename (in double quotes) */
139
140 Token = strtok (NULL, " \"");
141 if (Token)
142 {
143 Filename = ACPI_ALLOCATE_ZEROED (strlen (Token) + 1);
144 strcpy (Filename, Token);
145 FlSetFilename (Filename);
146 }
147
148 /* Third argument is not supported at this time */
149
150 ResetAndExit:
151
152 /* Reset globals for a new line */
153
154 Gbl_CurrentLineOffset += Gbl_CurrentColumn;
155 Gbl_CurrentColumn = 0;
156 Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
157 }
158
159
160 /*******************************************************************************
161 *
162 * FUNCTION: AslPopInputFileStack
163 *
164 * PARAMETERS: None
165 *
166 * RETURN: 0 if a node was popped, -1 otherwise
167 *
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.
172 *
173 ******************************************************************************/
174
175 int
176 AslPopInputFileStack (
177 void)
178 {
179 ASL_FILE_NODE *Fnode;
180
181
182 Fnode = Gbl_IncludeFileStack;
183 DbgPrint (ASL_PARSE_OUTPUT, "\nPop InputFile Stack, Fnode %p\n\n", Fnode);
184
185 if (!Fnode)
186 {
187 return (-1);
188 }
189
190 /* Close the current include file */
191
192 fclose (yyin);
193
194 /* Update the top-of-stack */
195
196 Gbl_IncludeFileStack = Fnode->Next;
197
198 /* Reset global line counter and filename */
199
200 Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
201 Gbl_CurrentLineNumber = Fnode->CurrentLineNumber;
202
203 /* Point the parser to the popped file */
204
205 yy_delete_buffer (YY_CURRENT_BUFFER);
206 yy_switch_to_buffer (Fnode->State);
207
208 /* All done with this node */
209
210 ACPI_FREE (Fnode);
211 return (0);
212 }
213
214
215 /*******************************************************************************
216 *
217 * FUNCTION: AslPushInputFileStack
218 *
219 * PARAMETERS: InputFile - Open file pointer
220 * Filename - Name of the file
221 *
222 * RETURN: None
223 *
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.
227 *
228 ******************************************************************************/
229
230 void
231 AslPushInputFileStack (
232 FILE *InputFile,
233 char *Filename)
234 {
235 ASL_FILE_NODE *Fnode;
236 YY_BUFFER_STATE State;
237
238
239 /* Save the current state in an Fnode */
240
241 Fnode = UtLocalCalloc (sizeof (ASL_FILE_NODE));
242
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;
248
249 /* Push it on the stack */
250
251 Gbl_IncludeFileStack = Fnode;
252
253 /* Point the parser to this file */
254
255 State = yy_create_buffer (InputFile, YY_BUF_SIZE);
256 yy_switch_to_buffer (State);
257
258 DbgPrint (ASL_PARSE_OUTPUT, "\nPush InputFile Stack, returning %p\n\n", InputFile);
259
260 /* Reset the global line count and filename */
261
262 Gbl_Files[ASL_FILE_INPUT].Filename = Filename;
263 Gbl_CurrentLineNumber = 1;
264 yyin = InputFile;
265 }
266
267
268 /*******************************************************************************
269 *
270 * FUNCTION: AslResetCurrentLineBuffer
271 *
272 * PARAMETERS: None
273 *
274 * RETURN: None
275 *
276 * DESCRIPTION: Reset the Line Buffer to zero, increment global line numbers.
277 *
278 ******************************************************************************/
279
280 void
281 AslResetCurrentLineBuffer (
282 void)
283 {
284
285 if (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle)
286 {
287 FlWriteFile (ASL_FILE_SOURCE_OUTPUT, Gbl_CurrentLineBuffer,
288 Gbl_LineBufPtr - Gbl_CurrentLineBuffer);
289 }
290
291 Gbl_CurrentLineOffset += Gbl_CurrentColumn;
292 Gbl_CurrentColumn = 0;
293
294 Gbl_CurrentLineNumber++;
295 Gbl_LogicalLineNumber++;
296 Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
297 }
298
299
300 /*******************************************************************************
301 *
302 * FUNCTION: AslInsertLineBuffer
303 *
304 * PARAMETERS: SourceChar - One char from the input ASL source file
305 *
306 * RETURN: None
307 *
308 * DESCRIPTION: Put one character of the source file into the temp line buffer
309 *
310 ******************************************************************************/
311
312 void
313 AslInsertLineBuffer (
314 int SourceChar)
315 {
316 UINT32 i;
317 UINT32 Count = 1;
318
319
320 if (SourceChar == EOF)
321 {
322 return;
323 }
324
325 Gbl_InputByteCount++;
326
327 /* Handle tabs. Convert to spaces */
328
329 if (SourceChar == '\t')
330 {
331 SourceChar = ' ';
332 Count = ASL_SPACES_PER_TAB -
333 (Gbl_CurrentColumn & (ASL_SPACES_PER_TAB-1));
334 }
335
336 for (i = 0; i < Count; i++)
337 {
338 Gbl_CurrentColumn++;
339
340 /* Insert the character into the line buffer */
341
342 *Gbl_LineBufPtr = (UINT8) SourceChar;
343 Gbl_LineBufPtr++;
344
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
358
359 AslResetCurrentLineBuffer ();
360 }
361 else if (SourceChar == '\n')
362 {
363 /* End of line */
364
365 AslResetCurrentLineBuffer ();
366 }
367 }
368 }
369
370
371 /*******************************************************************************
372 *
373 * FUNCTION: count
374 *
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
381 *
382 * RETURN: None
383 *
384 * DESCRIPTION: Count keywords and put them into the line buffer
385 *
386 ******************************************************************************/
387
388 static void
389 count (
390 int Type)
391 {
392 int i;
393
394
395 switch (Type)
396 {
397 case 2:
398
399 TotalKeywords++;
400 TotalNamedObjects++;
401 break;
402
403 case 3:
404
405 TotalKeywords++;
406 TotalExecutableOpcodes++;
407 break;
408
409 default:
410
411 break;
412 }
413
414 for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++)
415 {
416 AslInsertLineBuffer (yytext[i]);
417 *Gbl_LineBufPtr = 0;
418 }
419 }
420
421
422 /*******************************************************************************
423 *
424 * FUNCTION: AslDoComment
425 *
426 * PARAMETERS: none
427 *
428 * RETURN: none
429 *
430 * DESCRIPTION: Process a standard comment.
431 *
432 ******************************************************************************/
433
434 static char
435 AslDoComment (
436 void)
437 {
438 int c;
439 int c1 = 0;
440
441
442 AslInsertLineBuffer ('/');
443 AslInsertLineBuffer ('*');
444
445 loop:
446
447 /* Eat chars until end-of-comment */
448
449 while ((c = input()) != '*' && c != EOF)
450 {
451 AslInsertLineBuffer (c);
452 c1 = c;
453 }
454
455 if (c == EOF)
456 {
457 goto EarlyEOF;
458 }
459
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 }
471
472 /* Comment is closed only if the NEXT character is a slash */
473
474 AslInsertLineBuffer (c);
475
476 if ((c1 = input()) != '/' && c1 != EOF)
477 {
478 unput(c1);
479 goto loop;
480 }
481
482 if (c1 == EOF)
483 {
484 goto EarlyEOF;
485 }
486
487 AslInsertLineBuffer (c1);
488 return (TRUE);
489
490
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);
500 }
501
502
503 /*******************************************************************************
504 *
505 * FUNCTION: AslDoCommentType2
506 *
507 * PARAMETERS: none
508 *
509 * RETURN: none
510 *
511 * DESCRIPTION: Process a new "//" comment.
512 *
513 ******************************************************************************/
514
515 static char
516 AslDoCommentType2 (
517 void)
518 {
519 int c;
520
521
522 AslInsertLineBuffer ('/');
523 AslInsertLineBuffer ('/');
524
525 while ((c = input()) != '\n' && c != EOF)
526 {
527 AslInsertLineBuffer (c);
528 }
529
530 if (c == EOF)
531 {
532 /* End of file is OK, change to newline. Let parser detect EOF later */
533
534 c = '\n';
535 }
536
537 AslInsertLineBuffer (c);
538 return (TRUE);
539 }
540
541
542 /*******************************************************************************
543 *
544 * FUNCTION: AslDoStringLiteral
545 *
546 * PARAMETERS: none
547 *
548 * RETURN: none
549 *
550 * DESCRIPTION: Process a string literal (surrounded by quotes)
551 *
552 ******************************************************************************/
553
554 static char
555 AslDoStringLiteral (
556 void)
557 {
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];
566
567
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);
577
578 DoCharacter:
579 switch (State)
580 {
581 case ASL_NORMAL_CHAR:
582
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;
592
593 case '\"':
594
595 /* String terminator */
596
597 goto CompletedString;
598
599 default:
600
601 break;
602 }
603 break;
604
605
606 case ASL_ESCAPE_SEQUENCE:
607
608 State = ASL_NORMAL_CHAR;
609 switch (StringChar)
610 {
611 case 'a':
612
613 StringChar = 0x07; /* BELL */
614 break;
615
616 case 'b':
617
618 StringChar = 0x08; /* BACKSPACE */
619 break;
620
621 case 'f':
622
623 StringChar = 0x0C; /* FORMFEED */
624 break;
625
626 case 'n':
627
628 StringChar = 0x0A; /* LINEFEED */
629 break;
630
631 case 'r':
632
633 StringChar = 0x0D; /* CARRIAGE RETURN*/
634 break;
635
636 case 't':
637
638 StringChar = 0x09; /* HORIZONTAL TAB */
639 break;
640
641 case 'v':
642
643 StringChar = 0x0B; /* VERTICAL TAB */
644 break;
645
646 case 'x':
647
648 State = ASL_HEX_CONSTANT;
649 i = 0;
650 continue;
651
652 case '\'': /* Single Quote */
653 case '\"': /* Double Quote */
654 case '\\': /* Backslash */
655
656 break;
657
658 default:
659
660 /* Check for an octal digit (0-7) */
661
662 if (ACPI_IS_OCTAL_DIGIT (StringChar))
663 {
664 State = ASL_OCTAL_CONSTANT;
665 ConvertBuffer[0] = StringChar;
666 i = 1;
667 continue;
668 }
669
670 /* Unknown escape sequence issue warning, but use the character */
671
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;
679
680
681 case ASL_OCTAL_CONSTANT:
682
683 /* Up to three octal digits allowed */
684
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);
694
695 /* Check for NULL or non-ascii character (ignore if so) */
696
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 }
713
714 State = ASL_NORMAL_CHAR;
715 goto DoCharacter;
716 break;
717 }
718
719 /* Append another digit of the constant */
720
721 ConvertBuffer[i] = StringChar;
722 i++;
723 continue;
724
725 case ASL_HEX_CONSTANT:
726
727 /* Up to two hex digits allowed */
728
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);
738
739 /* Check for NULL or non-ascii character (ignore if so) */
740
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 }
757
758 State = ASL_NORMAL_CHAR;
759 goto DoCharacter;
760 break;
761 }
762
763 /* Append another digit of the constant */
764
765 ConvertBuffer[i] = StringChar;
766 i++;
767 continue;
768
769 default:
770
771 break;
772 }
773
774 /* Save the finished character */
775
776 *StringBuffer = StringChar;
777 StringBuffer++;
778 if (StringBuffer >= EndBuffer)
779 {
780 goto BufferOverflow;
781 }
782 }
783
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);
792
793
794 CompletedString:
795 /*
796 * Null terminate the input string and copy string to a new buffer
797 */
798 *StringBuffer = 0;
799
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 }
809
810 ACPI_STRCPY (CleanString, MsgBuffer);
811 AslCompilerlval.s = CleanString;
812 return (TRUE);
813
814
815 BufferOverflow:
816
817 /* Literal was too long */
818
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);
824 }
825