1 /******************************************************************************
   2  *
   3  * Module Name: asloptions - compiler command line processing
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 "aslcompiler.h"
  45 #include "acapps.h"
  46 #include "acdisasm.h"
  47 
  48 #define _COMPONENT          ACPI_COMPILER
  49         ACPI_MODULE_NAME    ("asloption")
  50 
  51 
  52 /* Local prototypes */
  53 
  54 static int
  55 AslDoOptions (
  56     int                     argc,
  57     char                    **argv,
  58     BOOLEAN                 IsResponseFile);
  59 
  60 static void
  61 AslMergeOptionTokens (
  62     char                    *InBuffer,
  63     char                    *OutBuffer);
  64 
  65 static int
  66 AslDoResponseFile (
  67     char                    *Filename);
  68 
  69 
  70 #define ASL_TOKEN_SEPARATORS    " \t\n"
  71 #define ASL_SUPPORTED_OPTIONS   "@:b|c|d^D:e:f^gh^i|I:l^m:no|p:P^r:s|t|T+G^v^w|x:z"
  72 
  73 
  74 /*******************************************************************************
  75  *
  76  * FUNCTION:    AslCommandLine
  77  *
  78  * PARAMETERS:  argc/argv
  79  *
  80  * RETURN:      Last argv index
  81  *
  82  * DESCRIPTION: Command line processing
  83  *
  84  ******************************************************************************/
  85 
  86 int
  87 AslCommandLine (
  88     int                     argc,
  89     char                    **argv)
  90 {
  91     int                     BadCommandLine = 0;
  92     ACPI_STATUS             Status;
  93 
  94 
  95     /* Minimum command line contains at least the command and an input file */
  96 
  97     if (argc < 2)
  98     {
  99         printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME));
 100         Usage ();
 101         exit (1);
 102     }
 103 
 104     /* Process all command line options */
 105 
 106     BadCommandLine = AslDoOptions (argc, argv, FALSE);
 107 
 108     if (Gbl_DoTemplates)
 109     {
 110         Status = DtCreateTemplates (Gbl_TemplateSignature);
 111         if (ACPI_FAILURE (Status))
 112         {
 113             exit (-1);
 114         }
 115         exit (1);
 116     }
 117 
 118     /* Next parameter must be the input filename */
 119 
 120     if (!argv[AcpiGbl_Optind] &&
 121         !Gbl_DisasmFlag &&
 122         !Gbl_GetAllTables)
 123     {
 124         printf ("Missing input filename\n");
 125         BadCommandLine = TRUE;
 126     }
 127 
 128     if (Gbl_DoSignon)
 129     {
 130         printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME));
 131         if (Gbl_IgnoreErrors)
 132         {
 133             printf ("Ignoring all errors, forcing AML file generation\n\n");
 134         }
 135     }
 136 
 137     if (BadCommandLine)
 138     {
 139         printf ("Use -h option for help information\n");
 140         exit (1);
 141     }
 142 
 143     return (AcpiGbl_Optind);
 144 }
 145 
 146 
 147 /*******************************************************************************
 148  *
 149  * FUNCTION:    AslDoOptions
 150  *
 151  * PARAMETERS:  argc/argv           - Standard argc/argv
 152  *              IsResponseFile      - TRUE if executing a response file.
 153  *
 154  * RETURN:      Status
 155  *
 156  * DESCRIPTION: Command line option processing
 157  *
 158  ******************************************************************************/
 159 
 160 static int
 161 AslDoOptions (
 162     int                     argc,
 163     char                    **argv,
 164     BOOLEAN                 IsResponseFile)
 165 {
 166     ACPI_STATUS             Status;
 167     UINT32                  j;
 168 
 169 
 170     /* Get the command line options */
 171 
 172     while ((j = AcpiGetopt (argc, argv, ASL_SUPPORTED_OPTIONS)) != EOF) switch (j)
 173     {
 174     case '@':   /* Begin a response file */
 175 
 176         if (IsResponseFile)
 177         {
 178             printf ("Nested command files are not supported\n");
 179             return (-1);
 180         }
 181 
 182         if (AslDoResponseFile (AcpiGbl_Optarg))
 183         {
 184             return (-1);
 185         }
 186         break;
 187 
 188     case 'b':   /* Debug output options */
 189 
 190         switch (AcpiGbl_Optarg[0])
 191         {
 192         case 'f':
 193 
 194             AslCompilerdebug = 1; /* same as yydebug */
 195             DtParserdebug = 1;
 196             PrParserdebug = 1;
 197             break;
 198 
 199         case 't':
 200 
 201             break;
 202 
 203         default:
 204 
 205             printf ("Unknown option: -b%s\n", AcpiGbl_Optarg);
 206             return (-1);
 207         }
 208 
 209         /* Produce debug output file */
 210 
 211         Gbl_DebugFlag = TRUE;
 212         break;
 213 
 214     case 'c':
 215 
 216         switch (AcpiGbl_Optarg[0])
 217         {
 218         case 'r':
 219 
 220             Gbl_NoResourceChecking = TRUE;
 221             break;
 222 
 223         default:
 224 
 225             printf ("Unknown option: -c%s\n", AcpiGbl_Optarg);
 226             return (-1);
 227         }
 228         break;
 229 
 230     case 'd':   /* Disassembler */
 231 
 232         switch (AcpiGbl_Optarg[0])
 233         {
 234         case '^':
 235 
 236             Gbl_DoCompile = FALSE;
 237             break;
 238 
 239         case 'a':
 240 
 241             Gbl_DoCompile = FALSE;
 242             Gbl_DisassembleAll = TRUE;
 243             break;
 244 
 245         case 'b':   /* Do not convert buffers to resource descriptors */
 246 
 247             AcpiGbl_NoResourceDisassembly = TRUE;
 248             break;
 249 
 250         case 'c':
 251 
 252             break;
 253 
 254         default:
 255 
 256             printf ("Unknown option: -d%s\n", AcpiGbl_Optarg);
 257             return (-1);
 258         }
 259 
 260         Gbl_DisasmFlag = TRUE;
 261         break;
 262 
 263     case 'D':   /* Define a symbol */
 264 
 265         PrAddDefine (AcpiGbl_Optarg, NULL, TRUE);
 266         break;
 267 
 268     case 'e':   /* External files for disassembler */
 269 
 270         /* Get entire list of external files */
 271 
 272         AcpiGbl_Optind--;
 273 
 274         while (argv[AcpiGbl_Optind] &&
 275               (argv[AcpiGbl_Optind][0] != '-'))
 276         {
 277             Status = AcpiDmAddToExternalFileList (argv[AcpiGbl_Optind]);
 278             if (ACPI_FAILURE (Status))
 279             {
 280                 printf ("Could not add %s to external list\n", argv[AcpiGbl_Optind]);
 281                 return (-1);
 282             }
 283 
 284             AcpiGbl_Optind++;
 285         }
 286         break;
 287 
 288     case 'f':
 289 
 290         switch (AcpiGbl_Optarg[0])
 291         {
 292         case '^':   /* Ignore errors and force creation of aml file */
 293 
 294             Gbl_IgnoreErrors = TRUE;
 295             break;
 296 
 297         case 'e':   /* Disassembler: Get external declaration file */
 298 
 299             if (AcpiGetoptArgument (argc, argv))
 300             {
 301                 return (-1);
 302             }
 303 
 304             Gbl_ExternalRefFilename = AcpiGbl_Optarg;
 305             break;
 306 
 307         default:
 308 
 309             printf ("Unknown option: -f%s\n", AcpiGbl_Optarg);
 310             return (-1);
 311         }
 312         break;
 313 
 314     case 'G':
 315 
 316         Gbl_CompileGeneric = TRUE;
 317         break;
 318 
 319     case 'g':   /* Get all ACPI tables */
 320 
 321         Gbl_GetAllTables = TRUE;
 322         Gbl_DoCompile = FALSE;
 323         break;
 324 
 325     case 'h':
 326 
 327         switch (AcpiGbl_Optarg[0])
 328         {
 329         case '^':
 330 
 331             Usage ();
 332             exit (0);
 333 
 334         case 'c':
 335 
 336             UtDisplayConstantOpcodes ();
 337             exit (0);
 338 
 339         case 'f':
 340 
 341             AslFilenameHelp ();
 342             exit (0);
 343 
 344         case 'r':
 345 
 346             /* reserved names */
 347 
 348             ApDisplayReservedNames ();
 349             exit (0);
 350 
 351         case 't':
 352 
 353             UtDisplaySupportedTables ();
 354             exit (0);
 355 
 356         default:
 357 
 358             printf ("Unknown option: -h%s\n", AcpiGbl_Optarg);
 359             return (-1);
 360         }
 361 
 362     case 'I':   /* Add an include file search directory */
 363 
 364         FlAddIncludeDirectory (AcpiGbl_Optarg);
 365         break;
 366 
 367     case 'i':   /* Output AML as an include file */
 368 
 369         switch (AcpiGbl_Optarg[0])
 370         {
 371         case 'a':
 372 
 373             /* Produce assembly code include file */
 374 
 375             Gbl_AsmIncludeOutputFlag = TRUE;
 376             break;
 377 
 378         case 'c':
 379 
 380             /* Produce C include file */
 381 
 382             Gbl_C_IncludeOutputFlag = TRUE;
 383             break;
 384 
 385         case 'n':
 386 
 387             /* Compiler/Disassembler: Ignore the NOOP operator */
 388 
 389             AcpiGbl_IgnoreNoopOperator = TRUE;
 390             break;
 391 
 392         default:
 393 
 394             printf ("Unknown option: -i%s\n", AcpiGbl_Optarg);
 395             return (-1);
 396         }
 397         break;
 398 
 399     case 'l':   /* Listing files */
 400 
 401         switch (AcpiGbl_Optarg[0])
 402         {
 403         case '^':
 404 
 405             /* Produce listing file (Mixed source/aml) */
 406 
 407             Gbl_ListingFlag = TRUE;
 408             break;
 409 
 410         case 'i':
 411 
 412             /* Produce preprocessor output file */
 413 
 414             Gbl_PreprocessorOutputFlag = TRUE;
 415             break;
 416 
 417         case 'n':
 418 
 419             /* Produce namespace file */
 420 
 421             Gbl_NsOutputFlag = TRUE;
 422             break;
 423 
 424         case 's':
 425 
 426             /* Produce combined source file */
 427 
 428             Gbl_SourceOutputFlag = TRUE;
 429             break;
 430 
 431         default:
 432 
 433             printf ("Unknown option: -l%s\n", AcpiGbl_Optarg);
 434             return (-1);
 435         }
 436         break;
 437 
 438     case 'm':   /* Set line buffer size */
 439 
 440         Gbl_LineBufferSize = (UINT32) strtoul (AcpiGbl_Optarg, NULL, 0) * 1024;
 441         if (Gbl_LineBufferSize < ASL_DEFAULT_LINE_BUFFER_SIZE)
 442         {
 443             Gbl_LineBufferSize = ASL_DEFAULT_LINE_BUFFER_SIZE;
 444         }
 445         printf ("Line Buffer Size: %u\n", Gbl_LineBufferSize);
 446         break;
 447 
 448     case 'n':   /* Parse only */
 449 
 450         Gbl_ParseOnlyFlag = TRUE;
 451         break;
 452 
 453     case 'o':   /* Control compiler AML optimizations */
 454 
 455         switch (AcpiGbl_Optarg[0])
 456         {
 457         case 'a':
 458 
 459             /* Disable all optimizations */
 460 
 461             Gbl_FoldConstants = FALSE;
 462             Gbl_IntegerOptimizationFlag = FALSE;
 463             Gbl_ReferenceOptimizationFlag = FALSE;
 464             break;
 465 
 466         case 'f':
 467 
 468             /* Disable folding on "normal" expressions */
 469 
 470             Gbl_FoldConstants = FALSE;
 471             break;
 472 
 473         case 'i':
 474 
 475             /* Disable integer optimization to constants */
 476 
 477             Gbl_IntegerOptimizationFlag = FALSE;
 478             break;
 479 
 480         case 'n':
 481 
 482             /* Disable named reference optimization */
 483 
 484             Gbl_ReferenceOptimizationFlag = FALSE;
 485             break;
 486 
 487         case 't':
 488 
 489             /* Display compile time(s) */
 490 
 491             Gbl_CompileTimesFlag = TRUE;
 492             break;
 493 
 494         default:
 495 
 496             printf ("Unknown option: -c%s\n", AcpiGbl_Optarg);
 497             return (-1);
 498         }
 499         break;
 500 
 501     case 'P':   /* Preprocessor options */
 502 
 503         switch (AcpiGbl_Optarg[0])
 504         {
 505         case '^':   /* Proprocess only, emit (.i) file */
 506 
 507             Gbl_PreprocessOnly = TRUE;
 508             Gbl_PreprocessorOutputFlag = TRUE;
 509             break;
 510 
 511         case 'n':   /* Disable preprocessor */
 512 
 513             Gbl_PreprocessFlag = FALSE;
 514             break;
 515 
 516         default:
 517 
 518             printf ("Unknown option: -P%s\n", AcpiGbl_Optarg);
 519             return (-1);
 520         }
 521         break;
 522 
 523     case 'p':   /* Override default AML output filename */
 524 
 525         Gbl_OutputFilenamePrefix = AcpiGbl_Optarg;
 526         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
 527 
 528         Gbl_UseDefaultAmlFilename = FALSE;
 529         break;
 530 
 531     case 'r':   /* Override revision found in table header */
 532 
 533         Gbl_RevisionOverride = (UINT8) strtoul (AcpiGbl_Optarg, NULL, 0);
 534         break;
 535 
 536     case 's':   /* Create AML in a source code file */
 537 
 538         switch (AcpiGbl_Optarg[0])
 539         {
 540         case 'a':
 541 
 542             /* Produce assembly code output file */
 543 
 544             Gbl_AsmOutputFlag = TRUE;
 545             break;
 546 
 547         case 'c':
 548 
 549             /* Produce C hex output file */
 550 
 551             Gbl_C_OutputFlag = TRUE;
 552             break;
 553 
 554         case 'o':
 555 
 556             /* Produce AML offset table in C */
 557 
 558             Gbl_C_OffsetTableFlag = TRUE;
 559             break;
 560 
 561         default:
 562 
 563             printf ("Unknown option: -s%s\n", AcpiGbl_Optarg);
 564             return (-1);
 565         }
 566         break;
 567 
 568     case 't':   /* Produce hex table output file */
 569 
 570         switch (AcpiGbl_Optarg[0])
 571         {
 572         case 'a':
 573 
 574             Gbl_HexOutputFlag = HEX_OUTPUT_ASM;
 575             break;
 576 
 577         case 'c':
 578 
 579             Gbl_HexOutputFlag = HEX_OUTPUT_C;
 580             break;
 581 
 582         case 's':
 583 
 584             Gbl_HexOutputFlag = HEX_OUTPUT_ASL;
 585             break;
 586 
 587         default:
 588 
 589             printf ("Unknown option: -t%s\n", AcpiGbl_Optarg);
 590             return (-1);
 591         }
 592         break;
 593 
 594     case 'T':   /* Create a ACPI table template file */
 595 
 596         Gbl_DoTemplates = TRUE;
 597         Gbl_TemplateSignature = AcpiGbl_Optarg;
 598         break;
 599 
 600     case 'v':   /* Version and verbosity settings */
 601 
 602         switch (AcpiGbl_Optarg[0])
 603         {
 604         case '^':
 605 
 606             printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME));
 607             exit (0);
 608 
 609         case 'a':
 610 
 611             /* Disable all error/warning/remark messages */
 612 
 613             Gbl_NoErrors = TRUE;
 614             break;
 615 
 616         case 'e':
 617 
 618             /* Disable all warning/remark messages (errors only) */
 619 
 620             Gbl_DisplayRemarks = FALSE;
 621             Gbl_DisplayWarnings = FALSE;
 622             break;
 623 
 624         case 'i':
 625             /*
 626              * Support for integrated development environment(s).
 627              *
 628              * 1) No compiler signon
 629              * 2) Send stderr messages to stdout
 630              * 3) Less verbose error messages (single line only for each)
 631              * 4) Error/warning messages are formatted appropriately to
 632              *    be recognized by MS Visual Studio
 633              */
 634             Gbl_VerboseErrors = FALSE;
 635             Gbl_DoSignon = FALSE;
 636             Gbl_Files[ASL_FILE_STDERR].Handle = stdout;
 637             break;
 638 
 639         case 'o':
 640 
 641             Gbl_DisplayOptimizations = TRUE;
 642             break;
 643 
 644         case 'r':
 645 
 646             Gbl_DisplayRemarks = FALSE;
 647             break;
 648 
 649         case 's':
 650 
 651             Gbl_DoSignon = FALSE;
 652             break;
 653 
 654         case 't':
 655 
 656             Gbl_VerboseTemplates = TRUE;
 657             break;
 658 
 659         case 'w':
 660 
 661             /* Get the required argument */
 662 
 663             if (AcpiGetoptArgument (argc, argv))
 664             {
 665                 return (-1);
 666             }
 667 
 668             Status = AslDisableException (AcpiGbl_Optarg);
 669             if (ACPI_FAILURE (Status))
 670             {
 671                 return (-1);
 672             }
 673             break;
 674 
 675         default:
 676 
 677             printf ("Unknown option: -v%s\n", AcpiGbl_Optarg);
 678             return (-1);
 679         }
 680         break;
 681 
 682     case 'w': /* Set warning levels */
 683 
 684         switch (AcpiGbl_Optarg[0])
 685         {
 686         case '1':
 687 
 688             Gbl_WarningLevel = ASL_WARNING;
 689             break;
 690 
 691         case '2':
 692 
 693             Gbl_WarningLevel = ASL_WARNING2;
 694             break;
 695 
 696         case '3':
 697 
 698             Gbl_WarningLevel = ASL_WARNING3;
 699             break;
 700 
 701         case 'e':
 702 
 703             Gbl_WarningsAsErrors = TRUE;
 704             break;
 705 
 706         default:
 707 
 708             printf ("Unknown option: -w%s\n", AcpiGbl_Optarg);
 709             return (-1);
 710         }
 711         break;
 712 
 713     case 'x':   /* Set debug print output level */
 714 
 715         AcpiDbgLevel = strtoul (AcpiGbl_Optarg, NULL, 16);
 716         break;
 717 
 718     case 'z':
 719 
 720         Gbl_UseOriginalCompilerId = TRUE;
 721         break;
 722 
 723     default:
 724 
 725         return (-1);
 726     }
 727 
 728     return (0);
 729 }
 730 
 731 
 732 /*******************************************************************************
 733  *
 734  * FUNCTION:    AslMergeOptionTokens
 735  *
 736  * PARAMETERS:  InBuffer            - Input containing an option string
 737  *              OutBuffer           - Merged output buffer
 738  *
 739  * RETURN:      None
 740  *
 741  * DESCRIPTION: Remove all whitespace from an option string.
 742  *
 743  ******************************************************************************/
 744 
 745 static void
 746 AslMergeOptionTokens (
 747     char                    *InBuffer,
 748     char                    *OutBuffer)
 749 {
 750     char                    *Token;
 751 
 752 
 753     *OutBuffer = 0;
 754 
 755     Token = strtok (InBuffer, ASL_TOKEN_SEPARATORS);
 756     while (Token)
 757     {
 758         strcat (OutBuffer, Token);
 759         Token = strtok (NULL, ASL_TOKEN_SEPARATORS);
 760     }
 761 }
 762 
 763 
 764 /*******************************************************************************
 765  *
 766  * FUNCTION:    AslDoResponseFile
 767  *
 768  * PARAMETERS:  Filename        - Name of the response file
 769  *
 770  * RETURN:      Status
 771  *
 772  * DESCRIPTION: Open a response file and process all options within.
 773  *
 774  ******************************************************************************/
 775 
 776 static int
 777 AslDoResponseFile (
 778     char                    *Filename)
 779 {
 780     char                    *argv = StringBuffer2;
 781     FILE                    *ResponseFile;
 782     int                     OptStatus = 0;
 783     int                     Opterr;
 784     int                     Optind;
 785 
 786 
 787     ResponseFile = fopen (Filename, "r");
 788     if (!ResponseFile)
 789     {
 790         printf ("Could not open command file %s, %s\n",
 791             Filename, strerror (errno));
 792         return (-1);
 793     }
 794 
 795     /* Must save the current GetOpt globals */
 796 
 797     Opterr = AcpiGbl_Opterr;
 798     Optind = AcpiGbl_Optind;
 799 
 800     /*
 801      * Process all lines in the response file. There must be one complete
 802      * option per line
 803      */
 804     while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ResponseFile))
 805     {
 806         /* Compress all tokens, allowing us to use a single argv entry */
 807 
 808         AslMergeOptionTokens (StringBuffer, StringBuffer2);
 809 
 810         /* Process the option */
 811 
 812         AcpiGbl_Opterr = 0;
 813         AcpiGbl_Optind = 0;
 814 
 815         OptStatus = AslDoOptions (1, &argv, TRUE);
 816         if (OptStatus)
 817         {
 818             printf ("Invalid option in command file %s: %s\n",
 819                 Filename, StringBuffer);
 820             break;
 821         }
 822     }
 823 
 824     /* Restore the GetOpt globals */
 825 
 826     AcpiGbl_Opterr = Opterr;
 827     AcpiGbl_Optind = Optind;
 828 
 829     fclose (ResponseFile);
 830     return (OptStatus);
 831 }