1 /******************************************************************************
   2  *
   3  * Module Name: asmain - Main module for the acpi source processor utility
   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 
  45 #include "acpisrc.h"
  46 #include "acapps.h"
  47 
  48 /* Local prototypes */
  49 
  50 int
  51 AsStricmp (
  52     char                    *String1,
  53     char                    *String2);
  54 
  55 int
  56 AsExaminePaths (
  57     ACPI_CONVERSION_TABLE   *ConversionTable,
  58     char                    *Source,
  59     char                    *Target,
  60     UINT32                  *SourceFileType);
  61 
  62 void
  63 AsDisplayStats (
  64     void);
  65 
  66 void
  67 AsDisplayUsage (
  68     void);
  69 
  70 /* Globals */
  71 
  72 UINT32                  Gbl_Tabs = 0;
  73 UINT32                  Gbl_MissingBraces = 0;
  74 UINT32                  Gbl_NonAnsiComments = 0;
  75 UINT32                  Gbl_Files = 0;
  76 UINT32                  Gbl_WhiteLines = 0;
  77 UINT32                  Gbl_CommentLines = 0;
  78 UINT32                  Gbl_SourceLines = 0;
  79 UINT32                  Gbl_LongLines = 0;
  80 UINT32                  Gbl_TotalLines = 0;
  81 UINT32                  Gbl_TotalSize = 0;
  82 UINT32                  Gbl_HeaderLines = 0;
  83 UINT32                  Gbl_HeaderSize = 0;
  84 void                    *Gbl_StructDefs = NULL;
  85 
  86 struct stat             Gbl_StatBuf;
  87 char                    *Gbl_FileBuffer;
  88 UINT32                  Gbl_FileSize;
  89 UINT32                  Gbl_FileType;
  90 BOOLEAN                 Gbl_VerboseMode = FALSE;
  91 BOOLEAN                 Gbl_QuietMode = FALSE;
  92 BOOLEAN                 Gbl_BatchMode = FALSE;
  93 BOOLEAN                 Gbl_DebugStatementsMode = FALSE;
  94 BOOLEAN                 Gbl_MadeChanges = FALSE;
  95 BOOLEAN                 Gbl_Overwrite = FALSE;
  96 BOOLEAN                 Gbl_WidenDeclarations = FALSE;
  97 BOOLEAN                 Gbl_IgnoreLoneLineFeeds = FALSE;
  98 BOOLEAN                 Gbl_HasLoneLineFeeds = FALSE;
  99 BOOLEAN                 Gbl_Cleanup = FALSE;
 100 BOOLEAN                 Gbl_IgnoreTranslationEscapes = FALSE;
 101 
 102 #define AS_UTILITY_NAME             "ACPI Source Code Conversion Utility"
 103 #define AS_SUPPORTED_OPTIONS        "cdhilqsuv^y"
 104 
 105 
 106 /******************************************************************************
 107  *
 108  * FUNCTION:    AsStricmp
 109  *
 110  * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
 111  *              strings with no case sensitivity)
 112  *
 113  ******************************************************************************/
 114 
 115 int
 116 AsStricmp (
 117     char                    *String1,
 118     char                    *String2)
 119 {
 120     int                     c1;
 121     int                     c2;
 122 
 123 
 124     do
 125     {
 126         c1 = tolower ((int) *String1);
 127         c2 = tolower ((int) *String2);
 128 
 129         String1++;
 130         String2++;
 131     }
 132     while ((c1 == c2) && (c1));
 133 
 134     return (c1 - c2);
 135 }
 136 
 137 
 138 /******************************************************************************
 139  *
 140  * FUNCTION:    AsExaminePaths
 141  *
 142  * DESCRIPTION: Source and Target pathname verification and handling
 143  *
 144  ******************************************************************************/
 145 
 146 int
 147 AsExaminePaths (
 148     ACPI_CONVERSION_TABLE   *ConversionTable,
 149     char                    *Source,
 150     char                    *Target,
 151     UINT32                  *SourceFileType)
 152 {
 153     int                     Status;
 154     int                     Response;
 155 
 156 
 157     Status = stat (Source, &Gbl_StatBuf);
 158     if (Status)
 159     {
 160         printf ("Source path \"%s\" does not exist\n", Source);
 161         return (-1);
 162     }
 163 
 164     /* Return the filetype -- file or a directory */
 165 
 166     *SourceFileType = 0;
 167     if (Gbl_StatBuf.st_mode & S_IFDIR)
 168     {
 169         *SourceFileType = S_IFDIR;
 170     }
 171 
 172     /*
 173      * If we are in no-output mode or in batch mode, we are done
 174      */
 175     if ((ConversionTable->Flags & FLG_NO_FILE_OUTPUT) ||
 176         (Gbl_BatchMode))
 177     {
 178         return (0);
 179     }
 180 
 181     if (!AsStricmp (Source, Target))
 182     {
 183         printf ("Target path is the same as the source path, overwrite?\n");
 184         Response = getchar ();
 185 
 186         /* Check response */
 187 
 188         if (Response != 'y')
 189         {
 190             return (-1);
 191         }
 192 
 193         Gbl_Overwrite = TRUE;
 194     }
 195     else
 196     {
 197         Status = stat (Target, &Gbl_StatBuf);
 198         if (!Status)
 199         {
 200             printf ("Target path already exists, overwrite?\n");
 201             Response = getchar ();
 202 
 203             /* Check response */
 204 
 205             if (Response != 'y')
 206             {
 207                 return (-1);
 208             }
 209         }
 210     }
 211 
 212     return (0);
 213 }
 214 
 215 
 216 /******************************************************************************
 217  *
 218  * FUNCTION:    AsDisplayStats
 219  *
 220  * DESCRIPTION: Display global statistics gathered during translation
 221  *
 222  ******************************************************************************/
 223 
 224 void
 225 AsDisplayStats (
 226     void)
 227 {
 228 
 229     if (Gbl_QuietMode)
 230     {
 231         return;
 232     }
 233 
 234     printf ("\nAcpiSrc statistics:\n\n");
 235     printf ("%8u Files processed\n", Gbl_Files);
 236 
 237     if (!Gbl_Files)
 238     {
 239         return;
 240     }
 241 
 242     printf ("%8u Total bytes (%.1fK/file)\n",
 243         Gbl_TotalSize, ((double) Gbl_TotalSize/Gbl_Files)/1024);
 244     printf ("%8u Tabs found\n", Gbl_Tabs);
 245     printf ("%8u Missing if/else braces\n", Gbl_MissingBraces);
 246     printf ("%8u Non-ANSI comments found\n", Gbl_NonAnsiComments);
 247     printf ("%8u Total Lines\n", Gbl_TotalLines);
 248     printf ("%8u Lines of code\n", Gbl_SourceLines);
 249     printf ("%8u Lines of non-comment whitespace\n", Gbl_WhiteLines);
 250     printf ("%8u Lines of comments\n", Gbl_CommentLines);
 251     printf ("%8u Long lines found\n", Gbl_LongLines);
 252 
 253     if (Gbl_WhiteLines > 0)
 254     {
 255         printf ("%8.1f Ratio of code to whitespace\n",
 256             ((float) Gbl_SourceLines / (float) Gbl_WhiteLines));
 257     }
 258 
 259     if ((Gbl_CommentLines + Gbl_NonAnsiComments) > 0)
 260     {
 261         printf ("%8.1f Ratio of code to comments\n",
 262             ((float) Gbl_SourceLines / (float) (Gbl_CommentLines + Gbl_NonAnsiComments)));
 263     }
 264 
 265     if (!Gbl_TotalLines)
 266     {
 267         return;
 268     }
 269 
 270     printf ("         %u%% code, %u%% comments, %u%% whitespace, %u%% headers\n",
 271         (Gbl_SourceLines * 100) / Gbl_TotalLines,
 272         (Gbl_CommentLines * 100) / Gbl_TotalLines,
 273         (Gbl_WhiteLines * 100) / Gbl_TotalLines,
 274         (Gbl_HeaderLines * 100) / Gbl_TotalLines);
 275     return;
 276 }
 277 
 278 
 279 /******************************************************************************
 280  *
 281  * FUNCTION:    AsDisplayUsage
 282  *
 283  * DESCRIPTION: Usage message
 284  *
 285  ******************************************************************************/
 286 
 287 void
 288 AsDisplayUsage (
 289     void)
 290 {
 291 
 292     ACPI_USAGE_HEADER ("acpisrc [-c|l|u] [-dsvy] <SourceDir> <DestinationDir>");
 293 
 294     ACPI_OPTION ("-c",          "Generate cleaned version of the source");
 295     ACPI_OPTION ("-h",          "Insert dual-license header into all modules");
 296     ACPI_OPTION ("-i",          "Cleanup macro indentation");
 297     ACPI_OPTION ("-l",          "Generate Linux version of the source");
 298     ACPI_OPTION ("-u",          "Generate Custom source translation");
 299 
 300     printf ("\n");
 301     ACPI_OPTION ("-d",          "Leave debug statements in code");
 302     ACPI_OPTION ("-s",          "Generate source statistics only");
 303     ACPI_OPTION ("-v",          "Display version information");
 304     ACPI_OPTION ("-vb",         "Verbose mode");
 305     ACPI_OPTION ("-y",          "Suppress file overwrite prompts");
 306 }
 307 
 308 
 309 /******************************************************************************
 310  *
 311  * FUNCTION:    main
 312  *
 313  * DESCRIPTION: C main function
 314  *
 315  ******************************************************************************/
 316 
 317 int ACPI_SYSTEM_XFACE
 318 main (
 319     int                     argc,
 320     char                    *argv[])
 321 {
 322     int                     j;
 323     ACPI_CONVERSION_TABLE   *ConversionTable = NULL;
 324     char                    *SourcePath;
 325     char                    *TargetPath;
 326     UINT32                  FileType;
 327 
 328 
 329     ACPI_DEBUG_INITIALIZE (); /* For debug version only */
 330     printf (ACPI_COMMON_SIGNON (AS_UTILITY_NAME));
 331 
 332     if (argc < 2)
 333     {
 334         AsDisplayUsage ();
 335         return (0);
 336     }
 337 
 338     /* Command line options */
 339 
 340     while ((j = AcpiGetopt (argc, argv, AS_SUPPORTED_OPTIONS)) != EOF) switch(j)
 341     {
 342     case 'l':
 343 
 344         /* Linux code generation */
 345 
 346         printf ("Creating Linux source code\n");
 347         ConversionTable = &LinuxConversionTable;
 348         Gbl_WidenDeclarations = TRUE;
 349         Gbl_IgnoreLoneLineFeeds = TRUE;
 350         break;
 351 
 352     case 'c':
 353 
 354         /* Cleanup code */
 355 
 356         printf ("Code cleanup\n");
 357         ConversionTable = &CleanupConversionTable;
 358         Gbl_Cleanup = TRUE;
 359         break;
 360 
 361     case 'h':
 362 
 363         /* Inject Dual-license header */
 364 
 365         printf ("Inserting Dual-license header to all modules\n");
 366         ConversionTable = &LicenseConversionTable;
 367         break;
 368 
 369     case 'i':
 370 
 371         /* Cleanup wrong indent result */
 372 
 373         printf ("Cleaning up macro indentation\n");
 374         ConversionTable = &IndentConversionTable;
 375         Gbl_IgnoreLoneLineFeeds = TRUE;
 376         Gbl_IgnoreTranslationEscapes = TRUE;
 377         break;
 378 
 379     case 's':
 380 
 381         /* Statistics only */
 382 
 383         break;
 384 
 385     case 'u':
 386 
 387         /* custom conversion  */
 388 
 389         printf ("Custom source translation\n");
 390         ConversionTable = &CustomConversionTable;
 391         break;
 392 
 393     case 'v':
 394 
 395         switch (AcpiGbl_Optarg[0])
 396         {
 397         case '^':  /* -v: (Version): signon already emitted, just exit */
 398 
 399             exit (0);
 400 
 401         case 'b':
 402 
 403             /* Verbose mode */
 404 
 405             Gbl_VerboseMode = TRUE;
 406             break;
 407 
 408         default:
 409 
 410             printf ("Unknown option: -v%s\n", AcpiGbl_Optarg);
 411             return (-1);
 412         }
 413 
 414         break;
 415 
 416     case 'y':
 417 
 418         /* Batch mode */
 419 
 420         Gbl_BatchMode = TRUE;
 421         break;
 422 
 423     case 'd':
 424 
 425         /* Leave debug statements in */
 426 
 427         Gbl_DebugStatementsMode = TRUE;
 428         break;
 429 
 430     case 'q':
 431 
 432         /* Quiet mode */
 433 
 434         Gbl_QuietMode = TRUE;
 435         break;
 436 
 437     default:
 438 
 439         AsDisplayUsage ();
 440         return (-1);
 441     }
 442 
 443 
 444     SourcePath = argv[AcpiGbl_Optind];
 445     if (!SourcePath)
 446     {
 447         printf ("Missing source path\n");
 448         AsDisplayUsage ();
 449         return (-1);
 450     }
 451 
 452     TargetPath = argv[AcpiGbl_Optind+1];
 453 
 454     if (!ConversionTable)
 455     {
 456         /* Just generate statistics. Ignore target path */
 457 
 458         TargetPath = SourcePath;
 459 
 460         printf ("Source code statistics only\n");
 461         ConversionTable = &StatsConversionTable;
 462     }
 463     else if (!TargetPath)
 464     {
 465         TargetPath = SourcePath;
 466     }
 467 
 468     if (Gbl_DebugStatementsMode)
 469     {
 470         ConversionTable->SourceFunctions &= ~CVT_REMOVE_DEBUG_MACROS;
 471     }
 472 
 473     /* Check source and target paths and files */
 474 
 475     if (AsExaminePaths (ConversionTable, SourcePath, TargetPath, &FileType))
 476     {
 477         return (-1);
 478     }
 479 
 480     /* Source/target can be either directories or a files */
 481 
 482     if (FileType == S_IFDIR)
 483     {
 484         /* Process the directory tree */
 485 
 486         AsProcessTree (ConversionTable, SourcePath, TargetPath);
 487     }
 488     else
 489     {
 490         /* Process a single file */
 491 
 492         /* Differentiate between source and header files */
 493 
 494         if (strstr (SourcePath, ".h"))
 495         {
 496             AsProcessOneFile (ConversionTable, NULL, TargetPath, 0, SourcePath, FILE_TYPE_HEADER);
 497         }
 498         else if (strstr (SourcePath, ".c"))
 499         {
 500             AsProcessOneFile (ConversionTable, NULL, TargetPath, 0, SourcePath, FILE_TYPE_SOURCE);
 501         }
 502         else if (strstr (SourcePath, ".patch"))
 503         {
 504             AsProcessOneFile (ConversionTable, NULL, TargetPath, 0, SourcePath, FILE_TYPE_PATCH);
 505         }
 506         else
 507         {
 508             printf ("Unknown file type - %s\n", SourcePath);
 509         }
 510     }
 511 
 512     /* Always display final summary and stats */
 513 
 514     AsDisplayStats ();
 515 
 516     return (0);
 517 }