xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dtio.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /******************************************************************************
2  *
3  * Module Name: dtio.c - File I/O support for data table compiler
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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.
25  *
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.
29  *
30  * NO WARRANTY
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.
42  */
43 
44 #include "aslcompiler.h"
45 #include "acapps.h"
46 
47 #define _COMPONENT          DT_COMPILER
48         ACPI_MODULE_NAME    ("dtio")
49 
50 
51 /* Local prototypes */
52 
53 static char *
54 DtTrim (
55     char                    *String);
56 
57 static void
58 DtLinkField (
59     DT_FIELD                *Field);
60 
61 static ACPI_STATUS
62 DtParseLine (
63     char                    *LineBuffer,
64     UINT32                  Line,
65     UINT32                  Offset);
66 
67 static void
68 DtWriteBinary (
69     DT_SUBTABLE             *Subtable,
70     void                    *Context,
71     void                    *ReturnValue);
72 
73 static void
74 DtDumpBuffer (
75     UINT32                  FileId,
76     UINT8                   *Buffer,
77     UINT32                  Offset,
78     UINT32                  Length);
79 
80 static void
81 DtDumpSubtableInfo (
82     DT_SUBTABLE             *Subtable,
83     void                    *Context,
84     void                    *ReturnValue);
85 
86 static void
87 DtDumpSubtableTree (
88     DT_SUBTABLE             *Subtable,
89     void                    *Context,
90     void                    *ReturnValue);
91 
92 
93 /* States for DtGetNextLine */
94 
95 #define DT_NORMAL_TEXT              0
96 #define DT_START_QUOTED_STRING      1
97 #define DT_START_COMMENT            2
98 #define DT_SLASH_ASTERISK_COMMENT   3
99 #define DT_SLASH_SLASH_COMMENT      4
100 #define DT_END_COMMENT              5
101 #define DT_MERGE_LINES              6
102 #define DT_ESCAPE_SEQUENCE          7
103 
104 static UINT32               Gbl_NextLineOffset;
105 
106 
107 /******************************************************************************
108  *
109  * FUNCTION:    DtTrim
110  *
111  * PARAMETERS:  String              - Current source code line to trim
112  *
113  * RETURN:      Trimmed line. Must be freed by caller.
114  *
115  * DESCRIPTION: Trim left and right spaces
116  *
117  *****************************************************************************/
118 
119 static char *
120 DtTrim (
121     char                    *String)
122 {
123     char                    *Start;
124     char                    *End;
125     char                    *ReturnString;
126     ACPI_SIZE               Length;
127 
128 
129     /* Skip lines that start with a space */
130 
131     if (!strcmp (String, " "))
132     {
133         ReturnString = UtLocalCacheCalloc (1);
134         return (ReturnString);
135     }
136 
137     /* Setup pointers to start and end of input string */
138 
139     Start = String;
140     End = String + strlen (String) - 1;
141 
142     /* Find first non-whitespace character */
143 
144     while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
145     {
146         Start++;
147     }
148 
149     /* Find last non-space character */
150 
151     while (End >= Start)
152     {
153         if (*End == '\r' || *End == '\n')
154         {
155             End--;
156             continue;
157         }
158 
159         if (*End != ' ')
160         {
161             break;
162         }
163 
164         End--;
165     }
166 
167     /* Remove any quotes around the string */
168 
169     if (*Start == '\"')
170     {
171         Start++;
172     }
173     if (*End == '\"')
174     {
175         End--;
176     }
177 
178     /* Create the trimmed return string */
179 
180     Length = ACPI_PTR_DIFF (End, Start) + 1;
181     ReturnString = UtLocalCacheCalloc (Length + 1);
182     if (strlen (Start))
183     {
184         strncpy (ReturnString, Start, Length);
185     }
186 
187     ReturnString[Length] = 0;
188     return (ReturnString);
189 }
190 
191 
192 /******************************************************************************
193  *
194  * FUNCTION:    DtLinkField
195  *
196  * PARAMETERS:  Field               - New field object to link
197  *
198  * RETURN:      None
199  *
200  * DESCRIPTION: Link one field name and value to the list
201  *
202  *****************************************************************************/
203 
204 static void
205 DtLinkField (
206     DT_FIELD                *Field)
207 {
208     DT_FIELD                *Prev;
209     DT_FIELD                *Next;
210 
211 
212     Prev = Next = Gbl_FieldList;
213 
214     while (Next)
215     {
216         Prev = Next;
217         Next = Next->Next;
218     }
219 
220     if (Prev)
221     {
222         Prev->Next = Field;
223     }
224     else
225     {
226         Gbl_FieldList = Field;
227     }
228 }
229 
230 
231 /******************************************************************************
232  *
233  * FUNCTION:    DtParseLine
234  *
235  * PARAMETERS:  LineBuffer          - Current source code line
236  *              Line                - Current line number in the source
237  *              Offset              - Current byte offset of the line
238  *
239  * RETURN:      Status
240  *
241  * DESCRIPTION: Parse one source line
242  *
243  *****************************************************************************/
244 
245 static ACPI_STATUS
246 DtParseLine (
247     char                    *LineBuffer,
248     UINT32                  Line,
249     UINT32                  Offset)
250 {
251     char                    *Start;
252     char                    *End;
253     char                    *TmpName;
254     char                    *TmpValue;
255     char                    *Name;
256     char                    *Value;
257     char                    *Colon;
258     UINT32                  Length;
259     DT_FIELD                *Field;
260     UINT32                  Column;
261     UINT32                  NameColumn;
262     BOOLEAN                 IsNullString = FALSE;
263 
264 
265     if (!LineBuffer)
266     {
267         return (AE_OK);
268     }
269 
270     /* All lines after "Raw Table Data" are ingored */
271 
272     if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
273     {
274         return (AE_NOT_FOUND);
275     }
276 
277     Colon = strchr (LineBuffer, ':');
278     if (!Colon)
279     {
280         return (AE_OK);
281     }
282 
283     Start = LineBuffer;
284     End = Colon;
285 
286     while (Start < Colon)
287     {
288         if (*Start == '[')
289         {
290             /* Found left bracket, go to the right bracket */
291 
292             while (Start < Colon && *Start != ']')
293             {
294                 Start++;
295             }
296         }
297         else if (*Start != ' ')
298         {
299             break;
300         }
301 
302         Start++;
303     }
304 
305     /*
306      * There are two column values. One for the field name,
307      * and one for the field value.
308      */
309     Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
310     NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
311 
312     Length = ACPI_PTR_DIFF (End, Start);
313 
314     TmpName = UtLocalCalloc (Length + 1);
315     strncpy (TmpName, Start, Length);
316     Name = DtTrim (TmpName);
317     ACPI_FREE (TmpName);
318 
319     Start = End = (Colon + 1);
320     while (*End)
321     {
322         /* Found left quotation, go to the right quotation and break */
323 
324         if (*End == '"')
325         {
326             End++;
327 
328             /* Check for an explicit null string */
329 
330             if (*End == '"')
331             {
332                 IsNullString = TRUE;
333             }
334             while (*End && (*End != '"'))
335             {
336                 End++;
337             }
338 
339             End++;
340             break;
341         }
342 
343         /*
344          * Special "comment" fields at line end, ignore them.
345          * Note: normal slash-slash and slash-asterisk comments are
346          * stripped already by the DtGetNextLine parser.
347          *
348          * TBD: Perhaps DtGetNextLine should parse the following type
349          * of comments also.
350          */
351         if (*End == '[')
352         {
353             End--;
354             break;
355         }
356 
357         End++;
358     }
359 
360     Length = ACPI_PTR_DIFF (End, Start);
361     TmpValue = UtLocalCalloc (Length + 1);
362 
363     strncpy (TmpValue, Start, Length);
364     Value = DtTrim (TmpValue);
365     ACPI_FREE (TmpValue);
366 
367     /* Create a new field object only if we have a valid value field */
368 
369     if ((Value && *Value) || IsNullString)
370     {
371         Field = UtFieldCacheCalloc ();
372         Field->Name = Name;
373         Field->Value = Value;
374         Field->Line = Line;
375         Field->ByteOffset = Offset;
376         Field->NameColumn = NameColumn;
377         Field->Column = Column;
378         Field->StringLength = Length;
379 
380         DtLinkField (Field);
381     }
382     /* Else -- Ignore this field, it has no valid data */
383 
384     return (AE_OK);
385 }
386 
387 
388 /******************************************************************************
389  *
390  * FUNCTION:    DtGetNextLine
391  *
392  * PARAMETERS:  Handle              - Open file handle for the source file
393  *
394  * RETURN:      Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
395  *
396  * DESCRIPTION: Get the next valid source line. Removes all comments.
397  *              Ignores empty lines.
398  *
399  * Handles both slash-asterisk and slash-slash comments.
400  * Also, quoted strings, but no escapes within.
401  *
402  * Line is returned in Gbl_CurrentLineBuffer.
403  * Line number in original file is returned in Gbl_CurrentLineNumber.
404  *
405  *****************************************************************************/
406 
407 UINT32
408 DtGetNextLine (
409     FILE                    *Handle,
410     UINT32                  Flags)
411 {
412     BOOLEAN                 LineNotAllBlanks = FALSE;
413     UINT32                  State = DT_NORMAL_TEXT;
414     UINT32                  CurrentLineOffset;
415     UINT32                  i;
416     int                     c;
417 
418 
419     memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize);
420     for (i = 0; ;)
421     {
422         /*
423          * If line is too long, expand the line buffers. Also increases
424          * Gbl_LineBufferSize.
425          */
426         if (i >= Gbl_LineBufferSize)
427         {
428             UtExpandLineBuffers ();
429         }
430 
431         c = getc (Handle);
432         if (c == EOF)
433         {
434             switch (State)
435             {
436             case DT_START_QUOTED_STRING:
437             case DT_SLASH_ASTERISK_COMMENT:
438 
439                 AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
440                 break;
441 
442             default:
443 
444                 break;
445             }
446 
447             /* Standalone EOF is OK */
448 
449             if (i == 0)
450             {
451                 return (ASL_EOF);
452             }
453 
454             /*
455              * Received an EOF in the middle of a line. Terminate the
456              * line with a newline. The next call to this function will
457              * return a standalone EOF. Thus, the upper parsing software
458              * never has to deal with an EOF within a valid line (or
459              * the last line does not get tossed on the floor.)
460              */
461             c = '\n';
462             State = DT_NORMAL_TEXT;
463         }
464 
465         switch (State)
466         {
467         case DT_NORMAL_TEXT:
468 
469             /* Normal text, insert char into line buffer */
470 
471             Gbl_CurrentLineBuffer[i] = (char) c;
472             switch (c)
473             {
474             case '/':
475 
476                 State = DT_START_COMMENT;
477                 break;
478 
479             case '"':
480 
481                 State = DT_START_QUOTED_STRING;
482                 LineNotAllBlanks = TRUE;
483                 i++;
484                 break;
485 
486             case '\\':
487                 /*
488                  * The continuation char MUST be last char on this line.
489                  * Otherwise, it will be assumed to be a valid ASL char.
490                  */
491                 State = DT_MERGE_LINES;
492                 break;
493 
494             case '\n':
495 
496                 CurrentLineOffset = Gbl_NextLineOffset;
497                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
498                 Gbl_CurrentLineNumber++;
499 
500                 /*
501                  * Exit if line is complete. Ignore empty lines (only \n)
502                  * or lines that contain nothing but blanks.
503                  */
504                 if ((i != 0) && LineNotAllBlanks)
505                 {
506                     if ((i + 1) >= Gbl_LineBufferSize)
507                     {
508                         UtExpandLineBuffers ();
509                     }
510 
511                     Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
512                     return (CurrentLineOffset);
513                 }
514 
515                 /* Toss this line and start a new one */
516 
517                 i = 0;
518                 LineNotAllBlanks = FALSE;
519                 break;
520 
521             default:
522 
523                 if (c != ' ')
524                 {
525                     LineNotAllBlanks = TRUE;
526                 }
527 
528                 i++;
529                 break;
530             }
531             break;
532 
533         case DT_START_QUOTED_STRING:
534 
535             /* Insert raw chars until end of quoted string */
536 
537             Gbl_CurrentLineBuffer[i] = (char) c;
538             i++;
539 
540             switch (c)
541             {
542             case '"':
543 
544                 State = DT_NORMAL_TEXT;
545                 break;
546 
547             case '\\':
548 
549                 State = DT_ESCAPE_SEQUENCE;
550                 break;
551 
552             case '\n':
553 
554                 if (!(Flags & DT_ALLOW_MULTILINE_QUOTES))
555                 {
556                     AcpiOsPrintf (
557                         "ERROR at line %u: Unterminated quoted string\n",
558                         Gbl_CurrentLineNumber++);
559                     State = DT_NORMAL_TEXT;
560                 }
561                 break;
562 
563             default:    /* Get next character */
564 
565                 break;
566             }
567             break;
568 
569         case DT_ESCAPE_SEQUENCE:
570 
571             /* Just copy the escaped character. TBD: sufficient for table compiler? */
572 
573             Gbl_CurrentLineBuffer[i] = (char) c;
574             i++;
575             State = DT_START_QUOTED_STRING;
576             break;
577 
578         case DT_START_COMMENT:
579 
580             /* Open comment if this character is an asterisk or slash */
581 
582             switch (c)
583             {
584             case '*':
585 
586                 State = DT_SLASH_ASTERISK_COMMENT;
587                 break;
588 
589             case '/':
590 
591                 State = DT_SLASH_SLASH_COMMENT;
592                 break;
593 
594             default:    /* Not a comment */
595 
596                 i++;    /* Save the preceding slash */
597                 if (i >= Gbl_LineBufferSize)
598                 {
599                     UtExpandLineBuffers ();
600                 }
601 
602                 Gbl_CurrentLineBuffer[i] = (char) c;
603                 i++;
604                 State = DT_NORMAL_TEXT;
605                 break;
606             }
607             break;
608 
609         case DT_SLASH_ASTERISK_COMMENT:
610 
611             /* Ignore chars until an asterisk-slash is found */
612 
613             switch (c)
614             {
615             case '\n':
616 
617                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
618                 Gbl_CurrentLineNumber++;
619                 break;
620 
621             case '*':
622 
623                 State = DT_END_COMMENT;
624                 break;
625 
626             default:
627 
628                 break;
629             }
630             break;
631 
632         case DT_SLASH_SLASH_COMMENT:
633 
634             /* Ignore chars until end-of-line */
635 
636             if (c == '\n')
637             {
638                 /* We will exit via the NORMAL_TEXT path */
639 
640                 ungetc (c, Handle);
641                 State = DT_NORMAL_TEXT;
642             }
643             break;
644 
645         case DT_END_COMMENT:
646 
647             /* End comment if this char is a slash */
648 
649             switch (c)
650             {
651             case '/':
652 
653                 State = DT_NORMAL_TEXT;
654                 break;
655 
656             case '\n':
657 
658                 CurrentLineOffset = Gbl_NextLineOffset;
659                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
660                 Gbl_CurrentLineNumber++;
661                 break;
662 
663             case '*':
664 
665                 /* Consume all adjacent asterisks */
666                 break;
667 
668             default:
669 
670                 State = DT_SLASH_ASTERISK_COMMENT;
671                 break;
672             }
673             break;
674 
675         case DT_MERGE_LINES:
676 
677             if (c != '\n')
678             {
679                 /*
680                  * This is not a continuation backslash, it is a normal
681                  * normal ASL backslash - for example: Scope(\_SB_)
682                  */
683                 i++; /* Keep the backslash that is already in the buffer */
684 
685                 ungetc (c, Handle);
686                 State = DT_NORMAL_TEXT;
687             }
688             else
689             {
690                 /*
691                  * This is a continuation line -- a backlash followed
692                  * immediately by a newline. Insert a space between the
693                  * lines (overwrite the backslash)
694                  */
695                 Gbl_CurrentLineBuffer[i] = ' ';
696                 i++;
697 
698                 /* Ignore newline, this will merge the lines */
699 
700                 CurrentLineOffset = Gbl_NextLineOffset;
701                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
702                 Gbl_CurrentLineNumber++;
703                 State = DT_NORMAL_TEXT;
704             }
705             break;
706 
707         default:
708 
709             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
710             return (ASL_EOF);
711         }
712     }
713 }
714 
715 
716 /******************************************************************************
717  *
718  * FUNCTION:    DtScanFile
719  *
720  * PARAMETERS:  Handle              - Open file handle for the source file
721  *
722  * RETURN:      Pointer to start of the constructed parse tree.
723  *
724  * DESCRIPTION: Scan source file, link all field names and values
725  *              to the global parse tree: Gbl_FieldList
726  *
727  *****************************************************************************/
728 
729 DT_FIELD *
730 DtScanFile (
731     FILE                    *Handle)
732 {
733     ACPI_STATUS             Status;
734     UINT32                  Offset;
735 
736 
737     ACPI_FUNCTION_NAME (DtScanFile);
738 
739 
740     /* Get the file size */
741 
742     Gbl_InputByteCount = CmGetFileSize (Handle);
743     if (Gbl_InputByteCount == ACPI_UINT32_MAX)
744     {
745         AslAbort ();
746     }
747 
748     Gbl_CurrentLineNumber = 0;
749     Gbl_CurrentLineOffset = 0;
750     Gbl_NextLineOffset = 0;
751 
752     /* Scan line-by-line */
753 
754     while ((Offset = DtGetNextLine (Handle, 0)) != ASL_EOF)
755     {
756         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
757             Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
758 
759         Status = DtParseLine (Gbl_CurrentLineBuffer,
760             Gbl_CurrentLineNumber, Offset);
761         if (Status == AE_NOT_FOUND)
762         {
763             break;
764         }
765     }
766 
767     /* Dump the parse tree if debug enabled */
768 
769     DtDumpFieldList (Gbl_FieldList);
770     return (Gbl_FieldList);
771 }
772 
773 
774 /*
775  * Output functions
776  */
777 
778 /******************************************************************************
779  *
780  * FUNCTION:    DtWriteBinary
781  *
782  * PARAMETERS:  DT_WALK_CALLBACK
783  *
784  * RETURN:      Status
785  *
786  * DESCRIPTION: Write one subtable of a binary ACPI table
787  *
788  *****************************************************************************/
789 
790 static void
791 DtWriteBinary (
792     DT_SUBTABLE             *Subtable,
793     void                    *Context,
794     void                    *ReturnValue)
795 {
796 
797     FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
798 }
799 
800 
801 /******************************************************************************
802  *
803  * FUNCTION:    DtOutputBinary
804  *
805  * PARAMETERS:
806  *
807  * RETURN:      Status
808  *
809  * DESCRIPTION: Write entire binary ACPI table (result of compilation)
810  *
811  *****************************************************************************/
812 
813 void
814 DtOutputBinary (
815     DT_SUBTABLE             *RootTable)
816 {
817 
818     if (!RootTable)
819     {
820         return;
821     }
822 
823     /* Walk the entire parse tree, emitting the binary data */
824 
825     DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
826 
827     Gbl_TableLength = CmGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
828     if (Gbl_TableLength == ACPI_UINT32_MAX)
829     {
830         AslAbort ();
831     }
832 }
833 
834 
835 /*
836  * Listing support
837  */
838 
839 /******************************************************************************
840  *
841  * FUNCTION:    DtDumpBuffer
842  *
843  * PARAMETERS:  FileID              - Where to write buffer data
844  *              Buffer              - Buffer to dump
845  *              Offset              - Offset in current table
846  *              Length              - Buffer Length
847  *
848  * RETURN:      None
849  *
850  * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
851  *
852  * TBD: merge dump buffer routines
853  *
854  *****************************************************************************/
855 
856 static void
857 DtDumpBuffer (
858     UINT32                  FileId,
859     UINT8                   *Buffer,
860     UINT32                  Offset,
861     UINT32                  Length)
862 {
863     UINT32                  i;
864     UINT32                  j;
865     UINT8                   BufChar;
866 
867 
868     FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ",
869         Offset, Offset, Length);
870 
871     i = 0;
872     while (i < Length)
873     {
874         if (i >= 16)
875         {
876             FlPrintFile (FileId, "%24s", "");
877         }
878 
879         /* Print 16 hex chars */
880 
881         for (j = 0; j < 16;)
882         {
883             if (i + j >= Length)
884             {
885                 /* Dump fill spaces */
886 
887                 FlPrintFile (FileId, "   ");
888                 j++;
889                 continue;
890             }
891 
892             FlPrintFile (FileId, "%02X ", Buffer[i+j]);
893             j++;
894         }
895 
896         FlPrintFile (FileId, " ");
897         for (j = 0; j < 16; j++)
898         {
899             if (i + j >= Length)
900             {
901                 FlPrintFile (FileId, "\n\n");
902                 return;
903             }
904 
905             BufChar = Buffer[(ACPI_SIZE) i + j];
906             if (isprint (BufChar))
907             {
908                 FlPrintFile (FileId, "%c", BufChar);
909             }
910             else
911             {
912                 FlPrintFile (FileId, ".");
913             }
914         }
915 
916         /* Done with that line. */
917 
918         FlPrintFile (FileId, "\n");
919         i += 16;
920     }
921 
922     FlPrintFile (FileId, "\n\n");
923 }
924 
925 
926 /******************************************************************************
927  *
928  * FUNCTION:    DtDumpFieldList
929  *
930  * PARAMETERS:  Field               - Root field
931  *
932  * RETURN:      None
933  *
934  * DESCRIPTION: Dump the entire field list
935  *
936  *****************************************************************************/
937 
938 void
939 DtDumpFieldList (
940     DT_FIELD                *Field)
941 {
942 
943     if (!Gbl_DebugFlag || !Field)
944     {
945         return;
946     }
947 
948     DbgPrint (ASL_DEBUG_OUTPUT,  "\nField List:\n"
949         "LineNo   ByteOff  NameCol  Column   TableOff "
950         "Flags %32s : %s\n\n", "Name", "Value");
951 
952     while (Field)
953     {
954         DbgPrint (ASL_DEBUG_OUTPUT,
955             "%.08X %.08X %.08X %.08X %.08X %2.2X    %32s : %s\n",
956             Field->Line, Field->ByteOffset, Field->NameColumn,
957             Field->Column, Field->TableOffset, Field->Flags,
958             Field->Name, Field->Value);
959 
960         Field = Field->Next;
961     }
962 
963     DbgPrint (ASL_DEBUG_OUTPUT,  "\n\n");
964 }
965 
966 
967 /******************************************************************************
968  *
969  * FUNCTION:    DtDumpSubtableInfo, DtDumpSubtableTree
970  *
971  * PARAMETERS:  DT_WALK_CALLBACK
972  *
973  * RETURN:      None
974  *
975  * DESCRIPTION: Info - dump a subtable tree entry with extra information.
976  *              Tree - dump a subtable tree formatted by depth indentation.
977  *
978  *****************************************************************************/
979 
980 static void
981 DtDumpSubtableInfo (
982     DT_SUBTABLE             *Subtable,
983     void                    *Context,
984     void                    *ReturnValue)
985 {
986 
987     DbgPrint (ASL_DEBUG_OUTPUT,
988         "[%.04X] %24s %.08X %.08X %.08X %.08X %.08X %p %p %p\n",
989         Subtable->Depth, Subtable->Name, Subtable->Length, Subtable->TotalLength,
990         Subtable->SizeOfLengthField, Subtable->Flags, Subtable,
991         Subtable->Parent, Subtable->Child, Subtable->Peer);
992 }
993 
994 static void
995 DtDumpSubtableTree (
996     DT_SUBTABLE             *Subtable,
997     void                    *Context,
998     void                    *ReturnValue)
999 {
1000 
1001     DbgPrint (ASL_DEBUG_OUTPUT,
1002         "[%.04X] %24s %*s%08X (%.02X) - (%.02X)\n",
1003         Subtable->Depth, Subtable->Name, (4 * Subtable->Depth), " ",
1004         Subtable, Subtable->Length, Subtable->TotalLength);
1005 }
1006 
1007 
1008 /******************************************************************************
1009  *
1010  * FUNCTION:    DtDumpSubtableList
1011  *
1012  * PARAMETERS:  None
1013  *
1014  * RETURN:      None
1015  *
1016  * DESCRIPTION: Dump the raw list of subtables with information, and also
1017  *              dump the subtable list in formatted tree format. Assists with
1018  *              the development of new table code.
1019  *
1020  *****************************************************************************/
1021 
1022 void
1023 DtDumpSubtableList (
1024     void)
1025 {
1026 
1027     if (!Gbl_DebugFlag || !Gbl_RootTable)
1028     {
1029         return;
1030     }
1031 
1032     DbgPrint (ASL_DEBUG_OUTPUT,
1033         "Subtable Info:\n"
1034         "Depth                      Name Length   TotalLen LenSize  Flags    "
1035         "This     Parent   Child    Peer\n\n");
1036     DtWalkTableTree (Gbl_RootTable, DtDumpSubtableInfo, NULL, NULL);
1037 
1038     DbgPrint (ASL_DEBUG_OUTPUT,
1039         "\nSubtable Tree: (Depth, Name, Subtable, Length, TotalLength)\n\n");
1040     DtWalkTableTree (Gbl_RootTable, DtDumpSubtableTree, NULL, NULL);
1041 
1042     DbgPrint (ASL_DEBUG_OUTPUT, "\n");
1043 }
1044 
1045 
1046 /******************************************************************************
1047  *
1048  * FUNCTION:    DtWriteFieldToListing
1049  *
1050  * PARAMETERS:  Buffer              - Contains the compiled data
1051  *              Field               - Field node for the input line
1052  *              Length              - Length of the output data
1053  *
1054  * RETURN:      None
1055  *
1056  * DESCRIPTION: Write one field to the listing file (if listing is enabled).
1057  *
1058  *****************************************************************************/
1059 
1060 void
1061 DtWriteFieldToListing (
1062     UINT8                   *Buffer,
1063     DT_FIELD                *Field,
1064     UINT32                  Length)
1065 {
1066     UINT8                   FileByte;
1067 
1068 
1069     if (!Gbl_ListingFlag || !Field)
1070     {
1071         return;
1072     }
1073 
1074     /* Dump the original source line */
1075 
1076     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input:  ");
1077     FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
1078 
1079     while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
1080     {
1081         FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
1082         if (FileByte == '\n')
1083         {
1084             break;
1085         }
1086     }
1087 
1088     /* Dump the line as parsed and represented internally */
1089 
1090     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s",
1091         Field->Column-4, Field->Name, Field->Value);
1092 
1093     if (strlen (Field->Value) > 64)
1094     {
1095         FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n",
1096             strlen (Field->Value));
1097     }
1098 
1099     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
1100 
1101     /* Dump the hex data that will be output for this field */
1102 
1103     DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
1104 }
1105 
1106 
1107 /******************************************************************************
1108  *
1109  * FUNCTION:    DtWriteTableToListing
1110  *
1111  * PARAMETERS:  None
1112  *
1113  * RETURN:      None
1114  *
1115  * DESCRIPTION: Write the entire compiled table to the listing file
1116  *              in hex format
1117  *
1118  *****************************************************************************/
1119 
1120 void
1121 DtWriteTableToListing (
1122     void)
1123 {
1124     UINT8                   *Buffer;
1125 
1126 
1127     if (!Gbl_ListingFlag)
1128     {
1129         return;
1130     }
1131 
1132     /* Read the entire table from the output file */
1133 
1134     Buffer = UtLocalCalloc (Gbl_TableLength);
1135     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1136     FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
1137 
1138     /* Dump the raw table data */
1139 
1140     AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
1141 
1142     AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
1143         ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
1144     AcpiUtDumpBuffer (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY, 0);
1145 
1146     AcpiOsRedirectOutput (stdout);
1147     ACPI_FREE (Buffer);
1148 }
1149