1 /******************************************************************************
3 * Module Name: dtio.c - File I/O support for data table compiler
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2012, 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 */
71 DT_SUBTABLE *Subtable,
83 /* States for DtGetNextLine */
85 #define DT_NORMAL_TEXT 0
86 #define DT_START_QUOTED_STRING 1
87 #define DT_START_COMMENT 2
88 #define DT_SLASH_ASTERISK_COMMENT 3
89 #define DT_SLASH_SLASH_COMMENT 4
90 #define DT_END_COMMENT 5
91 #define DT_MERGE_LINES 6
93 static UINT32 Gbl_NextLineOffset;
96 /******************************************************************************
100 * PARAMETERS: String - Current source code line to trim
102 * RETURN: Trimmed line. Must be freed by caller.
104 * DESCRIPTION: Trim left and right spaces
106 *****************************************************************************/
118 /* Skip lines that start with a space */
120 if (!ACPI_STRCMP (String, " "))
122 ReturnString = UtLocalCalloc (1);
123 return (ReturnString);
126 /* Setup pointers to start and end of input string */
129 End = String + ACPI_STRLEN (String) - 1;
131 /* Find first non-whitespace character */
133 while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
138 /* Find last non-space character */
142 if (*End == '\r' || *End == '\n')
156 /* Remove any quotes around the string */
167 /* Create the trimmed return string */
169 Length = ACPI_PTR_DIFF (End, Start) + 1;
170 ReturnString = UtLocalCalloc (Length + 1);
171 if (ACPI_STRLEN (Start))
173 ACPI_STRNCPY (ReturnString, Start, Length);
176 ReturnString[Length] = 0;
177 return (ReturnString);
181 /******************************************************************************
183 * FUNCTION: DtLinkField
185 * PARAMETERS: Field - New field object to link
189 * DESCRIPTION: Link one field name and value to the list
191 *****************************************************************************/
201 Prev = Next = Gbl_FieldList;
215 Gbl_FieldList = Field;
220 /******************************************************************************
222 * FUNCTION: DtParseLine
224 * PARAMETERS: LineBuffer - Current source code line
225 * Line - Current line number in the source
226 * Offset - Current byte offset of the line
230 * DESCRIPTION: Parse one source line
232 *****************************************************************************/
251 BOOLEAN IsNullString = FALSE;
259 /* All lines after "Raw Table Data" are ingored */
261 if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
263 return (AE_NOT_FOUND);
266 Colon = strchr (LineBuffer, ':');
275 while (Start < Colon)
283 /* Found left bracket, go to the right bracket */
287 while (Start < Colon && *Start != ']')
305 * There are two column values. One for the field name,
306 * and one for the field value.
308 Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
309 NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
311 Length = ACPI_PTR_DIFF (End, Start);
313 TmpName = UtLocalCalloc (Length + 1);
314 ACPI_STRNCPY (TmpName, Start, Length);
315 Name = DtTrim (TmpName);
318 Start = End = (Colon + 1);
321 /* Found left quotation, go to the right quotation and break */
327 /* Check for an explicit null string */
333 while (*End && (*End != '"'))
343 * Special "comment" fields at line end, ignore them.
344 * Note: normal slash-slash and slash-asterisk comments are
345 * stripped already by the DtGetNextLine parser.
347 * TBD: Perhaps DtGetNextLine should parse the following type
358 Length = ACPI_PTR_DIFF (End, Start);
359 TmpValue = UtLocalCalloc (Length + 1);
361 ACPI_STRNCPY (TmpValue, Start, Length);
362 Value = DtTrim (TmpValue);
363 ACPI_FREE (TmpValue);
365 /* Create a new field object only if we have a valid value field */
367 if ((Value && *Value) || IsNullString)
369 Field = UtLocalCalloc (sizeof (DT_FIELD));
371 Field->Value = Value;
373 Field->ByteOffset = Offset;
374 Field->NameColumn = NameColumn;
375 Field->Column = Column;
379 else /* Ignore this field, it has no valid data */
389 /******************************************************************************
391 * FUNCTION: DtGetNextLine
393 * PARAMETERS: Handle - Open file handle for the source file
395 * RETURN: Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
397 * DESCRIPTION: Get the next valid source line. Removes all comments.
398 * Ignores empty lines.
400 * Handles both slash-asterisk and slash-slash comments.
401 * Also, quoted strings, but no escapes within.
403 * Line is returned in Gbl_CurrentLineBuffer.
404 * Line number in original file is returned in Gbl_CurrentLineNumber.
406 *****************************************************************************/
412 BOOLEAN LineNotAllBlanks = FALSE;
413 UINT32 State = DT_NORMAL_TEXT;
414 UINT32 CurrentLineOffset;
419 for (i = 0; i < ASL_LINE_BUFFER_SIZE;)
421 c = (char) getc (Handle);
426 case DT_START_QUOTED_STRING:
427 case DT_SLASH_ASTERISK_COMMENT:
428 case DT_SLASH_SLASH_COMMENT:
430 AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
444 /* Normal text, insert char into line buffer */
446 Gbl_CurrentLineBuffer[i] = c;
450 State = DT_START_COMMENT;
454 State = DT_START_QUOTED_STRING;
455 LineNotAllBlanks = TRUE;
461 * The continuation char MUST be last char on this line.
462 * Otherwise, it will be assumed to be a valid ASL char.
464 State = DT_MERGE_LINES;
468 CurrentLineOffset = Gbl_NextLineOffset;
469 Gbl_NextLineOffset = (UINT32) ftell (Handle);
470 Gbl_CurrentLineNumber++;
473 * Exit if line is complete. Ignore empty lines (only \n)
474 * or lines that contain nothing but blanks.
476 if ((i != 0) && LineNotAllBlanks)
478 Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
479 return (CurrentLineOffset);
482 /* Toss this line and start a new one */
485 LineNotAllBlanks = FALSE;
491 LineNotAllBlanks = TRUE;
499 case DT_START_QUOTED_STRING:
501 /* Insert raw chars until end of quoted string */
503 Gbl_CurrentLineBuffer[i] = c;
508 State = DT_NORMAL_TEXT;
512 case DT_START_COMMENT:
514 /* Open comment if this character is an asterisk or slash */
519 State = DT_SLASH_ASTERISK_COMMENT;
523 State = DT_SLASH_SLASH_COMMENT;
526 default: /* Not a comment */
527 i++; /* Save the preceeding slash */
528 Gbl_CurrentLineBuffer[i] = c;
530 State = DT_NORMAL_TEXT;
535 case DT_SLASH_ASTERISK_COMMENT:
537 /* Ignore chars until an asterisk-slash is found */
542 Gbl_NextLineOffset = (UINT32) ftell (Handle);
543 Gbl_CurrentLineNumber++;
547 State = DT_END_COMMENT;
555 case DT_SLASH_SLASH_COMMENT:
557 /* Ignore chars until end-of-line */
561 /* We will exit via the NORMAL_TEXT path */
564 State = DT_NORMAL_TEXT;
570 /* End comment if this char is a slash */
575 State = DT_NORMAL_TEXT;
579 CurrentLineOffset = Gbl_NextLineOffset;
580 Gbl_NextLineOffset = (UINT32) ftell (Handle);
581 Gbl_CurrentLineNumber++;
585 /* Consume all adjacent asterisks */
589 State = DT_SLASH_ASTERISK_COMMENT;
599 * This is not a continuation backslash, it is a normal
600 * normal ASL backslash - for example: Scope(\_SB_)
602 i++; /* Keep the backslash that is already in the buffer */
605 State = DT_NORMAL_TEXT;
610 * This is a continuation line -- a backlash followed
611 * immediately by a newline. Insert a space between the
612 * lines (overwrite the backslash)
614 Gbl_CurrentLineBuffer[i] = ' ';
617 /* Ignore newline, this will merge the lines */
619 CurrentLineOffset = Gbl_NextLineOffset;
620 Gbl_NextLineOffset = (UINT32) ftell (Handle);
621 Gbl_CurrentLineNumber++;
622 State = DT_NORMAL_TEXT;
627 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
632 printf ("ERROR - Input line is too long (max %u)\n", ASL_LINE_BUFFER_SIZE);
637 /******************************************************************************
639 * FUNCTION: DtScanFile
641 * PARAMETERS: Handle - Open file handle for the source file
643 * RETURN: Pointer to start of the constructed parse tree.
645 * DESCRIPTION: Scan source file, link all field names and values
646 * to the global parse tree: Gbl_FieldList
648 *****************************************************************************/
659 ACPI_FUNCTION_NAME (DtScanFile);
662 /* Get the file size */
664 Gbl_InputByteCount = DtGetFileSize (Handle);
666 Gbl_CurrentLineNumber = 0;
667 Gbl_CurrentLineOffset = 0;
668 Gbl_NextLineOffset = 0;
670 /* Scan line-by-line */
672 while ((Offset = DtGetNextLine (Handle)) != ASL_EOF)
674 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
675 Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
677 Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset);
678 if (Status == AE_NOT_FOUND)
684 /* Dump the parse tree if debug enabled */
688 Next = Gbl_FieldList;
689 DbgPrint (ASL_DEBUG_OUTPUT, "Tree: %32s %32s %8s %8s %8s %8s %8s %8s\n\n",
690 "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags");
694 DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n",
708 return (Gbl_FieldList);
716 /******************************************************************************
718 * FUNCTION: DtWriteBinary
720 * PARAMETERS: DT_WALK_CALLBACK
724 * DESCRIPTION: Write one subtable of a binary ACPI table
726 *****************************************************************************/
730 DT_SUBTABLE *Subtable,
735 FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
739 /******************************************************************************
741 * FUNCTION: DtOutputBinary
747 * DESCRIPTION: Write entire binary ACPI table (result of compilation)
749 *****************************************************************************/
753 DT_SUBTABLE *RootTable)
761 /* Walk the entire parse tree, emitting the binary data */
763 DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
764 Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
772 /******************************************************************************
774 * FUNCTION: DtDumpBuffer
776 * PARAMETERS: FileID - Where to write buffer data
777 * Buffer - Buffer to dump
778 * Offset - Offset in current table
779 * Length - Buffer Length
783 * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
785 * TBD: merge dump buffer routines
787 *****************************************************************************/
801 FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ",
802 Offset, Offset, Length);
809 FlPrintFile (FileId, "%24s", "");
812 /* Print 16 hex chars */
818 /* Dump fill spaces */
820 FlPrintFile (FileId, " ");
825 FlPrintFile (FileId, "%02X ", Buffer[i+j]);
829 FlPrintFile (FileId, " ");
830 for (j = 0; j < 16; j++)
834 FlPrintFile (FileId, "\n\n");
838 BufChar = Buffer[(ACPI_SIZE) i + j];
839 if (ACPI_IS_PRINT (BufChar))
841 FlPrintFile (FileId, "%c", BufChar);
845 FlPrintFile (FileId, ".");
849 /* Done with that line. */
851 FlPrintFile (FileId, "\n");
855 FlPrintFile (FileId, "\n\n");
859 /******************************************************************************
861 * FUNCTION: DtWriteFieldToListing
863 * PARAMETERS: Buffer - Contains the compiled data
864 * Field - Field node for the input line
865 * Length - Length of the output data
869 * DESCRIPTION: Write one field to the listing file (if listing is enabled).
871 *****************************************************************************/
874 DtWriteFieldToListing (
882 if (!Gbl_ListingFlag || !Field)
887 /* Dump the original source line */
889 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input: ");
890 FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
892 while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
894 FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
895 if (FileByte == '\n')
901 /* Dump the line as parsed and represented internally */
903 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s",
904 Field->Column-4, Field->Name, Field->Value);
906 if (strlen (Field->Value) > 64)
908 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n",
909 strlen (Field->Value));
911 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
913 /* Dump the hex data that will be output for this field */
915 DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
919 /******************************************************************************
921 * FUNCTION: DtWriteTableToListing
927 * DESCRIPTION: Write the entire compiled table to the listing file
930 *****************************************************************************/
933 DtWriteTableToListing (
939 if (!Gbl_ListingFlag)
944 /* Read the entire table from the output file */
946 Buffer = UtLocalCalloc (Gbl_TableLength);
947 FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
948 FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
950 /* Dump the raw table data */
952 AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
954 AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
955 ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
956 AcpiUtDumpBuffer2 (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY);
958 AcpiOsRedirectOutput (stdout);