1 /******************************************************************************
3 * Module Name: dtio.c - File I/O support for data table compiler
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2011, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
46 #include <contrib/dev/acpica/compiler/aslcompiler.h>
47 #include <contrib/dev/acpica/compiler/dtcompiler.h>
49 #define _COMPONENT DT_COMPILER
50 ACPI_MODULE_NAME ("dtio")
53 /* Local prototypes */
75 DT_SUBTABLE *Subtable,
87 /* States for DtGetNextLine */
89 #define DT_NORMAL_TEXT 0
90 #define DT_START_QUOTED_STRING 1
91 #define DT_START_COMMENT 2
92 #define DT_SLASH_ASTERISK_COMMENT 3
93 #define DT_SLASH_SLASH_COMMENT 4
94 #define DT_END_COMMENT 5
95 #define DT_MERGE_LINES 6
97 static UINT32 Gbl_NextLineOffset;
100 /******************************************************************************
104 * PARAMETERS: String - Current source code line to trim
106 * RETURN: Trimmed line. Must be freed by caller.
108 * DESCRIPTION: Trim left and right spaces
110 *****************************************************************************/
122 /* Skip lines that start with a space */
124 if (!ACPI_STRCMP (String, " "))
126 ReturnString = UtLocalCalloc (1);
127 return (ReturnString);
130 /* Setup pointers to start and end of input string */
133 End = String + ACPI_STRLEN (String) - 1;
135 /* Find first non-whitespace character */
137 while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
142 /* Find last non-space character */
146 if (*End == '\r' || *End == '\n')
160 /* Remove any quotes around the string */
171 /* Create the trimmed return string */
173 Length = ACPI_PTR_DIFF (End, Start) + 1;
174 ReturnString = UtLocalCalloc (Length + 1);
175 if (ACPI_STRLEN (Start))
177 ACPI_STRNCPY (ReturnString, Start, Length);
180 ReturnString[Length] = 0;
181 return (ReturnString);
185 /******************************************************************************
187 * FUNCTION: DtLinkField
189 * PARAMETERS: Field - New field object to link
193 * DESCRIPTION: Link one field name and value to the list
195 *****************************************************************************/
205 Prev = Next = Gbl_FieldList;
219 Gbl_FieldList = Field;
224 /******************************************************************************
226 * FUNCTION: DtParseLine
228 * PARAMETERS: LineBuffer - Current source code line
229 * Line - Current line number in the source
230 * Offset - Current byte offset of the line
234 * DESCRIPTION: Parse one source line
236 *****************************************************************************/
255 BOOLEAN IsNullString = FALSE;
263 /* All lines after "Raw Table Data" are ingored */
265 if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
267 return (AE_NOT_FOUND);
270 Colon = strchr (LineBuffer, ':');
279 while (Start < Colon)
287 /* Found left bracket, go to the right bracket */
291 while (Start < Colon && *Start != ']')
309 * There are two column values. One for the field name,
310 * and one for the field value.
312 Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
313 NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
315 Length = ACPI_PTR_DIFF (End, Start);
317 TmpName = UtLocalCalloc (Length + 1);
318 ACPI_STRNCPY (TmpName, Start, Length);
319 Name = DtTrim (TmpName);
322 Start = End = (Colon + 1);
325 /* Found left quotation, go to the right quotation and break */
331 /* Check for an explicit null string */
337 while (*End && (*End != '"'))
347 * Special "comment" fields at line end, ignore them.
348 * Note: normal slash-slash and slash-asterisk comments are
349 * stripped already by the DtGetNextLine parser.
351 * TBD: Perhaps DtGetNextLine should parse the following type
362 Length = ACPI_PTR_DIFF (End, Start);
363 TmpValue = UtLocalCalloc (Length + 1);
365 ACPI_STRNCPY (TmpValue, Start, Length);
366 Value = DtTrim (TmpValue);
367 ACPI_FREE (TmpValue);
369 /* Create a new field object only if we have a valid value field */
371 if ((Value && *Value) || IsNullString)
373 Field = UtLocalCalloc (sizeof (DT_FIELD));
375 Field->Value = Value;
377 Field->ByteOffset = Offset;
378 Field->NameColumn = NameColumn;
379 Field->Column = Column;
383 else /* Ignore this field, it has no valid data */
393 /******************************************************************************
395 * FUNCTION: DtGetNextLine
397 * PARAMETERS: Handle - Open file handle for the source file
399 * RETURN: Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
401 * DESCRIPTION: Get the next valid source line. Removes all comments.
402 * Ignores empty lines.
404 * Handles both slash-asterisk and slash-slash comments.
405 * Also, quoted strings, but no escapes within.
407 * Line is returned in Gbl_CurrentLineBuffer.
408 * Line number in original file is returned in Gbl_CurrentLineNumber.
410 *****************************************************************************/
416 BOOLEAN LineNotAllBlanks = FALSE;
417 UINT32 State = DT_NORMAL_TEXT;
418 UINT32 CurrentLineOffset;
423 for (i = 0; i < ASL_LINE_BUFFER_SIZE;)
425 c = (char) getc (Handle);
430 case DT_START_QUOTED_STRING:
431 case DT_SLASH_ASTERISK_COMMENT:
432 case DT_SLASH_SLASH_COMMENT:
434 AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
448 /* Normal text, insert char into line buffer */
450 Gbl_CurrentLineBuffer[i] = c;
454 State = DT_START_COMMENT;
458 State = DT_START_QUOTED_STRING;
459 LineNotAllBlanks = TRUE;
465 * The continuation char MUST be last char on this line.
466 * Otherwise, it will be assumed to be a valid ASL char.
468 State = DT_MERGE_LINES;
472 CurrentLineOffset = Gbl_NextLineOffset;
473 Gbl_NextLineOffset = (UINT32) ftell (Handle);
474 Gbl_CurrentLineNumber++;
477 * Exit if line is complete. Ignore empty lines (only \n)
478 * or lines that contain nothing but blanks.
480 if ((i != 0) && LineNotAllBlanks)
482 Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
483 return (CurrentLineOffset);
486 /* Toss this line and start a new one */
489 LineNotAllBlanks = FALSE;
495 LineNotAllBlanks = TRUE;
503 case DT_START_QUOTED_STRING:
505 /* Insert raw chars until end of quoted string */
507 Gbl_CurrentLineBuffer[i] = c;
512 State = DT_NORMAL_TEXT;
516 case DT_START_COMMENT:
518 /* Open comment if this character is an asterisk or slash */
523 State = DT_SLASH_ASTERISK_COMMENT;
527 State = DT_SLASH_SLASH_COMMENT;
530 default: /* Not a comment */
531 i++; /* Save the preceeding slash */
532 Gbl_CurrentLineBuffer[i] = c;
534 State = DT_NORMAL_TEXT;
539 case DT_SLASH_ASTERISK_COMMENT:
541 /* Ignore chars until an asterisk-slash is found */
546 Gbl_NextLineOffset = (UINT32) ftell (Handle);
547 Gbl_CurrentLineNumber++;
551 State = DT_END_COMMENT;
559 case DT_SLASH_SLASH_COMMENT:
561 /* Ignore chars until end-of-line */
565 /* We will exit via the NORMAL_TEXT path */
568 State = DT_NORMAL_TEXT;
574 /* End comment if this char is a slash */
579 State = DT_NORMAL_TEXT;
583 CurrentLineOffset = Gbl_NextLineOffset;
584 Gbl_NextLineOffset = (UINT32) ftell (Handle);
585 Gbl_CurrentLineNumber++;
589 /* Consume all adjacent asterisks */
593 State = DT_SLASH_ASTERISK_COMMENT;
603 * This is not a continuation backslash, it is a normal
604 * normal ASL backslash - for example: Scope(\_SB_)
606 i++; /* Keep the backslash that is already in the buffer */
609 State = DT_NORMAL_TEXT;
614 * This is a continuation line -- a backlash followed
615 * immediately by a newline. Insert a space between the
616 * lines (overwrite the backslash)
618 Gbl_CurrentLineBuffer[i] = ' ';
621 /* Ignore newline, this will merge the lines */
623 CurrentLineOffset = Gbl_NextLineOffset;
624 Gbl_NextLineOffset = (UINT32) ftell (Handle);
625 Gbl_CurrentLineNumber++;
626 State = DT_NORMAL_TEXT;
631 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
636 printf ("ERROR - Input line is too long (max %u)\n", ASL_LINE_BUFFER_SIZE);
641 /******************************************************************************
643 * FUNCTION: DtScanFile
645 * PARAMETERS: Handle - Open file handle for the source file
647 * RETURN: Pointer to start of the constructed parse tree.
649 * DESCRIPTION: Scan source file, link all field names and values
650 * to the global parse tree: Gbl_FieldList
652 *****************************************************************************/
663 ACPI_FUNCTION_NAME (DtScanFile);
666 /* Get the file size */
668 Gbl_InputByteCount = DtGetFileSize (Handle);
670 Gbl_CurrentLineNumber = 0;
671 Gbl_CurrentLineOffset = 0;
672 Gbl_NextLineOffset = 0;
674 /* Scan line-by-line */
676 while ((Offset = DtGetNextLine (Handle)) != ASL_EOF)
678 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
679 Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
681 Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset);
682 if (Status == AE_NOT_FOUND)
688 /* Dump the parse tree if debug enabled */
692 Next = Gbl_FieldList;
693 DbgPrint (ASL_DEBUG_OUTPUT, "Tree: %32s %32s %8s %8s %8s %8s %8s %8s\n\n",
694 "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags");
698 DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n",
712 return (Gbl_FieldList);
720 /******************************************************************************
722 * FUNCTION: DtWriteBinary
724 * PARAMETERS: DT_WALK_CALLBACK
728 * DESCRIPTION: Write one subtable of a binary ACPI table
730 *****************************************************************************/
734 DT_SUBTABLE *Subtable,
739 FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
743 /******************************************************************************
745 * FUNCTION: DtOutputBinary
751 * DESCRIPTION: Write entire binary ACPI table (result of compilation)
753 *****************************************************************************/
757 DT_SUBTABLE *RootTable)
765 /* Walk the entire parse tree, emitting the binary data */
767 DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
768 Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
776 /******************************************************************************
778 * FUNCTION: DtDumpBuffer
780 * PARAMETERS: FileID - Where to write buffer data
781 * Buffer - Buffer to dump
782 * Offset - Offset in current table
783 * Length - Buffer Length
787 * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
789 * TBD: merge dump buffer routines
791 *****************************************************************************/
805 FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ",
806 Offset, Offset, Length);
813 FlPrintFile (FileId, "%24s", "");
816 /* Print 16 hex chars */
822 /* Dump fill spaces */
824 FlPrintFile (FileId, " ");
829 FlPrintFile (FileId, "%02X ", Buffer[i+j]);
833 FlPrintFile (FileId, " ");
834 for (j = 0; j < 16; j++)
838 FlPrintFile (FileId, "\n\n");
842 BufChar = Buffer[(ACPI_SIZE) i + j];
843 if (ACPI_IS_PRINT (BufChar))
845 FlPrintFile (FileId, "%c", BufChar);
849 FlPrintFile (FileId, ".");
853 /* Done with that line. */
855 FlPrintFile (FileId, "\n");
859 FlPrintFile (FileId, "\n\n");
863 /******************************************************************************
865 * FUNCTION: DtWriteFieldToListing
867 * PARAMETERS: Buffer - Contains the compiled data
868 * Field - Field node for the input line
869 * Length - Length of the output data
873 * DESCRIPTION: Write one field to the listing file (if listing is enabled).
875 *****************************************************************************/
878 DtWriteFieldToListing (
886 if (!Gbl_ListingFlag || !Field)
891 /* Dump the original source line */
893 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input: ");
894 FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
896 while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
898 FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
899 if (FileByte == '\n')
905 /* Dump the line as parsed and represented internally */
907 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s",
908 Field->Column-4, Field->Name, Field->Value);
910 if (strlen (Field->Value) > 64)
912 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n",
913 strlen (Field->Value));
915 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
917 /* Dump the hex data that will be output for this field */
919 DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
923 /******************************************************************************
925 * FUNCTION: DtWriteTableToListing
931 * DESCRIPTION: Write the entire compiled table to the listing file
934 *****************************************************************************/
937 DtWriteTableToListing (
943 if (!Gbl_ListingFlag)
948 /* Read the entire table from the output file */
950 Buffer = UtLocalCalloc (Gbl_TableLength);
951 FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
952 FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
954 /* Dump the raw table data */
956 AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
958 AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
959 ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
960 AcpiUtDumpBuffer2 (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY);
962 AcpiOsRedirectOutput (stdout);