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