Home | History | Annotate | Download | only in Common
      1 /** @file
      2 EFI tools utility functions to display warning, error, and informational messages
      3 
      4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 --*/
     14 
     15 #include <stdio.h>
     16 #include <string.h>
     17 #include <ctype.h>
     18 #include <stdarg.h>
     19 #include <time.h>
     20 
     21 #include "EfiUtilityMsgs.h"
     22 
     23 //
     24 // Declare module globals for keeping track of the the utility's
     25 // name and other settings.
     26 //
     27 STATIC STATUS mStatus                 = STATUS_SUCCESS;
     28 STATIC CHAR8  mUtilityName[50]        = { 0 };
     29 STATIC UINT64 mPrintLogLevel          = INFO_LOG_LEVEL;
     30 STATIC CHAR8  *mSourceFileName        = NULL;
     31 STATIC UINT32 mSourceFileLineNum      = 0;
     32 STATIC UINT32 mErrorCount             = 0;
     33 STATIC UINT32 mWarningCount           = 0;
     34 STATIC UINT32 mMaxErrors              = 0;
     35 STATIC UINT32 mMaxWarnings            = 0;
     36 STATIC UINT32 mMaxWarningsPlusErrors  = 0;
     37 STATIC INT8   mPrintLimitsSet         = 0;
     38 
     39 STATIC
     40 VOID
     41 PrintLimitExceeded (
     42   VOID
     43   );
     44 
     45 VOID
     46 Error (
     47   CHAR8   *FileName,
     48   UINT32  LineNumber,
     49   UINT32  MessageCode,
     50   CHAR8   *Text,
     51   CHAR8   *MsgFmt,
     52   ...
     53   )
     54 /*++
     55 
     56 Routine Description:
     57   Prints an error message.
     58 
     59 Arguments:
     60   All arguments are optional, though the printed message may be useless if
     61   at least something valid is not specified.
     62 
     63   FileName - name of the file or application. If not specified, then the
     64              utilty name (as set by the utility calling SetUtilityName()
     65              earlier) is used. Otherwise "Unknown utility" is used.
     66 
     67   LineNumber - the line number of error, typically used by parsers. If the
     68                utility is not a parser, then 0 should be specified. Otherwise
     69                the FileName and LineNumber info can be used to cause
     70                MS Visual Studio to jump to the error.
     71 
     72   MessageCode - an application-specific error code that can be referenced in
     73               other documentation.
     74 
     75   Text        - the text in question, typically used by parsers.
     76 
     77   MsgFmt - the format string for the error message. Can contain formatting
     78            controls for use with the varargs.
     79 
     80 Returns:
     81   None.
     82 
     83 Notes:
     84   We print the following (similar to the Warn() and Debug()
     85   W
     86   Typical error/warning message format:
     87 
     88   bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
     89 
     90   BUGBUG -- these three utility functions are almost identical, and
     91   should be modified to share code.
     92 
     93   Visual Studio does not find error messages with:
     94 
     95      " error :"
     96      " error 1:"
     97      " error c1:"
     98      " error 1000:"
     99      " error c100:"
    100 
    101   It does find:
    102      " error c1000:"
    103 --*/
    104 {
    105   va_list List;
    106   //
    107   // If limits have been set, then check that we have not exceeded them
    108   //
    109   if (mPrintLimitsSet) {
    110     //
    111     // See if we've exceeded our total count
    112     //
    113     if (mMaxWarningsPlusErrors != 0) {
    114       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
    115         PrintLimitExceeded ();
    116         return ;
    117       }
    118     }
    119     //
    120     // See if we've exceeded our error count
    121     //
    122     if (mMaxErrors != 0) {
    123       if (mErrorCount > mMaxErrors) {
    124         PrintLimitExceeded ();
    125         return ;
    126       }
    127     }
    128   }
    129 
    130   mErrorCount++;
    131   va_start (List, MsgFmt);
    132   PrintMessage ("ERROR", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
    133   va_end (List);
    134 }
    135 
    136 VOID
    137 ParserError (
    138   UINT32  MessageCode,
    139   CHAR8   *Text,
    140   CHAR8   *MsgFmt,
    141   ...
    142   )
    143 /*++
    144 
    145 Routine Description:
    146   Print a parser error, using the source file name and line number
    147   set by a previous call to SetParserPosition().
    148 
    149 Arguments:
    150   MessageCode   - application-specific error code
    151   Text          - text to print in the error message
    152   MsgFmt        - format string to print at the end of the error message
    153 
    154 Returns:
    155   NA
    156 
    157 --*/
    158 {
    159   va_list List;
    160   //
    161   // If limits have been set, then check them
    162   //
    163   if (mPrintLimitsSet) {
    164     //
    165     // See if we've exceeded our total count
    166     //
    167     if (mMaxWarningsPlusErrors != 0) {
    168       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
    169         PrintLimitExceeded ();
    170         return ;
    171       }
    172     }
    173     //
    174     // See if we've exceeded our error count
    175     //
    176     if (mMaxErrors != 0) {
    177       if (mErrorCount > mMaxErrors) {
    178         PrintLimitExceeded ();
    179         return ;
    180       }
    181     }
    182   }
    183 
    184   mErrorCount++;
    185   va_start (List, MsgFmt);
    186   PrintMessage ("ERROR", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);
    187   va_end (List);
    188 }
    189 
    190 VOID
    191 ParserWarning (
    192   UINT32  ErrorCode,
    193   CHAR8   *OffendingText,
    194   CHAR8   *MsgFmt,
    195   ...
    196   )
    197 /*++
    198 
    199 Routine Description:
    200   Print a parser warning, using the source file name and line number
    201   set by a previous call to SetParserPosition().
    202 
    203 Arguments:
    204   ErrorCode     - application-specific error code
    205   OffendingText - text to print in the warning message
    206   MsgFmt        - format string to print at the end of the warning message
    207 
    208 Returns:
    209   NA
    210 
    211 --*/
    212 {
    213   va_list List;
    214   //
    215   // If limits have been set, then check them
    216   //
    217   if (mPrintLimitsSet) {
    218     //
    219     // See if we've exceeded our total count
    220     //
    221     if (mMaxWarningsPlusErrors != 0) {
    222       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
    223         PrintLimitExceeded ();
    224         return ;
    225       }
    226     }
    227     //
    228     // See if we've exceeded our warning count
    229     //
    230     if (mMaxWarnings != 0) {
    231       if (mWarningCount > mMaxWarnings) {
    232         PrintLimitExceeded ();
    233         return ;
    234       }
    235     }
    236   }
    237 
    238   mWarningCount++;
    239   va_start (List, MsgFmt);
    240   PrintMessage ("WARNING", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);
    241   va_end (List);
    242   //
    243   // Don't set warning status accordingly
    244   //
    245   //  if (mStatus < STATUS_WARNING) {
    246   //    mStatus = STATUS_WARNING;
    247   //  }
    248 }
    249 
    250 VOID
    251 Warning (
    252   CHAR8   *FileName,
    253   UINT32  LineNumber,
    254   UINT32  MessageCode,
    255   CHAR8   *Text,
    256   CHAR8   *MsgFmt,
    257   ...
    258   )
    259 /*++
    260 
    261 Routine Description:
    262   Print a warning message.
    263 
    264 Arguments:
    265   FileName    - name of the file where the warning was detected, or the name
    266                 of the application that detected the warning
    267 
    268   LineNumber  - the line number where the warning was detected (parsers).
    269                 0 should be specified if the utility is not a parser.
    270 
    271   MessageCode - an application-specific warning code that can be referenced in
    272                 other documentation.
    273 
    274   Text        - the text in question (parsers)
    275 
    276   MsgFmt      - the format string for the warning message. Can contain formatting
    277                 controls for use with varargs.
    278 
    279 Returns:
    280   None.
    281 
    282 --*/
    283 {
    284   va_list List;
    285 
    286   //
    287   // Current Print Level not output warning information.
    288   //
    289   if (WARNING_LOG_LEVEL < mPrintLogLevel) {
    290     return;
    291   }
    292   //
    293   // If limits have been set, then check them
    294   //
    295   if (mPrintLimitsSet) {
    296     //
    297     // See if we've exceeded our total count
    298     //
    299     if (mMaxWarningsPlusErrors != 0) {
    300       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
    301         PrintLimitExceeded ();
    302         return ;
    303       }
    304     }
    305     //
    306     // See if we've exceeded our warning count
    307     //
    308     if (mMaxWarnings != 0) {
    309       if (mWarningCount > mMaxWarnings) {
    310         PrintLimitExceeded ();
    311         return ;
    312       }
    313     }
    314   }
    315 
    316   mWarningCount++;
    317   va_start (List, MsgFmt);
    318   PrintMessage ("WARNING", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
    319   va_end (List);
    320 }
    321 
    322 VOID
    323 DebugMsg (
    324   CHAR8   *FileName,
    325   UINT32  LineNumber,
    326   UINT64  MsgLevel,
    327   CHAR8   *Text,
    328   CHAR8   *MsgFmt,
    329   ...
    330   )
    331 /*++
    332 
    333 Routine Description:
    334   Print a Debug message.
    335 
    336 Arguments:
    337   FileName    - typically the name of the utility printing the debug message, but
    338                 can be the name of a file being parsed.
    339 
    340   LineNumber  - the line number in FileName (parsers)
    341 
    342   MsgLevel    - Debug message print level (0~9)
    343 
    344   Text        - the text in question (parsers)
    345 
    346   MsgFmt      - the format string for the debug message. Can contain formatting
    347                 controls for use with varargs.
    348 
    349 Returns:
    350   None.
    351 
    352 --*/
    353 {
    354   va_list List;
    355   //
    356   // If the debug level is less than current print level, then do nothing.
    357   //
    358   if (MsgLevel < mPrintLogLevel) {
    359     return ;
    360   }
    361 
    362   va_start (List, MsgFmt);
    363   PrintMessage ("DEBUG", FileName, LineNumber, 0, Text, MsgFmt, List);
    364   va_end (List);
    365 }
    366 
    367 VOID
    368 PrintMessage (
    369   CHAR8   *Type,
    370   CHAR8   *FileName,
    371   UINT32  LineNumber,
    372   UINT32  MessageCode,
    373   CHAR8   *Text,
    374   CHAR8   *MsgFmt,
    375   va_list List
    376   )
    377 /*++
    378 
    379 Routine Description:
    380   Worker routine for all the utility printing services. Prints the message in
    381   a format that Visual Studio will find when scanning build outputs for
    382   errors or warnings.
    383 
    384 Arguments:
    385   Type        - "warning" or "error" string to insert into the message to be
    386                 printed. The first character of this string (converted to uppercase)
    387                 is used to preceed the MessageCode value in the output string.
    388 
    389   FileName    - name of the file where the warning was detected, or the name
    390                 of the application that detected the warning
    391 
    392   LineNumber  - the line number where the warning was detected (parsers).
    393                 0 should be specified if the utility is not a parser.
    394 
    395   MessageCode - an application-specific warning code that can be referenced in
    396                 other documentation.
    397 
    398   Text        - part of the message to print
    399 
    400   MsgFmt      - the format string for the message. Can contain formatting
    401                 controls for use with varargs.
    402   List        - the variable list.
    403 
    404 Returns:
    405   None.
    406 
    407 Notes:
    408   If FileName == NULL then this utility will use the string passed into SetUtilityName().
    409 
    410   LineNumber is only used if the caller is a parser, in which case FileName refers to the
    411   file being parsed.
    412 
    413   Text and MsgFmt are both optional, though it would be of little use calling this function with
    414   them both NULL.
    415 
    416   Output will typically be of the form:
    417     <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
    418 
    419     Parser (LineNumber != 0)
    420       VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
    421     Generic utility (LineNumber == 0)
    422       UtilityName : error E1234 : Text string : MsgFmt string and args
    423 
    424 --*/
    425 {
    426   CHAR8       Line[MAX_LINE_LEN];
    427   CHAR8       Line2[MAX_LINE_LEN];
    428   CHAR8       *Cptr;
    429   struct tm   *NewTime;
    430   time_t      CurrentTime;
    431 
    432   //
    433   // init local variable
    434   //
    435   Line[0] = '\0';
    436   Line2[0] = '\0';
    437 
    438   //
    439   // If given a filename, then add it (and the line number) to the string.
    440   // If there's no filename, then use the program name if provided.
    441   //
    442   if (FileName != NULL) {
    443     Cptr = FileName;
    444   } else {
    445     Cptr = NULL;
    446   }
    447 
    448   if (strcmp (Type, "DEBUG") == 0) {
    449     //
    450     // Debug Message requires current time.
    451     //
    452     time (&CurrentTime);
    453     NewTime = localtime (&CurrentTime);
    454     if (NewTime != NULL) {
    455       fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d",
    456                        NewTime->tm_year + 1900,
    457                        NewTime->tm_mon + 1,
    458                        NewTime->tm_mday,
    459                        NewTime->tm_hour,
    460                        NewTime->tm_min,
    461                        NewTime->tm_sec
    462                        );
    463     }
    464     if (Cptr != NULL) {
    465       sprintf (Line, ": %s", Cptr);
    466       if (LineNumber != 0) {
    467         sprintf (Line2, "(%u)", (unsigned) LineNumber);
    468         strcat (Line, Line2);
    469       }
    470     }
    471   } else {
    472     //
    473     // Error and Warning Information.
    474     //
    475     if (Cptr != NULL) {
    476       if (mUtilityName[0] != '\0') {
    477         fprintf (stdout, "%s...\n", mUtilityName);
    478       }
    479       sprintf (Line, "%s", Cptr);
    480       if (LineNumber != 0) {
    481         sprintf (Line2, "(%u)", (unsigned) LineNumber);
    482         strcat (Line, Line2);
    483       }
    484     } else {
    485       if (mUtilityName[0] != '\0') {
    486         sprintf (Line, "%s", mUtilityName);
    487       }
    488     }
    489 
    490     if (strcmp (Type, "ERROR") == 0) {
    491       //
    492       // Set status accordingly for ERROR information.
    493       //
    494       if (mStatus < STATUS_ERROR) {
    495         mStatus = STATUS_ERROR;
    496       }
    497     }
    498   }
    499 
    500   //
    501   // Have to print an error code or Visual Studio won't find the
    502   // message for you. It has to be decimal digits too.
    503   //
    504   if (MessageCode != 0) {
    505     sprintf (Line2, ": %s %04u", Type, (unsigned) MessageCode);
    506   } else {
    507     sprintf (Line2, ": %s", Type);
    508   }
    509   strcat (Line, Line2);
    510   fprintf (stdout, "%s", Line);
    511   //
    512   // If offending text was provided, then print it
    513   //
    514   if (Text != NULL) {
    515     fprintf (stdout, ": %s", Text);
    516   }
    517   fprintf (stdout, "\n");
    518 
    519   //
    520   // Print formatted message if provided
    521   //
    522   if (MsgFmt != NULL) {
    523     vsprintf (Line2, MsgFmt, List);
    524     fprintf (stdout, "  %s\n", Line2);
    525   }
    526 
    527 }
    528 
    529 STATIC
    530 VOID
    531 PrintSimpleMessage (
    532   CHAR8   *MsgFmt,
    533   va_list List
    534   )
    535 /*++
    536 Routine Description:
    537   Print message into stdout.
    538 
    539 Arguments:
    540   MsgFmt      - the format string for the message. Can contain formatting
    541                 controls for use with varargs.
    542   List        - the variable list.
    543 
    544 Returns:
    545   None.
    546 --*/
    547 {
    548   CHAR8       Line[MAX_LINE_LEN];
    549   //
    550   // Print formatted message if provided
    551   //
    552   if (MsgFmt != NULL) {
    553     vsprintf (Line, MsgFmt, List);
    554     fprintf (stdout, "%s\n", Line);
    555   }
    556 }
    557 
    558 VOID
    559 ParserSetPosition (
    560   CHAR8   *SourceFileName,
    561   UINT32  LineNum
    562   )
    563 /*++
    564 
    565 Routine Description:
    566   Set the position in a file being parsed. This can be used to
    567   print error messages deeper down in a parser.
    568 
    569 Arguments:
    570   SourceFileName - name of the source file being parsed
    571   LineNum        - line number of the source file being parsed
    572 
    573 Returns:
    574   NA
    575 
    576 --*/
    577 {
    578   mSourceFileName     = SourceFileName;
    579   mSourceFileLineNum  = LineNum;
    580 }
    581 
    582 VOID
    583 SetUtilityName (
    584   CHAR8   *UtilityName
    585   )
    586 /*++
    587 
    588 Routine Description:
    589   All printed error/warning/debug messages follow the same format, and
    590   typically will print a filename or utility name followed by the error
    591   text. However if a filename is not passed to the print routines, then
    592   they'll print the utility name if you call this function early in your
    593   app to set the utility name.
    594 
    595 Arguments:
    596   UtilityName  -  name of the utility, which will be printed with all
    597                   error/warning/debug messags.
    598 
    599 Returns:
    600   NA
    601 
    602 --*/
    603 {
    604   //
    605   // Save the name of the utility in our local variable. Make sure its
    606   // length does not exceed our buffer.
    607   //
    608   if (UtilityName != NULL) {
    609     if (strlen (UtilityName) >= sizeof (mUtilityName)) {
    610       Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");
    611       strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);
    612       mUtilityName[sizeof (mUtilityName) - 1] = 0;
    613       return ;
    614     } else {
    615       strcpy (mUtilityName, UtilityName);
    616     }
    617   } else {
    618     Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
    619   }
    620 }
    621 
    622 STATUS
    623 GetUtilityStatus (
    624   VOID
    625   )
    626 /*++
    627 
    628 Routine Description:
    629   When you call Error() or Warning(), this module keeps track of it and
    630   sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
    631   exits, it can call this function to get the status and use it as a return
    632   value.
    633 
    634 Arguments:
    635   None.
    636 
    637 Returns:
    638   Worst-case status reported, as defined by which print function was called.
    639 
    640 --*/
    641 {
    642   return mStatus;
    643 }
    644 
    645 VOID
    646 SetPrintLevel (
    647   UINT64  LogLevel
    648   )
    649 /*++
    650 
    651 Routine Description:
    652   Set the printing message Level. This is used by the PrintMsg() function
    653   to determine when/if a message should be printed.
    654 
    655 Arguments:
    656   LogLevel  - 0~50 to specify the different level message.
    657 
    658 Returns:
    659   NA
    660 
    661 --*/
    662 {
    663   mPrintLogLevel = LogLevel;
    664 }
    665 
    666 VOID
    667 VerboseMsg (
    668   CHAR8   *MsgFmt,
    669   ...
    670   )
    671 /*++
    672 
    673 Routine Description:
    674   Print a verbose level message.
    675 
    676 Arguments:
    677   MsgFmt      - the format string for the message. Can contain formatting
    678                 controls for use with varargs.
    679   List        - the variable list.
    680 
    681 Returns:
    682   NA
    683 
    684 --*/
    685 {
    686   va_list List;
    687   //
    688   // If the debug level is less than current print level, then do nothing.
    689   //
    690   if (VERBOSE_LOG_LEVEL < mPrintLogLevel) {
    691     return ;
    692   }
    693 
    694   va_start (List, MsgFmt);
    695   PrintSimpleMessage (MsgFmt, List);
    696   va_end (List);
    697 }
    698 
    699 VOID
    700 NormalMsg (
    701   CHAR8   *MsgFmt,
    702   ...
    703   )
    704 /*++
    705 
    706 Routine Description:
    707   Print a default level message.
    708 
    709 Arguments:
    710   MsgFmt      - the format string for the message. Can contain formatting
    711                 controls for use with varargs.
    712   List        - the variable list.
    713 
    714 Returns:
    715   NA
    716 
    717 --*/
    718 {
    719   va_list List;
    720   //
    721   // If the debug level is less than current print level, then do nothing.
    722   //
    723   if (INFO_LOG_LEVEL < mPrintLogLevel) {
    724     return ;
    725   }
    726 
    727   va_start (List, MsgFmt);
    728   PrintSimpleMessage (MsgFmt, List);
    729   va_end (List);
    730 }
    731 
    732 VOID
    733 KeyMsg (
    734   CHAR8   *MsgFmt,
    735   ...
    736   )
    737 /*++
    738 
    739 Routine Description:
    740   Print a key level message.
    741 
    742 Arguments:
    743   MsgFmt      - the format string for the message. Can contain formatting
    744                 controls for use with varargs.
    745   List        - the variable list.
    746 
    747 Returns:
    748   NA
    749 
    750 --*/
    751 {
    752   va_list List;
    753   //
    754   // If the debug level is less than current print level, then do nothing.
    755   //
    756   if (KEY_LOG_LEVEL < mPrintLogLevel) {
    757     return ;
    758   }
    759 
    760   va_start (List, MsgFmt);
    761   PrintSimpleMessage (MsgFmt, List);
    762   va_end (List);
    763 }
    764 
    765 VOID
    766 SetPrintLimits (
    767   UINT32  MaxErrors,
    768   UINT32  MaxWarnings,
    769   UINT32  MaxWarningsPlusErrors
    770   )
    771 /*++
    772 
    773 Routine Description:
    774   Set the limits of how many errors, warnings, and errors+warnings
    775   we will print.
    776 
    777 Arguments:
    778   MaxErrors       - maximum number of error messages to print
    779   MaxWarnings     - maximum number of warning messages to print
    780   MaxWarningsPlusErrors
    781                   - maximum number of errors+warnings to print
    782 
    783 Returns:
    784   NA
    785 
    786 --*/
    787 {
    788   mMaxErrors              = MaxErrors;
    789   mMaxWarnings            = MaxWarnings;
    790   mMaxWarningsPlusErrors  = MaxWarningsPlusErrors;
    791   mPrintLimitsSet         = 1;
    792 }
    793 
    794 STATIC
    795 VOID
    796 PrintLimitExceeded (
    797   VOID
    798   )
    799 {
    800   STATIC INT8 mPrintLimitExceeded = 0;
    801   //
    802   // If we've already printed the message, do nothing. Otherwise
    803   // temporarily increase our print limits so we can pass one
    804   // more message through.
    805   //
    806   if (mPrintLimitExceeded == 0) {
    807     mPrintLimitExceeded++;
    808     mMaxErrors++;
    809     mMaxWarnings++;
    810     mMaxWarningsPlusErrors++;
    811     Error (NULL, 0, 0, "error/warning print limit exceeded", NULL);
    812     mMaxErrors--;
    813     mMaxWarnings--;
    814     mMaxWarningsPlusErrors--;
    815   }
    816 }
    817 
    818 #if 0
    819 VOID
    820 TestUtilityMessages (
    821   VOID
    822   )
    823 {
    824   CHAR8 *ArgStr = "ArgString";
    825   int   ArgInt;
    826 
    827   ArgInt  = 0x12345678;
    828   //
    829   // Test without setting utility name
    830   //
    831   fprintf (stdout, "* Testing without setting utility name\n");
    832   fprintf (stdout, "** Test debug message not printed\n");
    833   DebugMsg (NULL, 0, 0x00000001, NULL, NULL);
    834   fprintf (stdout, "** Test warning with two strings and two args\n");
    835   Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    836   fprintf (stdout, "** Test error with two strings and two args\n");
    837   Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    838   fprintf (stdout, "** Test parser warning with nothing\n");
    839   ParserWarning (0, NULL, NULL);
    840   fprintf (stdout, "** Test parser error with nothing\n");
    841   ParserError (0, NULL, NULL);
    842   //
    843   // Test with utility name set now
    844   //
    845   fprintf (stdout, "** Testingin with utility name set\n");
    846   SetUtilityName ("MyUtilityName");
    847   //
    848   // Test debug prints
    849   //
    850   SetDebugMsgMask (2);
    851   fprintf (stdout, "** Test debug message with one string\n");
    852   DebugMsg (NULL, 0, 0x00000002, "Text1", NULL);
    853   fprintf (stdout, "** Test debug message with one string\n");
    854   DebugMsg (NULL, 0, 0x00000002, NULL, "Text2");
    855   fprintf (stdout, "** Test debug message with two strings\n");
    856   DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2");
    857   fprintf (stdout, "** Test debug message with two strings and two args\n");
    858   DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    859   //
    860   // Test warning prints
    861   //
    862   fprintf (stdout, "** Test warning with no strings\n");
    863   Warning (NULL, 0, 1234, NULL, NULL);
    864   fprintf (stdout, "** Test warning with one string\n");
    865   Warning (NULL, 0, 1234, "Text1", NULL);
    866   fprintf (stdout, "** Test warning with one string\n");
    867   Warning (NULL, 0, 1234, NULL, "Text2");
    868   fprintf (stdout, "** Test warning with two strings and two args\n");
    869   Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    870   //
    871   // Test error prints
    872   //
    873   fprintf (stdout, "** Test error with no strings\n");
    874   Error (NULL, 0, 1234, NULL, NULL);
    875   fprintf (stdout, "** Test error with one string\n");
    876   Error (NULL, 0, 1234, "Text1", NULL);
    877   fprintf (stdout, "** Test error with one string\n");
    878   Error (NULL, 0, 1234, NULL, "Text2");
    879   fprintf (stdout, "** Test error with two strings and two args\n");
    880   Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    881   //
    882   // Test parser prints
    883   //
    884   fprintf (stdout, "** Test parser errors\n");
    885   ParserSetPosition (__FILE__, __LINE__ + 1);
    886   ParserError (1234, NULL, NULL);
    887   ParserSetPosition (__FILE__, __LINE__ + 1);
    888   ParserError (1234, "Text1", NULL);
    889   ParserSetPosition (__FILE__, __LINE__ + 1);
    890   ParserError (1234, NULL, "Text2");
    891   ParserSetPosition (__FILE__, __LINE__ + 1);
    892   ParserError (1234, "Text1", "Text2");
    893   ParserSetPosition (__FILE__, __LINE__ + 1);
    894   ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    895 
    896   fprintf (stdout, "** Test parser warnings\n");
    897   ParserSetPosition (__FILE__, __LINE__ + 1);
    898   ParserWarning (4321, NULL, NULL);
    899   ParserSetPosition (__FILE__, __LINE__ + 1);
    900   ParserWarning (4321, "Text1", NULL);
    901   ParserSetPosition (__FILE__, __LINE__ + 1);
    902   ParserWarning (4321, NULL, "Text2");
    903   ParserSetPosition (__FILE__, __LINE__ + 1);
    904   ParserWarning (4321, "Text1", "Text2");
    905   ParserSetPosition (__FILE__, __LINE__ + 1);
    906   ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
    907 }
    908 #endif
    909