1 2 /****************************************************************************** 3 * 4 * Module Name: asfile - Main module for the acpi source processor utility 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include "acpisrc.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 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 strlwr (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 311 312 switch (FileType) 313 { 314 case FILE_TYPE_SOURCE: 315 Functions = ConversionTable->SourceFunctions; 316 StringTable = ConversionTable->SourceStringTable; 317 LineTable = ConversionTable->SourceLineTable; 318 ConditionalTable = ConversionTable->SourceConditionalTable; 319 MacroTable = ConversionTable->SourceMacroTable; 320 StructTable = ConversionTable->SourceStructTable; 321 break; 322 323 case FILE_TYPE_HEADER: 324 Functions = ConversionTable->HeaderFunctions; 325 StringTable = ConversionTable->HeaderStringTable; 326 LineTable = ConversionTable->HeaderLineTable; 327 ConditionalTable = ConversionTable->HeaderConditionalTable; 328 MacroTable = ConversionTable->HeaderMacroTable; 329 StructTable = ConversionTable->HeaderStructTable; 330 break; 331 332 default: 333 printf ("Unknown file type, cannot process\n"); 334 return; 335 } 336 337 338 Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs"); 339 Gbl_Files++; 340 VERBOSE_PRINT (("Processing %u bytes\n", 341 (unsigned int) strlen (FileBuffer))); 342 343 if (ConversionTable->LowerCaseTable) 344 { 345 for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++) 346 { 347 AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier, 348 FileBuffer); 349 } 350 } 351 352 /* Process all the string replacements */ 353 354 if (StringTable) 355 { 356 for (i = 0; StringTable[i].Target; i++) 357 { 358 AsReplaceString (StringTable[i].Target, StringTable[i].Replacement, 359 StringTable[i].Type, FileBuffer); 360 } 361 } 362 363 if (LineTable) 364 { 365 for (i = 0; LineTable[i].Identifier; i++) 366 { 367 AsRemoveLine (FileBuffer, LineTable[i].Identifier); 368 } 369 } 370 371 if (ConditionalTable) 372 { 373 for (i = 0; ConditionalTable[i].Identifier; i++) 374 { 375 AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier); 376 } 377 } 378 379 if (MacroTable) 380 { 381 for (i = 0; MacroTable[i].Identifier; i++) 382 { 383 AsRemoveMacro (FileBuffer, MacroTable[i].Identifier); 384 } 385 } 386 387 if (StructTable) 388 { 389 for (i = 0; StructTable[i].Identifier; i++) 390 { 391 AsInsertPrefix (FileBuffer, StructTable[i].Identifier, StructTable[i].Type); 392 } 393 } 394 395 /* Process the function table */ 396 397 for (i = 0; i < 32; i++) 398 { 399 /* Decode the function bitmap */ 400 401 switch ((1 << i) & Functions) 402 { 403 case 0: 404 /* This function not configured */ 405 break; 406 407 408 case CVT_COUNT_TABS: 409 410 AsCountTabs (FileBuffer, Filename); 411 break; 412 413 414 case CVT_COUNT_NON_ANSI_COMMENTS: 415 416 AsCountNonAnsiComments (FileBuffer, Filename); 417 break; 418 419 420 case CVT_CHECK_BRACES: 421 422 AsCheckForBraces (FileBuffer, Filename); 423 break; 424 425 426 case CVT_TRIM_LINES: 427 428 AsTrimLines (FileBuffer, Filename); 429 break; 430 431 432 case CVT_COUNT_LINES: 433 434 AsCountSourceLines (FileBuffer, Filename); 435 break; 436 437 438 case CVT_BRACES_ON_SAME_LINE: 439 440 AsBracesOnSameLine (FileBuffer); 441 break; 442 443 444 case CVT_MIXED_CASE_TO_UNDERSCORES: 445 446 AsMixedCaseToUnderscores (FileBuffer); 447 break; 448 449 450 case CVT_LOWER_CASE_IDENTIFIERS: 451 452 AsLowerCaseIdentifiers (FileBuffer); 453 break; 454 455 456 case CVT_REMOVE_DEBUG_MACROS: 457 458 AsRemoveDebugMacros (FileBuffer); 459 break; 460 461 462 case CVT_TRIM_WHITESPACE: 463 464 AsTrimWhitespace (FileBuffer); 465 break; 466 467 468 case CVT_REMOVE_EMPTY_BLOCKS: 469 470 AsRemoveEmptyBlocks (FileBuffer, Filename); 471 break; 472 473 474 case CVT_REDUCE_TYPEDEFS: 475 476 AsReduceTypedefs (FileBuffer, "typedef union"); 477 AsReduceTypedefs (FileBuffer, "typedef struct"); 478 break; 479 480 481 case CVT_SPACES_TO_TABS4: 482 483 AsTabify4 (FileBuffer); 484 break; 485 486 487 case CVT_SPACES_TO_TABS8: 488 489 AsTabify8 (FileBuffer); 490 break; 491 492 case CVT_COUNT_SHORTMULTILINE_COMMENTS: 493 494 #ifdef ACPI_FUTURE_IMPLEMENTATION 495 AsTrimComments (FileBuffer, Filename); 496 #endif 497 break; 498 499 default: 500 501 printf ("Unknown conversion subfunction opcode\n"); 502 break; 503 } 504 } 505 506 if (ConversionTable->NewHeader) 507 { 508 AsReplaceHeader (FileBuffer, ConversionTable->NewHeader); 509 } 510 } 511 512 513 /****************************************************************************** 514 * 515 * FUNCTION: AsProcessOneFile 516 * 517 * DESCRIPTION: Process one source file. The file is opened, read entirely 518 * into a buffer, converted, then written to a new file. 519 * 520 ******************************************************************************/ 521 522 ACPI_NATIVE_INT 523 AsProcessOneFile ( 524 ACPI_CONVERSION_TABLE *ConversionTable, 525 char *SourcePath, 526 char *TargetPath, 527 int MaxPathLength, 528 char *Filename, 529 ACPI_NATIVE_INT FileType) 530 { 531 char *Pathname; 532 char *OutPathname = NULL; 533 534 535 /* Allocate a file pathname buffer for both source and target */ 536 537 Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1); 538 if (!Pathname) 539 { 540 printf ("Could not allocate buffer for file pathnames\n"); 541 return -1; 542 } 543 544 Gbl_FileType = FileType; 545 546 /* Generate the source pathname and read the file */ 547 548 if (SourcePath) 549 { 550 strcpy (Pathname, SourcePath); 551 strcat (Pathname, "/"); 552 } 553 554 strcat (Pathname, Filename); 555 556 if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize)) 557 { 558 return -1; 559 } 560 561 Gbl_HeaderSize = 0; 562 if (strstr (Filename, ".asl")) 563 { 564 Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */ 565 } 566 else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE)) 567 { 568 Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */ 569 } 570 else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE)) 571 { 572 Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */ 573 } 574 575 /* Process the file in the buffer */ 576 577 Gbl_MadeChanges = FALSE; 578 if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds) 579 { 580 /* 581 * All lone LFs will be converted to CR/LF 582 * (when file is written, Windows version only) 583 */ 584 printf ("Converting lone linefeeds\n"); 585 Gbl_MadeChanges = TRUE; 586 } 587 588 AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType); 589 590 if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT)) 591 { 592 if (!(Gbl_Overwrite && !Gbl_MadeChanges)) 593 { 594 /* Generate the target pathname and write the file */ 595 596 OutPathname = calloc (MaxPathLength + strlen (Filename) + 2 + strlen (TargetPath), 1); 597 if (!OutPathname) 598 { 599 printf ("Could not allocate buffer for file pathnames\n"); 600 return -1; 601 } 602 603 strcpy (OutPathname, TargetPath); 604 if (SourcePath) 605 { 606 strcat (OutPathname, "/"); 607 strcat (OutPathname, Filename); 608 } 609 610 AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags); 611 } 612 } 613 614 free (Gbl_FileBuffer); 615 free (Pathname); 616 if (OutPathname) 617 { 618 free (OutPathname); 619 } 620 621 return 0; 622 } 623 624 625 /****************************************************************************** 626 * 627 * FUNCTION: AsCheckForDirectory 628 * 629 * DESCRIPTION: Check if the current file is a valid directory. If not, 630 * construct the full pathname for the source and target paths. 631 * Checks for the dot and dot-dot files (they are ignored) 632 * 633 ******************************************************************************/ 634 635 ACPI_NATIVE_INT 636 AsCheckForDirectory ( 637 char *SourceDirPath, 638 char *TargetDirPath, 639 char *Filename, 640 char **SourcePath, 641 char **TargetPath) 642 { 643 char *SrcPath; 644 char *TgtPath; 645 646 647 if (!(strcmp (Filename, ".")) || 648 !(strcmp (Filename, ".."))) 649 { 650 return -1; 651 } 652 653 SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1); 654 if (!SrcPath) 655 { 656 printf ("Could not allocate buffer for directory source pathname\n"); 657 return -1; 658 } 659 660 TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1); 661 if (!TgtPath) 662 { 663 printf ("Could not allocate buffer for directory target pathname\n"); 664 free (SrcPath); 665 return -1; 666 } 667 668 strcpy (SrcPath, SourceDirPath); 669 strcat (SrcPath, "/"); 670 strcat (SrcPath, Filename); 671 672 strcpy (TgtPath, TargetDirPath); 673 strcat (TgtPath, "/"); 674 strcat (TgtPath, Filename); 675 676 *SourcePath = SrcPath; 677 *TargetPath = TgtPath; 678 return 0; 679 } 680 681 682 /****************************************************************************** 683 * 684 * FUNCTION: AsGetFile 685 * 686 * DESCRIPTION: Open a file and read it entirely into a an allocated buffer 687 * 688 ******************************************************************************/ 689 690 int 691 AsGetFile ( 692 char *Filename, 693 char **FileBuffer, 694 UINT32 *FileSize) 695 { 696 697 int FileHandle; 698 UINT32 Size; 699 char *Buffer; 700 701 702 /* Binary mode leaves CR/LF pairs */ 703 704 FileHandle = open (Filename, O_BINARY | O_RDONLY); 705 if (!FileHandle) 706 { 707 printf ("Could not open %s\n", Filename); 708 return -1; 709 } 710 711 if (fstat (FileHandle, &Gbl_StatBuf)) 712 { 713 printf ("Could not get file status for %s\n", Filename); 714 goto ErrorExit; 715 } 716 717 /* 718 * Create a buffer for the entire file 719 * Add plenty extra buffer to accomodate string replacements 720 */ 721 Size = Gbl_StatBuf.st_size; 722 Gbl_TotalSize += Size; 723 724 Buffer = calloc (Size * 2, 1); 725 if (!Buffer) 726 { 727 printf ("Could not allocate buffer of size %u\n", Size * 2); 728 goto ErrorExit; 729 } 730 731 /* Read the entire file */ 732 733 Size = read (FileHandle, Buffer, Size); 734 if (Size == -1) 735 { 736 printf ("Could not read the input file %s\n", Filename); 737 goto ErrorExit; 738 } 739 740 Buffer [Size] = 0; /* Null terminate the buffer */ 741 close (FileHandle); 742 743 /* Check for unix contamination */ 744 745 Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer); 746 747 /* 748 * Convert all CR/LF pairs to LF only. We do this locally so that 749 * this code is portable across operating systems. 750 */ 751 AsConvertToLineFeeds (Buffer); 752 753 *FileBuffer = Buffer; 754 *FileSize = Size; 755 756 return 0; 757 758 759 ErrorExit: 760 761 close (FileHandle); 762 return -1; 763 } 764 765 766 /****************************************************************************** 767 * 768 * FUNCTION: AsPutFile 769 * 770 * DESCRIPTION: Create a new output file and write the entire contents of the 771 * buffer to the new file. Buffer must be a zero terminated string 772 * 773 ******************************************************************************/ 774 775 int 776 AsPutFile ( 777 char *Pathname, 778 char *FileBuffer, 779 UINT32 SystemFlags) 780 { 781 UINT32 FileSize; 782 int DestHandle; 783 int OpenFlags; 784 785 786 /* Create the target file */ 787 788 OpenFlags = O_TRUNC | O_CREAT | O_WRONLY | O_BINARY; 789 790 if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS)) 791 { 792 /* Put back the CR before each LF */ 793 794 AsInsertCarriageReturns (FileBuffer); 795 } 796 797 DestHandle = open (Pathname, OpenFlags, S_IREAD | S_IWRITE); 798 if (DestHandle == -1) 799 { 800 perror ("Could not create destination file"); 801 printf ("Could not create destination file \"%s\"\n", Pathname); 802 return -1; 803 } 804 805 /* Write the buffer to the file */ 806 807 FileSize = strlen (FileBuffer); 808 write (DestHandle, FileBuffer, FileSize); 809 810 close (DestHandle); 811 812 return 0; 813 } 814 815 816