xref: /freebsd/sys/contrib/dev/acpica/compiler/dtio.c (revision 8fc257994d0ce2396196d7a06d50d20c8015f4b7)
1 /******************************************************************************
2  *
3  * Module Name: dtio.c - File I/O support for data table compiler
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights.  You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code.  No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision.  In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change.  Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee.  Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution.  In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government.  In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #define __DTIO_C__
117 
118 #include <contrib/dev/acpica/compiler/aslcompiler.h>
119 #include <contrib/dev/acpica/compiler/dtcompiler.h>
120 
121 #define _COMPONENT          DT_COMPILER
122         ACPI_MODULE_NAME    ("dtio")
123 
124 
125 /* Local prototypes */
126 
127 static char *
128 DtTrim (
129     char                    *String);
130 
131 static void
132 DtLinkField (
133     DT_FIELD                *Field);
134 
135 static void
136 DtParseLine (
137     char                    *LineBuffer,
138     UINT32                  Line,
139     UINT32                  Offset);
140 
141 static UINT32
142 DtGetNextLine (
143     FILE                    *Handle);
144 
145 static void
146 DtWriteBinary (
147     DT_SUBTABLE             *Subtable,
148     void                    *Context,
149     void                    *ReturnValue);
150 
151 
152 /* States for DtGetNextLine */
153 
154 #define DT_NORMAL_TEXT              0
155 #define DT_START_QUOTED_STRING      1
156 #define DT_START_COMMENT            2
157 #define DT_SLASH_ASTERISK_COMMENT   3
158 #define DT_SLASH_SLASH_COMMENT      4
159 #define DT_END_COMMENT              5
160 
161 UINT32  Gbl_NextLineOffset;
162 
163 
164 /******************************************************************************
165  *
166  * FUNCTION:    DtTrim
167  *
168  * PARAMETERS:  String              - Current source code line to trim
169  *
170  * RETURN:      Trimmed line. Must be freed by caller.
171  *
172  * DESCRIPTION: Trim left and right spaces
173  *
174  *****************************************************************************/
175 
176 static char *
177 DtTrim (
178     char                    *String)
179 {
180     char                    *Start;
181     char                    *End;
182     char                    *ReturnString;
183     ACPI_SIZE               Length;
184 
185 
186     /* Skip lines that start with a space */
187 
188     if (!ACPI_STRCMP (String, " "))
189     {
190         ReturnString = UtLocalCalloc (1);
191         return (ReturnString);
192     }
193 
194     /* Setup pointers to start and end of input string */
195 
196     Start = String;
197     End = String + ACPI_STRLEN (String) - 1;
198 
199     /* Find first non-whitespace character */
200 
201     while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
202     {
203         Start++;
204     }
205 
206     /* Find last non-space character */
207 
208     while (End >= Start)
209     {
210         if (*End == '\r' || *End == '\n')
211         {
212             End--;
213             continue;
214         }
215 
216         if (*End != ' ')
217         {
218             break;
219         }
220 
221         End--;
222     }
223 
224     /* Remove any quotes around the string */
225 
226     if (*Start == '\"')
227     {
228         Start++;
229     }
230     if (*End == '\"')
231     {
232         End--;
233     }
234 
235     /* Create the trimmed return string */
236 
237     Length = ACPI_PTR_DIFF (End, Start) + 1;
238     ReturnString = UtLocalCalloc (Length + 1);
239     if (ACPI_STRLEN (Start))
240     {
241         ACPI_STRNCPY (ReturnString, Start, Length);
242     }
243 
244     ReturnString[Length] = 0;
245     return (ReturnString);
246 }
247 
248 
249 /******************************************************************************
250  *
251  * FUNCTION:    DtLinkField
252  *
253  * PARAMETERS:  Field               - New field object to link
254  *
255  * RETURN:      None
256  *
257  * DESCRIPTION: Link one field name and value to the list
258  *
259  *****************************************************************************/
260 
261 static void
262 DtLinkField (
263     DT_FIELD                *Field)
264 {
265     DT_FIELD                *Prev;
266     DT_FIELD                *Next;
267 
268 
269     Prev = Next = Gbl_FieldList;
270 
271     while (Next)
272     {
273         Prev = Next;
274         Next = Next->Next;
275     }
276 
277     if (Prev)
278     {
279         Prev->Next = Field;
280     }
281     else
282     {
283         Gbl_FieldList = Field;
284     }
285 }
286 
287 
288 /******************************************************************************
289  *
290  * FUNCTION:    DtParseLine
291  *
292  * PARAMETERS:  LineBuffer          - Current source code line
293  *              Line                - Current line number in the source
294  *              Offset              - Current byte offset of the line
295  *
296  * RETURN:      None
297  *
298  * DESCRIPTION: Parse one source line
299  *
300  *****************************************************************************/
301 
302 static void
303 DtParseLine (
304     char                    *LineBuffer,
305     UINT32                  Line,
306     UINT32                  Offset)
307 {
308     char                    *Start;
309     char                    *End;
310     char                    *TmpName;
311     char                    *TmpValue;
312     char                    *Name;
313     char                    *Value;
314     char                    *Colon;
315     UINT32                  Length;
316     DT_FIELD                *Field;
317     UINT32                  Column;
318     UINT32                  NameColumn;
319 
320 
321     if (!LineBuffer)
322     {
323         return;
324     }
325 
326     Colon = strchr (LineBuffer, ':');
327     if (!Colon || *(Colon - 1) != ' ')
328     {
329         return;
330     }
331 
332     Start = LineBuffer;
333     End = Colon;
334 
335     while (Start < Colon)
336     {
337         if (*Start == ' ')
338         {
339             Start++;
340             continue;
341         }
342 
343         /* Found left bracket, go to the right bracket */
344 
345         if (*Start == '[')
346         {
347             while (Start < Colon && *Start != ']')
348             {
349                 Start++;
350             }
351 
352             if (Start == Colon)
353             {
354                 MYDEBUG ("ERROR: right bracket reaches colon position\n");
355                 break;
356             }
357 
358             Start++;
359             continue;
360         }
361 
362         break;
363     }
364 
365     /*
366      * There are two column values. One for the field name,
367      * and one for the field value.
368      */
369     Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
370     NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
371 
372     Length = ACPI_PTR_DIFF (End, Start);
373 
374     TmpName = UtLocalCalloc (Length + 1);
375     ACPI_STRNCPY (TmpName, Start, Length);
376     Name = DtTrim (TmpName);
377     ACPI_FREE (TmpName);
378 
379     Start = End = (Colon + 1);
380 
381     while (*End)
382     {
383         /* Found left quotation, go to the right quotation and break */
384 
385         if (*End == '"')
386         {
387             End++;
388             while (*End && *End != '"')
389             {
390                 End++;
391             }
392 
393             End++;
394             break;
395         }
396 
397         if (*End == '(' ||
398             *End == '<' ||
399             *End == '/')
400         {
401             break;
402         }
403 
404         End++;
405     }
406 
407     Length = ACPI_PTR_DIFF (End, Start);
408     TmpValue = UtLocalCalloc (Length + 1);
409     ACPI_STRNCPY (TmpValue, Start, Length);
410     Value = DtTrim (TmpValue);
411     ACPI_FREE (TmpValue);
412 
413     if (Name && Value)
414     {
415         Field = UtLocalCalloc (sizeof (DT_FIELD));
416         Field->Name = Name;
417         Field->Value = Value;
418         Field->Line = Line;
419         Field->ByteOffset = Offset;
420         Field->NameColumn = NameColumn;
421         Field->Column = Column;
422 
423         DtLinkField (Field);
424     }
425 }
426 
427 
428 /******************************************************************************
429  *
430  * FUNCTION:    DtGetNextLine
431  *
432  * PARAMETERS:  Handle              - Open file handle for the source file
433  *
434  * RETURN:      Filled line buffer and offset of start-of-line (zero on EOF)
435  *
436  * DESCRIPTION: Get the next valid source line. Removes all comments.
437  *              Ignores empty lines.
438  *
439  * Handles both slash-asterisk and slash-slash comments.
440  * Also, quoted strings, but no escapes within.
441  *
442  * Line is returned in Gbl_CurrentLineBuffer.
443  * Line number in original file is returned in Gbl_CurrentLineNumber.
444  *
445  *****************************************************************************/
446 
447 static UINT32
448 DtGetNextLine (
449     FILE                    *Handle)
450 {
451     UINT32                  State = DT_NORMAL_TEXT;
452     UINT32                  CurrentLineOffset;
453     UINT32                  i;
454     char                    c;
455 
456 
457     for (i = 0; i < ASL_LINE_BUFFER_SIZE;)
458     {
459         c = (char) getc (Handle);
460         if (c == EOF)
461         {
462             return (0);
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] = c;
472             switch (c)
473             {
474             case '/':
475                 State = DT_START_COMMENT;
476                 break;
477 
478             case '"':
479                 State = DT_START_QUOTED_STRING;
480                 i++;
481                 break;
482 
483             case '\n':
484                 CurrentLineOffset = Gbl_NextLineOffset;
485                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
486                 Gbl_CurrentLineNumber++;
487 
488                 /* Exit if line is complete. Ignore blank lines */
489 
490                 if (i != 0)
491                 {
492                     Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate line */
493                     return (CurrentLineOffset);
494                 }
495                 break;
496 
497             default:
498                 i++;
499                 break;
500             }
501             break;
502 
503         case DT_START_QUOTED_STRING:
504 
505             /* Insert raw chars until end of quoted string */
506 
507             Gbl_CurrentLineBuffer[i] = c;
508             i++;
509 
510             if (c == '"')
511             {
512                 State = DT_NORMAL_TEXT;
513             }
514             break;
515 
516         case DT_START_COMMENT:
517 
518             /* Open comment if this character is an asterisk or slash */
519 
520             switch (c)
521             {
522             case '*':
523                 State = DT_SLASH_ASTERISK_COMMENT;
524                 break;
525 
526             case '/':
527                 State = DT_SLASH_SLASH_COMMENT;
528                 break;
529 
530             default:    /* Not a comment */
531                 i++;    /* Save the preceeding slash */
532                 Gbl_CurrentLineBuffer[i] = c;
533                 i++;
534                 State = DT_NORMAL_TEXT;
535                 break;
536             }
537             break;
538 
539         case DT_SLASH_ASTERISK_COMMENT:
540 
541             /* Ignore chars until an asterisk-slash is found */
542 
543             switch (c)
544             {
545             case '\n':
546                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
547                 Gbl_CurrentLineNumber++;
548                 break;
549 
550             case '*':
551                 State = DT_END_COMMENT;
552                 break;
553 
554             default:
555                 break;
556             }
557             break;
558 
559         case DT_SLASH_SLASH_COMMENT:
560 
561             /* Ignore chars until end-of-line */
562 
563             if (c == '\n')
564             {
565                 /* We will exit via the NORMAL_TEXT path */
566 
567                 ungetc (c, Handle);
568                 State = DT_NORMAL_TEXT;
569             }
570             break;
571 
572         case DT_END_COMMENT:
573 
574             /* End comment if this char is a slash */
575 
576             switch (c)
577             {
578             case '/':
579                 State = DT_NORMAL_TEXT;
580                 break;
581 
582             default:
583                 State = DT_SLASH_ASTERISK_COMMENT;
584                 break;
585             }
586             break;
587 
588         default:
589             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
590             return (0);
591         }
592     }
593 
594     printf ("ERROR - Input line is too long (max %u)\n", ASL_LINE_BUFFER_SIZE);
595     return (0);
596 }
597 
598 
599 /******************************************************************************
600  *
601  * FUNCTION:    DtScanFile
602  *
603  * PARAMETERS:  Handle              - Open file handle for the source file
604  *
605  * RETURN:      Pointer to start of the constructed parse tree.
606  *
607  * DESCRIPTION: Scan source file, link all field names and values
608  *              to the global parse tree: Gbl_FieldList
609  *
610  *****************************************************************************/
611 
612 DT_FIELD *
613 DtScanFile (
614     FILE                    *Handle)
615 {
616     UINT32                  Offset;
617 
618 
619     ACPI_FUNCTION_NAME (DtScanFile);
620 
621 
622     /* Get the file size */
623 
624     Gbl_InputByteCount = DtGetFileSize (Handle);
625 
626     Gbl_CurrentLineNumber = 0;
627     Gbl_CurrentLineOffset = 0;
628     Gbl_NextLineOffset = 0;
629 
630     /* Scan line-by-line */
631 
632     while ((Offset = DtGetNextLine (Handle)))
633     {
634         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
635             Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
636 
637         DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset);
638     }
639 
640     return (Gbl_FieldList);
641 }
642 
643 
644 /*
645  * Output functions
646  */
647 
648 
649 /******************************************************************************
650  *
651  * FUNCTION:    DtWriteBinary
652  *
653  * PARAMETERS:  DT_WALK_CALLBACK
654  *
655  * RETURN:      Status
656  *
657  * DESCRIPTION: Write one subtable of a binary ACPI table
658  *
659  *****************************************************************************/
660 
661 static void
662 DtWriteBinary (
663     DT_SUBTABLE             *Subtable,
664     void                    *Context,
665     void                    *ReturnValue)
666 {
667 
668     FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
669 }
670 
671 
672 /******************************************************************************
673  *
674  * FUNCTION:    DtOutputBinary
675  *
676  * PARAMETERS:
677  *
678  * RETURN:      Status
679  *
680  * DESCRIPTION: Write entire binary ACPI table (result of compilation)
681  *
682  *****************************************************************************/
683 
684 void
685 DtOutputBinary (
686     DT_SUBTABLE             *RootTable)
687 {
688 
689     if (!RootTable)
690     {
691         return;
692     }
693 
694     /* Walk the entire parse tree, emitting the binary data */
695 
696     DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
697     Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
698 }
699