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