1 /******************************************************************************
   2  *
   3  * Module Name: asremove - Source conversion - removal functions
   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 AsRemoveStatement (
  50     char                    *Buffer,
  51     char                    *Keyword,
  52     UINT32                  Type);
  53 
  54 
  55 /******************************************************************************
  56  *
  57  * FUNCTION:    AsRemoveStatement
  58  *
  59  * DESCRIPTION: Remove all statements that contain the given keyword.
  60  *              Limitations:  Removes text from the start of the line that
  61  *              contains the keyword to the next semicolon. Currently
  62  *              doesn't ignore comments.
  63  *
  64  ******************************************************************************/
  65 
  66 void
  67 AsRemoveStatement (
  68     char                    *Buffer,
  69     char                    *Keyword,
  70     UINT32                  Type)
  71 {
  72     char                    *SubString;
  73     char                    *SubBuffer;
  74     int                     KeywordLength;
  75 
  76 
  77     KeywordLength = strlen (Keyword);
  78     SubBuffer = Buffer;
  79     SubString = Buffer;
  80 
  81 
  82     while (SubString)
  83     {
  84         SubString = strstr (SubBuffer, Keyword);
  85 
  86         if (SubString)
  87         {
  88             SubBuffer = SubString;
  89 
  90             if ((Type == REPLACE_WHOLE_WORD) &&
  91                 (!AsMatchExactWord (SubString, KeywordLength)))
  92             {
  93                 SubBuffer++;
  94                 continue;
  95             }
  96 
  97             /* Find start of this line */
  98 
  99             while (*SubString != '\n')
 100             {
 101                 SubString--;
 102             }
 103             SubString++;
 104 
 105             /* Find end of this statement */
 106 
 107             SubBuffer = AsSkipPastChar (SubBuffer, ';');
 108             if (!SubBuffer)
 109             {
 110                 return;
 111             }
 112 
 113             /* Find end of this line */
 114 
 115             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
 116             if (!SubBuffer)
 117             {
 118                 return;
 119             }
 120 
 121             /* If next line is blank, remove it too */
 122 
 123             if (*SubBuffer == '\n')
 124             {
 125                 SubBuffer++;
 126             }
 127 
 128             /* Remove the lines */
 129 
 130             SubBuffer = AsRemoveData (SubString, SubBuffer);
 131         }
 132     }
 133 }
 134 
 135 
 136 /******************************************************************************
 137  *
 138  * FUNCTION:    AsRemoveConditionalCompile
 139  *
 140  * DESCRIPTION: Remove a "#ifdef" statement, and all text that it encompasses.
 141  *              Limitations: cannot handle nested ifdefs.
 142  *
 143  ******************************************************************************/
 144 
 145 void
 146 AsRemoveConditionalCompile (
 147     char                    *Buffer,
 148     char                    *Keyword)
 149 {
 150     char                    *SubString;
 151     char                    *SubBuffer;
 152     char                    *IfPtr;
 153     char                    *EndifPtr;
 154     char                    *ElsePtr;
 155     char                    *Comment;
 156     int                     KeywordLength;
 157 
 158 
 159     KeywordLength = strlen (Keyword);
 160     SubBuffer = Buffer;
 161     SubString = Buffer;
 162 
 163 
 164     while (SubString)
 165     {
 166         SubBuffer = strstr (SubString, Keyword);
 167         if (!SubBuffer)
 168         {
 169             return;
 170         }
 171 
 172         /*
 173          * Check for translation escape string -- means to ignore
 174          * blocks of code while replacing
 175          */
 176         if (Gbl_IgnoreTranslationEscapes)
 177         {
 178             Comment = NULL;
 179         }
 180         else
 181         {
 182             Comment = strstr (SubString, AS_START_IGNORE);
 183         }
 184 
 185         if ((Comment) &&
 186             (Comment < SubBuffer))
 187         {
 188             SubString = strstr (Comment, AS_STOP_IGNORE);
 189             if (!SubString)
 190             {
 191                 return;
 192             }
 193 
 194             SubString += 3;
 195             continue;
 196         }
 197 
 198         /* Check for ordinary comment */
 199 
 200         Comment = strstr (SubString, "/*");
 201 
 202         if ((Comment) &&
 203             (Comment < SubBuffer))
 204         {
 205             SubString = strstr (Comment, "*/");
 206             if (!SubString)
 207             {
 208                 return;
 209             }
 210 
 211             SubString += 2;
 212             continue;
 213         }
 214 
 215         SubString = SubBuffer;
 216         if (!AsMatchExactWord (SubString, KeywordLength))
 217         {
 218             SubString++;
 219             continue;
 220         }
 221 
 222         /* Find start of this line */
 223 
 224         while (*SubString != '\n' && (SubString > Buffer))
 225         {
 226             SubString--;
 227         }
 228         SubString++;
 229 
 230         /* Find the "#ifxxxx" */
 231 
 232         IfPtr = strstr (SubString, "#if");
 233         if (!IfPtr)
 234         {
 235             return;
 236         }
 237 
 238         if (IfPtr > SubBuffer)
 239         {
 240             /* Not the right #if */
 241 
 242             SubString = SubBuffer + strlen (Keyword);
 243             continue;
 244         }
 245 
 246         /* Find closing #endif or #else */
 247 
 248         EndifPtr = strstr (SubBuffer, "#endif");
 249         if (!EndifPtr)
 250         {
 251             /* There has to be an #endif */
 252 
 253             return;
 254         }
 255 
 256         ElsePtr = strstr (SubBuffer, "#else");
 257         if ((ElsePtr) &&
 258             (EndifPtr > ElsePtr))
 259         {
 260             /* This #ifdef contains an #else clause */
 261             /* Find end of this line */
 262 
 263             SubBuffer = AsSkipPastChar (ElsePtr, '\n');
 264             if (!SubBuffer)
 265             {
 266                 return;
 267             }
 268 
 269             /* Remove the #ifdef .... #else code */
 270 
 271             AsRemoveData (SubString, SubBuffer);
 272 
 273             /* Next, we will remove the #endif statement */
 274 
 275             EndifPtr = strstr (SubString, "#endif");
 276             if (!EndifPtr)
 277             {
 278                 /* There has to be an #endif */
 279 
 280                 return;
 281             }
 282 
 283             SubString = EndifPtr;
 284         }
 285 
 286         /* Remove the ... #endif part */
 287         /* Find end of this line */
 288 
 289         SubBuffer = AsSkipPastChar (EndifPtr, '\n');
 290         if (!SubBuffer)
 291         {
 292             return;
 293         }
 294 
 295         /* Remove the lines */
 296 
 297         SubBuffer = AsRemoveData (SubString, SubBuffer);
 298     }
 299 }
 300 
 301 
 302 /******************************************************************************
 303  *
 304  * FUNCTION:    AsRemoveMacro
 305  *
 306  * DESCRIPTION: Remove every line that contains the keyword. Does not
 307  *              skip comments.
 308  *
 309  ******************************************************************************/
 310 
 311 void
 312 AsRemoveMacro (
 313     char                    *Buffer,
 314     char                    *Keyword)
 315 {
 316     char                    *SubString;
 317     char                    *SubBuffer;
 318     int                     NestLevel;
 319 
 320 
 321     SubBuffer = Buffer;
 322     SubString = Buffer;
 323 
 324 
 325     while (SubString)
 326     {
 327         SubString = strstr (SubBuffer, Keyword);
 328 
 329         if (SubString)
 330         {
 331             SubBuffer = SubString;
 332 
 333             /* Find start of the macro parameters */
 334 
 335             while (*SubString != '(')
 336             {
 337                 SubString++;
 338             }
 339             SubString++;
 340 
 341             /* Remove the macro name and opening paren */
 342 
 343             SubString = AsRemoveData (SubBuffer, SubString);
 344 
 345             NestLevel = 1;
 346             while (*SubString)
 347             {
 348                 if (*SubString == '(')
 349                 {
 350                     NestLevel++;
 351                 }
 352                 else if (*SubString == ')')
 353                 {
 354                     NestLevel--;
 355                 }
 356 
 357                 SubString++;
 358 
 359                 if (NestLevel == 0)
 360                 {
 361                     break;
 362                 }
 363             }
 364 
 365             /* Remove the closing paren */
 366 
 367             SubBuffer = AsRemoveData (SubString-1, SubString);
 368         }
 369     }
 370 }
 371 
 372 
 373 /******************************************************************************
 374  *
 375  * FUNCTION:    AsRemoveLine
 376  *
 377  * DESCRIPTION: Remove every line that contains the keyword. Does not
 378  *              skip comments.
 379  *
 380  ******************************************************************************/
 381 
 382 void
 383 AsRemoveLine (
 384     char                    *Buffer,
 385     char                    *Keyword)
 386 {
 387     char                    *SubString;
 388     char                    *SubBuffer;
 389 
 390 
 391     SubBuffer = Buffer;
 392     SubString = Buffer;
 393 
 394 
 395     while (SubString)
 396     {
 397         SubString = strstr (SubBuffer, Keyword);
 398 
 399         if (SubString)
 400         {
 401             SubBuffer = SubString;
 402 
 403             /* Find start of this line */
 404 
 405             while (*SubString != '\n')
 406             {
 407                 SubString--;
 408             }
 409             SubString++;
 410 
 411             /* Find end of this line */
 412 
 413             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
 414             if (!SubBuffer)
 415             {
 416                 return;
 417             }
 418 
 419             /* Remove the line */
 420 
 421             SubBuffer = AsRemoveData (SubString, SubBuffer);
 422         }
 423     }
 424 }
 425 
 426 
 427 /******************************************************************************
 428  *
 429  * FUNCTION:    AsReduceTypedefs
 430  *
 431  * DESCRIPTION: Eliminate certain typedefs
 432  *
 433  ******************************************************************************/
 434 
 435 void
 436 AsReduceTypedefs (
 437     char                    *Buffer,
 438     char                    *Keyword)
 439 {
 440     char                    *SubString;
 441     char                    *SubBuffer;
 442     int                     NestLevel;
 443 
 444 
 445     SubBuffer = Buffer;
 446     SubString = Buffer;
 447 
 448 
 449     while (SubString)
 450     {
 451         SubString = strstr (SubBuffer, Keyword);
 452 
 453         if (SubString)
 454         {
 455             /* Remove the typedef itself */
 456 
 457             SubBuffer = SubString + strlen ("typedef") + 1;
 458             SubBuffer = AsRemoveData (SubString, SubBuffer);
 459 
 460             /* Find the opening brace of the struct or union */
 461 
 462             while (*SubString != '{')
 463             {
 464                 SubString++;
 465             }
 466             SubString++;
 467 
 468             /* Find the closing brace. Handles nested braces */
 469 
 470             NestLevel = 1;
 471             while (*SubString)
 472             {
 473                 if (*SubString == '{')
 474                 {
 475                     NestLevel++;
 476                 }
 477                 else if (*SubString == '}')
 478                 {
 479                     NestLevel--;
 480                 }
 481 
 482                 SubString++;
 483 
 484                 if (NestLevel == 0)
 485                 {
 486                     break;
 487                 }
 488             }
 489 
 490             /* Remove an extra line feed if present */
 491 
 492             if (!strncmp (SubString - 3, "\n\n", 2))
 493             {
 494                 *(SubString -2) = '}';
 495                 SubString--;
 496             }
 497 
 498             /* Find the end of the typedef name */
 499 
 500             SubBuffer = AsSkipUntilChar (SubString, ';');
 501 
 502             /* And remove the typedef name */
 503 
 504             SubBuffer = AsRemoveData (SubString, SubBuffer);
 505         }
 506     }
 507 }
 508 
 509 
 510 /******************************************************************************
 511  *
 512  * FUNCTION:    AsRemoveEmptyBlocks
 513  *
 514  * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This
 515  *              can happen as a result of removing lines such as DEBUG_PRINT.
 516  *
 517  ******************************************************************************/
 518 
 519 void
 520 AsRemoveEmptyBlocks (
 521     char                    *Buffer,
 522     char                    *Filename)
 523 {
 524     char                    *SubBuffer;
 525     char                    *BlockStart;
 526     BOOLEAN                 EmptyBlock = TRUE;
 527     BOOLEAN                 AnotherPassRequired = TRUE;
 528     UINT32                  BlockCount = 0;
 529 
 530 
 531     while (AnotherPassRequired)
 532     {
 533         SubBuffer = Buffer;
 534         AnotherPassRequired = FALSE;
 535 
 536         while (*SubBuffer)
 537         {
 538             if (*SubBuffer == '{')
 539             {
 540                 BlockStart = SubBuffer;
 541                 EmptyBlock = TRUE;
 542 
 543                 SubBuffer++;
 544                 while (*SubBuffer != '}')
 545                 {
 546                     if ((*SubBuffer != ' ') &&
 547                         (*SubBuffer != '\n'))
 548                     {
 549                         EmptyBlock = FALSE;
 550                         break;
 551                     }
 552                     SubBuffer++;
 553                 }
 554 
 555                 if (EmptyBlock)
 556                 {
 557                     /* Find start of the first line of the block */
 558 
 559                     while (*BlockStart != '\n')
 560                     {
 561                         BlockStart--;
 562                     }
 563 
 564                     /* Find end of the last line of the block */
 565 
 566                     SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
 567                     if (!SubBuffer)
 568                     {
 569                         break;
 570                     }
 571 
 572                     /* Remove the block */
 573 
 574                     SubBuffer = AsRemoveData (BlockStart, SubBuffer);
 575                     BlockCount++;
 576                     AnotherPassRequired = TRUE;
 577                     continue;
 578                 }
 579             }
 580 
 581             SubBuffer++;
 582         }
 583     }
 584 
 585     if (BlockCount)
 586     {
 587         Gbl_MadeChanges = TRUE;
 588         AsPrint ("Code blocks deleted", BlockCount, Filename);
 589     }
 590 }
 591 
 592 
 593 /******************************************************************************
 594  *
 595  * FUNCTION:    AsRemoveDebugMacros
 596  *
 597  * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output.
 598  *
 599  ******************************************************************************/
 600 
 601 void
 602 AsRemoveDebugMacros (
 603     char                    *Buffer)
 604 {
 605     AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT");
 606 
 607     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT",      REPLACE_WHOLE_WORD);
 608     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW",  REPLACE_WHOLE_WORD);
 609     AsRemoveStatement (Buffer, "DEBUG_EXEC",            REPLACE_WHOLE_WORD);
 610     AsRemoveStatement (Buffer, "FUNCTION_ENTRY",        REPLACE_WHOLE_WORD);
 611     AsRemoveStatement (Buffer, "PROC_NAME",             REPLACE_WHOLE_WORD);
 612     AsRemoveStatement (Buffer, "FUNCTION_TRACE",        REPLACE_SUBSTRINGS);
 613     AsRemoveStatement (Buffer, "DUMP_",                 REPLACE_SUBSTRINGS);
 614 
 615     AsReplaceString ("return_VOID",         "return", REPLACE_WHOLE_WORD, Buffer);
 616     AsReplaceString ("return_PTR",          "return", REPLACE_WHOLE_WORD, Buffer);
 617     AsReplaceString ("return_ACPI_STATUS",  "return", REPLACE_WHOLE_WORD, Buffer);
 618     AsReplaceString ("return_acpi_status",  "return", REPLACE_WHOLE_WORD, Buffer);
 619     AsReplaceString ("return_VALUE",        "return", REPLACE_WHOLE_WORD, Buffer);
 620 }
 621 
 622 
 623 /******************************************************************************
 624  *
 625  * FUNCTION:    AsCleanupSpecialMacro
 626  *
 627  * DESCRIPTION: For special macro invocations (invoked without ";" at the end
 628  *              of the lines), do the following:
 629  *              1. Remove spaces appended by indent at the beginning of lines.
 630  *              2. Add an empty line between two special macro invocations.
 631  *
 632  ******************************************************************************/
 633 
 634 void
 635 AsCleanupSpecialMacro (
 636     char                    *Buffer,
 637     char                    *Keyword)
 638 {
 639     char                    *SubString;
 640     char                    *SubBuffer;
 641     char                    *CommentEnd;
 642     int                     NewLine;
 643     int                     NestLevel;
 644 
 645 
 646     SubBuffer = Buffer;
 647     SubString = Buffer;
 648 
 649     while (SubString)
 650     {
 651         SubString = strstr (SubBuffer, Keyword);
 652 
 653         if (SubString)
 654         {
 655             /* Find start of the macro parameters */
 656 
 657             while (*SubString != '(')
 658             {
 659                 SubString++;
 660             }
 661             SubString++;
 662 
 663             NestLevel = 1;
 664             while (*SubString)
 665             {
 666                 if (*SubString == '(')
 667                 {
 668                     NestLevel++;
 669                 }
 670                 else if (*SubString == ')')
 671                 {
 672                     NestLevel--;
 673                 }
 674 
 675                 SubString++;
 676 
 677                 if (NestLevel == 0)
 678                 {
 679                     break;
 680                 }
 681             }
 682 
 683 SkipLine:
 684 
 685             /* Find end of the line */
 686 
 687             NewLine = FALSE;
 688             while (!NewLine && *SubString)
 689             {
 690                 if (*SubString == '\n' && *(SubString - 1) != '\\')
 691                 {
 692                     NewLine = TRUE;
 693                 }
 694                 SubString++;
 695             }
 696 
 697             /* Find end of the line */
 698 
 699             if (*SubString == '#' || *SubString == '\n')
 700             {
 701                 goto SkipLine;
 702             }
 703 
 704             SubBuffer = SubString;
 705 
 706             /* Find start of the non-space */
 707 
 708             while (*SubString == ' ')
 709             {
 710                 SubString++;
 711             }
 712 
 713             /* Find end of the line */
 714 
 715             if (*SubString == '#' || *SubString == '\n')
 716             {
 717                 goto SkipLine;
 718             }
 719 
 720             /* Find end of the line */
 721 
 722             if (*SubString == '/' || *SubString == '*')
 723             {
 724                 CommentEnd = strstr (SubString, "*/");
 725                 if (CommentEnd)
 726                 {
 727                     SubString = CommentEnd + 2;
 728                     goto SkipLine;
 729                 }
 730             }
 731 
 732             SubString = AsRemoveData (SubBuffer, SubString);
 733         }
 734     }
 735 }