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