1 /****************************************************************************** 2 * 3 * Module Name: asconvrt - Source conversion code 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 AS_BRACE_INFO Gbl_BraceInfo[] = 47 { 48 {" if", 3}, 49 {" else if", 8}, 50 {" else while", 11}, 51 {" else", 5}, 52 {" do ", 4}, 53 {NULL, 0} 54 }; 55 56 57 /* Local prototypes */ 58 59 static char * 60 AsMatchValidToken ( 61 char *Buffer, 62 char *Filename, 63 char TargetChar, 64 AS_SCAN_CALLBACK Callback); 65 66 static char * 67 AsCheckBracesCallback ( 68 char *Buffer, 69 char *Filename, 70 UINT32 LineNumber); 71 72 static UINT32 73 AsCountLines ( 74 char *Buffer, 75 char *Filename); 76 77 78 79 #define MODULE_HEADER_BEGIN "/******************************************************************************\n *\n * Module Name:"; 80 #define MODULE_HEADER_END " *****************************************************************************/\n\n" 81 #define INTEL_COPYRIGHT " * Copyright (C) 2000 - 2018, Intel Corp.\n" 82 83 /* Opening signature of the Intel legal header */ 84 85 char *HeaderBegin = "/******************************************************************************\n *\n * 1. Copyright Notice"; 86 87 UINT32 NonAnsiCommentCount; 88 89 char CopyRightHeaderEnd[] = INTEL_COPYRIGHT " *\n" MODULE_HEADER_END; 90 91 /****************************************************************************** 92 * 93 * FUNCTION: AsCountNonAnsiComments 94 * 95 * DESCRIPTION: Count the number of "//" comments. This type of comment is 96 * non-ANSI C. 97 * 98 * NOTE: July 2014: Allows // within quoted strings and within normal 99 * comments. Eliminates extraneous warnings from this utility. 100 * 101 ******************************************************************************/ 102 103 void 104 AsCountNonAnsiComments ( 105 char *Buffer, 106 char *Filename) 107 { 108 109 AsMatchValidToken (Buffer, Filename, 0, NULL); 110 111 /* Error if any slash-slash comments found */ 112 113 if (NonAnsiCommentCount) 114 { 115 AsPrint ("Non-ANSI // Comments Found", NonAnsiCommentCount, Filename); 116 Gbl_NonAnsiComments += NonAnsiCommentCount; 117 } 118 } 119 120 121 /****************************************************************************** 122 * 123 * FUNCTION: AsCheckForBraces 124 * 125 * DESCRIPTION: Check for an open brace after each if/else/do (etc.) 126 * statement 127 * 128 ******************************************************************************/ 129 130 void 131 AsCheckForBraces ( 132 char *Buffer, 133 char *Filename) 134 { 135 136 AsMatchValidToken (Buffer, Filename, 0, AsCheckBracesCallback); 137 } 138 139 140 /****************************************************************************** 141 * 142 * FUNCTION: AsCheckBracesCallback 143 * 144 * DESCRIPTION: Check if/else/do statements. Ensure that braces 145 * are always used. 146 * 147 * TBD: Currently, don't check while() statements. The problem is that there 148 * are two forms: do {} while (); and while () {}. 149 * 150 ******************************************************************************/ 151 152 static char * 153 AsCheckBracesCallback ( 154 char *Buffer, 155 char *Filename, 156 UINT32 LineNumber) 157 { 158 char *SubBuffer = Buffer; 159 char *NextBrace; 160 char *NextSemicolon; 161 AS_BRACE_INFO *BraceInfo; 162 163 164 for (BraceInfo = Gbl_BraceInfo; BraceInfo->Operator; BraceInfo++) 165 { 166 if (!(strncmp (BraceInfo->Operator, SubBuffer, BraceInfo->Length))) 167 { 168 SubBuffer += (BraceInfo->Length - 1); 169 170 /* Find next brace and the next semicolon */ 171 172 NextBrace = AsMatchValidToken (SubBuffer, Filename, '{', NULL); 173 NextSemicolon = AsMatchValidToken (SubBuffer, Filename, ';', NULL); 174 175 /* Next brace should appear before next semicolon */ 176 177 if ((!NextBrace) || 178 (NextSemicolon && (NextBrace > NextSemicolon))) 179 { 180 Gbl_MissingBraces++; 181 182 if (!Gbl_QuietMode) 183 { 184 printf ("Missing braces for <%s>, line %u: %s\n", 185 BraceInfo->Operator + 1, LineNumber, Filename); 186 } 187 } 188 189 return (SubBuffer); 190 } 191 } 192 193 /* No match, just return original buffer */ 194 195 return (Buffer); 196 } 197 198 199 /****************************************************************************** 200 * 201 * FUNCTION: AsMatchValidToken 202 * 203 * DESCRIPTION: Find the next matching token in the input buffer. 204 * 205 ******************************************************************************/ 206 207 static char * 208 AsMatchValidToken ( 209 char *Buffer, 210 char *Filename, 211 char TargetChar, 212 AS_SCAN_CALLBACK Callback) 213 { 214 char *SubBuffer = Buffer; 215 char *StringStart; 216 UINT32 TotalLines; 217 218 219 TotalLines = 1; 220 NonAnsiCommentCount = 0; 221 222 /* Scan from current position up to the end if necessary */ 223 224 while (*SubBuffer) 225 { 226 /* Skip normal comments */ 227 228 if ((*SubBuffer == '/') && 229 (*(SubBuffer + 1) == '*')) 230 { 231 /* Must maintain line count */ 232 233 SubBuffer += 2; 234 while (strncmp ("*/", SubBuffer, 2)) 235 { 236 if (*SubBuffer == '\n') 237 { 238 TotalLines++; 239 } 240 SubBuffer++; 241 } 242 243 SubBuffer += 2; 244 continue; 245 } 246 247 /* Skip single quoted chars */ 248 249 if (*SubBuffer == '\'') 250 { 251 SubBuffer++; 252 if (!(*SubBuffer)) 253 { 254 break; 255 } 256 257 if (*SubBuffer == '\\') 258 { 259 SubBuffer++; 260 } 261 262 SubBuffer++; 263 continue; 264 } 265 266 /* Skip quoted strings */ 267 268 if (*SubBuffer == '"') 269 { 270 StringStart = SubBuffer; 271 SubBuffer++; 272 if (!(*SubBuffer)) 273 { 274 break; 275 } 276 277 while (*SubBuffer != '"') 278 { 279 if ((*SubBuffer == '\n') || 280 (!(*SubBuffer))) 281 { 282 AsPrint ("Unbalanced quoted string",1, Filename); 283 printf (" %.32s (line %u)\n", StringStart, TotalLines); 284 break; 285 } 286 287 /* Handle escapes within the string */ 288 289 if (*SubBuffer == '\\') 290 { 291 SubBuffer++; 292 } 293 294 SubBuffer++; 295 } 296 297 SubBuffer++; 298 continue; 299 } 300 301 /* Now we can check for a slash-slash comment */ 302 303 if ((*SubBuffer == '/') && 304 (*(SubBuffer + 1) == '/')) 305 { 306 NonAnsiCommentCount++; 307 308 /* Skip to end-of-line */ 309 310 while ((*SubBuffer != '\n') && 311 (*SubBuffer)) 312 { 313 SubBuffer++; 314 } 315 316 if (!(*SubBuffer)) 317 { 318 break; 319 } 320 321 if (*SubBuffer == '\n') 322 { 323 TotalLines++; 324 } 325 326 SubBuffer++; 327 continue; 328 } 329 330 /* Finally, check for a newline */ 331 332 if (*SubBuffer == '\n') 333 { 334 TotalLines++; 335 SubBuffer++; 336 continue; 337 } 338 339 /* Normal character, do the user actions */ 340 341 if (Callback) 342 { 343 SubBuffer = Callback (SubBuffer, Filename, TotalLines); 344 } 345 346 if (TargetChar && (*SubBuffer == TargetChar)) 347 { 348 return (SubBuffer); 349 } 350 351 SubBuffer++; 352 } 353 354 return (NULL); 355 } 356 357 358 /****************************************************************************** 359 * 360 * FUNCTION: AsRemoveExtraLines 361 * 362 * DESCRIPTION: Remove all extra lines at the start and end of the file. 363 * 364 ******************************************************************************/ 365 366 void 367 AsRemoveExtraLines ( 368 char *FileBuffer, 369 char *Filename) 370 { 371 char *FileEnd; 372 int Length; 373 374 375 /* Remove any extra lines at the start of the file */ 376 377 while (*FileBuffer == '\n') 378 { 379 printf ("Removing extra line at start of file: %s\n", Filename); 380 AsRemoveData (FileBuffer, FileBuffer + 1); 381 } 382 383 /* Remove any extra lines at the end of the file */ 384 385 Length = strlen (FileBuffer); 386 FileEnd = FileBuffer + (Length - 2); 387 388 while (*FileEnd == '\n') 389 { 390 printf ("Removing extra line at end of file: %s\n", Filename); 391 AsRemoveData (FileEnd, FileEnd + 1); 392 FileEnd--; 393 } 394 } 395 396 397 /****************************************************************************** 398 * 399 * FUNCTION: AsRemoveSpacesAfterPeriod 400 * 401 * DESCRIPTION: Remove an extra space after a period. 402 * 403 ******************************************************************************/ 404 405 void 406 AsRemoveSpacesAfterPeriod ( 407 char *FileBuffer, 408 char *Filename) 409 { 410 int ReplaceCount = 0; 411 char *Possible; 412 413 414 Possible = FileBuffer; 415 while (Possible) 416 { 417 Possible = strstr (Possible, ". "); 418 if (Possible) 419 { 420 if ((*(Possible -1) == '.') || 421 (*(Possible -1) == '\"') || 422 (*(Possible -1) == '\n')) 423 { 424 Possible += 3; 425 continue; 426 } 427 428 Possible = AsReplaceData (Possible, 3, ". ", 2); 429 ReplaceCount++; 430 } 431 } 432 433 if (ReplaceCount) 434 { 435 printf ("Removed %d extra blanks after a period: %s\n", 436 ReplaceCount, Filename); 437 } 438 } 439 440 441 /****************************************************************************** 442 * 443 * FUNCTION: AsMatchExactWord 444 * 445 * DESCRIPTION: Check previous and next characters for whitespace 446 * 447 ******************************************************************************/ 448 449 BOOLEAN 450 AsMatchExactWord ( 451 char *Word, 452 UINT32 WordLength) 453 { 454 char NextChar; 455 char PrevChar; 456 457 458 NextChar = Word[WordLength]; 459 PrevChar = * (Word -1); 460 461 if (isalnum ((int) NextChar) || 462 (NextChar == '_') || 463 isalnum ((int) PrevChar) || 464 (PrevChar == '_')) 465 { 466 return (FALSE); 467 } 468 469 return (TRUE); 470 } 471 472 473 /****************************************************************************** 474 * 475 * FUNCTION: AsPrint 476 * 477 * DESCRIPTION: Common formatted print 478 * 479 ******************************************************************************/ 480 481 void 482 AsPrint ( 483 char *Message, 484 UINT32 Count, 485 char *Filename) 486 { 487 488 if (Gbl_QuietMode) 489 { 490 return; 491 } 492 493 printf ("-- %4u %28.28s : %s\n", Count, Message, Filename); 494 } 495 496 497 /****************************************************************************** 498 * 499 * FUNCTION: AsTrimLines 500 * 501 * DESCRIPTION: Remove extra blanks from the end of source lines. Does not 502 * check for tabs. 503 * 504 ******************************************************************************/ 505 506 void 507 AsTrimLines ( 508 char *Buffer, 509 char *Filename) 510 { 511 char *SubBuffer = Buffer; 512 char *StartWhiteSpace = NULL; 513 UINT32 SpaceCount = 0; 514 515 516 while (*SubBuffer) 517 { 518 while (*SubBuffer != '\n') 519 { 520 if (!*SubBuffer) 521 { 522 goto Exit; 523 } 524 525 if (*SubBuffer == ' ') 526 { 527 if (!StartWhiteSpace) 528 { 529 StartWhiteSpace = SubBuffer; 530 } 531 } 532 else 533 { 534 StartWhiteSpace = NULL; 535 } 536 537 SubBuffer++; 538 } 539 540 if (StartWhiteSpace) 541 { 542 SpaceCount += (SubBuffer - StartWhiteSpace); 543 544 /* Remove the spaces */ 545 546 SubBuffer = AsRemoveData (StartWhiteSpace, SubBuffer); 547 StartWhiteSpace = NULL; 548 } 549 550 SubBuffer++; 551 } 552 553 554 Exit: 555 if (SpaceCount) 556 { 557 Gbl_MadeChanges = TRUE; 558 AsPrint ("Extraneous spaces removed", SpaceCount, Filename); 559 } 560 } 561 562 563 /****************************************************************************** 564 * 565 * FUNCTION: AsTrimWhitespace 566 * 567 * DESCRIPTION: Remove "excess" blank lines - any more than 2 blank lines. 568 * this can happen during the translation when lines are removed. 569 * 570 ******************************************************************************/ 571 572 void 573 AsTrimWhitespace ( 574 char *Buffer) 575 { 576 char *SubBuffer; 577 int ReplaceCount = 1; 578 579 580 while (ReplaceCount) 581 { 582 ReplaceCount = AsReplaceString ("\n\n\n\n", "\n\n\n", 583 REPLACE_SUBSTRINGS, Buffer); 584 } 585 586 /* 587 * Check for exactly one blank line after the copyright header 588 */ 589 590 /* Find the header */ 591 592 SubBuffer = strstr (Buffer, HeaderBegin); 593 if (!SubBuffer) 594 { 595 return; 596 } 597 598 /* Find the end of the header */ 599 600 SubBuffer = strstr (SubBuffer, "*/"); 601 SubBuffer = AsSkipPastChar (SubBuffer, '\n'); 602 603 /* Replace a double blank line with a single */ 604 605 if (!strncmp (SubBuffer, "\n\n", 2)) 606 { 607 AsReplaceData (SubBuffer, 2, "\n", 1); 608 AcpiOsPrintf ("Found multiple blank lines after copyright\n"); 609 } 610 611 /* If no blank line after header, insert one */ 612 613 else if (*SubBuffer != '\n') 614 { 615 AsInsertData (SubBuffer, "\n", 1); 616 AcpiOsPrintf ("Inserted blank line after copyright\n"); 617 } 618 } 619 620 621 /****************************************************************************** 622 * 623 * FUNCTION: AsReplaceHeader 624 * 625 * DESCRIPTION: Replace the default Intel legal header with a new header 626 * 627 ******************************************************************************/ 628 629 void 630 AsReplaceHeader ( 631 char *Buffer, 632 char *NewHeader) 633 { 634 char *SubBuffer; 635 char *TokenEnd; 636 637 638 /* Find the original header */ 639 640 SubBuffer = strstr (Buffer, HeaderBegin); 641 if (!SubBuffer) 642 { 643 return; 644 } 645 646 /* Find the end of the original header */ 647 648 TokenEnd = strstr (SubBuffer, "*/"); 649 TokenEnd = AsSkipPastChar (TokenEnd, '\n'); 650 651 /* Delete old header, insert new one */ 652 653 AsReplaceData (SubBuffer, TokenEnd - SubBuffer, 654 NewHeader, strlen (NewHeader)); 655 } 656 657 658 /****************************************************************************** 659 * 660 * FUNCTION: AsDoSpdxHeader 661 * 662 * DESCRIPTION: Replace the default Intel legal header with a new header 663 * 664 ******************************************************************************/ 665 666 void 667 AsDoSpdxHeader ( 668 char *Buffer, 669 char *SpdxHeader) 670 { 671 char *SubBuffer; 672 673 674 /* Place an SPDX header at the very top */ 675 676 AsReplaceData (Buffer, 0, 677 SpdxHeader, strlen (SpdxHeader)); 678 679 /* Place an Intel copyright notice in the module header */ 680 681 SubBuffer = strstr (Buffer, MODULE_HEADER_END); 682 if (!SubBuffer) 683 { 684 return; 685 } 686 687 AsReplaceData (SubBuffer, strlen (MODULE_HEADER_END), 688 CopyRightHeaderEnd, strlen (CopyRightHeaderEnd)); 689 } 690 691 /****************************************************************************** 692 * 693 * FUNCTION: AsReplaceString 694 * 695 * DESCRIPTION: Replace all instances of a target string with a replacement 696 * string. Returns count of the strings replaced. 697 * 698 ******************************************************************************/ 699 700 int 701 AsReplaceString ( 702 char *Target, 703 char *Replacement, 704 UINT8 Type, 705 char *Buffer) 706 { 707 char *SubString1; 708 char *SubString2; 709 char *SubBuffer; 710 int TargetLength; 711 int ReplacementLength; 712 int ReplaceCount = 0; 713 714 715 TargetLength = strlen (Target); 716 ReplacementLength = strlen (Replacement); 717 718 SubBuffer = Buffer; 719 SubString1 = Buffer; 720 721 while (SubString1) 722 { 723 /* Find the target string */ 724 725 SubString1 = strstr (SubBuffer, Target); 726 if (!SubString1) 727 { 728 return (ReplaceCount); 729 } 730 731 /* 732 * Check for translation escape string -- means to ignore 733 * blocks of code while replacing 734 */ 735 if (Gbl_IgnoreTranslationEscapes) 736 { 737 SubString2 = NULL; 738 } 739 else 740 { 741 SubString2 = strstr (SubBuffer, AS_START_IGNORE); 742 } 743 744 if ((SubString2) && 745 (SubString2 < SubString1)) 746 { 747 /* Find end of the escape block starting at "Substring2" */ 748 749 SubString2 = strstr (SubString2, AS_STOP_IGNORE); 750 if (!SubString2) 751 { 752 /* Didn't find terminator */ 753 754 return (ReplaceCount); 755 } 756 757 /* Move buffer to end of escape block and continue */ 758 759 SubBuffer = SubString2; 760 } 761 762 /* Do the actual replace if the target was found */ 763 764 else 765 { 766 if ((Type & REPLACE_MASK) == REPLACE_WHOLE_WORD) 767 { 768 if (!AsMatchExactWord (SubString1, TargetLength)) 769 { 770 SubBuffer = SubString1 + 1; 771 continue; 772 } 773 } 774 775 SubBuffer = AsReplaceData (SubString1, TargetLength, 776 Replacement, ReplacementLength); 777 778 if ((Type & EXTRA_INDENT_C) && 779 (!Gbl_StructDefs)) 780 { 781 SubBuffer = AsInsertData (SubBuffer, " ", 8); 782 } 783 784 ReplaceCount++; 785 } 786 } 787 788 return (ReplaceCount); 789 } 790 791 792 /****************************************************************************** 793 * 794 * FUNCTION: AsConvertToLineFeeds 795 * 796 * DESCRIPTION: Convert all CR/LF pairs to LF only. 797 * 798 ******************************************************************************/ 799 800 void 801 AsConvertToLineFeeds ( 802 char *Buffer) 803 { 804 char *SubString; 805 char *SubBuffer; 806 807 808 SubBuffer = Buffer; 809 SubString = Buffer; 810 811 while (SubString) 812 { 813 /* Find the target string */ 814 815 SubString = strstr (SubBuffer, "\r\n"); 816 if (!SubString) 817 { 818 return; 819 } 820 821 SubBuffer = AsReplaceData (SubString, 1, NULL, 0); 822 } 823 } 824 825 826 /****************************************************************************** 827 * 828 * FUNCTION: AsInsertCarriageReturns 829 * 830 * DESCRIPTION: Convert lone LFs to CR/LF pairs. 831 * 832 ******************************************************************************/ 833 834 void 835 AsInsertCarriageReturns ( 836 char *Buffer) 837 { 838 char *SubString; 839 char *SubBuffer; 840 841 842 SubBuffer = Buffer; 843 SubString = Buffer; 844 845 while (SubString) 846 { 847 /* Find the target string */ 848 849 SubString = strstr (SubBuffer, "\n"); 850 if (!SubString) 851 { 852 return; 853 } 854 855 SubBuffer = AsInsertData (SubString, "\r", 1); 856 SubBuffer += 1; 857 } 858 } 859 860 861 /****************************************************************************** 862 * 863 * FUNCTION: AsBracesOnSameLine 864 * 865 * DESCRIPTION: Move opening braces up to the same line as an if, for, else, 866 * or while statement (leave function opening brace on separate 867 * line). 868 * 869 ******************************************************************************/ 870 871 void 872 AsBracesOnSameLine ( 873 char *Buffer) 874 { 875 char *SubBuffer = Buffer; 876 char *Beginning; 877 char *StartOfThisLine; 878 char *Next; 879 BOOLEAN BlockBegin = TRUE; 880 881 882 while (*SubBuffer) 883 { 884 /* Ignore comments */ 885 886 if ((SubBuffer[0] == '/') && 887 (SubBuffer[1] == '*')) 888 { 889 SubBuffer = strstr (SubBuffer, "*/"); 890 if (!SubBuffer) 891 { 892 return; 893 } 894 895 SubBuffer += 2; 896 continue; 897 } 898 899 /* Ignore quoted strings */ 900 901 if (*SubBuffer == '\"') 902 { 903 SubBuffer++; 904 SubBuffer = AsSkipPastChar (SubBuffer, '\"'); 905 if (!SubBuffer) 906 { 907 return; 908 } 909 } 910 911 if (!strncmp ("\n}", SubBuffer, 2)) 912 { 913 /* 914 * A newline followed by a closing brace closes a function 915 * or struct or initializer block 916 */ 917 BlockBegin = TRUE; 918 } 919 920 /* 921 * Move every standalone brace up to the previous line 922 * Check for digit will ignore initializer lists surrounded by braces. 923 * This will work until we we need more complex detection. 924 */ 925 if ((*SubBuffer == '{') && !isdigit ((int) SubBuffer[1])) 926 { 927 if (BlockBegin) 928 { 929 BlockBegin = FALSE; 930 } 931 else 932 { 933 /* 934 * Backup to previous non-whitespace 935 */ 936 Beginning = SubBuffer - 1; 937 while ((*Beginning == ' ') || 938 (*Beginning == '\n')) 939 { 940 Beginning--; 941 } 942 943 StartOfThisLine = Beginning; 944 while (*StartOfThisLine != '\n') 945 { 946 StartOfThisLine--; 947 } 948 949 /* 950 * Move the brace up to the previous line, UNLESS: 951 * 952 * 1) There is a conditional compile on the line (starts with '#') 953 * 2) Previous line ends with an '=' (Start of initializer block) 954 * 3) Previous line ends with a comma (part of an init list) 955 * 4) Previous line ends with a backslash (part of a macro) 956 */ 957 if ((StartOfThisLine[1] != '#') && 958 (*Beginning != '\\') && 959 (*Beginning != '/') && 960 (*Beginning != '{') && 961 (*Beginning != '=') && 962 (*Beginning != ',')) 963 { 964 Beginning++; 965 SubBuffer++; 966 967 Gbl_MadeChanges = TRUE; 968 969 #ifdef ADD_EXTRA_WHITESPACE 970 AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3); 971 #else 972 /* Find non-whitespace start of next line */ 973 974 Next = SubBuffer + 1; 975 while ((*Next == ' ') || 976 (*Next == '\t')) 977 { 978 Next++; 979 } 980 981 /* Find non-whitespace start of this line */ 982 983 StartOfThisLine++; 984 while ((*StartOfThisLine == ' ') || 985 (*StartOfThisLine == '\t')) 986 { 987 StartOfThisLine++; 988 } 989 990 /* 991 * Must be a single-line comment to need more whitespace 992 * Even then, we don't need more if the previous statement 993 * is an "else". 994 */ 995 if ((Next[0] == '/') && 996 (Next[1] == '*') && 997 (Next[2] != '\n') && 998 999 (!strncmp (StartOfThisLine, "else if", 7) || 1000 !strncmp (StartOfThisLine, "else while", 10) || 1001 strncmp (StartOfThisLine, "else", 4))) 1002 { 1003 AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3); 1004 } 1005 else 1006 { 1007 AsReplaceData (Beginning, SubBuffer - Beginning, " {", 2); 1008 } 1009 #endif 1010 } 1011 } 1012 } 1013 1014 SubBuffer++; 1015 } 1016 } 1017 1018 1019 /****************************************************************************** 1020 * 1021 * FUNCTION: AsTabify4 1022 * 1023 * DESCRIPTION: Convert the text to tabbed text. Alignment of text is 1024 * preserved. 1025 * 1026 ******************************************************************************/ 1027 1028 void 1029 AsTabify4 ( 1030 char *Buffer) 1031 { 1032 char *SubBuffer = Buffer; 1033 char *NewSubBuffer; 1034 UINT32 SpaceCount = 0; 1035 UINT32 Column = 0; 1036 1037 1038 while (*SubBuffer) 1039 { 1040 if (*SubBuffer == '\n') 1041 { 1042 Column = 0; 1043 } 1044 else 1045 { 1046 Column++; 1047 } 1048 1049 /* Ignore comments */ 1050 1051 if ((SubBuffer[0] == '/') && 1052 (SubBuffer[1] == '*')) 1053 { 1054 SubBuffer = strstr (SubBuffer, "*/"); 1055 if (!SubBuffer) 1056 { 1057 return; 1058 } 1059 1060 SubBuffer += 2; 1061 continue; 1062 } 1063 1064 /* Ignore quoted strings */ 1065 1066 if (*SubBuffer == '\"') 1067 { 1068 SubBuffer++; 1069 SubBuffer = AsSkipPastChar (SubBuffer, '\"'); 1070 if (!SubBuffer) 1071 { 1072 return; 1073 } 1074 SpaceCount = 0; 1075 } 1076 1077 if (*SubBuffer == ' ') 1078 { 1079 SpaceCount++; 1080 1081 if (SpaceCount >= 4) 1082 { 1083 SpaceCount = 0; 1084 1085 NewSubBuffer = (SubBuffer + 1) - 4; 1086 *NewSubBuffer = '\t'; 1087 NewSubBuffer++; 1088 1089 /* Remove the spaces */ 1090 1091 SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer + 1); 1092 } 1093 1094 if ((Column % 4) == 0) 1095 { 1096 SpaceCount = 0; 1097 } 1098 } 1099 else 1100 { 1101 SpaceCount = 0; 1102 } 1103 1104 SubBuffer++; 1105 } 1106 } 1107 1108 1109 /****************************************************************************** 1110 * 1111 * FUNCTION: AsTabify8 1112 * 1113 * DESCRIPTION: Convert the text to tabbed text. Alignment of text is 1114 * preserved. 1115 * 1116 ******************************************************************************/ 1117 1118 void 1119 AsTabify8 ( 1120 char *Buffer) 1121 { 1122 char *SubBuffer = Buffer; 1123 char *NewSubBuffer; 1124 char *CommentEnd = NULL; 1125 UINT32 SpaceCount = 0; 1126 UINT32 Column = 0; 1127 UINT32 TabCount = 0; 1128 UINT32 LastLineTabCount = 0; 1129 UINT32 LastLineColumnStart = 0; 1130 UINT32 ThisColumnStart = 0; 1131 UINT32 ThisTabCount = 0; 1132 char *FirstNonBlank = NULL; 1133 1134 1135 while (*SubBuffer) 1136 { 1137 if (*SubBuffer == '\n') 1138 { 1139 /* This is a standalone blank line */ 1140 1141 FirstNonBlank = NULL; 1142 Column = 0; 1143 SpaceCount = 0; 1144 TabCount = 0; 1145 SubBuffer++; 1146 continue; 1147 } 1148 1149 if (!FirstNonBlank) 1150 { 1151 /* Find the first non-blank character on this line */ 1152 1153 FirstNonBlank = SubBuffer; 1154 while (*FirstNonBlank == ' ') 1155 { 1156 FirstNonBlank++; 1157 } 1158 1159 /* 1160 * This mechanism limits the difference in tab counts from 1161 * line to line. It helps avoid the situation where a second 1162 * continuation line (which was indented correctly for tabs=4) would 1163 * get indented off the screen if we just blindly converted to tabs. 1164 */ 1165 ThisColumnStart = FirstNonBlank - SubBuffer; 1166 1167 if (LastLineTabCount == 0) 1168 { 1169 ThisTabCount = 0; 1170 } 1171 else if (ThisColumnStart == LastLineColumnStart) 1172 { 1173 ThisTabCount = LastLineTabCount -1; 1174 } 1175 else 1176 { 1177 ThisTabCount = LastLineTabCount + 1; 1178 } 1179 } 1180 1181 Column++; 1182 1183 /* Check if we are in a comment */ 1184 1185 if ((SubBuffer[0] == '*') && 1186 (SubBuffer[1] == '/')) 1187 { 1188 SpaceCount = 0; 1189 SubBuffer += 2; 1190 1191 if (*SubBuffer == '\n') 1192 { 1193 if (TabCount > 0) 1194 { 1195 LastLineTabCount = TabCount; 1196 TabCount = 0; 1197 } 1198 1199 FirstNonBlank = NULL; 1200 LastLineColumnStart = ThisColumnStart; 1201 SubBuffer++; 1202 } 1203 1204 continue; 1205 } 1206 1207 /* Check for comment open */ 1208 1209 if ((SubBuffer[0] == '/') && 1210 (SubBuffer[1] == '*')) 1211 { 1212 /* Find the end of the comment, it must exist */ 1213 1214 CommentEnd = strstr (SubBuffer, "*/"); 1215 if (!CommentEnd) 1216 { 1217 return; 1218 } 1219 1220 /* Toss the rest of this line or single-line comment */ 1221 1222 while ((SubBuffer < CommentEnd) && 1223 (*SubBuffer != '\n')) 1224 { 1225 SubBuffer++; 1226 } 1227 1228 if (*SubBuffer == '\n') 1229 { 1230 if (TabCount > 0) 1231 { 1232 LastLineTabCount = TabCount; 1233 TabCount = 0; 1234 } 1235 1236 FirstNonBlank = NULL; 1237 LastLineColumnStart = ThisColumnStart; 1238 } 1239 1240 SpaceCount = 0; 1241 continue; 1242 } 1243 1244 /* Ignore quoted strings */ 1245 1246 if ((!CommentEnd) && (*SubBuffer == '\"')) 1247 { 1248 SubBuffer++; 1249 SubBuffer = AsSkipPastChar (SubBuffer, '\"'); 1250 if (!SubBuffer) 1251 { 1252 return; 1253 } 1254 1255 SpaceCount = 0; 1256 } 1257 1258 if (*SubBuffer != ' ') 1259 { 1260 /* Not a space, skip to end of line */ 1261 1262 SubBuffer = AsSkipUntilChar (SubBuffer, '\n'); 1263 if (!SubBuffer) 1264 { 1265 return; 1266 } 1267 if (TabCount > 0) 1268 { 1269 LastLineTabCount = TabCount; 1270 TabCount = 0; 1271 } 1272 1273 FirstNonBlank = NULL; 1274 LastLineColumnStart = ThisColumnStart; 1275 Column = 0; 1276 SpaceCount = 0; 1277 } 1278 else 1279 { 1280 /* Another space */ 1281 1282 SpaceCount++; 1283 1284 if (SpaceCount >= 4) 1285 { 1286 /* Replace this group of spaces with a tab character */ 1287 1288 SpaceCount = 0; 1289 1290 NewSubBuffer = SubBuffer - 3; 1291 1292 if (TabCount <= ThisTabCount ? (ThisTabCount +1) : 0) 1293 { 1294 *NewSubBuffer = '\t'; 1295 NewSubBuffer++; 1296 SubBuffer++; 1297 TabCount++; 1298 } 1299 1300 /* Remove the spaces */ 1301 1302 SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer); 1303 continue; 1304 } 1305 } 1306 1307 SubBuffer++; 1308 } 1309 } 1310 1311 1312 /****************************************************************************** 1313 * 1314 * FUNCTION: AsCountLines 1315 * 1316 * DESCRIPTION: Count the number of lines in the input buffer. Also count 1317 * the number of long lines (lines longer than 80 chars). 1318 * 1319 ******************************************************************************/ 1320 1321 static UINT32 1322 AsCountLines ( 1323 char *Buffer, 1324 char *Filename) 1325 { 1326 char *SubBuffer = Buffer; 1327 char *EndOfLine; 1328 UINT32 LineCount = 0; 1329 UINT32 LongLineCount = 0; 1330 1331 1332 while (*SubBuffer) 1333 { 1334 EndOfLine = AsSkipUntilChar (SubBuffer, '\n'); 1335 if (!EndOfLine) 1336 { 1337 Gbl_TotalLines += LineCount; 1338 return (LineCount); 1339 } 1340 1341 if ((EndOfLine - SubBuffer) > 80) 1342 { 1343 LongLineCount++; 1344 VERBOSE_PRINT (("long: %.80s\n", SubBuffer)); 1345 } 1346 1347 LineCount++; 1348 SubBuffer = EndOfLine + 1; 1349 } 1350 1351 if (LongLineCount) 1352 { 1353 VERBOSE_PRINT (("%u Lines longer than 80 found in %s\n", 1354 LongLineCount, Filename)); 1355 1356 Gbl_LongLines += LongLineCount; 1357 } 1358 1359 Gbl_TotalLines += LineCount; 1360 return (LineCount); 1361 } 1362 1363 1364 /****************************************************************************** 1365 * 1366 * FUNCTION: AsCountTabs 1367 * 1368 * DESCRIPTION: Simply count the number of tabs in the input file buffer 1369 * 1370 ******************************************************************************/ 1371 1372 void 1373 AsCountTabs ( 1374 char *Buffer, 1375 char *Filename) 1376 { 1377 UINT32 i; 1378 UINT32 TabCount = 0; 1379 1380 1381 for (i = 0; Buffer[i]; i++) 1382 { 1383 if (Buffer[i] == '\t') 1384 { 1385 TabCount++; 1386 } 1387 } 1388 1389 if (TabCount) 1390 { 1391 AsPrint ("Tabs found", TabCount, Filename); 1392 Gbl_Tabs += TabCount; 1393 } 1394 1395 AsCountLines (Buffer, Filename); 1396 } 1397 1398 1399 /****************************************************************************** 1400 * 1401 * FUNCTION: AsCountSourceLines 1402 * 1403 * DESCRIPTION: Count the number of C source lines. Defined by 1) not a 1404 * comment, and 2) not a blank line. 1405 * 1406 ******************************************************************************/ 1407 1408 void 1409 AsCountSourceLines ( 1410 char *Buffer, 1411 char *Filename) 1412 { 1413 char *SubBuffer = Buffer; 1414 UINT32 LineCount = 0; 1415 UINT32 WhiteCount = 0; 1416 UINT32 CommentCount = 0; 1417 1418 1419 while (*SubBuffer) 1420 { 1421 /* Detect comments (// comments are not used, non-ansii) */ 1422 1423 if ((SubBuffer[0] == '/') && 1424 (SubBuffer[1] == '*')) 1425 { 1426 SubBuffer += 2; 1427 1428 /* First line of multi-line comment is often just whitespace */ 1429 1430 if (SubBuffer[0] == '\n') 1431 { 1432 WhiteCount++; 1433 SubBuffer++; 1434 } 1435 else 1436 { 1437 CommentCount++; 1438 } 1439 1440 /* Find end of comment */ 1441 1442 while (SubBuffer[0] && SubBuffer[1] && 1443 !(((SubBuffer[0] == '*') && 1444 (SubBuffer[1] == '/')))) 1445 { 1446 if (SubBuffer[0] == '\n') 1447 { 1448 CommentCount++; 1449 } 1450 1451 SubBuffer++; 1452 } 1453 } 1454 1455 /* A linefeed followed by a non-linefeed is a valid source line */ 1456 1457 else if ((SubBuffer[0] == '\n') && 1458 (SubBuffer[1] != '\n')) 1459 { 1460 LineCount++; 1461 } 1462 1463 /* Two back-to-back linefeeds indicate a whitespace line */ 1464 1465 else if ((SubBuffer[0] == '\n') && 1466 (SubBuffer[1] == '\n')) 1467 { 1468 WhiteCount++; 1469 } 1470 1471 SubBuffer++; 1472 } 1473 1474 /* Adjust comment count for legal header */ 1475 1476 if (Gbl_HeaderSize < CommentCount) 1477 { 1478 CommentCount -= Gbl_HeaderSize; 1479 Gbl_HeaderLines += Gbl_HeaderSize; 1480 } 1481 1482 Gbl_SourceLines += LineCount; 1483 Gbl_WhiteLines += WhiteCount; 1484 Gbl_CommentLines += CommentCount; 1485 1486 VERBOSE_PRINT (("%u Comment %u White %u Code %u Lines in %s\n", 1487 CommentCount, WhiteCount, LineCount, 1488 LineCount + WhiteCount + CommentCount, Filename)); 1489 } 1490 1491 1492 /****************************************************************************** 1493 * 1494 * FUNCTION: AsInsertPrefix 1495 * 1496 * DESCRIPTION: Insert struct or union prefixes 1497 * 1498 ******************************************************************************/ 1499 1500 void 1501 AsInsertPrefix ( 1502 char *Buffer, 1503 char *Keyword, 1504 UINT8 Type) 1505 { 1506 char *SubString; 1507 char *SubBuffer; 1508 char *EndKeyword; 1509 int InsertLength; 1510 char *InsertString; 1511 int TrailingSpaces; 1512 char LowerKeyword[128]; 1513 int KeywordLength; 1514 1515 1516 switch (Type) 1517 { 1518 case SRC_TYPE_STRUCT: 1519 1520 InsertString = "struct "; 1521 break; 1522 1523 case SRC_TYPE_UNION: 1524 1525 InsertString = "union "; 1526 break; 1527 1528 default: 1529 1530 return; 1531 } 1532 1533 strcpy (LowerKeyword, Keyword); 1534 AcpiUtStrlwr (LowerKeyword); 1535 1536 SubBuffer = Buffer; 1537 SubString = Buffer; 1538 InsertLength = strlen (InsertString); 1539 KeywordLength = strlen (Keyword); 1540 1541 1542 while (SubString) 1543 { 1544 /* Find an instance of the keyword */ 1545 1546 SubString = strstr (SubBuffer, LowerKeyword); 1547 if (!SubString) 1548 { 1549 return; 1550 } 1551 1552 SubBuffer = SubString; 1553 1554 /* Must be standalone word, not a substring */ 1555 1556 if (AsMatchExactWord (SubString, KeywordLength)) 1557 { 1558 /* Make sure the keyword isn't already prefixed with the insert */ 1559 1560 if (!strncmp (SubString - InsertLength, InsertString, InsertLength)) 1561 { 1562 /* Add spaces if not already at the end-of-line */ 1563 1564 if (*(SubBuffer + KeywordLength) != '\n') 1565 { 1566 /* Already present, add spaces after to align structure members */ 1567 1568 #if 0 1569 /* ONLY FOR C FILES */ 1570 AsInsertData (SubBuffer + KeywordLength, " ", 8); 1571 #endif 1572 } 1573 goto Next; 1574 } 1575 1576 /* Make sure the keyword isn't at the end of a struct/union */ 1577 /* Note: This code depends on a single space after the brace */ 1578 1579 if (*(SubString - 2) == '}') 1580 { 1581 goto Next; 1582 } 1583 1584 /* Prefix the keyword with the insert string */ 1585 1586 Gbl_MadeChanges = TRUE; 1587 1588 /* Is there room for insertion */ 1589 1590 EndKeyword = SubString + strlen (LowerKeyword); 1591 1592 TrailingSpaces = 0; 1593 while (EndKeyword[TrailingSpaces] == ' ') 1594 { 1595 TrailingSpaces++; 1596 } 1597 1598 /* 1599 * Use "if (TrailingSpaces > 1)" if we want to ignore casts 1600 */ 1601 SubBuffer = SubString + InsertLength; 1602 1603 if (TrailingSpaces > InsertLength) 1604 { 1605 /* Insert the keyword */ 1606 1607 memmove (SubBuffer, SubString, KeywordLength); 1608 1609 /* Insert the keyword */ 1610 1611 memmove (SubString, InsertString, InsertLength); 1612 } 1613 else 1614 { 1615 AsInsertData (SubString, InsertString, InsertLength); 1616 } 1617 } 1618 1619 Next: 1620 SubBuffer += KeywordLength; 1621 } 1622 } 1623 1624 #ifdef ACPI_FUTURE_IMPLEMENTATION 1625 /****************************************************************************** 1626 * 1627 * FUNCTION: AsTrimComments 1628 * 1629 * DESCRIPTION: Finds 3-line comments with only a single line of text 1630 * 1631 ******************************************************************************/ 1632 1633 void 1634 AsTrimComments ( 1635 char *Buffer, 1636 char *Filename) 1637 { 1638 char *SubBuffer = Buffer; 1639 char *Ptr1; 1640 char *Ptr2; 1641 UINT32 LineCount; 1642 UINT32 ShortCommentCount = 0; 1643 1644 1645 while (1) 1646 { 1647 /* Find comment open, within procedure level */ 1648 1649 SubBuffer = strstr (SubBuffer, " /*"); 1650 if (!SubBuffer) 1651 { 1652 goto Exit; 1653 } 1654 1655 /* Find comment terminator */ 1656 1657 Ptr1 = strstr (SubBuffer, "*/"); 1658 if (!Ptr1) 1659 { 1660 goto Exit; 1661 } 1662 1663 /* Find next EOL (from original buffer) */ 1664 1665 Ptr2 = strstr (SubBuffer, "\n"); 1666 if (!Ptr2) 1667 { 1668 goto Exit; 1669 } 1670 1671 /* Ignore one-line comments */ 1672 1673 if (Ptr1 < Ptr2) 1674 { 1675 /* Normal comment, ignore and continue; */ 1676 1677 SubBuffer = Ptr2; 1678 continue; 1679 } 1680 1681 /* Examine multi-line comment */ 1682 1683 LineCount = 1; 1684 while (Ptr1 > Ptr2) 1685 { 1686 /* Find next EOL */ 1687 1688 Ptr2++; 1689 Ptr2 = strstr (Ptr2, "\n"); 1690 if (!Ptr2) 1691 { 1692 goto Exit; 1693 } 1694 1695 LineCount++; 1696 } 1697 1698 SubBuffer = Ptr1; 1699 1700 if (LineCount <= 3) 1701 { 1702 ShortCommentCount++; 1703 } 1704 } 1705 1706 1707 Exit: 1708 1709 if (ShortCommentCount) 1710 { 1711 AsPrint ("Short Comments found", ShortCommentCount, Filename); 1712 } 1713 } 1714 #endif 1715 1716 #ifdef ACPI_UNUSED_FUNCTIONS 1717 /****************************************************************************** 1718 * 1719 * FUNCTION: AsCheckAndSkipLiterals 1720 * 1721 * DESCRIPTION: Generic routine to skip comments and quoted string literals. 1722 * Keeps a line count. 1723 * 1724 ******************************************************************************/ 1725 1726 static char * 1727 AsCheckAndSkipLiterals ( 1728 char *Buffer, 1729 UINT32 *TotalLines); 1730 1731 1732 static char * 1733 AsCheckAndSkipLiterals ( 1734 char *Buffer, 1735 UINT32 *TotalLines) 1736 { 1737 UINT32 NewLines = 0; 1738 char *SubBuffer = Buffer; 1739 char *LiteralEnd; 1740 1741 1742 /* Ignore comments */ 1743 1744 if ((SubBuffer[0] == '/') && 1745 (SubBuffer[1] == '*')) 1746 { 1747 LiteralEnd = strstr (SubBuffer, "*/"); 1748 SubBuffer += 2; /* Get past comment opening */ 1749 1750 if (!LiteralEnd) 1751 { 1752 return (SubBuffer); 1753 } 1754 1755 while (SubBuffer < LiteralEnd) 1756 { 1757 if (*SubBuffer == '\n') 1758 { 1759 NewLines++; 1760 } 1761 1762 SubBuffer++; 1763 } 1764 1765 SubBuffer += 2; /* Get past comment close */ 1766 } 1767 1768 /* Ignore quoted strings */ 1769 1770 else if (*SubBuffer == '\"') 1771 { 1772 SubBuffer++; 1773 LiteralEnd = AsSkipPastChar (SubBuffer, '\"'); 1774 if (!LiteralEnd) 1775 { 1776 return (SubBuffer); 1777 } 1778 } 1779 1780 if (TotalLines) 1781 { 1782 (*TotalLines) += NewLines; 1783 } 1784 return (SubBuffer); 1785 } 1786 #endif 1787