xref: /freebsd/sys/contrib/dev/acpica/compiler/dtio.c (revision 25408c853d9ecb2e76b9e38407338f86ecb8a55c)
1 /******************************************************************************
2  *
3  * Module Name: dtio.c - File I/O support for data table compiler
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 #define __DTIO_C__
45 
46 #include <contrib/dev/acpica/compiler/aslcompiler.h>
47 #include <contrib/dev/acpica/compiler/dtcompiler.h>
48 
49 #define _COMPONENT          DT_COMPILER
50         ACPI_MODULE_NAME    ("dtio")
51 
52 
53 /* Local prototypes */
54 
55 static char *
56 DtTrim (
57     char                    *String);
58 
59 static void
60 DtLinkField (
61     DT_FIELD                *Field);
62 
63 static ACPI_STATUS
64 DtParseLine (
65     char                    *LineBuffer,
66     UINT32                  Line,
67     UINT32                  Offset);
68 
69 static void
70 DtWriteBinary (
71     DT_SUBTABLE             *Subtable,
72     void                    *Context,
73     void                    *ReturnValue);
74 
75 static void
76 DtDumpBuffer (
77     UINT32                  FileId,
78     UINT8                   *Buffer,
79     UINT32                  Offset,
80     UINT32                  Length);
81 
82 
83 /* States for DtGetNextLine */
84 
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
92 #define DT_ESCAPE_SEQUENCE          7
93 
94 static UINT32  Gbl_NextLineOffset;
95 
96 
97 /******************************************************************************
98  *
99  * FUNCTION:    DtTrim
100  *
101  * PARAMETERS:  String              - Current source code line to trim
102  *
103  * RETURN:      Trimmed line. Must be freed by caller.
104  *
105  * DESCRIPTION: Trim left and right spaces
106  *
107  *****************************************************************************/
108 
109 static char *
110 DtTrim (
111     char                    *String)
112 {
113     char                    *Start;
114     char                    *End;
115     char                    *ReturnString;
116     ACPI_SIZE               Length;
117 
118 
119     /* Skip lines that start with a space */
120 
121     if (!ACPI_STRCMP (String, " "))
122     {
123         ReturnString = UtLocalCalloc (1);
124         return (ReturnString);
125     }
126 
127     /* Setup pointers to start and end of input string */
128 
129     Start = String;
130     End = String + ACPI_STRLEN (String) - 1;
131 
132     /* Find first non-whitespace character */
133 
134     while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
135     {
136         Start++;
137     }
138 
139     /* Find last non-space character */
140 
141     while (End >= Start)
142     {
143         if (*End == '\r' || *End == '\n')
144         {
145             End--;
146             continue;
147         }
148 
149         if (*End != ' ')
150         {
151             break;
152         }
153 
154         End--;
155     }
156 
157     /* Remove any quotes around the string */
158 
159     if (*Start == '\"')
160     {
161         Start++;
162     }
163     if (*End == '\"')
164     {
165         End--;
166     }
167 
168     /* Create the trimmed return string */
169 
170     Length = ACPI_PTR_DIFF (End, Start) + 1;
171     ReturnString = UtLocalCalloc (Length + 1);
172     if (ACPI_STRLEN (Start))
173     {
174         ACPI_STRNCPY (ReturnString, Start, Length);
175     }
176 
177     ReturnString[Length] = 0;
178     return (ReturnString);
179 }
180 
181 
182 /******************************************************************************
183  *
184  * FUNCTION:    DtLinkField
185  *
186  * PARAMETERS:  Field               - New field object to link
187  *
188  * RETURN:      None
189  *
190  * DESCRIPTION: Link one field name and value to the list
191  *
192  *****************************************************************************/
193 
194 static void
195 DtLinkField (
196     DT_FIELD                *Field)
197 {
198     DT_FIELD                *Prev;
199     DT_FIELD                *Next;
200 
201 
202     Prev = Next = Gbl_FieldList;
203 
204     while (Next)
205     {
206         Prev = Next;
207         Next = Next->Next;
208     }
209 
210     if (Prev)
211     {
212         Prev->Next = Field;
213     }
214     else
215     {
216         Gbl_FieldList = Field;
217     }
218 }
219 
220 
221 /******************************************************************************
222  *
223  * FUNCTION:    DtParseLine
224  *
225  * PARAMETERS:  LineBuffer          - Current source code line
226  *              Line                - Current line number in the source
227  *              Offset              - Current byte offset of the line
228  *
229  * RETURN:      Status
230  *
231  * DESCRIPTION: Parse one source line
232  *
233  *****************************************************************************/
234 
235 static ACPI_STATUS
236 DtParseLine (
237     char                    *LineBuffer,
238     UINT32                  Line,
239     UINT32                  Offset)
240 {
241     char                    *Start;
242     char                    *End;
243     char                    *TmpName;
244     char                    *TmpValue;
245     char                    *Name;
246     char                    *Value;
247     char                    *Colon;
248     UINT32                  Length;
249     DT_FIELD                *Field;
250     UINT32                  Column;
251     UINT32                  NameColumn;
252     BOOLEAN                 IsNullString = FALSE;
253 
254 
255     if (!LineBuffer)
256     {
257         return (AE_OK);
258     }
259 
260     /* All lines after "Raw Table Data" are ingored */
261 
262     if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
263     {
264         return (AE_NOT_FOUND);
265     }
266 
267     Colon = strchr (LineBuffer, ':');
268     if (!Colon)
269     {
270         return (AE_OK);
271     }
272 
273     Start = LineBuffer;
274     End = Colon;
275 
276     while (Start < Colon)
277     {
278         if (*Start == ' ')
279         {
280             Start++;
281             continue;
282         }
283 
284         /* Found left bracket, go to the right bracket */
285 
286         if (*Start == '[')
287         {
288             while (Start < Colon && *Start != ']')
289             {
290                 Start++;
291             }
292 
293             if (Start == Colon)
294             {
295                 break;
296             }
297 
298             Start++;
299             continue;
300         }
301 
302         break;
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     ACPI_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         End++;
357     }
358 
359     Length = ACPI_PTR_DIFF (End, Start);
360     TmpValue = UtLocalCalloc (Length + 1);
361 
362     ACPI_STRNCPY (TmpValue, Start, Length);
363     Value = DtTrim (TmpValue);
364     ACPI_FREE (TmpValue);
365 
366     /* Create a new field object only if we have a valid value field */
367 
368     if ((Value && *Value) || IsNullString)
369     {
370         Field = UtLocalCalloc (sizeof (DT_FIELD));
371         Field->Name = Name;
372         Field->Value = Value;
373         Field->Line = Line;
374         Field->ByteOffset = Offset;
375         Field->NameColumn = NameColumn;
376         Field->Column = Column;
377 
378         DtLinkField (Field);
379     }
380     else /* Ignore this field, it has no valid data */
381     {
382         ACPI_FREE (Name);
383         ACPI_FREE (Value);
384     }
385 
386     return (AE_OK);
387 }
388 
389 
390 /******************************************************************************
391  *
392  * FUNCTION:    DtGetNextLine
393  *
394  * PARAMETERS:  Handle              - Open file handle for the source file
395  *
396  * RETURN:      Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
397  *
398  * DESCRIPTION: Get the next valid source line. Removes all comments.
399  *              Ignores empty lines.
400  *
401  * Handles both slash-asterisk and slash-slash comments.
402  * Also, quoted strings, but no escapes within.
403  *
404  * Line is returned in Gbl_CurrentLineBuffer.
405  * Line number in original file is returned in Gbl_CurrentLineNumber.
406  *
407  *****************************************************************************/
408 
409 UINT32
410 DtGetNextLine (
411     FILE                    *Handle)
412 {
413     BOOLEAN                 LineNotAllBlanks = FALSE;
414     UINT32                  State = DT_NORMAL_TEXT;
415     UINT32                  CurrentLineOffset;
416     UINT32                  i;
417     char                    c;
418 
419 
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 = (char) 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                 break;
444             }
445 
446             /* Standalone EOF is OK */
447 
448             if (i == 0)
449             {
450                 return (ASL_EOF);
451             }
452 
453             /*
454              * Received an EOF in the middle of a line. Terminate the
455              * line with a newline. The next call to this function will
456              * return a standalone EOF. Thus, the upper parsing software
457              * never has to deal with an EOF within a valid line (or
458              * the last line does not get tossed on the floor.)
459              */
460             c = '\n';
461             State = DT_NORMAL_TEXT;
462         }
463 
464         switch (State)
465         {
466         case DT_NORMAL_TEXT:
467 
468             /* Normal text, insert char into line buffer */
469 
470             Gbl_CurrentLineBuffer[i] = c;
471             switch (c)
472             {
473             case '/':
474                 State = DT_START_COMMENT;
475                 break;
476 
477             case '"':
478                 State = DT_START_QUOTED_STRING;
479                 LineNotAllBlanks = TRUE;
480                 i++;
481                 break;
482 
483             case '\\':
484                 /*
485                  * The continuation char MUST be last char on this line.
486                  * Otherwise, it will be assumed to be a valid ASL char.
487                  */
488                 State = DT_MERGE_LINES;
489                 break;
490 
491             case '\n':
492                 CurrentLineOffset = Gbl_NextLineOffset;
493                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
494                 Gbl_CurrentLineNumber++;
495 
496                 /*
497                  * Exit if line is complete. Ignore empty lines (only \n)
498                  * or lines that contain nothing but blanks.
499                  */
500                 if ((i != 0) && LineNotAllBlanks)
501                 {
502                     if ((i + 1) >= Gbl_LineBufferSize)
503                     {
504                         UtExpandLineBuffers ();
505                     }
506 
507                     Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
508                     return (CurrentLineOffset);
509                 }
510 
511                 /* Toss this line and start a new one */
512 
513                 i = 0;
514                 LineNotAllBlanks = FALSE;
515                 break;
516 
517             default:
518                 if (c != ' ')
519                 {
520                     LineNotAllBlanks = TRUE;
521                 }
522 
523                 i++;
524                 break;
525             }
526             break;
527 
528         case DT_START_QUOTED_STRING:
529 
530             /* Insert raw chars until end of quoted string */
531 
532             Gbl_CurrentLineBuffer[i] = c;
533             i++;
534 
535             switch (c)
536             {
537             case '"':
538                 State = DT_NORMAL_TEXT;
539                 break;
540 
541             case '\\':
542                 State = DT_ESCAPE_SEQUENCE;
543                 break;
544 
545             case '\n':
546                 AcpiOsPrintf ("ERROR at line %u: Unterminated quoted string\n",
547                     Gbl_CurrentLineNumber++);
548                 State = DT_NORMAL_TEXT;
549                 break;
550 
551             default:    /* Get next character */
552                 break;
553             }
554             break;
555 
556         case DT_ESCAPE_SEQUENCE:
557 
558             /* Just copy the escaped character. TBD: sufficient for table compiler? */
559 
560             Gbl_CurrentLineBuffer[i] = c;
561             i++;
562             State = DT_START_QUOTED_STRING;
563             break;
564 
565         case DT_START_COMMENT:
566 
567             /* Open comment if this character is an asterisk or slash */
568 
569             switch (c)
570             {
571             case '*':
572                 State = DT_SLASH_ASTERISK_COMMENT;
573                 break;
574 
575             case '/':
576                 State = DT_SLASH_SLASH_COMMENT;
577                 break;
578 
579             default:    /* Not a comment */
580                 i++;    /* Save the preceeding slash */
581                 if (i >= Gbl_LineBufferSize)
582                 {
583                     UtExpandLineBuffers ();
584                 }
585 
586                 Gbl_CurrentLineBuffer[i] = c;
587                 i++;
588                 State = DT_NORMAL_TEXT;
589                 break;
590             }
591             break;
592 
593         case DT_SLASH_ASTERISK_COMMENT:
594 
595             /* Ignore chars until an asterisk-slash is found */
596 
597             switch (c)
598             {
599             case '\n':
600                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
601                 Gbl_CurrentLineNumber++;
602                 break;
603 
604             case '*':
605                 State = DT_END_COMMENT;
606                 break;
607 
608             default:
609                 break;
610             }
611             break;
612 
613         case DT_SLASH_SLASH_COMMENT:
614 
615             /* Ignore chars until end-of-line */
616 
617             if (c == '\n')
618             {
619                 /* We will exit via the NORMAL_TEXT path */
620 
621                 ungetc (c, Handle);
622                 State = DT_NORMAL_TEXT;
623             }
624             break;
625 
626         case DT_END_COMMENT:
627 
628             /* End comment if this char is a slash */
629 
630             switch (c)
631             {
632             case '/':
633                 State = DT_NORMAL_TEXT;
634                 break;
635 
636             case '\n':
637                 CurrentLineOffset = Gbl_NextLineOffset;
638                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
639                 Gbl_CurrentLineNumber++;
640                 break;
641 
642             case '*':
643                 /* Consume all adjacent asterisks */
644                 break;
645 
646             default:
647                 State = DT_SLASH_ASTERISK_COMMENT;
648                 break;
649             }
650             break;
651 
652         case DT_MERGE_LINES:
653 
654             if (c != '\n')
655             {
656                 /*
657                  * This is not a continuation backslash, it is a normal
658                  * normal ASL backslash - for example: Scope(\_SB_)
659                  */
660                 i++; /* Keep the backslash that is already in the buffer */
661 
662                 ungetc (c, Handle);
663                 State = DT_NORMAL_TEXT;
664             }
665             else
666             {
667                 /*
668                  * This is a continuation line -- a backlash followed
669                  * immediately by a newline. Insert a space between the
670                  * lines (overwrite the backslash)
671                  */
672                 Gbl_CurrentLineBuffer[i] = ' ';
673                 i++;
674 
675                 /* Ignore newline, this will merge the lines */
676 
677                 CurrentLineOffset = Gbl_NextLineOffset;
678                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
679                 Gbl_CurrentLineNumber++;
680                 State = DT_NORMAL_TEXT;
681             }
682             break;
683 
684         default:
685             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
686             return (ASL_EOF);
687         }
688     }
689 }
690 
691 
692 /******************************************************************************
693  *
694  * FUNCTION:    DtScanFile
695  *
696  * PARAMETERS:  Handle              - Open file handle for the source file
697  *
698  * RETURN:      Pointer to start of the constructed parse tree.
699  *
700  * DESCRIPTION: Scan source file, link all field names and values
701  *              to the global parse tree: Gbl_FieldList
702  *
703  *****************************************************************************/
704 
705 DT_FIELD *
706 DtScanFile (
707     FILE                    *Handle)
708 {
709     ACPI_STATUS             Status;
710     UINT32                  Offset;
711     DT_FIELD                *Next;
712 
713 
714     ACPI_FUNCTION_NAME (DtScanFile);
715 
716 
717     /* Get the file size */
718 
719     Gbl_InputByteCount = DtGetFileSize (Handle);
720 
721     Gbl_CurrentLineNumber = 0;
722     Gbl_CurrentLineOffset = 0;
723     Gbl_NextLineOffset = 0;
724 
725     /* Scan line-by-line */
726 
727     while ((Offset = DtGetNextLine (Handle)) != ASL_EOF)
728     {
729         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
730             Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
731 
732         Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset);
733         if (Status == AE_NOT_FOUND)
734         {
735             break;
736         }
737     }
738 
739     /* Dump the parse tree if debug enabled */
740 
741     if (Gbl_DebugFlag)
742     {
743         Next = Gbl_FieldList;
744         DbgPrint (ASL_DEBUG_OUTPUT, "Tree:  %32s %32s %8s %8s %8s %8s %8s %8s\n\n",
745             "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags");
746 
747         while (Next)
748         {
749             DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n",
750                 Next->Name,
751                 Next->Value,
752                 Next->Line,
753                 Next->ByteOffset,
754                 Next->NameColumn,
755                 Next->Column,
756                 Next->TableOffset,
757                 Next->Flags);
758 
759             Next = Next->Next;
760         }
761     }
762 
763     return (Gbl_FieldList);
764 }
765 
766 
767 /*
768  * Output functions
769  */
770 
771 /******************************************************************************
772  *
773  * FUNCTION:    DtWriteBinary
774  *
775  * PARAMETERS:  DT_WALK_CALLBACK
776  *
777  * RETURN:      Status
778  *
779  * DESCRIPTION: Write one subtable of a binary ACPI table
780  *
781  *****************************************************************************/
782 
783 static void
784 DtWriteBinary (
785     DT_SUBTABLE             *Subtable,
786     void                    *Context,
787     void                    *ReturnValue)
788 {
789 
790     FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
791 }
792 
793 
794 /******************************************************************************
795  *
796  * FUNCTION:    DtOutputBinary
797  *
798  * PARAMETERS:
799  *
800  * RETURN:      Status
801  *
802  * DESCRIPTION: Write entire binary ACPI table (result of compilation)
803  *
804  *****************************************************************************/
805 
806 void
807 DtOutputBinary (
808     DT_SUBTABLE             *RootTable)
809 {
810 
811     if (!RootTable)
812     {
813         return;
814     }
815 
816     /* Walk the entire parse tree, emitting the binary data */
817 
818     DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
819     Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
820 }
821 
822 
823 /*
824  * Listing support
825  */
826 
827 /******************************************************************************
828  *
829  * FUNCTION:    DtDumpBuffer
830  *
831  * PARAMETERS:  FileID              - Where to write buffer data
832  *              Buffer              - Buffer to dump
833  *              Offset              - Offset in current table
834  *              Length              - Buffer Length
835  *
836  * RETURN:      None
837  *
838  * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
839  *
840  * TBD: merge dump buffer routines
841  *
842  *****************************************************************************/
843 
844 static void
845 DtDumpBuffer (
846     UINT32                  FileId,
847     UINT8                   *Buffer,
848     UINT32                  Offset,
849     UINT32                  Length)
850 {
851     UINT32                  i;
852     UINT32                  j;
853     UINT8                   BufChar;
854 
855 
856     FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ",
857         Offset, Offset, Length);
858 
859     i = 0;
860     while (i < Length)
861     {
862         if (i >= 16)
863         {
864             FlPrintFile (FileId, "%24s", "");
865         }
866 
867         /* Print 16 hex chars */
868 
869         for (j = 0; j < 16;)
870         {
871             if (i + j >= Length)
872             {
873                 /* Dump fill spaces */
874 
875                 FlPrintFile (FileId, "   ");
876                 j++;
877                 continue;
878             }
879 
880             FlPrintFile (FileId, "%02X ", Buffer[i+j]);
881             j++;
882         }
883 
884         FlPrintFile (FileId, " ");
885         for (j = 0; j < 16; j++)
886         {
887             if (i + j >= Length)
888             {
889                 FlPrintFile (FileId, "\n\n");
890                 return;
891             }
892 
893             BufChar = Buffer[(ACPI_SIZE) i + j];
894             if (ACPI_IS_PRINT (BufChar))
895             {
896                 FlPrintFile (FileId, "%c", BufChar);
897             }
898             else
899             {
900                 FlPrintFile (FileId, ".");
901             }
902         }
903 
904         /* Done with that line. */
905 
906         FlPrintFile (FileId, "\n");
907         i += 16;
908     }
909 
910     FlPrintFile (FileId, "\n\n");
911 }
912 
913 
914 /******************************************************************************
915  *
916  * FUNCTION:    DtWriteFieldToListing
917  *
918  * PARAMETERS:  Buffer              - Contains the compiled data
919  *              Field               - Field node for the input line
920  *              Length              - Length of the output data
921  *
922  * RETURN:      None
923  *
924  * DESCRIPTION: Write one field to the listing file (if listing is enabled).
925  *
926  *****************************************************************************/
927 
928 void
929 DtWriteFieldToListing (
930     UINT8                   *Buffer,
931     DT_FIELD                *Field,
932     UINT32                  Length)
933 {
934     UINT8                   FileByte;
935 
936 
937     if (!Gbl_ListingFlag || !Field)
938     {
939         return;
940     }
941 
942     /* Dump the original source line */
943 
944     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input:  ");
945     FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
946 
947     while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
948     {
949         FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
950         if (FileByte == '\n')
951         {
952             break;
953         }
954     }
955 
956     /* Dump the line as parsed and represented internally */
957 
958     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s",
959         Field->Column-4, Field->Name, Field->Value);
960 
961     if (strlen (Field->Value) > 64)
962     {
963         FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n",
964             strlen (Field->Value));
965     }
966     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
967 
968     /* Dump the hex data that will be output for this field */
969 
970     DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
971 }
972 
973 
974 /******************************************************************************
975  *
976  * FUNCTION:    DtWriteTableToListing
977  *
978  * PARAMETERS:  None
979  *
980  * RETURN:      None
981  *
982  * DESCRIPTION: Write the entire compiled table to the listing file
983  *              in hex format
984  *
985  *****************************************************************************/
986 
987 void
988 DtWriteTableToListing (
989     void)
990 {
991     UINT8                   *Buffer;
992 
993 
994     if (!Gbl_ListingFlag)
995     {
996         return;
997     }
998 
999     /* Read the entire table from the output file */
1000 
1001     Buffer = UtLocalCalloc (Gbl_TableLength);
1002     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1003     FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
1004 
1005     /* Dump the raw table data */
1006 
1007     AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
1008 
1009     AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
1010         ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
1011     AcpiUtDumpBuffer2 (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY);
1012 
1013     AcpiOsRedirectOutput (stdout);
1014 }
1015