1 /******************************************************************************
2  *
3  * Module Name: aslfiles - File support functions
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2019, 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  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "aslcompiler.h"
153 #include "acapps.h"
154 
155 #define _COMPONENT          ACPI_COMPILER
156         ACPI_MODULE_NAME    ("aslfiles")
157 
158 /* Local prototypes */
159 
160 static FILE *
161 FlOpenIncludeWithPrefix (
162     char                    *PrefixDir,
163     ACPI_PARSE_OBJECT       *Op,
164     char                    *Filename);
165 
166 static BOOLEAN
167 FlInputFileExists (
168     char                    *InputFilename);
169 
170 #ifdef ACPI_OBSOLETE_FUNCTIONS
171 ACPI_STATUS
172 FlParseInputPathname (
173     char                    *InputFilename);
174 #endif
175 
176 
177 /*******************************************************************************
178  *
179  * FUNCTION:    FlInitOneFile
180  *
181  * PARAMETERS:  InputFilename       - The user-specified ASL source file to be
182  *                                    compiled
183  *
184  * RETURN:      Status
185  *
186  * DESCRIPTION: Initialize global file structure for one input file. This file
187  *              structure contains references to input, output, debugging, and
188  *              other miscellaneous files that are associated for a single
189  *              input ASL file.
190  *
191  ******************************************************************************/
192 
193 ACPI_STATUS
194 FlInitOneFile (
195     char                    *InputFilename)
196 {
197     UINT32                  i;
198     ASL_GLOBAL_FILE_NODE    *NewFileNode;
199 
200 
201     if (FlInputFileExists (InputFilename))
202     {
203         AslError (ASL_ERROR, ASL_MSG_DUPLICATE_INPUT_FILE, NULL, InputFilename);
204         return (AE_ALREADY_EXISTS);
205     }
206 
207     NewFileNode = ACPI_CAST_PTR (ASL_GLOBAL_FILE_NODE,
208         UtLocalCacheCalloc (sizeof (ASL_GLOBAL_FILE_NODE)));
209 
210     if (!NewFileNode)
211     {
212         AslError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, NULL, NULL);
213         return (AE_NO_MEMORY);
214     }
215 
216     NewFileNode->ParserErrorDetected = FALSE;
217     NewFileNode->Next = AslGbl_FilesList;
218 
219     AslGbl_FilesList = NewFileNode;
220     AslGbl_Files = NewFileNode->Files;
221 
222     for (i = 0; i < ASL_NUM_FILES; i++)
223     {
224         AslGbl_Files[i].Handle = NULL;
225         AslGbl_Files[i].Filename = NULL;
226     }
227 
228     AslGbl_Files[ASL_FILE_STDOUT].Handle   = stdout;
229     AslGbl_Files[ASL_FILE_STDOUT].Filename = "STDOUT";
230 
231     if (AslGbl_VerboseErrors)
232     {
233         AslGbl_Files[ASL_FILE_STDERR].Handle = stderr;
234     }
235     else
236     {
237         AslGbl_Files[ASL_FILE_STDERR].Handle = stdout;
238     }
239 
240     AslGbl_Files[ASL_FILE_STDERR].Filename = "STDERR";
241     return (AE_OK);
242 }
243 
244 
245 /*******************************************************************************
246  *
247  * FUNCTION:    FlInputFileExists
248  *
249  * PARAMETERS:  Filename       - File name to be searched
250  *
251  * RETURN:      Status
252  *
253  * DESCRIPTION: Returns true if the file name already exists.
254  *
255  ******************************************************************************/
256 
257 static BOOLEAN
258 FlInputFileExists (
259     char                    *Filename)
260 {
261     ASL_GLOBAL_FILE_NODE    *Current = AslGbl_FilesList;
262 
263 
264     while (Current)
265     {
266         if (!strcmp (Filename, Current->Files[ASL_FILE_INPUT].Filename))
267         {
268             return (TRUE);
269         }
270 
271         Current = Current->Next;
272     }
273 
274     return (FALSE);
275 }
276 
277 
278 /*******************************************************************************
279  *
280  * FUNCTION:    FlSwitchFileSet
281  *
282  * PARAMETERS:  Op        - Parse node for the LINE asl statement
283  *
284  * RETURN:      None.
285  *
286  * DESCRIPTION: Set the current line number
287  *
288  ******************************************************************************/
289 
290 ASL_FILE_SWITCH_STATUS
291 FlSwitchFileSet (
292     char                    *InputFilename)
293 {
294     ASL_GLOBAL_FILE_NODE    *Current = AslGbl_FilesList;
295     char                    *PrevFilename = Current->Files[ASL_FILE_INPUT].Filename;
296 
297 
298     while (Current)
299     {
300         if (!strcmp(Current->Files[ASL_FILE_INPUT].Filename, InputFilename))
301         {
302             AslGbl_Files = Current->Files;
303             AslGbl_TableSignature = Current->TableSignature;
304             AslGbl_TableId = Current->TableId;
305 
306             if (!strcmp (InputFilename, PrevFilename))
307             {
308                 return (SWITCH_TO_SAME_FILE);
309             }
310             else
311             {
312                 return (SWITCH_TO_DIFFERENT_FILE);
313             }
314         }
315 
316         Current = Current->Next;
317     }
318 
319     return (FILE_NOT_FOUND);
320 }
321 
322 
323 /*******************************************************************************
324  *
325  * FUNCTION:    FlGetFileHandle
326  *
327  * PARAMETERS:  OutFileId       - denotes file type of output handle
328  *              InFileId        - denotes file type of the input Filename
329  *              Filename
330  *
331  * RETURN:      File handle
332  *
333  * DESCRIPTION: Get the file handle for a particular filename/FileId. This
334  *              function also allows the caller to specify the file Id of the
335  *              desired type.
336  *
337  ******************************************************************************/
338 
339 FILE *
340 FlGetFileHandle (
341     UINT32                  OutFileId,
342     UINT32                  InFileId,
343     char                    *Filename)
344 {
345     ASL_GLOBAL_FILE_NODE    *Current = AslGbl_FilesList;
346 
347 
348     if (!Filename)
349     {
350         return (NULL);
351     }
352 
353     while (Current)
354     {
355         if (!strcmp (Current->Files[InFileId].Filename, Filename))
356         {
357             return (Current->Files[OutFileId].Handle);
358         }
359 
360         Current = Current->Next;
361     }
362 
363     return (NULL);
364 }
365 
366 
367 /*******************************************************************************
368  *
369  * FUNCTION:    FlGetFileNode
370  *
371  * PARAMETERS:  FileId        - File type (ID) of the input Filename
372  *              Filename      - File to search for
373  *
374  * RETURN:      A global file node
375  *
376  * DESCRIPTION: Get the file node for a particular filename/FileId.
377  *
378  ******************************************************************************/
379 
380 ASL_GLOBAL_FILE_NODE *
381 FlGetFileNode (
382     UINT32                  FileId,
383     char                    *Filename)
384 {
385     ASL_GLOBAL_FILE_NODE    *Current = AslGbl_FilesList;
386 
387 
388     if (!Filename)
389     {
390         return (NULL);
391     }
392 
393     while (Current)
394     {
395         if (!strcmp (Current->Files[FileId].Filename, Filename))
396         {
397             return (Current);
398         }
399 
400         Current = Current->Next;
401     }
402 
403     return (NULL);
404 }
405 
406 
407 /*******************************************************************************
408  *
409  * FUNCTION:    FlGetCurrentFileNode
410  *
411  * PARAMETERS:  None
412  *
413  * RETURN:      Global file node
414  *
415  * DESCRIPTION: Get the current input file node
416  *
417  ******************************************************************************/
418 
419 ASL_GLOBAL_FILE_NODE *
420 FlGetCurrentFileNode (
421     void)
422 {
423     return (FlGetFileNode (
424         ASL_FILE_INPUT,AslGbl_Files[ASL_FILE_INPUT].Filename));
425 }
426 
427 
428 /*******************************************************************************
429  *
430  * FUNCTION:    FlSetLineNumber
431  *
432  * PARAMETERS:  Op        - Parse node for the LINE asl statement
433  *
434  * RETURN:      None.
435  *
436  * DESCRIPTION: Set the current line number
437  *
438  ******************************************************************************/
439 
440 void
441 FlSetLineNumber (
442     UINT32                  LineNumber)
443 {
444 
445     DbgPrint (ASL_PARSE_OUTPUT, "\n#line: New line number %u (old %u)\n",
446          LineNumber, AslGbl_LogicalLineNumber);
447 
448     AslGbl_CurrentLineNumber = LineNumber;
449 }
450 
451 
452 /*******************************************************************************
453  *
454  * FUNCTION:    FlSetFilename
455  *
456  * PARAMETERS:  Op        - Parse node for the LINE asl statement
457  *
458  * RETURN:      None.
459  *
460  * DESCRIPTION: Set the current filename
461  *
462  ******************************************************************************/
463 
464 void
465 FlSetFilename (
466     char                    *Filename)
467 {
468 
469     DbgPrint (ASL_PARSE_OUTPUT, "\n#line: New filename %s (old %s)\n",
470          Filename, AslGbl_Files[ASL_FILE_INPUT].Filename);
471 
472     /* No need to free any existing filename */
473 
474     AslGbl_Files[ASL_FILE_INPUT].Filename = Filename;
475 }
476 
477 
478 /*******************************************************************************
479  *
480  * FUNCTION:    FlAddIncludeDirectory
481  *
482  * PARAMETERS:  Dir             - Directory pathname string
483  *
484  * RETURN:      None
485  *
486  * DESCRIPTION: Add a directory the list of include prefix directories.
487  *
488  ******************************************************************************/
489 
490 void
491 FlAddIncludeDirectory (
492     char                    *Dir)
493 {
494     ASL_INCLUDE_DIR         *NewDir;
495     ASL_INCLUDE_DIR         *NextDir;
496     ASL_INCLUDE_DIR         *PrevDir = NULL;
497     UINT32                  NeedsSeparator = 0;
498     size_t                  DirLength;
499 
500 
501     DirLength = strlen (Dir);
502     if (!DirLength)
503     {
504         return;
505     }
506 
507     /* Make sure that the pathname ends with a path separator */
508 
509     if ((Dir[DirLength-1] != '/') &&
510         (Dir[DirLength-1] != '\\'))
511     {
512         NeedsSeparator = 1;
513     }
514 
515     NewDir = ACPI_CAST_PTR (ASL_INCLUDE_DIR,
516         UtLocalCacheCalloc (sizeof (ASL_INCLUDE_DIR)));
517     NewDir->Dir = UtLocalCacheCalloc (DirLength + 1 + NeedsSeparator);
518     strcpy (NewDir->Dir, Dir);
519     if (NeedsSeparator)
520     {
521         strcat (NewDir->Dir, "/");
522     }
523 
524     /*
525      * Preserve command line ordering of -I options by adding new elements
526      * at the end of the list
527      */
528     NextDir = AslGbl_IncludeDirList;
529     while (NextDir)
530     {
531         PrevDir = NextDir;
532         NextDir = NextDir->Next;
533     }
534 
535     if (PrevDir)
536     {
537         PrevDir->Next = NewDir;
538     }
539     else
540     {
541         AslGbl_IncludeDirList = NewDir;
542     }
543 }
544 
545 
546 /*******************************************************************************
547  *
548  * FUNCTION:    FlMergePathnames
549  *
550  * PARAMETERS:  PrefixDir       - Prefix directory pathname. Can be NULL or
551  *                                a zero length string.
552  *              FilePathname    - The include filename from the source ASL.
553  *
554  * RETURN:      Merged pathname string
555  *
556  * DESCRIPTION: Merge two pathnames that (probably) have common elements, to
557  *              arrive at a minimal length string. Merge can occur if the
558  *              FilePathname is relative to the PrefixDir.
559  *
560  ******************************************************************************/
561 
562 char *
563 FlMergePathnames (
564     char                    *PrefixDir,
565     char                    *FilePathname)
566 {
567     char                    *CommonPath;
568     char                    *Pathname;
569     char                    *LastElement;
570 
571 
572     DbgPrint (ASL_PARSE_OUTPUT, "Include: Prefix path - \"%s\"\n"
573         "Include: FilePathname - \"%s\"\n",
574          PrefixDir, FilePathname);
575 
576     /*
577      * If there is no prefix directory or if the file pathname is absolute,
578      * just return the original file pathname
579      */
580     if (!PrefixDir || (!*PrefixDir) ||
581         (*FilePathname == '/') ||
582          (FilePathname[1] == ':'))
583     {
584         Pathname = UtLocalCacheCalloc (strlen (FilePathname) + 1);
585         strcpy (Pathname, FilePathname);
586         goto ConvertBackslashes;
587     }
588 
589     /* Need a local copy of the prefix directory path */
590 
591     CommonPath = UtLocalCacheCalloc (strlen (PrefixDir) + 1);
592     strcpy (CommonPath, PrefixDir);
593 
594     /*
595      * Walk forward through the file path, and simultaneously backward
596      * through the prefix directory path until there are no more
597      * relative references at the start of the file path.
598      */
599     while (*FilePathname && (!strncmp (FilePathname, "../", 3)))
600     {
601         /* Remove last element of the prefix directory path */
602 
603         LastElement = strrchr (CommonPath, '/');
604         if (!LastElement)
605         {
606             goto ConcatenatePaths;
607         }
608 
609         *LastElement = 0;   /* Terminate CommonPath string */
610         FilePathname += 3;  /* Point to next path element */
611     }
612 
613     /*
614      * Remove the last element of the prefix directory path (it is the same as
615      * the first element of the file pathname), and build the final merged
616      * pathname.
617      */
618     LastElement = strrchr (CommonPath, '/');
619     if (LastElement)
620     {
621         *LastElement = 0;
622     }
623 
624     /* Build the final merged pathname */
625 
626 ConcatenatePaths:
627     Pathname = UtLocalCacheCalloc (
628         strlen (CommonPath) + strlen (FilePathname) + 2);
629     if (LastElement && *CommonPath)
630     {
631         strcpy (Pathname, CommonPath);
632         strcat (Pathname, "/");
633     }
634     strcat (Pathname, FilePathname);
635 
636     /* Convert all backslashes to normal slashes */
637 
638 ConvertBackslashes:
639     UtConvertBackslashes (Pathname);
640 
641     DbgPrint (ASL_PARSE_OUTPUT, "Include: Merged Pathname - \"%s\"\n",
642          Pathname);
643     return (Pathname);
644 }
645 
646 
647 /*******************************************************************************
648  *
649  * FUNCTION:    FlOpenIncludeWithPrefix
650  *
651  * PARAMETERS:  PrefixDir       - Prefix directory pathname. Can be a zero
652  *                                length string.
653  *              Filename        - The include filename from the source ASL.
654  *
655  * RETURN:      Valid file descriptor if successful. Null otherwise.
656  *
657  * DESCRIPTION: Open an include file and push it on the input file stack.
658  *
659  ******************************************************************************/
660 
661 static FILE *
662 FlOpenIncludeWithPrefix (
663     char                    *PrefixDir,
664     ACPI_PARSE_OBJECT       *Op,
665     char                    *Filename)
666 {
667     FILE                    *IncludeFile;
668     char                    *Pathname;
669     UINT32                  OriginalLineNumber;
670 
671 
672     /* Build the full pathname to the file */
673 
674     Pathname = FlMergePathnames (PrefixDir, Filename);
675 
676     DbgPrint (ASL_PARSE_OUTPUT, "Include: Opening file - \"%s\"\n\n",
677         Pathname);
678 
679     /* Attempt to open the file, push if successful */
680 
681     IncludeFile = fopen (Pathname, "r");
682     if (!IncludeFile)
683     {
684         return (NULL);
685     }
686 
687     /*
688      * Check the entire include file for any # preprocessor directives.
689      * This is because there may be some confusion between the #include
690      * preprocessor directive and the ASL Include statement. A file included
691      * by the ASL include cannot contain preprocessor directives because
692      * the preprocessor has already run by the time the ASL include is
693      * recognized (by the compiler, not the preprocessor.)
694      *
695      * Note: DtGetNextLine strips/ignores comments.
696      * Save current line number since DtGetNextLine modifies it.
697      */
698     AslGbl_CurrentLineNumber--;
699     OriginalLineNumber = AslGbl_CurrentLineNumber;
700 
701     while (DtGetNextLine (IncludeFile, DT_ALLOW_MULTILINE_QUOTES) != ASL_EOF)
702     {
703         if (AslGbl_CurrentLineBuffer[0] == '#')
704         {
705             AslError (ASL_ERROR, ASL_MSG_INCLUDE_FILE,
706                 Op, "use #include instead");
707         }
708     }
709 
710     AslGbl_CurrentLineNumber = OriginalLineNumber;
711 
712     /* Must seek back to the start of the file */
713 
714     fseek (IncludeFile, 0, SEEK_SET);
715 
716     /* Push the include file on the open input file stack */
717 
718     AslPushInputFileStack (IncludeFile, Pathname);
719     return (IncludeFile);
720 }
721 
722 
723 /*******************************************************************************
724  *
725  * FUNCTION:    FlOpenIncludeFile
726  *
727  * PARAMETERS:  Op        - Parse node for the INCLUDE ASL statement
728  *
729  * RETURN:      None.
730  *
731  * DESCRIPTION: Open an include file and push it on the input file stack.
732  *
733  ******************************************************************************/
734 
735 void
736 FlOpenIncludeFile (
737     ACPI_PARSE_OBJECT       *Op)
738 {
739     FILE                    *IncludeFile;
740     ASL_INCLUDE_DIR         *NextDir;
741 
742 
743     /* Op must be valid */
744 
745     if (!Op)
746     {
747         AslCommonError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN,
748             AslGbl_CurrentLineNumber, AslGbl_LogicalLineNumber,
749             AslGbl_InputByteCount, AslGbl_CurrentColumn,
750             AslGbl_Files[ASL_FILE_INPUT].Filename, " - Null parse node");
751 
752         return;
753     }
754 
755     /*
756      * Flush out the "include ()" statement on this line, start
757      * the actual include file on the next line
758      */
759     AslResetCurrentLineBuffer ();
760     FlPrintFile (ASL_FILE_SOURCE_OUTPUT, "\n");
761     AslGbl_CurrentLineOffset++;
762 
763 
764     /* Attempt to open the include file */
765 
766     /* If the file specifies an absolute path, just open it */
767 
768     if ((Op->Asl.Value.String[0] == '/')  ||
769         (Op->Asl.Value.String[0] == '\\') ||
770         (Op->Asl.Value.String[1] == ':'))
771     {
772         IncludeFile = FlOpenIncludeWithPrefix ("", Op, Op->Asl.Value.String);
773         if (!IncludeFile)
774         {
775             goto ErrorExit;
776         }
777         return;
778     }
779 
780     /*
781      * The include filename is not an absolute path.
782      *
783      * First, search for the file within the "local" directory -- meaning
784      * the same directory that contains the source file.
785      *
786      * Construct the file pathname from the global directory name.
787      */
788     IncludeFile = FlOpenIncludeWithPrefix (
789         AslGbl_DirectoryPath, Op, Op->Asl.Value.String);
790     if (IncludeFile)
791     {
792         return;
793     }
794 
795     /*
796      * Second, search for the file within the (possibly multiple) directories
797      * specified by the -I option on the command line.
798      */
799     NextDir = AslGbl_IncludeDirList;
800     while (NextDir)
801     {
802         IncludeFile = FlOpenIncludeWithPrefix (
803             NextDir->Dir, Op, Op->Asl.Value.String);
804         if (IncludeFile)
805         {
806             return;
807         }
808 
809         NextDir = NextDir->Next;
810     }
811 
812     /* We could not open the include file after trying very hard */
813 
814 ErrorExit:
815     sprintf (AslGbl_MsgBuffer, "%s, %s", Op->Asl.Value.String, strerror (errno));
816     AslError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, Op, AslGbl_MsgBuffer);
817 }
818 
819 
820 /*******************************************************************************
821  *
822  * FUNCTION:    FlOpenInputFile
823  *
824  * PARAMETERS:  InputFilename       - The user-specified ASL source file to be
825  *                                    compiled
826  *
827  * RETURN:      Status
828  *
829  * DESCRIPTION: Open the specified input file, and save the directory path to
830  *              the file so that include files can be opened in
831  *              the same directory.
832  *
833  ******************************************************************************/
834 
835 ACPI_STATUS
836 FlOpenInputFile (
837     char                    *InputFilename)
838 {
839 
840     /* Open the input ASL file, text mode */
841 
842     FlOpenFile (ASL_FILE_INPUT, InputFilename, "rt");
843     AslCompilerin = AslGbl_Files[ASL_FILE_INPUT].Handle;
844 
845     return (AE_OK);
846 }
847 
848 
849 /*******************************************************************************
850  *
851  * FUNCTION:    FlOpenAmlOutputFile
852  *
853  * PARAMETERS:  FilenamePrefix       - The user-specified ASL source file
854  *
855  * RETURN:      Status
856  *
857  * DESCRIPTION: Create the output filename (*.AML) and open the file. The file
858  *              is created in the same directory as the parent input file.
859  *
860  ******************************************************************************/
861 
862 ACPI_STATUS
863 FlOpenAmlOutputFile (
864     char                    *FilenamePrefix)
865 {
866     char                    *Filename;
867 
868 
869     /* Output filename usually comes from the ASL itself */
870 
871     Filename = AslGbl_Files[ASL_FILE_AML_OUTPUT].Filename;
872     if (!Filename)
873     {
874         /* Create the output AML filename */
875         if (!AcpiGbl_CaptureComments)
876         {
877             Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_AML_CODE);
878         }
879         else
880         {
881             Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_CONVERT_AML);
882         }
883         if (!Filename)
884         {
885             AslCommonError (ASL_ERROR, ASL_MSG_OUTPUT_FILENAME,
886                 0, 0, 0, 0, NULL, NULL);
887             return (AE_ERROR);
888         }
889 
890         AslGbl_Files[ASL_FILE_AML_OUTPUT].Filename = Filename;
891     }
892 
893     /* Open the output AML file in binary mode */
894 
895     FlOpenFile (ASL_FILE_AML_OUTPUT, Filename, "w+b");
896     return (AE_OK);
897 }
898 
899 
900 /*******************************************************************************
901  *
902  * FUNCTION:    FlOpenMiscOutputFiles
903  *
904  * PARAMETERS:  FilenamePrefix       - The user-specified ASL source file
905  *
906  * RETURN:      Status
907  *
908  * DESCRIPTION: Create and open the various output files needed, depending on
909  *              the command line options
910  *
911  ******************************************************************************/
912 
913 ACPI_STATUS
914 FlOpenMiscOutputFiles (
915     char                    *FilenamePrefix)
916 {
917     char                    *Filename;
918 
919 
920      /* Create/Open a map file if requested */
921 
922     if (AslGbl_MapfileFlag)
923     {
924         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_MAP);
925         if (!Filename)
926         {
927             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
928                 0, 0, 0, 0, NULL, NULL);
929             return (AE_ERROR);
930         }
931 
932         /* Open the hex file, text mode (closed at compiler exit) */
933 
934         FlOpenFile (ASL_FILE_MAP_OUTPUT, Filename, "w+t");
935 
936         AslCompilerSignon (ASL_FILE_MAP_OUTPUT);
937         AslCompilerFileHeader (ASL_FILE_MAP_OUTPUT);
938     }
939 
940     /* All done for disassembler */
941 
942     if (AslGbl_FileType == ASL_INPUT_TYPE_BINARY_ACPI_TABLE)
943     {
944         return (AE_OK);
945     }
946 
947     /* Create/Open a hex output file if asked */
948 
949     if (AslGbl_HexOutputFlag)
950     {
951         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_HEX_DUMP);
952         if (!Filename)
953         {
954             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
955                 0, 0, 0, 0, NULL, NULL);
956             return (AE_ERROR);
957         }
958 
959         /* Open the hex file, text mode */
960 
961         FlOpenFile (ASL_FILE_HEX_OUTPUT, Filename, "w+t");
962 
963         AslCompilerSignon (ASL_FILE_HEX_OUTPUT);
964         AslCompilerFileHeader (ASL_FILE_HEX_OUTPUT);
965     }
966 
967     /* Create/Open a debug output file if asked */
968 
969     if (AslGbl_DebugFlag)
970     {
971         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_DEBUG);
972         if (!Filename)
973         {
974             AslCommonError (ASL_ERROR, ASL_MSG_DEBUG_FILENAME,
975                 0, 0, 0, 0, NULL, NULL);
976             return (AE_ERROR);
977         }
978 
979         /* Open the debug file as STDERR, text mode */
980 
981         AslGbl_Files[ASL_FILE_DEBUG_OUTPUT].Filename = Filename;
982         AslGbl_Files[ASL_FILE_DEBUG_OUTPUT].Handle =
983             freopen (Filename, "w+t", stderr);
984 
985         if (!AslGbl_Files[ASL_FILE_DEBUG_OUTPUT].Handle)
986         {
987             /*
988              * A problem with freopen is that on error, we no longer
989              * have stderr and cannot emit normal error messages.
990              * Emit error to stdout, close files, and exit.
991              */
992             fprintf (stdout,
993                 "\nCould not open debug output file: %s\n\n", Filename);
994 
995             CmCleanupAndExit ();
996             exit (1);
997         }
998 
999         AslCompilerSignon (ASL_FILE_DEBUG_OUTPUT);
1000         AslCompilerFileHeader (ASL_FILE_DEBUG_OUTPUT);
1001     }
1002 
1003     /* Create/Open a cross-reference output file if asked */
1004 
1005     if (AslGbl_CrossReferenceOutput)
1006     {
1007         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_XREF);
1008         if (!Filename)
1009         {
1010             AslCommonError (ASL_ERROR, ASL_MSG_DEBUG_FILENAME,
1011                 0, 0, 0, 0, NULL, NULL);
1012             return (AE_ERROR);
1013         }
1014 
1015         FlOpenFile (ASL_FILE_XREF_OUTPUT, Filename, "w+t");
1016 
1017         AslCompilerSignon (ASL_FILE_XREF_OUTPUT);
1018         AslCompilerFileHeader (ASL_FILE_XREF_OUTPUT);
1019     }
1020 
1021     /* Create/Open a listing output file if asked */
1022 
1023     if (AslGbl_ListingFlag)
1024     {
1025         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_LISTING);
1026         if (!Filename)
1027         {
1028             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1029                 0, 0, 0, 0, NULL, NULL);
1030             return (AE_ERROR);
1031         }
1032 
1033         /* Open the listing file, text mode */
1034 
1035         FlOpenFile (ASL_FILE_LISTING_OUTPUT, Filename, "w+t");
1036 
1037         AslCompilerSignon (ASL_FILE_LISTING_OUTPUT);
1038         AslCompilerFileHeader (ASL_FILE_LISTING_OUTPUT);
1039     }
1040 
1041     /* Create the preprocessor output temp file if preprocessor enabled */
1042 
1043     if (AslGbl_PreprocessFlag)
1044     {
1045         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_PREPROCESSOR);
1046         if (!Filename)
1047         {
1048             AslCommonError (ASL_ERROR, ASL_MSG_PREPROCESSOR_FILENAME,
1049                 0, 0, 0, 0, NULL, NULL);
1050             return (AE_ERROR);
1051         }
1052 
1053         FlOpenFile (ASL_FILE_PREPROCESSOR, Filename, "w+t");
1054     }
1055 
1056     /*
1057      * Create the "user" preprocessor output file if -li flag set.
1058      * Note, this file contains no embedded #line directives.
1059      */
1060     if (AslGbl_PreprocessorOutputFlag)
1061     {
1062         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_PREPROC_USER);
1063         if (!Filename)
1064         {
1065             AslCommonError (ASL_ERROR, ASL_MSG_PREPROCESSOR_FILENAME,
1066                 0, 0, 0, 0, NULL, NULL);
1067             return (AE_ERROR);
1068         }
1069 
1070         FlOpenFile (ASL_FILE_PREPROCESSOR_USER, Filename, "w+t");
1071     }
1072 
1073     /* All done for data table compiler */
1074 
1075     if (AslGbl_FileType == ASL_INPUT_TYPE_ASCII_DATA)
1076     {
1077         return (AE_OK);
1078     }
1079 
1080     /* Create/Open a combined source output file */
1081 
1082     Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_SOURCE);
1083     if (!Filename)
1084     {
1085         AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1086             0, 0, 0, 0, NULL, NULL);
1087         return (AE_ERROR);
1088     }
1089 
1090     /*
1091      * Open the source output file, binary mode (so that LF does not get
1092      * expanded to CR/LF on some systems, messing up our seek
1093      * calculations.)
1094      */
1095     FlOpenFile (ASL_FILE_SOURCE_OUTPUT, Filename, "w+b");
1096 
1097 /*
1098 // TBD: TEMP
1099 //    AslCompilerin = AslGbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle;
1100 */
1101     /* Create/Open a assembly code source output file if asked */
1102 
1103     if (AslGbl_AsmOutputFlag)
1104     {
1105         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_ASM_SOURCE);
1106         if (!Filename)
1107         {
1108             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1109                 0, 0, 0, 0, NULL, NULL);
1110             return (AE_ERROR);
1111         }
1112 
1113         /* Open the assembly code source file, text mode */
1114 
1115         FlOpenFile (ASL_FILE_ASM_SOURCE_OUTPUT, Filename, "w+t");
1116 
1117         AslCompilerSignon (ASL_FILE_ASM_SOURCE_OUTPUT);
1118         AslCompilerFileHeader (ASL_FILE_ASM_SOURCE_OUTPUT);
1119     }
1120 
1121     /* Create/Open a C code source output file if asked */
1122 
1123     if (AslGbl_C_OutputFlag)
1124     {
1125         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_C_SOURCE);
1126         if (!Filename)
1127         {
1128             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1129                 0, 0, 0, 0, NULL, NULL);
1130             return (AE_ERROR);
1131         }
1132 
1133         /* Open the C code source file, text mode */
1134 
1135         FlOpenFile (ASL_FILE_C_SOURCE_OUTPUT, Filename, "w+t");
1136 
1137         FlPrintFile (ASL_FILE_C_SOURCE_OUTPUT, "/*\n");
1138         AslCompilerSignon (ASL_FILE_C_SOURCE_OUTPUT);
1139         AslCompilerFileHeader (ASL_FILE_C_SOURCE_OUTPUT);
1140     }
1141 
1142     /* Create/Open a C code source output file for the offset table if asked */
1143 
1144     if (AslGbl_C_OffsetTableFlag)
1145     {
1146         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_C_OFFSET);
1147         if (!Filename)
1148         {
1149             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1150                 0, 0, 0, 0, NULL, NULL);
1151             return (AE_ERROR);
1152         }
1153 
1154         /* Open the C code source file, text mode */
1155 
1156         FlOpenFile (ASL_FILE_C_OFFSET_OUTPUT, Filename, "w+t");
1157 
1158         FlPrintFile (ASL_FILE_C_OFFSET_OUTPUT, "/*\n");
1159         AslCompilerSignon (ASL_FILE_C_OFFSET_OUTPUT);
1160         AslCompilerFileHeader (ASL_FILE_C_OFFSET_OUTPUT);
1161     }
1162 
1163     /* Create/Open a assembly include output file if asked */
1164 
1165     if (AslGbl_AsmIncludeOutputFlag)
1166     {
1167         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_ASM_INCLUDE);
1168         if (!Filename)
1169         {
1170             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1171                 0, 0, 0, 0, NULL, NULL);
1172             return (AE_ERROR);
1173         }
1174 
1175         /* Open the assembly include file, text mode */
1176 
1177         FlOpenFile (ASL_FILE_ASM_INCLUDE_OUTPUT, Filename, "w+t");
1178 
1179         AslCompilerSignon (ASL_FILE_ASM_INCLUDE_OUTPUT);
1180         AslCompilerFileHeader (ASL_FILE_ASM_INCLUDE_OUTPUT);
1181     }
1182 
1183     /* Create/Open a C include output file if asked */
1184 
1185     if (AslGbl_C_IncludeOutputFlag)
1186     {
1187         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_C_INCLUDE);
1188         if (!Filename)
1189         {
1190             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1191                 0, 0, 0, 0, NULL, NULL);
1192             return (AE_ERROR);
1193         }
1194 
1195         /* Open the C include file, text mode */
1196 
1197         FlOpenFile (ASL_FILE_C_INCLUDE_OUTPUT, Filename, "w+t");
1198 
1199         FlPrintFile (ASL_FILE_C_INCLUDE_OUTPUT, "/*\n");
1200         AslCompilerSignon (ASL_FILE_C_INCLUDE_OUTPUT);
1201         AslCompilerFileHeader (ASL_FILE_C_INCLUDE_OUTPUT);
1202     }
1203 
1204     /* Create a namespace output file if asked */
1205 
1206     if (AslGbl_NsOutputFlag)
1207     {
1208         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_NAMESPACE);
1209         if (!Filename)
1210         {
1211             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1212                 0, 0, 0, 0, NULL, NULL);
1213             return (AE_ERROR);
1214         }
1215 
1216         /* Open the namespace file, text mode */
1217 
1218         FlOpenFile (ASL_FILE_NAMESPACE_OUTPUT, Filename, "w+t");
1219 
1220         AslCompilerSignon (ASL_FILE_NAMESPACE_OUTPUT);
1221         AslCompilerFileHeader (ASL_FILE_NAMESPACE_OUTPUT);
1222     }
1223 
1224     /* Create a debug file for the converter */
1225 
1226     if (AcpiGbl_DebugAslConversion)
1227     {
1228         Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_CONVERT_DEBUG);
1229         if (!Filename)
1230         {
1231             AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
1232                 0, 0, 0, 0, NULL, NULL);
1233             return (AE_ERROR);
1234         }
1235 
1236         /* Open the converter debug file, text mode */
1237 
1238         FlOpenFile (ASL_FILE_CONV_DEBUG_OUTPUT, Filename, "w+t");
1239 
1240         AslCompilerSignon (ASL_FILE_CONV_DEBUG_OUTPUT);
1241         AslCompilerFileHeader (ASL_FILE_CONV_DEBUG_OUTPUT);
1242 
1243         AcpiGbl_ConvDebugFile = AslGbl_Files[ASL_FILE_CONV_DEBUG_OUTPUT].Handle;
1244     }
1245 
1246     return (AE_OK);
1247 }
1248 
1249 
1250 #ifdef ACPI_OBSOLETE_FUNCTIONS
1251 /*******************************************************************************
1252  *
1253  * FUNCTION:    FlParseInputPathname
1254  *
1255  * PARAMETERS:  InputFilename       - The user-specified ASL source file to be
1256  *                                    compiled
1257  *
1258  * RETURN:      Status
1259  *
1260  * DESCRIPTION: Split the input path into a directory and filename part
1261  *              1) Directory part used to open include files
1262  *              2) Filename part used to generate output filenames
1263  *
1264  ******************************************************************************/
1265 
1266 ACPI_STATUS
1267 FlParseInputPathname (
1268     char                    *InputFilename)
1269 {
1270     char                    *Substring;
1271 
1272 
1273     if (!InputFilename)
1274     {
1275         return (AE_OK);
1276     }
1277 
1278     /* Get the path to the input filename's directory */
1279 
1280     AslGbl_DirectoryPath = strdup (InputFilename);
1281     if (!AslGbl_DirectoryPath)
1282     {
1283         return (AE_NO_MEMORY);
1284     }
1285 
1286     Substring = strrchr (AslGbl_DirectoryPath, '\\');
1287     if (!Substring)
1288     {
1289         Substring = strrchr (AslGbl_DirectoryPath, '/');
1290         if (!Substring)
1291         {
1292             Substring = strrchr (AslGbl_DirectoryPath, ':');
1293         }
1294     }
1295 
1296     if (!Substring)
1297     {
1298         AslGbl_DirectoryPath[0] = 0;
1299         if (AslGbl_UseDefaultAmlFilename)
1300         {
1301             AslGbl_OutputFilenamePrefix = strdup (InputFilename);
1302         }
1303     }
1304     else
1305     {
1306         if (AslGbl_UseDefaultAmlFilename)
1307         {
1308             AslGbl_OutputFilenamePrefix = strdup (Substring + 1);
1309         }
1310         *(Substring+1) = 0;
1311     }
1312 
1313     UtConvertBackslashes (AslGbl_OutputFilenamePrefix);
1314     return (AE_OK);
1315 }
1316 #endif
1317