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