Home | History | Annotate | Download | only in GuidChk
      1 /*++
      2 
      3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   UtilsMsgs.c
     15 
     16 Abstract:
     17 
     18   EFI tools utility functions to display warning, error, and informational
     19   messages.
     20 
     21 --*/
     22 
     23 #include <stdio.h>
     24 #include <string.h>
     25 #include <ctype.h>
     26 #include <stdarg.h>
     27 
     28 #include "Tiano.h"
     29 #include "EfiUtilityMsgs.h"
     30 
     31 #define MAX_LINE_LEN  200
     32 
     33 //
     34 // Declare module globals for keeping track of the the utility's
     35 // name and other settings.
     36 //
     37 static STATUS mStatus             = STATUS_SUCCESS;
     38 static INT8   mUtilityName[50]    = { 0 };
     39 static INT8   *mSourceFileName    = NULL;
     40 static UINT32 mSourceFileLineNum  = 0;
     41 static UINT32 mErrorCount         = 0;
     42 static UINT32 mWarningCount       = 0;
     43 static UINT32 mDebugMsgMask       = 0;
     44 
     45 static
     46 void
     47 PrintMessage (
     48   INT8    *Type,
     49   INT8    *FileName,
     50   UINT32  LineNumber,
     51   UINT32  MessageCode,
     52   INT8    *Text,
     53   INT8    *MsgFmt,
     54   va_list List
     55   );
     56 
     57 void
     58 Error (
     59   INT8    *FileName,
     60   UINT32  LineNumber,
     61   UINT32  MessageCode,
     62   INT8    *Text,
     63   INT8    *MsgFmt,
     64   ...
     65   )
     66 /*++
     67 
     68 Routine Description:
     69   Prints an error message.
     70 
     71 Arguments:
     72   All arguments are optional, though the printed message may be useless if
     73   at least something valid is not specified.
     74 
     75   FileName - name of the file or application. If not specified, then the
     76              utilty name (as set by the utility calling SetUtilityName()
     77              earlier) is used. Otherwise "Unknown utility" is used.
     78 
     79   LineNumber - the line number of error, typically used by parsers. If the
     80                utility is not a parser, then 0 should be specified. Otherwise
     81                the FileName and LineNumber info can be used to cause
     82                MS Visual Studio to jump to the error.
     83 
     84   MessageCode - an application-specific error code that can be referenced in
     85               other documentation.
     86 
     87   Text        - the text in question, typically used by parsers.
     88 
     89   MsgFmt - the format string for the error message. Can contain formatting
     90            controls for use with the varargs.
     91 
     92 Returns:
     93   None.
     94 
     95 Notes:
     96   We print the following (similar to the Warn() and Debug()
     97   W
     98   Typical error/warning message format:
     99 
    100   bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
    101 
    102   BUGBUG -- these three utility functions are almost identical, and
    103   should be modified to share code.
    104 
    105   Visual Studio does not find error messages with:
    106 
    107      " error :"
    108      " error 1:"
    109      " error c1:"
    110      " error 1000:"
    111      " error c100:"
    112 
    113   It does find:
    114      " error c1000:"
    115 --*/
    116 {
    117   va_list List;
    118   mErrorCount++;
    119   va_start (List, MsgFmt);
    120   PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
    121   va_end (List);
    122   //
    123   // Set status accordingly
    124   //
    125   if (mStatus < STATUS_ERROR) {
    126     mStatus = STATUS_ERROR;
    127   }
    128 }
    129 
    130 void
    131 ParserError (
    132   UINT32  MessageCode,
    133   INT8    *Text,
    134   INT8    *MsgFmt,
    135   ...
    136   )
    137 /*++
    138 
    139 Routine Description:
    140   Print a parser error, using the source file name and line number
    141   set by a previous call to SetParserPosition().
    142 
    143 Arguments:
    144   MessageCode   - application-specific error code
    145   Text          - text to print in the error message
    146   MsgFmt        - format string to print at the end of the error message
    147   ...
    148 
    149 Returns:
    150   NA
    151 
    152 --*/
    153 {
    154   va_list List;
    155   mErrorCount++;
    156   va_start (List, MsgFmt);
    157   PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);
    158   va_end (List);
    159   //
    160   // Set status accordingly
    161   //
    162   if (mStatus < STATUS_ERROR) {
    163     mStatus = STATUS_ERROR;
    164   }
    165 }
    166 
    167 void
    168 ParserWarning (
    169   UINT32  ErrorCode,
    170   INT8    *OffendingText,
    171   INT8    *MsgFmt,
    172   ...
    173   )
    174 /*++
    175 
    176 Routine Description:
    177   Print a parser warning, using the source file name and line number
    178   set by a previous call to SetParserPosition().
    179 
    180 Arguments:
    181   ErrorCode     - application-specific error code
    182   OffendingText - text to print in the warning message
    183   MsgFmt        - format string to print at the end of the warning message
    184   ...
    185 
    186 Returns:
    187   NA
    188 
    189 --*/
    190 {
    191   va_list List;
    192   mWarningCount++;
    193   va_start (List, MsgFmt);
    194   PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);
    195   va_end (List);
    196   //
    197   // Set status accordingly
    198   //
    199   if (mStatus < STATUS_WARNING) {
    200     mStatus = STATUS_WARNING;
    201   }
    202 }
    203 
    204 void
    205 Warning (
    206   INT8    *FileName,
    207   UINT32  LineNumber,
    208   UINT32  MessageCode,
    209   INT8    *Text,
    210   INT8    *MsgFmt,
    211   ...
    212   )
    213 /*++
    214 
    215 Routine Description:
    216   Print a warning message.
    217 
    218 Arguments:
    219   FileName    - name of the file where the warning was detected, or the name
    220                 of the application that detected the warning
    221 
    222   LineNumber  - the line number where the warning was detected (parsers).
    223                 0 should be specified if the utility is not a parser.
    224 
    225   MessageCode - an application-specific warning code that can be referenced in
    226                 other documentation.
    227 
    228   Text        - the text in question (parsers)
    229 
    230   MsgFmt      - the format string for the warning message. Can contain formatting
    231                 controls for use with varargs.
    232 
    233   ...
    234 
    235 Returns:
    236   None.
    237 
    238 --*/
    239 {
    240   va_list List;
    241   mWarningCount++;
    242   va_start (List, MsgFmt);
    243   PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
    244   va_end (List);
    245   //
    246   // Set status accordingly
    247   //
    248   if (mStatus < STATUS_WARNING) {
    249     mStatus = STATUS_WARNING;
    250   }
    251 }
    252 
    253 void
    254 DebugMsg (
    255   INT8    *FileName,
    256   UINT32  LineNumber,
    257   UINT32  MsgMask,
    258   INT8    *Text,
    259   INT8    *MsgFmt,
    260   ...
    261   )
    262 /*++
    263 
    264 Routine Description:
    265   Print a warning message.
    266 
    267 Arguments:
    268   FileName    - typically the name of the utility printing the debug message, but
    269                 can be the name of a file being parsed.
    270 
    271   LineNumber  - the line number in FileName (parsers)
    272 
    273   MsgMask     - an application-specific bitmask that, in combination with mDebugMsgMask,
    274                 determines if the debug message gets printed.
    275 
    276   Text        - the text in question (parsers)
    277 
    278   MsgFmt      - the format string for the debug message. Can contain formatting
    279                 controls for use with varargs.
    280 
    281   ...
    282 Returns:
    283   None.
    284 
    285 --*/
    286 {
    287   va_list List;
    288   //
    289   // If the debug mask is not applicable, then do nothing.
    290   //
    291   if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) {
    292     return ;
    293   }
    294 
    295   va_start (List, MsgFmt);
    296   PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List);
    297   va_end (List);
    298 }
    299 
    300 static
    301 void
    302 PrintMessage (
    303   INT8    *Type,
    304   INT8    *FileName,
    305   UINT32  LineNumber,
    306   UINT32  MessageCode,
    307   INT8    *Text,
    308   INT8    *MsgFmt,
    309   va_list List
    310   )
    311 /*++
    312 
    313 Routine Description:
    314   Worker routine for all the utility printing services. Prints the message in
    315   a format that Visual Studio will find when scanning build outputs for
    316   errors or warnings.
    317 
    318 Arguments:
    319   Type        - "warning" or "error" string to insert into the message to be
    320                 printed. The first character of this string (converted to uppercase)
    321                 is used to preceed the MessageCode value in the output string.
    322 
    323   FileName    - name of the file where the warning was detected, or the name
    324                 of the application that detected the warning
    325 
    326   LineNumber  - the line number where the warning was detected (parsers).
    327                 0 should be specified if the utility is not a parser.
    328 
    329   MessageCode - an application-specific warning code that can be referenced in
    330                 other documentation.
    331 
    332   Text        - part of the message to print
    333 
    334   MsgFmt      - the format string for the message. Can contain formatting
    335                 controls for use with varargs.
    336 
    337   List        - Variable function parameter list.
    338 Returns:
    339   None.
    340 
    341 Notes:
    342   If FileName == NULL then this utility will use the string passed into SetUtilityName().
    343 
    344   LineNumber is only used if the caller is a parser, in which case FileName refers to the
    345   file being parsed.
    346 
    347   Text and MsgFmt are both optional, though it would be of little use calling this function with
    348   them both NULL.
    349 
    350   Output will typically be of the form:
    351     <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
    352 
    353     Parser (LineNumber != 0)
    354       VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
    355     Generic utility (LineNumber == 0)
    356       UtilityName : error E1234 : Text string : MsgFmt string and args
    357 
    358 --*/
    359 {
    360   INT8  Line[MAX_LINE_LEN];
    361   INT8  Line2[MAX_LINE_LEN];
    362   INT8  *Cptr;
    363   //
    364   // If given a filename, then add it (and the line number) to the string.
    365   // If there's no filename, then use the program name if provided.
    366   //
    367   if (FileName != NULL) {
    368     Cptr = FileName;
    369   } else if (mUtilityName[0] != 0) {
    370     Cptr = mUtilityName;
    371   } else {
    372     Cptr = "Unknown utility";
    373   }
    374 
    375   strcpy (Line, Cptr);
    376   if (LineNumber != 0) {
    377     sprintf (Line2, "(%d)", LineNumber);
    378     strcat (Line, Line2);
    379   }
    380   //
    381   // Have to print an error code or Visual Studio won't find the
    382   // message for you. It has to be decimal digits too.
    383   //
    384   sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode);
    385   strcat (Line, Line2);
    386   fprintf (stdout, "%s", Line);
    387   //
    388   // If offending text was provided, then print it
    389   //
    390   if (Text != NULL) {
    391     fprintf (stdout, ": %s ", Text);
    392   }
    393   //
    394   // Print formatted message if provided
    395   //
    396   if (MsgFmt != NULL) {
    397     vsprintf (Line2, MsgFmt, List);
    398     fprintf (stdout, ": %s", Line2);
    399   }
    400 
    401   fprintf (stdout, "\n");
    402 }
    403 
    404 void
    405 ParserSetPosition (
    406   INT8    *SourceFileName,
    407   UINT32  LineNum
    408   )
    409 /*++
    410 
    411 Routine Description:
    412   Set the position in a file being parsed. This can be used to
    413   print error messages deeper down in a parser.
    414 
    415 Arguments:
    416   SourceFileName - name of the source file being parsed
    417   LineNum        - line number of the source file being parsed
    418 
    419 Returns:
    420   NA
    421 
    422 --*/
    423 {
    424   mSourceFileName     = SourceFileName;
    425   mSourceFileLineNum  = LineNum;
    426 }
    427 
    428 void
    429 SetUtilityName (
    430   INT8    *UtilityName
    431   )
    432 /*++
    433 
    434 Routine Description:
    435   All printed error/warning/debug messages follow the same format, and
    436   typically will print a filename or utility name followed by the error
    437   text. However if a filename is not passed to the print routines, then
    438   they'll print the utility name if you call this function early in your
    439   app to set the utility name.
    440 
    441 Arguments:
    442   UtilityName  -  name of the utility, which will be printed with all
    443                   error/warning/debug messags.
    444 
    445 Returns:
    446   NA
    447 
    448 --*/
    449 {
    450   //
    451   // Save the name of the utility in our local variable. Make sure its
    452   // length does not exceed our buffer.
    453   //
    454   if (UtilityName != NULL) {
    455     if (strlen (UtilityName) >= sizeof (mUtilityName)) {
    456       Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");
    457       strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);
    458       mUtilityName[sizeof (mUtilityName) - 1] = 0;
    459       return ;
    460     } else {
    461       strcpy (mUtilityName, UtilityName);
    462     }
    463   } else {
    464     Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
    465   }
    466 }
    467 
    468 STATUS
    469 GetUtilityStatus (
    470   VOID
    471   )
    472 /*++
    473 
    474 Routine Description:
    475   When you call Error() or Warning(), this module keeps track of it and
    476   sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
    477   exits, it can call this function to get the status and use it as a return
    478   value.
    479 
    480 Arguments:
    481   None.
    482 
    483 Returns:
    484   Worst-case status reported, as defined by which print function was called.
    485 
    486 --*/
    487 {
    488   return mStatus;
    489 }
    490