1 /******************************************************************************
2  *
3  * Module Name: asfile - Main module for the acpi source processor utility
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, 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 MERCHANTIBILITY 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 "acpisrc.h"
45 
46 /* Local prototypes */
47 
48 void
49 AsDoWildcard (
50     ACPI_CONVERSION_TABLE   *ConversionTable,
51     char                    *SourcePath,
52     char                    *TargetPath,
53     int                     MaxPathLength,
54     int                     FileType,
55     char                    *WildcardSpec);
56 
57 BOOLEAN
58 AsDetectLoneLineFeeds (
59     char                    *Filename,
60     char                    *Buffer);
61 
62 static ACPI_INLINE int
63 AsMaxInt (int a, int b)
64 {
65     return (a > b ? a : b);
66 }
67 
68 
69 /******************************************************************************
70  *
71  * FUNCTION:    AsDoWildcard
72  *
73  * DESCRIPTION: Process files via wildcards
74  *
75  ******************************************************************************/
76 
77 void
78 AsDoWildcard (
79     ACPI_CONVERSION_TABLE   *ConversionTable,
80     char                    *SourcePath,
81     char                    *TargetPath,
82     int                     MaxPathLength,
83     int                     FileType,
84     char                    *WildcardSpec)
85 {
86     void                    *DirInfo;
87     char                    *Filename;
88     char                    *SourceDirPath;
89     char                    *TargetDirPath;
90     char                    RequestedFileType;
91 
92 
93     if (FileType == FILE_TYPE_DIRECTORY)
94     {
95         RequestedFileType = REQUEST_DIR_ONLY;
96     }
97     else
98     {
99         RequestedFileType = REQUEST_FILE_ONLY;
100     }
101 
102     VERBOSE_PRINT (("Checking for %s source files in directory \"%s\"\n",
103             WildcardSpec, SourcePath));
104 
105     /* Open the directory for wildcard search */
106 
107     DirInfo = AcpiOsOpenDirectory (SourcePath, WildcardSpec, RequestedFileType);
108     if (DirInfo)
109     {
110         /*
111          * Get all of the files that match both the
112          * wildcard and the requested file type
113          */
114         while ((Filename = AcpiOsGetNextFilename (DirInfo)))
115         {
116             /* Looking for directory files, must check file type */
117 
118             switch (RequestedFileType)
119             {
120             case REQUEST_DIR_ONLY:
121 
122                 /* If we actually have a dir, process the subtree */
123 
124                 if (!AsCheckForDirectory (SourcePath, TargetPath, Filename,
125                         &SourceDirPath, &TargetDirPath))
126                 {
127                     VERBOSE_PRINT (("Subdirectory: %s\n", Filename));
128 
129                     AsProcessTree (ConversionTable, SourceDirPath, TargetDirPath);
130                     free (SourceDirPath);
131                     free (TargetDirPath);
132                 }
133                 break;
134 
135             case REQUEST_FILE_ONLY:
136 
137                 /* Otherwise, this is a file, not a directory */
138 
139                 VERBOSE_PRINT (("File: %s\n", Filename));
140 
141                 AsProcessOneFile (ConversionTable, SourcePath, TargetPath,
142                         MaxPathLength, Filename, FileType);
143                 break;
144 
145             default:
146 
147                 break;
148             }
149         }
150 
151         /* Cleanup */
152 
153         AcpiOsCloseDirectory (DirInfo);
154     }
155 }
156 
157 
158 /******************************************************************************
159  *
160  * FUNCTION:    AsProcessTree
161  *
162  * DESCRIPTION: Process the directory tree. Files with the extension ".C" and
163  *              ".H" are processed as the tree is traversed.
164  *
165  ******************************************************************************/
166 
167 ACPI_NATIVE_INT
168 AsProcessTree (
169     ACPI_CONVERSION_TABLE   *ConversionTable,
170     char                    *SourcePath,
171     char                    *TargetPath)
172 {
173     int                     MaxPathLength;
174 
175 
176     MaxPathLength = AsMaxInt (strlen (SourcePath), strlen (TargetPath));
177 
178     if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT))
179     {
180         if (ConversionTable->Flags & FLG_LOWERCASE_DIRNAMES)
181         {
182             AsStrlwr (TargetPath);
183         }
184 
185         VERBOSE_PRINT (("Creating Directory \"%s\"\n", TargetPath));
186         if (mkdir (TargetPath))
187         {
188             if (errno != EEXIST)
189             {
190                 printf ("Could not create target directory\n");
191                 return (-1);
192             }
193         }
194     }
195 
196     /* Do the C source files */
197 
198     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
199             FILE_TYPE_SOURCE, "*.c");
200 
201     /* Do the C header files */
202 
203     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
204             FILE_TYPE_HEADER, "*.h");
205 
206     /* Do the Lex file(s) */
207 
208     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
209             FILE_TYPE_SOURCE, "*.l");
210 
211     /* Do the yacc file(s) */
212 
213     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
214             FILE_TYPE_SOURCE, "*.y");
215 
216     /* Do any ASL files */
217 
218     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
219             FILE_TYPE_HEADER, "*.asl");
220 
221     /* Do any subdirectories */
222 
223     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
224             FILE_TYPE_DIRECTORY, "*");
225 
226     return (0);
227 }
228 
229 
230 /******************************************************************************
231  *
232  * FUNCTION:    AsDetectLoneLineFeeds
233  *
234  * DESCRIPTION: Find LF without CR.
235  *
236  ******************************************************************************/
237 
238 BOOLEAN
239 AsDetectLoneLineFeeds (
240     char                    *Filename,
241     char                    *Buffer)
242 {
243     UINT32                  i = 1;
244     UINT32                  LfCount = 0;
245     UINT32                  LineCount = 0;
246 
247 
248     if (!Buffer[0])
249     {
250         return (FALSE);
251     }
252 
253     while (Buffer[i])
254     {
255         if (Buffer[i] == 0x0A)
256         {
257             if (Buffer[i-1] != 0x0D)
258             {
259                 LfCount++;
260             }
261             LineCount++;
262         }
263         i++;
264     }
265 
266     if (LfCount)
267     {
268         if (LineCount == LfCount)
269         {
270             if (!Gbl_IgnoreLoneLineFeeds)
271             {
272                 printf ("%s: ****File has UNIX format**** (LF only, not CR/LF) %u lines\n",
273                     Filename, LfCount);
274             }
275         }
276         else
277         {
278             printf ("%s: %u lone linefeeds in file\n", Filename, LfCount);
279         }
280         return (TRUE);
281     }
282 
283     return (FALSE);
284 }
285 
286 
287 /******************************************************************************
288  *
289  * FUNCTION:    AsConvertFile
290  *
291  * DESCRIPTION: Perform the requested transforms on the file buffer (as
292  *              determined by the ConversionTable and the FileType).
293  *
294  ******************************************************************************/
295 
296 void
297 AsConvertFile (
298     ACPI_CONVERSION_TABLE   *ConversionTable,
299     char                    *FileBuffer,
300     char                    *Filename,
301     ACPI_NATIVE_INT         FileType)
302 {
303     UINT32                  i;
304     UINT32                  Functions;
305     ACPI_STRING_TABLE       *StringTable;
306     ACPI_IDENTIFIER_TABLE   *ConditionalTable;
307     ACPI_IDENTIFIER_TABLE   *LineTable;
308     ACPI_IDENTIFIER_TABLE   *MacroTable;
309     ACPI_TYPED_IDENTIFIER_TABLE *StructTable;
310     ACPI_IDENTIFIER_TABLE   *SpecialMacroTable;
311 
312 
313     switch (FileType)
314     {
315     case FILE_TYPE_SOURCE:
316 
317         Functions           = ConversionTable->SourceFunctions;
318         StringTable         = ConversionTable->SourceStringTable;
319         LineTable           = ConversionTable->SourceLineTable;
320         ConditionalTable    = ConversionTable->SourceConditionalTable;
321         MacroTable          = ConversionTable->SourceMacroTable;
322         StructTable         = ConversionTable->SourceStructTable;
323         SpecialMacroTable   = ConversionTable->SourceSpecialMacroTable;
324        break;
325 
326     case FILE_TYPE_HEADER:
327 
328         Functions           = ConversionTable->HeaderFunctions;
329         StringTable         = ConversionTable->HeaderStringTable;
330         LineTable           = ConversionTable->HeaderLineTable;
331         ConditionalTable    = ConversionTable->HeaderConditionalTable;
332         MacroTable          = ConversionTable->HeaderMacroTable;
333         StructTable         = ConversionTable->HeaderStructTable;
334         SpecialMacroTable   = ConversionTable->HeaderSpecialMacroTable;
335         break;
336 
337     case FILE_TYPE_PATCH:
338 
339         Functions           = ConversionTable->PatchFunctions;
340         StringTable         = ConversionTable->PatchStringTable;
341         LineTable           = ConversionTable->PatchLineTable;
342         ConditionalTable    = ConversionTable->PatchConditionalTable;
343         MacroTable          = ConversionTable->PatchMacroTable;
344         StructTable         = ConversionTable->PatchStructTable;
345         SpecialMacroTable   = ConversionTable->PatchSpecialMacroTable;
346         break;
347 
348     default:
349 
350         printf ("Unknown file type, cannot process\n");
351         return;
352     }
353 
354 
355     Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs");
356     Gbl_Files++;
357     VERBOSE_PRINT (("Processing %u bytes\n",
358         (unsigned int) strlen (FileBuffer)));
359 
360     if (Gbl_Cleanup)
361     {
362         AsRemoveExtraLines (FileBuffer, Filename);
363         AsRemoveSpacesAfterPeriod (FileBuffer, Filename);
364     }
365 
366     if (ConversionTable->LowerCaseTable)
367     {
368         for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++)
369         {
370             AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier,
371                                 FileBuffer);
372         }
373     }
374 
375     /* Process all the string replacements */
376 
377     if (StringTable)
378     {
379         for (i = 0; StringTable[i].Target; i++)
380         {
381             AsReplaceString (StringTable[i].Target, StringTable[i].Replacement,
382                     StringTable[i].Type, FileBuffer);
383         }
384     }
385 
386     if (LineTable)
387     {
388         for (i = 0; LineTable[i].Identifier; i++)
389         {
390             AsRemoveLine (FileBuffer, LineTable[i].Identifier);
391         }
392     }
393 
394     if (ConditionalTable)
395     {
396         for (i = 0; ConditionalTable[i].Identifier; i++)
397         {
398             AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier);
399         }
400     }
401 
402     if (MacroTable)
403     {
404         for (i = 0; MacroTable[i].Identifier; i++)
405         {
406             AsRemoveMacro (FileBuffer, MacroTable[i].Identifier);
407         }
408     }
409 
410     if (StructTable)
411     {
412         for (i = 0; StructTable[i].Identifier; i++)
413         {
414             AsInsertPrefix (FileBuffer, StructTable[i].Identifier, StructTable[i].Type);
415         }
416     }
417 
418     if (SpecialMacroTable)
419     {
420         for (i = 0; SpecialMacroTable[i].Identifier; i++)
421         {
422             AsCleanupSpecialMacro (FileBuffer, SpecialMacroTable[i].Identifier);
423         }
424     }
425 
426     /* Process the function table */
427 
428     for (i = 0; i < 32; i++)
429     {
430         /* Decode the function bitmap */
431 
432         switch ((1 << i) & Functions)
433         {
434         case 0:
435 
436             /* This function not configured */
437             break;
438 
439         case CVT_COUNT_TABS:
440 
441             AsCountTabs (FileBuffer, Filename);
442             break;
443 
444         case CVT_COUNT_NON_ANSI_COMMENTS:
445 
446             AsCountNonAnsiComments (FileBuffer, Filename);
447             break;
448 
449         case CVT_CHECK_BRACES:
450 
451             AsCheckForBraces (FileBuffer, Filename);
452             break;
453 
454         case CVT_TRIM_LINES:
455 
456             AsTrimLines (FileBuffer, Filename);
457             break;
458 
459         case CVT_COUNT_LINES:
460 
461             AsCountSourceLines (FileBuffer, Filename);
462             break;
463 
464         case CVT_BRACES_ON_SAME_LINE:
465 
466             AsBracesOnSameLine (FileBuffer);
467             break;
468 
469         case CVT_MIXED_CASE_TO_UNDERSCORES:
470 
471             AsMixedCaseToUnderscores (FileBuffer, Filename);
472             break;
473 
474         case CVT_LOWER_CASE_IDENTIFIERS:
475 
476             AsLowerCaseIdentifiers (FileBuffer);
477             break;
478 
479         case CVT_REMOVE_DEBUG_MACROS:
480 
481             AsRemoveDebugMacros (FileBuffer);
482             break;
483 
484         case CVT_TRIM_WHITESPACE:
485 
486             AsTrimWhitespace (FileBuffer);
487             break;
488 
489         case CVT_REMOVE_EMPTY_BLOCKS:
490 
491             AsRemoveEmptyBlocks (FileBuffer, Filename);
492             break;
493 
494         case CVT_REDUCE_TYPEDEFS:
495 
496             AsReduceTypedefs (FileBuffer, "typedef union");
497             AsReduceTypedefs (FileBuffer, "typedef struct");
498             break;
499 
500         case CVT_SPACES_TO_TABS4:
501 
502             AsTabify4 (FileBuffer);
503             break;
504 
505         case CVT_SPACES_TO_TABS8:
506 
507             AsTabify8 (FileBuffer);
508             break;
509 
510         case CVT_COUNT_SHORTMULTILINE_COMMENTS:
511 
512 #ifdef ACPI_FUTURE_IMPLEMENTATION
513             AsTrimComments (FileBuffer, Filename);
514 #endif
515             break;
516 
517         default:
518 
519             printf ("Unknown conversion subfunction opcode\n");
520             break;
521         }
522     }
523 
524     if (ConversionTable->NewHeader)
525     {
526         AsReplaceHeader (FileBuffer, ConversionTable->NewHeader);
527     }
528 }
529 
530 
531 /******************************************************************************
532  *
533  * FUNCTION:    AsProcessOneFile
534  *
535  * DESCRIPTION: Process one source file. The file is opened, read entirely
536  *              into a buffer, converted, then written to a new file.
537  *
538  ******************************************************************************/
539 
540 ACPI_NATIVE_INT
541 AsProcessOneFile (
542     ACPI_CONVERSION_TABLE   *ConversionTable,
543     char                    *SourcePath,
544     char                    *TargetPath,
545     int                     MaxPathLength,
546     char                    *Filename,
547     ACPI_NATIVE_INT         FileType)
548 {
549     char                    *Pathname;
550     char                    *OutPathname = NULL;
551 
552 
553     /* Allocate a file pathname buffer for both source and target */
554 
555     Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1);
556     if (!Pathname)
557     {
558         printf ("Could not allocate buffer for file pathnames\n");
559         return (-1);
560     }
561 
562     Gbl_FileType = FileType;
563 
564     /* Generate the source pathname and read the file */
565 
566     if (SourcePath)
567     {
568         strcpy (Pathname, SourcePath);
569         strcat (Pathname, "/");
570     }
571 
572     strcat (Pathname, Filename);
573 
574     if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize))
575     {
576         return (-1);
577     }
578 
579     Gbl_HeaderSize = 0;
580     if (strstr (Filename, ".asl"))
581     {
582         Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */
583     }
584     else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE))
585     {
586         Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */
587     }
588     else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE))
589     {
590         Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */
591     }
592 
593     /* Process the file in the buffer */
594 
595     Gbl_MadeChanges = FALSE;
596     if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds)
597     {
598         /*
599          * All lone LFs will be converted to CR/LF
600          * (when file is written, Windows version only)
601          */
602         printf ("Converting lone linefeeds\n");
603         Gbl_MadeChanges = TRUE;
604     }
605 
606     AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType);
607 
608     if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT))
609     {
610         if (!(Gbl_Overwrite && !Gbl_MadeChanges))
611         {
612             /* Generate the target pathname and write the file */
613 
614             OutPathname = calloc (MaxPathLength + strlen (Filename) + 2 + strlen (TargetPath), 1);
615             if (!OutPathname)
616             {
617                 printf ("Could not allocate buffer for file pathnames\n");
618                 return (-1);
619             }
620 
621             strcpy (OutPathname, TargetPath);
622             if (SourcePath)
623             {
624                 strcat (OutPathname, "/");
625                 strcat (OutPathname, Filename);
626             }
627 
628             AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags);
629         }
630     }
631 
632     free (Gbl_FileBuffer);
633     free (Pathname);
634     if (OutPathname)
635     {
636         free (OutPathname);
637     }
638 
639     return (0);
640 }
641 
642 
643 /******************************************************************************
644  *
645  * FUNCTION:    AsCheckForDirectory
646  *
647  * DESCRIPTION: Check if the current file is a valid directory. If not,
648  *              construct the full pathname for the source and target paths.
649  *              Checks for the dot and dot-dot files (they are ignored)
650  *
651  ******************************************************************************/
652 
653 ACPI_NATIVE_INT
654 AsCheckForDirectory (
655     char                    *SourceDirPath,
656     char                    *TargetDirPath,
657     char                    *Filename,
658     char                    **SourcePath,
659     char                    **TargetPath)
660 {
661     char                    *SrcPath;
662     char                    *TgtPath;
663 
664 
665     if (!(strcmp (Filename, ".")) ||
666         !(strcmp (Filename, "..")))
667     {
668         return (-1);
669     }
670 
671     SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1);
672     if (!SrcPath)
673     {
674         printf ("Could not allocate buffer for directory source pathname\n");
675         return (-1);
676     }
677 
678     TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1);
679     if (!TgtPath)
680     {
681         printf ("Could not allocate buffer for directory target pathname\n");
682         free (SrcPath);
683         return (-1);
684     }
685 
686     strcpy (SrcPath, SourceDirPath);
687     strcat (SrcPath, "/");
688     strcat (SrcPath, Filename);
689 
690     strcpy (TgtPath, TargetDirPath);
691     strcat (TgtPath, "/");
692     strcat (TgtPath, Filename);
693 
694     *SourcePath = SrcPath;
695     *TargetPath = TgtPath;
696     return (0);
697 }
698 
699 
700 /******************************************************************************
701  *
702  * FUNCTION:    AsGetFile
703  *
704  * DESCRIPTION: Open a file and read it entirely into a an allocated buffer
705  *
706  ******************************************************************************/
707 
708 int
709 AsGetFile (
710     char                    *Filename,
711     char                    **FileBuffer,
712     UINT32                  *FileSize)
713 {
714     FILE                    *File;
715     UINT32                  Size;
716     char                    *Buffer;
717     int                     Seek1;
718     int                     Seek2;
719     size_t                  Actual;
720 
721 
722     /* Binary mode leaves CR/LF pairs */
723 
724     File = fopen (Filename, "rb");
725     if (!File)
726     {
727         printf ("Could not open file %s\n", Filename);
728         return (-1);
729     }
730 
731     /* Need file size to allocate a buffer */
732 
733     Seek1 = fseek (File, 0L, SEEK_END);
734     Size = ftell (File);
735     Seek2 = fseek (File, 0L, SEEK_SET);
736 
737     if (Seek1 || Seek2 || (Size == -1))
738     {
739         printf ("Could not get file size for %s\n", Filename);
740         goto ErrorExit;
741     }
742 
743     /*
744      * Create a buffer for the entire file
745      * Add plenty extra buffer to accommodate string replacements
746      */
747     Gbl_TotalSize += Size;
748 
749     Buffer = calloc (Size * 2, 1);
750     if (!Buffer)
751     {
752         printf ("Could not allocate buffer of size %u\n", Size * 2);
753         goto ErrorExit;
754     }
755 
756     /* Read the entire file */
757 
758     Actual = fread (Buffer, 1, Size, File);
759     if (Actual != Size)
760     {
761         printf ("Could not read the input file %s (%u bytes)\n",
762             Filename, Size);
763         goto ErrorExit;
764     }
765 
766     Buffer [Size] = 0;         /* Null terminate the buffer */
767     fclose (File);
768 
769     /* Check for unix contamination */
770 
771     Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer);
772 
773     /*
774      * Convert all CR/LF pairs to LF only. We do this locally so that
775      * this code is portable across operating systems.
776      */
777     AsConvertToLineFeeds (Buffer);
778 
779     *FileBuffer = Buffer;
780     *FileSize = Size;
781     return (0);
782 
783 
784 ErrorExit:
785 
786     fclose (File);
787     return (-1);
788 }
789 
790 
791 /******************************************************************************
792  *
793  * FUNCTION:    AsPutFile
794  *
795  * DESCRIPTION: Create a new output file and write the entire contents of the
796  *              buffer to the new file. Buffer must be a zero terminated string
797  *
798  ******************************************************************************/
799 
800 int
801 AsPutFile (
802     char                    *Pathname,
803     char                    *FileBuffer,
804     UINT32                  SystemFlags)
805 {
806     FILE                    *File;
807     UINT32                  FileSize;
808     size_t                  Actual;
809     int                     Status = 0;
810 
811 
812     /* Create the target file */
813 
814     if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS))
815     {
816         /* Put back the CR before each LF */
817 
818         AsInsertCarriageReturns (FileBuffer);
819     }
820 
821     File = fopen (Pathname, "w+b");
822     if (!File)
823     {
824         perror ("Could not create destination file");
825         printf ("Could not create destination file \"%s\"\n", Pathname);
826         return (-1);
827     }
828 
829     /* Write the buffer to the file */
830 
831     FileSize = strlen (FileBuffer);
832     Actual = fwrite (FileBuffer, 1, FileSize, File);
833     if (Actual != FileSize)
834     {
835         printf ("Error writing output file \"%s\"\n", Pathname);
836         Status = -1;
837     }
838 
839     fclose (File);
840     return (Status);
841 }
842