1 /******************************************************************************
   2  *
   3  * Module Name: asfile - Main module for the acpi source processor utility
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2013, 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     default:
 338 
 339         printf ("Unknown file type, cannot process\n");
 340         return;
 341     }
 342 
 343 
 344     Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs");
 345     Gbl_Files++;
 346     VERBOSE_PRINT (("Processing %u bytes\n",
 347         (unsigned int) strlen (FileBuffer)));
 348 
 349     if (Gbl_Cleanup)
 350     {
 351         AsRemoveExtraLines (FileBuffer, Filename);
 352         AsRemoveSpacesAfterPeriod (FileBuffer, Filename);
 353     }
 354 
 355     if (ConversionTable->LowerCaseTable)
 356     {
 357         for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++)
 358         {
 359             AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier,
 360                                 FileBuffer);
 361         }
 362     }
 363 
 364     /* Process all the string replacements */
 365 
 366     if (StringTable)
 367     {
 368         for (i = 0; StringTable[i].Target; i++)
 369         {
 370             AsReplaceString (StringTable[i].Target, StringTable[i].Replacement,
 371                     StringTable[i].Type, FileBuffer);
 372         }
 373     }
 374 
 375     if (LineTable)
 376     {
 377         for (i = 0; LineTable[i].Identifier; i++)
 378         {
 379             AsRemoveLine (FileBuffer, LineTable[i].Identifier);
 380         }
 381     }
 382 
 383     if (ConditionalTable)
 384     {
 385         for (i = 0; ConditionalTable[i].Identifier; i++)
 386         {
 387             AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier);
 388         }
 389     }
 390 
 391     if (MacroTable)
 392     {
 393         for (i = 0; MacroTable[i].Identifier; i++)
 394         {
 395             AsRemoveMacro (FileBuffer, MacroTable[i].Identifier);
 396         }
 397     }
 398 
 399     if (StructTable)
 400     {
 401         for (i = 0; StructTable[i].Identifier; i++)
 402         {
 403             AsInsertPrefix (FileBuffer, StructTable[i].Identifier, StructTable[i].Type);
 404         }
 405     }
 406 
 407     if (SpecialMacroTable)
 408     {
 409         for (i = 0; SpecialMacroTable[i].Identifier; i++)
 410         {
 411             AsCleanupSpecialMacro (FileBuffer, SpecialMacroTable[i].Identifier);
 412         }
 413     }
 414 
 415     /* Process the function table */
 416 
 417     for (i = 0; i < 32; i++)
 418     {
 419         /* Decode the function bitmap */
 420 
 421         switch ((1 << i) & Functions)
 422         {
 423         case 0:
 424 
 425             /* This function not configured */
 426             break;
 427 
 428         case CVT_COUNT_TABS:
 429 
 430             AsCountTabs (FileBuffer, Filename);
 431             break;
 432 
 433         case CVT_COUNT_NON_ANSI_COMMENTS:
 434 
 435             AsCountNonAnsiComments (FileBuffer, Filename);
 436             break;
 437 
 438         case CVT_CHECK_BRACES:
 439 
 440             AsCheckForBraces (FileBuffer, Filename);
 441             break;
 442 
 443         case CVT_TRIM_LINES:
 444 
 445             AsTrimLines (FileBuffer, Filename);
 446             break;
 447 
 448         case CVT_COUNT_LINES:
 449 
 450             AsCountSourceLines (FileBuffer, Filename);
 451             break;
 452 
 453         case CVT_BRACES_ON_SAME_LINE:
 454 
 455             AsBracesOnSameLine (FileBuffer);
 456             break;
 457 
 458         case CVT_MIXED_CASE_TO_UNDERSCORES:
 459 
 460             AsMixedCaseToUnderscores (FileBuffer, Filename);
 461             break;
 462 
 463         case CVT_LOWER_CASE_IDENTIFIERS:
 464 
 465             AsLowerCaseIdentifiers (FileBuffer);
 466             break;
 467 
 468         case CVT_REMOVE_DEBUG_MACROS:
 469 
 470             AsRemoveDebugMacros (FileBuffer);
 471             break;
 472 
 473         case CVT_TRIM_WHITESPACE:
 474 
 475             AsTrimWhitespace (FileBuffer);
 476             break;
 477 
 478         case CVT_REMOVE_EMPTY_BLOCKS:
 479 
 480             AsRemoveEmptyBlocks (FileBuffer, Filename);
 481             break;
 482 
 483         case CVT_REDUCE_TYPEDEFS:
 484 
 485             AsReduceTypedefs (FileBuffer, "typedef union");
 486             AsReduceTypedefs (FileBuffer, "typedef struct");
 487             break;
 488 
 489         case CVT_SPACES_TO_TABS4:
 490 
 491             AsTabify4 (FileBuffer);
 492             break;
 493 
 494         case CVT_SPACES_TO_TABS8:
 495 
 496             AsTabify8 (FileBuffer);
 497             break;
 498 
 499         case CVT_COUNT_SHORTMULTILINE_COMMENTS:
 500 
 501 #ifdef ACPI_FUTURE_IMPLEMENTATION
 502             AsTrimComments (FileBuffer, Filename);
 503 #endif
 504             break;
 505 
 506         default:
 507 
 508             printf ("Unknown conversion subfunction opcode\n");
 509             break;
 510         }
 511     }
 512 
 513     if (ConversionTable->NewHeader)
 514     {
 515         AsReplaceHeader (FileBuffer, ConversionTable->NewHeader);
 516     }
 517 }
 518 
 519 
 520 /******************************************************************************
 521  *
 522  * FUNCTION:    AsProcessOneFile
 523  *
 524  * DESCRIPTION: Process one source file. The file is opened, read entirely
 525  *              into a buffer, converted, then written to a new file.
 526  *
 527  ******************************************************************************/
 528 
 529 ACPI_NATIVE_INT
 530 AsProcessOneFile (
 531     ACPI_CONVERSION_TABLE   *ConversionTable,
 532     char                    *SourcePath,
 533     char                    *TargetPath,
 534     int                     MaxPathLength,
 535     char                    *Filename,
 536     ACPI_NATIVE_INT         FileType)
 537 {
 538     char                    *Pathname;
 539     char                    *OutPathname = NULL;
 540 
 541 
 542     /* Allocate a file pathname buffer for both source and target */
 543 
 544     Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1);
 545     if (!Pathname)
 546     {
 547         printf ("Could not allocate buffer for file pathnames\n");
 548         return (-1);
 549     }
 550 
 551     Gbl_FileType = FileType;
 552 
 553     /* Generate the source pathname and read the file */
 554 
 555     if (SourcePath)
 556     {
 557         strcpy (Pathname, SourcePath);
 558         strcat (Pathname, "/");
 559     }
 560 
 561     strcat (Pathname, Filename);
 562 
 563     if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize))
 564     {
 565         return (-1);
 566     }
 567 
 568     Gbl_HeaderSize = 0;
 569     if (strstr (Filename, ".asl"))
 570     {
 571         Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */
 572     }
 573     else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE))
 574     {
 575         Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */
 576     }
 577     else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE))
 578     {
 579         Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */
 580     }
 581 
 582     /* Process the file in the buffer */
 583 
 584     Gbl_MadeChanges = FALSE;
 585     if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds)
 586     {
 587         /*
 588          * All lone LFs will be converted to CR/LF
 589          * (when file is written, Windows version only)
 590          */
 591         printf ("Converting lone linefeeds\n");
 592         Gbl_MadeChanges = TRUE;
 593     }
 594 
 595     AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType);
 596 
 597     if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT))
 598     {
 599         if (!(Gbl_Overwrite && !Gbl_MadeChanges))
 600         {
 601             /* Generate the target pathname and write the file */
 602 
 603             OutPathname = calloc (MaxPathLength + strlen (Filename) + 2 + strlen (TargetPath), 1);
 604             if (!OutPathname)
 605             {
 606                 printf ("Could not allocate buffer for file pathnames\n");
 607                 return (-1);
 608             }
 609 
 610             strcpy (OutPathname, TargetPath);
 611             if (SourcePath)
 612             {
 613                 strcat (OutPathname, "/");
 614                 strcat (OutPathname, Filename);
 615             }
 616 
 617             AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags);
 618         }
 619     }
 620 
 621     free (Gbl_FileBuffer);
 622     free (Pathname);
 623     if (OutPathname)
 624     {
 625         free (OutPathname);
 626     }
 627 
 628     return (0);
 629 }
 630 
 631 
 632 /******************************************************************************
 633  *
 634  * FUNCTION:    AsCheckForDirectory
 635  *
 636  * DESCRIPTION: Check if the current file is a valid directory. If not,
 637  *              construct the full pathname for the source and target paths.
 638  *              Checks for the dot and dot-dot files (they are ignored)
 639  *
 640  ******************************************************************************/
 641 
 642 ACPI_NATIVE_INT
 643 AsCheckForDirectory (
 644     char                    *SourceDirPath,
 645     char                    *TargetDirPath,
 646     char                    *Filename,
 647     char                    **SourcePath,
 648     char                    **TargetPath)
 649 {
 650     char                    *SrcPath;
 651     char                    *TgtPath;
 652 
 653 
 654     if (!(strcmp (Filename, ".")) ||
 655         !(strcmp (Filename, "..")))
 656     {
 657         return (-1);
 658     }
 659 
 660     SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1);
 661     if (!SrcPath)
 662     {
 663         printf ("Could not allocate buffer for directory source pathname\n");
 664         return (-1);
 665     }
 666 
 667     TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1);
 668     if (!TgtPath)
 669     {
 670         printf ("Could not allocate buffer for directory target pathname\n");
 671         free (SrcPath);
 672         return (-1);
 673     }
 674 
 675     strcpy (SrcPath, SourceDirPath);
 676     strcat (SrcPath, "/");
 677     strcat (SrcPath, Filename);
 678 
 679     strcpy (TgtPath, TargetDirPath);
 680     strcat (TgtPath, "/");
 681     strcat (TgtPath, Filename);
 682 
 683     *SourcePath = SrcPath;
 684     *TargetPath = TgtPath;
 685     return (0);
 686 }
 687 
 688 
 689 /******************************************************************************
 690  *
 691  * FUNCTION:    AsGetFile
 692  *
 693  * DESCRIPTION: Open a file and read it entirely into a an allocated buffer
 694  *
 695  ******************************************************************************/
 696 
 697 int
 698 AsGetFile (
 699     char                    *Filename,
 700     char                    **FileBuffer,
 701     UINT32                  *FileSize)
 702 {
 703     FILE                    *File;
 704     UINT32                  Size;
 705     char                    *Buffer;
 706     int                     Seek1;
 707     int                     Seek2;
 708     size_t                  Actual;
 709 
 710 
 711     /* Binary mode leaves CR/LF pairs */
 712 
 713     File = fopen (Filename, "rb");
 714     if (!File)
 715     {
 716         printf ("Could not open file %s\n", Filename);
 717         return (-1);
 718     }
 719 
 720     /* Need file size to allocate a buffer */
 721 
 722     Seek1 = fseek (File, 0L, SEEK_END);
 723     Size = ftell (File);
 724     Seek2 = fseek (File, 0L, SEEK_SET);
 725 
 726     if (Seek1 || Seek2 || (Size == -1))
 727     {
 728         printf ("Could not get file size for %s\n", Filename);
 729         goto ErrorExit;
 730     }
 731 
 732     /*
 733      * Create a buffer for the entire file
 734      * Add plenty extra buffer to accommodate string replacements
 735      */
 736     Gbl_TotalSize += Size;
 737 
 738     Buffer = calloc (Size * 2, 1);
 739     if (!Buffer)
 740     {
 741         printf ("Could not allocate buffer of size %u\n", Size * 2);
 742         goto ErrorExit;
 743     }
 744 
 745     /* Read the entire file */
 746 
 747     Actual = fread (Buffer, 1, Size, File);
 748     if (Actual != Size)
 749     {
 750         printf ("Could not read the input file %s (%u bytes)\n",
 751             Filename, Size);
 752         goto ErrorExit;
 753     }
 754 
 755     Buffer [Size] = 0;         /* Null terminate the buffer */
 756     fclose (File);
 757 
 758     /* Check for unix contamination */
 759 
 760     Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer);
 761 
 762     /*
 763      * Convert all CR/LF pairs to LF only. We do this locally so that
 764      * this code is portable across operating systems.
 765      */
 766     AsConvertToLineFeeds (Buffer);
 767 
 768     *FileBuffer = Buffer;
 769     *FileSize = Size;
 770     return (0);
 771 
 772 
 773 ErrorExit:
 774 
 775     fclose (File);
 776     return (-1);
 777 }
 778 
 779 
 780 /******************************************************************************
 781  *
 782  * FUNCTION:    AsPutFile
 783  *
 784  * DESCRIPTION: Create a new output file and write the entire contents of the
 785  *              buffer to the new file. Buffer must be a zero terminated string
 786  *
 787  ******************************************************************************/
 788 
 789 int
 790 AsPutFile (
 791     char                    *Pathname,
 792     char                    *FileBuffer,
 793     UINT32                  SystemFlags)
 794 {
 795     FILE                    *File;
 796     UINT32                  FileSize;
 797     size_t                  Actual;
 798     int                     Status = 0;
 799 
 800 
 801     /* Create the target file */
 802 
 803     if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS))
 804     {
 805         /* Put back the CR before each LF */
 806 
 807         AsInsertCarriageReturns (FileBuffer);
 808     }
 809 
 810     File = fopen (Pathname, "w+b");
 811     if (!File)
 812     {
 813         perror ("Could not create destination file");
 814         printf ("Could not create destination file \"%s\"\n", Pathname);
 815         return (-1);
 816     }
 817 
 818     /* Write the buffer to the file */
 819 
 820     FileSize = strlen (FileBuffer);
 821     Actual = fwrite (FileBuffer, 1, FileSize, File);
 822     if (Actual != FileSize)
 823     {
 824         printf ("Error writing output file \"%s\"\n", Pathname);
 825         Status = -1;
 826     }
 827 
 828     fclose (File);
 829     return (Status);
 830 }