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 }