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