1 /** @file 2 EFI tools utility functions to display warning, error, and informational messages 3 4 Copyright (c) 2004 - 2014, 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 fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d", 455 NewTime->tm_year + 1900, 456 NewTime->tm_mon + 1, 457 NewTime->tm_mday, 458 NewTime->tm_hour, 459 NewTime->tm_min, 460 NewTime->tm_sec 461 ); 462 if (Cptr != NULL) { 463 sprintf (Line, ": %s", Cptr); 464 if (LineNumber != 0) { 465 sprintf (Line2, "(%u)", (unsigned) LineNumber); 466 strcat (Line, Line2); 467 } 468 } 469 } else { 470 // 471 // Error and Warning Information. 472 // 473 if (Cptr != NULL) { 474 if (mUtilityName[0] != '\0') { 475 fprintf (stdout, "%s...\n", mUtilityName); 476 } 477 sprintf (Line, "%s", Cptr); 478 if (LineNumber != 0) { 479 sprintf (Line2, "(%u)", (unsigned) LineNumber); 480 strcat (Line, Line2); 481 } 482 } else { 483 if (mUtilityName[0] != '\0') { 484 sprintf (Line, "%s", mUtilityName); 485 } 486 } 487 488 if (strcmp (Type, "ERROR") == 0) { 489 // 490 // Set status accordingly for ERROR information. 491 // 492 if (mStatus < STATUS_ERROR) { 493 mStatus = STATUS_ERROR; 494 } 495 } 496 } 497 498 // 499 // Have to print an error code or Visual Studio won't find the 500 // message for you. It has to be decimal digits too. 501 // 502 if (MessageCode != 0) { 503 sprintf (Line2, ": %s %04u", Type, (unsigned) MessageCode); 504 } else { 505 sprintf (Line2, ": %s", Type); 506 } 507 strcat (Line, Line2); 508 fprintf (stdout, "%s", Line); 509 // 510 // If offending text was provided, then print it 511 // 512 if (Text != NULL) { 513 fprintf (stdout, ": %s", Text); 514 } 515 fprintf (stdout, "\n"); 516 517 // 518 // Print formatted message if provided 519 // 520 if (MsgFmt != NULL) { 521 vsprintf (Line2, MsgFmt, List); 522 fprintf (stdout, " %s\n", Line2); 523 } 524 525 } 526 527 STATIC 528 VOID 529 PrintSimpleMessage ( 530 CHAR8 *MsgFmt, 531 va_list List 532 ) 533 /*++ 534 Routine Description: 535 Print message into stdout. 536 537 Arguments: 538 MsgFmt - the format string for the message. Can contain formatting 539 controls for use with varargs. 540 List - the variable list. 541 542 Returns: 543 None. 544 --*/ 545 { 546 CHAR8 Line[MAX_LINE_LEN]; 547 // 548 // Print formatted message if provided 549 // 550 if (MsgFmt != NULL) { 551 vsprintf (Line, MsgFmt, List); 552 fprintf (stdout, "%s\n", Line); 553 } 554 } 555 556 VOID 557 ParserSetPosition ( 558 CHAR8 *SourceFileName, 559 UINT32 LineNum 560 ) 561 /*++ 562 563 Routine Description: 564 Set the position in a file being parsed. This can be used to 565 print error messages deeper down in a parser. 566 567 Arguments: 568 SourceFileName - name of the source file being parsed 569 LineNum - line number of the source file being parsed 570 571 Returns: 572 NA 573 574 --*/ 575 { 576 mSourceFileName = SourceFileName; 577 mSourceFileLineNum = LineNum; 578 } 579 580 VOID 581 SetUtilityName ( 582 CHAR8 *UtilityName 583 ) 584 /*++ 585 586 Routine Description: 587 All printed error/warning/debug messages follow the same format, and 588 typically will print a filename or utility name followed by the error 589 text. However if a filename is not passed to the print routines, then 590 they'll print the utility name if you call this function early in your 591 app to set the utility name. 592 593 Arguments: 594 UtilityName - name of the utility, which will be printed with all 595 error/warning/debug messags. 596 597 Returns: 598 NA 599 600 --*/ 601 { 602 // 603 // Save the name of the utility in our local variable. Make sure its 604 // length does not exceed our buffer. 605 // 606 if (UtilityName != NULL) { 607 if (strlen (UtilityName) >= sizeof (mUtilityName)) { 608 Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size"); 609 strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1); 610 mUtilityName[sizeof (mUtilityName) - 1] = 0; 611 return ; 612 } else { 613 strcpy (mUtilityName, UtilityName); 614 } 615 } else { 616 Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name"); 617 } 618 } 619 620 STATUS 621 GetUtilityStatus ( 622 VOID 623 ) 624 /*++ 625 626 Routine Description: 627 When you call Error() or Warning(), this module keeps track of it and 628 sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility 629 exits, it can call this function to get the status and use it as a return 630 value. 631 632 Arguments: 633 None. 634 635 Returns: 636 Worst-case status reported, as defined by which print function was called. 637 638 --*/ 639 { 640 return mStatus; 641 } 642 643 VOID 644 SetPrintLevel ( 645 UINT64 LogLevel 646 ) 647 /*++ 648 649 Routine Description: 650 Set the printing message Level. This is used by the PrintMsg() function 651 to determine when/if a message should be printed. 652 653 Arguments: 654 LogLevel - 0~50 to specify the different level message. 655 656 Returns: 657 NA 658 659 --*/ 660 { 661 mPrintLogLevel = LogLevel; 662 } 663 664 VOID 665 VerboseMsg ( 666 CHAR8 *MsgFmt, 667 ... 668 ) 669 /*++ 670 671 Routine Description: 672 Print a verbose level message. 673 674 Arguments: 675 MsgFmt - the format string for the message. Can contain formatting 676 controls for use with varargs. 677 List - the variable list. 678 679 Returns: 680 NA 681 682 --*/ 683 { 684 va_list List; 685 // 686 // If the debug level is less than current print level, then do nothing. 687 // 688 if (VERBOSE_LOG_LEVEL < mPrintLogLevel) { 689 return ; 690 } 691 692 va_start (List, MsgFmt); 693 PrintSimpleMessage (MsgFmt, List); 694 va_end (List); 695 } 696 697 VOID 698 NormalMsg ( 699 CHAR8 *MsgFmt, 700 ... 701 ) 702 /*++ 703 704 Routine Description: 705 Print a default level message. 706 707 Arguments: 708 MsgFmt - the format string for the message. Can contain formatting 709 controls for use with varargs. 710 List - the variable list. 711 712 Returns: 713 NA 714 715 --*/ 716 { 717 va_list List; 718 // 719 // If the debug level is less than current print level, then do nothing. 720 // 721 if (INFO_LOG_LEVEL < mPrintLogLevel) { 722 return ; 723 } 724 725 va_start (List, MsgFmt); 726 PrintSimpleMessage (MsgFmt, List); 727 va_end (List); 728 } 729 730 VOID 731 KeyMsg ( 732 CHAR8 *MsgFmt, 733 ... 734 ) 735 /*++ 736 737 Routine Description: 738 Print a key level message. 739 740 Arguments: 741 MsgFmt - the format string for the message. Can contain formatting 742 controls for use with varargs. 743 List - the variable list. 744 745 Returns: 746 NA 747 748 --*/ 749 { 750 va_list List; 751 // 752 // If the debug level is less than current print level, then do nothing. 753 // 754 if (KEY_LOG_LEVEL < mPrintLogLevel) { 755 return ; 756 } 757 758 va_start (List, MsgFmt); 759 PrintSimpleMessage (MsgFmt, List); 760 va_end (List); 761 } 762 763 VOID 764 SetPrintLimits ( 765 UINT32 MaxErrors, 766 UINT32 MaxWarnings, 767 UINT32 MaxWarningsPlusErrors 768 ) 769 /*++ 770 771 Routine Description: 772 Set the limits of how many errors, warnings, and errors+warnings 773 we will print. 774 775 Arguments: 776 MaxErrors - maximum number of error messages to print 777 MaxWarnings - maximum number of warning messages to print 778 MaxWarningsPlusErrors 779 - maximum number of errors+warnings to print 780 781 Returns: 782 NA 783 784 --*/ 785 { 786 mMaxErrors = MaxErrors; 787 mMaxWarnings = MaxWarnings; 788 mMaxWarningsPlusErrors = MaxWarningsPlusErrors; 789 mPrintLimitsSet = 1; 790 } 791 792 STATIC 793 VOID 794 PrintLimitExceeded ( 795 VOID 796 ) 797 { 798 STATIC INT8 mPrintLimitExceeded = 0; 799 // 800 // If we've already printed the message, do nothing. Otherwise 801 // temporarily increase our print limits so we can pass one 802 // more message through. 803 // 804 if (mPrintLimitExceeded == 0) { 805 mPrintLimitExceeded++; 806 mMaxErrors++; 807 mMaxWarnings++; 808 mMaxWarningsPlusErrors++; 809 Error (NULL, 0, 0, "error/warning print limit exceeded", NULL); 810 mMaxErrors--; 811 mMaxWarnings--; 812 mMaxWarningsPlusErrors--; 813 } 814 } 815 816 #if 0 817 VOID 818 TestUtilityMessages ( 819 VOID 820 ) 821 { 822 CHAR8 *ArgStr = "ArgString"; 823 int ArgInt; 824 825 ArgInt = 0x12345678; 826 // 827 // Test without setting utility name 828 // 829 fprintf (stdout, "* Testing without setting utility name\n"); 830 fprintf (stdout, "** Test debug message not printed\n"); 831 DebugMsg (NULL, 0, 0x00000001, NULL, NULL); 832 fprintf (stdout, "** Test warning with two strings and two args\n"); 833 Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 834 fprintf (stdout, "** Test error with two strings and two args\n"); 835 Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 836 fprintf (stdout, "** Test parser warning with nothing\n"); 837 ParserWarning (0, NULL, NULL); 838 fprintf (stdout, "** Test parser error with nothing\n"); 839 ParserError (0, NULL, NULL); 840 // 841 // Test with utility name set now 842 // 843 fprintf (stdout, "** Testingin with utility name set\n"); 844 SetUtilityName ("MyUtilityName"); 845 // 846 // Test debug prints 847 // 848 SetDebugMsgMask (2); 849 fprintf (stdout, "** Test debug message with one string\n"); 850 DebugMsg (NULL, 0, 0x00000002, "Text1", NULL); 851 fprintf (stdout, "** Test debug message with one string\n"); 852 DebugMsg (NULL, 0, 0x00000002, NULL, "Text2"); 853 fprintf (stdout, "** Test debug message with two strings\n"); 854 DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2"); 855 fprintf (stdout, "** Test debug message with two strings and two args\n"); 856 DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 857 // 858 // Test warning prints 859 // 860 fprintf (stdout, "** Test warning with no strings\n"); 861 Warning (NULL, 0, 1234, NULL, NULL); 862 fprintf (stdout, "** Test warning with one string\n"); 863 Warning (NULL, 0, 1234, "Text1", NULL); 864 fprintf (stdout, "** Test warning with one string\n"); 865 Warning (NULL, 0, 1234, NULL, "Text2"); 866 fprintf (stdout, "** Test warning with two strings and two args\n"); 867 Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 868 // 869 // Test error prints 870 // 871 fprintf (stdout, "** Test error with no strings\n"); 872 Error (NULL, 0, 1234, NULL, NULL); 873 fprintf (stdout, "** Test error with one string\n"); 874 Error (NULL, 0, 1234, "Text1", NULL); 875 fprintf (stdout, "** Test error with one string\n"); 876 Error (NULL, 0, 1234, NULL, "Text2"); 877 fprintf (stdout, "** Test error with two strings and two args\n"); 878 Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 879 // 880 // Test parser prints 881 // 882 fprintf (stdout, "** Test parser errors\n"); 883 ParserSetPosition (__FILE__, __LINE__ + 1); 884 ParserError (1234, NULL, NULL); 885 ParserSetPosition (__FILE__, __LINE__ + 1); 886 ParserError (1234, "Text1", NULL); 887 ParserSetPosition (__FILE__, __LINE__ + 1); 888 ParserError (1234, NULL, "Text2"); 889 ParserSetPosition (__FILE__, __LINE__ + 1); 890 ParserError (1234, "Text1", "Text2"); 891 ParserSetPosition (__FILE__, __LINE__ + 1); 892 ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 893 894 fprintf (stdout, "** Test parser warnings\n"); 895 ParserSetPosition (__FILE__, __LINE__ + 1); 896 ParserWarning (4321, NULL, NULL); 897 ParserSetPosition (__FILE__, __LINE__ + 1); 898 ParserWarning (4321, "Text1", NULL); 899 ParserSetPosition (__FILE__, __LINE__ + 1); 900 ParserWarning (4321, NULL, "Text2"); 901 ParserSetPosition (__FILE__, __LINE__ + 1); 902 ParserWarning (4321, "Text1", "Text2"); 903 ParserSetPosition (__FILE__, __LINE__ + 1); 904 ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); 905 } 906 #endif 907