1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** ERRORS.C 82** 83** FACILITY: 84** 85** Interface Definition Language (IDL) Compiler 86** 87** ABSTRACT: 88** 89** IDL Error logging and reporting routines. 90** 91** VERSION: DCE 1.0 92** 93*/ 94 95#include <nidl.h> 96#include <errors.h> 97#include <nametbl.h> 98#include <frontend.h> 99#include <message.h> 100#include <nidlmsg.h> 101#include <driver.h> 102#include <nidl.h> 103#include <stdarg.h> 104 105#define MAX_LINE_LEN 256 106#define WHERE_TEXT_LEN 20 107#define MAX_WARNINGS 5 108#define MAX_ERROR_FILES 10 109 110 111/* 112 * Error log record format. 113 */ 114typedef struct error_log_rec_t 115{ 116 STRTAB_str_t filename; /* Error file name */ 117 int lineno; /* Source line number */ 118 idl_error_list_t msgs; /* msgid + args */ 119 union /* Tree node or List node */ 120 { 121 struct 122 { /* As tree node: */ 123 struct error_log_rec_t *left; /* Left pointer */ 124 struct error_log_rec_t *right; /* Right pointer */ 125 } asBinTree; 126 struct 127 { /* As list node: */ 128 struct error_log_rec_t *next; /* Ptr to next for this lineno */ 129 } asList; 130 } links; 131 struct error_log_rec_t *first_this_line; /* 1st addtl msg this line */ 132 struct error_log_rec_t *last_this_line; /* last addtl msg this line */ 133} error_log_rec_t; 134 135/* Pointers to IDL parser or ACF parser global variables. */ 136 137FILE *yyin_p; /* Points to yyin or acf_yyin */ 138unsigned*yylineno_p; /* Points to yylineno or acf_yylineno */ 139 140boolean ERR_no_warnings; /* Global copy of -no_warn command line option */ 141 142static int warnings = 0; /* Warning count */ 143static STRTAB_str_t error_files[MAX_ERROR_FILES]; /* List of all files with errors */ 144static int error_file_count = 0; /* Number of files with errors */ 145static int last_error_line = 0; /* Line of last error */ 146 147#if !YYDEBUG 148static 149#endif 150char const *current_file = NULL; /* Current source file name */ 151 152error_log_rec_t *errors = NULL; /* Tree root for error nodes */ 153int error_count = 0; /* Error count */ 154static STRTAB_str_t error_file_name_id; /* Id of current source file */ 155 156extern void sysdep_cleanup_temp ( void ); 157 158/* 159 * y y w h e r e 160 * 161 * Function: Returns current input position for yyparse. 162 * 163 * Globals: yy*_p 164 * 165 */ 166 167void yywhere 168( 169 const struct parser_location_t * location 170) 171{ 172 boolean have_text = false; /* True if have source text to output */ 173 int text_len = 0; /* Length of source text to output */ 174 int lineno; /* Source line number of relevant text */ 175 long msg_id; /* ID of message to output */ 176 char const *near_text; /* Text of object near error */ 177 STRTAB_str_t string_id; /* Entry in string table of near text */ 178 char wherebuf[WHERE_TEXT_LEN+1]; 179 const char * text_p; 180 181 text_p = location->text; 182 lineno = location->lineno; 183 error_file_name_id = location->fileid; 184 185 if (text_p && *text_p) 186 { 187 for (text_len = 0; text_len < WHERE_TEXT_LEN; ++text_len) 188 { 189 if (text_p[text_len] == '\0' || text_p[text_len] == '\n') 190 break; 191 wherebuf[text_len] = text_p[text_len]; 192 } 193 wherebuf[text_len] = '\0'; 194 195 if (text_len > 0) 196 { 197 have_text = true; 198 lineno = lineno - (*text_p == '\n' || ! *text_p); 199 } 200 /* printf("wherebuf is %s, yytext has %s\n", wherebuf, *yytext_p); */ 201 } 202 203 /* 204 * If there is some text to show, put it in the string table 205 */ 206 if (have_text) 207 { 208 string_id = STRTAB_add_string(wherebuf); 209 STRTAB_str_to_string(string_id, &near_text); 210 } 211 212 if (have_text) 213 { 214 if (yyin_p && feof(yyin_p)) 215 msg_id = NIDL_EOFNEAR; 216 else 217 msg_id = NIDL_SYNTAXNEAR; 218 } 219 else 220 { 221 if (yyin_p && feof(yyin_p)) 222 msg_id = NIDL_EOF; 223 else 224 msg_id = NIDL_SYNTAXERR; 225 } 226 log_error(lineno, msg_id, text_len, near_text, NULL); 227} 228 229/* 230 * i d l _ y y e r r o r 231 * 232 * Function: Called by yypaser when a parse error is encountered. 233 * 234 * Inputs: message - error message to display 235 * token - expected token 236 * 237 * Globals: 238 * 239 * Notes: This was adapted from the book 240 * "Compiler Construction under Unix" 241 * by A. T. Schreiner & H. G. Friedman 242 */ 243 244void idl_yyerror 245( 246 parser_location_p location, 247 char const * message 248) 249{ 250 static int list = 0; /* Note: Currently always 0 */ 251 252 if (message || !list) 253 { 254 error_count++; 255 yywhere(location); 256 257 /* 258 * Only print the yacc version of errors if it isn't for a syntax error. 259 */ 260 if (strcmp(message,"syntax error") != 0) 261 { 262 fputs(message, stderr); 263 putc('\n', stderr); 264 return; 265 } 266 267 return; 268 } 269 270 putc('\n', stderr); 271 list = 0; 272} 273 274 275/* 276 * a l l o c _ l o g _ r e c 277 * 278 * Function: Allocates and initializes error log record. 279 * 280 * Inputs: lineno - source line number 281 * message - message text 282 * 283 * Outputs: Address of error log record. 284 */ 285 286static error_log_rec_t *alloc_log_rec 287( 288 STRTAB_str_t filename, 289 int lineno, 290 idl_error_list_t *msgs 291) 292{ 293 error_log_rec_t *log_rec_p; 294 int i; 295 296 log_rec_p = NEW (error_log_rec_t); 297 298 log_rec_p->lineno = lineno; 299 log_rec_p->filename = filename; 300 log_rec_p->msgs = *msgs; 301 log_rec_p->first_this_line = 0; 302 log_rec_p->last_this_line = 0; 303 304 log_rec_p->links.asBinTree.left = 0; 305 log_rec_p->links.asBinTree.right = 0; 306 307 log_rec_p->links.asList.next = 0; 308 309 /* 310 * If this file is not listed in the error file list 311 */ 312 for (i = 0; i < error_file_count; i++) 313 if (error_files[i] == filename) 314 break; 315 316 /* 317 * Add the file with errors to the error_file list 318 */ 319 if (i == error_file_count) 320 error_files[error_file_count++] = filename; 321 322 /* 323 * If we have too many files with errors, just ignore some 324 */ 325 if (error_file_count >= MAX_ERROR_FILES) 326 error_file_count--; 327 328 return log_rec_p; 329} 330 331/* 332 * f r e e _ l o g _ r e c 333 * 334 * Function: Frees an error log record and anything below it 335 * 336 * Inputs: record - error log record to free 337 * Outputs: none 338 */ 339 340static void free_log_rec 341( 342 error_log_rec_t *log_rec_p 343) 344{ 345 if (log_rec_p->links.asBinTree.left != NULL) 346 { 347 free_log_rec(log_rec_p->links.asBinTree.left); 348 log_rec_p->links.asBinTree.left = NULL; 349 } 350 351 if (log_rec_p->links.asBinTree.right != NULL) 352 { 353 free_log_rec(log_rec_p->links.asBinTree.right); 354 log_rec_p->links.asBinTree.right = NULL; 355 } 356 357 /* 358 * Free all errors logged for this line number 359 */ 360 while (log_rec_p->first_this_line != NULL) 361 { 362 error_log_rec_t *ep; 363 ep = log_rec_p->first_this_line; 364 log_rec_p->first_this_line = log_rec_p->links.asList.next; 365 FREE(ep); 366 } 367 368 FREE(log_rec_p); 369} 370 371/* 372 * q u e u e _ e r r o r 373 * 374 * Function: Adds an error message to the end of a list of 375 * errors queued for a particular line. 376 * 377 * Inputs: log_rec_p - a pointer to the header error log rec. 378 * message - the error message. 379 */ 380 381static void queue_error 382( 383 error_log_rec_t *log_rec_p, 384 STRTAB_str_t filename, 385 idl_error_list_t *msgs 386) 387{ 388 error_log_rec_t *new_log_rec_p; 389 390 new_log_rec_p = alloc_log_rec(filename, log_rec_p->lineno, msgs); 391 392 if (log_rec_p->first_this_line == NULL) 393 { 394 log_rec_p->first_this_line = new_log_rec_p; 395 log_rec_p->last_this_line = new_log_rec_p; 396 return; 397 } 398 399 log_rec_p->last_this_line->links.asList.next = new_log_rec_p; 400 log_rec_p->last_this_line = new_log_rec_p; 401} 402 403/* 404 * a d d _ e r r o r _ l o g _ r e c 405 * 406 * Function: Adds an error log to the sorted binary tree of 407 * error messages. 408 * 409 * Inputs: log_rec_p - pointer to current root of tree. 410 * lineno - line number on which error occurred. 411 * message - the error message. 412 */ 413 414static void add_error_log_rec 415( 416 error_log_rec_t *log_rec_p, 417 STRTAB_str_t filename, 418 int lineno, 419 idl_error_list_t *msgs 420) 421{ 422 if (log_rec_p->lineno < lineno) 423 { 424 if (log_rec_p->links.asBinTree.right != NULL) 425 add_error_log_rec(log_rec_p->links.asBinTree.right, filename, lineno, 426 msgs); 427 else 428 log_rec_p->links.asBinTree.right = alloc_log_rec(filename, lineno, 429 msgs); 430 431 return; 432 } 433 434 if (log_rec_p->lineno > lineno) 435 { 436 if (log_rec_p->links.asBinTree.left != NULL) 437 add_error_log_rec(log_rec_p->links.asBinTree.left, filename, lineno, 438 msgs); 439 440 else 441 log_rec_p->links.asBinTree.left = alloc_log_rec(filename, lineno, 442 msgs); 443 return; 444 } 445 446 if (log_rec_p->lineno == lineno) 447 queue_error(log_rec_p, filename, msgs); 448} 449 450/* 451 * l o g _ s o u r c e _ v a 452 * 453 * Function: Accumulates a warning or error message for later printout. 454 * All accumulated errors are printed by print_errors. 455 * Errors are kept sorted by line number and source 456 * file name. 457 * 458 * Inputs: 459 * counter - which counter should be increased (error/warning) 460 * filename - STRTAB_str_t of full source file name 461 * lineno - the line number of the error. 462 * msg_id - the error message ID. 463 * ap - va_list for the parameter last must be NULL if # < IDL_ERROR_LIST_SIZE 464 * 465 * Outputs: An error log record is inserted in the error tree. 466 * 467 */ 468 469static void log_source_va 470( 471 int* counter, 472 STRTAB_str_t filename, 473 int lineno, 474 long msg_id, 475 va_list ap 476) 477{ 478 idl_error_list_t msgs = {0, {NULL}}; 479 480 size_t idx; 481 482 ++*counter; 483 484 msgs.msg_id = msg_id; 485 for (idx = 0; idx < IDL_ERROR_LIST_SIZE; idx++) { 486 msgs.arg[idx] = va_arg(ap, void*); 487 if (!msgs.arg[idx]) 488 break; 489 } 490 491 if (errors == NULL) 492 errors = alloc_log_rec(filename, lineno, &msgs); 493 else 494 add_error_log_rec(errors, filename, lineno, &msgs); 495} 496 497 498/* 499 * l o g _ s o u r c e _ e r r o r 500 * 501 * Function: Accumulates an error message for later printout. 502 * All accumulated errors are printed by print_errors. 503 * Errors are kept sorted by line number and source 504 * file name. 505 * 506 * Inputs: 507 * filename - STRTAB_str_t of full source file name 508 * lineno - the line number of the error. 509 * msg_id - the error message ID. 510 * [arg1,...,arg5] - 0 to 5 arguments for error message formatting 511 * 512 * Outputs: An error log record is inserted in the error tree. 513 * 514 */ 515 516void vlog_source_error 517( 518 STRTAB_str_t filename, 519 int lineno, 520 long msg_id, 521 va_list ap 522 ) 523{ 524 log_source_va(&error_count, filename, lineno, msg_id, ap); 525} 526 527void log_source_error 528( 529 STRTAB_str_t filename, 530 int lineno, 531 long msg_id, 532 ... 533) 534{ 535 va_list ap; 536 537 va_start(ap, msg_id); 538 539 vlog_source_error(filename, lineno, msg_id, ap); 540 541 va_end(ap); 542} 543 544/* 545 * l o g _ s o u r c e _ w a r n i n g 546 * 547 * Function: Accumulates a warning message for later printout. 548 * All accumulated errors are printed by print_errors. 549 * Errors are kept sorted by line number and source 550 * file name. 551 * 552 * Inputs: 553 * filename - STRTAB_str_t of full source file name 554 * lineno - the line number of the error. 555 * msg_id - the error message ID. 556 * [arg1,...,arg5] - 0 to 5 arguments for error message formatting 557 * 558 * Outputs: An error log record is inserted in the error tree. 559 * 560 */ 561void vlog_source_warning 562( 563 STRTAB_str_t filename, 564 int lineno, 565 long msg_id, 566 va_list ap 567) 568{ 569 /* Return if warnings are suppressed. */ 570 if (ERR_no_warnings) 571 return; 572 573 log_source_va(&warnings, filename, lineno, msg_id, ap); 574} 575 576void log_source_warning 577( 578 STRTAB_str_t filename, 579 int lineno, 580 long msg_id, 581 ... 582) 583{ 584 va_list ap; 585 586 /* Return if warnings are suppressed. */ 587 if (ERR_no_warnings) 588 return; 589 590 va_start(ap, msg_id); 591 592 vlog_source_warning(filename, lineno, msg_id, ap); 593 594 va_end(ap); 595} 596 597/* 598 * l o g _ e r r o r 599 * 600 * Function: Accumulates an error message for later printout. 601 * All accumulated errors are printed by print_errors. 602 * Errors are kept sorted by line number. The error 603 * is logged on the file for which set_name_for_errors 604 * was most recently called. 605 * 606 * Inputs: lineno - the line number of the error. 607 * msg_id - the error message ID. 608 * [arg1,...,arg5] - 0 to 5 arguments for error message formatting 609 * 610 * Outputs: An error log record is inserted in the error tree. 611 * 612 */ 613void vlog_error 614( 615 int lineno, 616 long msg_id, 617 va_list ap 618) 619{ 620 log_source_va(&error_count, error_file_name_id, lineno, msg_id, ap); 621} 622 623void log_error 624( 625 int lineno, 626 long msg_id, 627 ... 628) 629{ 630 va_list ap; 631 632 va_start(ap, msg_id); 633 634 vlog_error(lineno, msg_id, ap); 635 636 va_end(ap); 637} 638 639 640/* 641 * l o g _ w a r n i n g 642 * 643 * Function: Accumulates a warning message for later printout. 644 * All accumulated errors are printed by print_errors. 645 * Errors are kept sorted by line number. The warning 646 * is logged on the file for which set_name_for_errors 647 * was most recently called. 648 * 649 * Inputs: lineno - the line number of the warning. 650 * msg_id - the error message ID. 651 * [arg1,...,arg5] - 0 to 5 arguments for error message formatting 652 * 653 * Outputs: An error log record is inserted in the error tree. 654 * 655 */ 656void vlog_warning 657( 658 int lineno, 659 long msg_id, 660 va_list ap 661) 662{ 663 if (ERR_no_warnings) 664 return; 665 666 log_source_va(&warnings, error_file_name_id, lineno, msg_id, ap); 667} 668 669void log_warning 670( 671 int lineno, 672 long msg_id, 673 ... 674) 675{ 676 va_list ap; 677 678 if (ERR_no_warnings) 679 return; 680 va_start(ap, msg_id); 681 682 vlog_warning(lineno, msg_id, ap); 683 684 va_end(ap); 685} 686 687 688/* 689 * s e e k _ f o r _ l i n e 690 * 691 * Function: Reads the line specified by lineno. 692 * 693 * Inputs: source - the file descriptor for the source file. 694 * lineno - the number of the line in error. 695 * 696 * Outputs: source_line - the source line is returned through here 697 * 698 * Globals: last_error_line 699 */ 700 701void seek_for_line 702( 703 FILE *source_file, 704 int lineno, 705 char *source_line 706) 707{ 708 int lines_to_skip; 709 int i; 710 711 /* 712 * If the FILE is NULL then can't get the source 713 */ 714 if (source_file == NULL) 715 { 716 source_line[0] = 0; 717 return; 718 } 719 720 lines_to_skip = lineno - last_error_line; 721 722 for (i=0; i<lines_to_skip; i++) 723 (void) fgets(source_line, MAX_LINE_LEN, source_file); 724 725 /* Strip off newline. */ 726 i = strlen(source_line) - 1; 727 if (source_line[i] == '\n') 728 source_line[i] = '\0'; 729 730 last_error_line = lineno; 731} 732 733/* 734 * p r i n t _ e r r o r s _ f o r _ l i n e 735 * 736 * Function: Prints out a source line and accumulated errors 737 * for that line. 738 * 739 * Inputs: fd - file descriptor for source file 740 * log_rec_ptr - a pointer to the header log rec for the line 741 * source - source file name 742 */ 743 744void print_errors_for_line 745( 746 FILE *fd, 747 char const *source, 748 STRTAB_str_t source_id, 749 error_log_rec_t *log_rec_ptr 750) 751{ 752 char source_line[MAX_LINE_LEN]; 753 boolean source_printed = false; 754 error_log_rec_t *erp; 755 756 /* Print the error only if it in this file */ 757 if (source_id == log_rec_ptr->filename) 758 { 759 source_printed = true; 760 seek_for_line(fd, log_rec_ptr->lineno, source_line); 761 message_print( 762 NIDL_FILESOURCE, source, log_rec_ptr->lineno, source_line 763 ); 764 message_print( 765 log_rec_ptr->msgs.msg_id, 766 log_rec_ptr->msgs.arg[0], 767 log_rec_ptr->msgs.arg[1], 768 log_rec_ptr->msgs.arg[2], 769 log_rec_ptr->msgs.arg[3], 770 log_rec_ptr->msgs.arg[4] 771 ); 772 } 773 774 for (erp = log_rec_ptr->first_this_line; erp; erp=erp->links.asList.next) 775 { 776 /* Print the error only if it in this file */ 777 if (source_id == erp->filename) 778 { 779 /* If we haven't output the source line text yet, the do so */ 780 if (!source_printed) 781 { 782 source_printed = true; 783 seek_for_line(fd, log_rec_ptr->lineno, source_line); 784 message_print( 785 NIDL_FILESOURCE, source, log_rec_ptr->lineno, source_line 786 ); 787 } 788 789 /* Now print out the actual error message */ 790 message_print( 791 erp->msgs.msg_id, 792 erp->msgs.arg[0], 793 erp->msgs.arg[1], 794 erp->msgs.arg[2], 795 erp->msgs.arg[3], 796 erp->msgs.arg[4] 797 ); 798 } 799 } 800} 801 802/* 803 * p r i n t _ e r r o r _ m e s s a g e s 804 * 805 * Function: Recursively prints all accumulated error messages. 806 * 807 * Inputs: fd - file descriptor for source file 808 * source - name of source file 809 * log_rec_ptr - root of error log tree 810 */ 811 812void print_error_messages 813( 814 FILE *fd, 815 char const *source, 816 STRTAB_str_t source_id, 817 error_log_rec_t *log_rec_ptr 818) 819{ 820 if (log_rec_ptr->links.asBinTree.left != NULL) 821 print_error_messages(fd, source, source_id, log_rec_ptr->links.asBinTree.left); 822 823 print_errors_for_line(fd, source, source_id, log_rec_ptr); 824 825 if (log_rec_ptr->links.asBinTree.right != NULL) 826 print_error_messages(fd, source, source_id, log_rec_ptr->links.asBinTree.right); 827} 828 829/* 830 * p r i n t _ e r r o r s 831 * 832 * Function: Prints all accumulated error messages. 833 * 834 * Inputs: source - String table ID of source file name 835 * 836 * Functional value: true - if any errors were printed 837 * false otherwise 838 * 839 */ 840 841boolean print_errors 842( 843 void 844) 845 846{ 847 FILE *fd; 848 char const *fn; 849 int i; 850 STRTAB_str_t source_id; 851 error_log_rec_t *error_root; 852 853 /* 854 * If there are no errors, just return 855 */ 856 if (errors == NULL) return 0; 857 858 /* 859 * Copy the root of the error tree and null it out so that 860 * it looks like all the errors have been printed if we get 861 * an error while printing them out. 862 */ 863 error_root = errors; 864 errors = NULL; 865 866 /* 867 * Loop through all files with errors 868 */ 869 for (i = 0; i < error_file_count; i++) 870 { 871 source_id = error_files[i]; 872 STRTAB_str_to_string(source_id, &fn); 873 fd = fopen(fn, "r"); 874 print_error_messages(fd, fn, source_id, error_root); 875 last_error_line = 0; 876 } 877 878 /* 879 * Free the tree of errors, 880 */ 881 free_log_rec(error_root); 882 error_file_count = 0; 883 884 /* 885 * Return true if we found any errors. 886 */ 887 return (error_file_count != 0); 888} 889 890/* 891 * e r r o r 892 * 893 * Function: Prints the specifed error message and terminates the program 894 * 895 * Inputs: msg_id - the error message ID. 896 * [arg1,...,arg5] - 0 to 5 arguments for error message formatting 897 * 898 * Notes: This call terminates the calling program with a failure status 899 * 900 */ 901 902void error 903( 904 long msg_id, 905 ... 906) 907{ 908 va_list arglist; 909 910 if (current_file) 911 message_print(NIDL_LINEFILE, current_file, 912 yylineno_p ? *yylineno_p : 0); 913 914 va_start (arglist, msg_id); 915 vmessage_print (msg_id, arglist); 916 va_end (arglist); 917 918#ifndef HASPOPEN 919 sysdep_cleanup_temp(); 920#endif 921 922 nidl_terminate(); 923} 924 925/* 926 * e r r o r _ l i s t 927 * 928 * Function: Prints the specifed error message(s) and terminates the program 929 * 930 * Inputs: vecsize - number of messages 931 * errvec - pointer to one or more message info elements 932 * exitflag - TRUE => exit program 933 * 934 * Notes: This call terminates the calling program with a failure status 935 * 936 */ 937 938void error_list 939( 940 int vecsize, 941 idl_error_list_p errvec, 942 boolean exitflag 943) 944{ 945 int i; 946 947 for (i = 0; i < vecsize; i++) 948 { 949 message_print(errvec[i].msg_id, 950 errvec[i].arg[0], 951 errvec[i].arg[1], 952 errvec[i].arg[2], 953 errvec[i].arg[3], 954 errvec[i].arg[4] 955 ); 956 } 957 958 if (!exitflag) return; 959 960#ifndef HASPOPEN 961 sysdep_cleanup_temp(); 962#endif 963 964 nidl_terminate(); 965} 966 967/* 968 * w a r n i n g 969 * 970 * Function: Prints the specifed error message. Terminates if the 971 * error count excees the threshold. 972 * 973 * Inputs: msg_id - the error message ID. 974 * [arg1,...,arg5] - 0 to 5 arguments for error message formatting 975 * 976 * Globals: yylineno_p 977 * 978 * Notes: This call terminates the calling program with a status of -2. 979 * 980 */ 981 982void warning 983( 984 long msg_id, 985 ... 986) 987{ 988 va_list arglist; 989 990 /* Return if warnings are suppressed. */ 991 if (ERR_no_warnings) 992 return; 993 994 if (current_file) 995 message_print(NIDL_LINEFILE, current_file, 996 yylineno_p ? *yylineno_p : 0); 997 998 va_start (arglist, msg_id); 999 vmessage_print (msg_id, arglist); 1000 va_end (arglist); 1001 1002 if (++warnings > MAX_WARNINGS) 1003 { 1004 message_print(NIDL_MAXWARN, MAX_WARNINGS); 1005 nidl_terminate(); 1006 } 1007} 1008 1009/* 1010 * s e t _ n a m e _ f o r _ e r r o r s 1011 * 1012 * Function: Records the name of the file being processed. This name 1013 * will be prepended onto error messages. 1014 * 1015 * Inputs: name - a pointer to the file name. 1016 * 1017 */ 1018 1019void set_name_for_errors 1020( 1021 char const *filename 1022) 1023{ 1024 if (filename != NULL) 1025 { 1026 error_file_name_id = STRTAB_add_string(filename); 1027 STRTAB_str_to_string(error_file_name_id, ¤t_file); 1028 } 1029 else 1030 { 1031 current_file = NULL; 1032 } 1033} 1034 1035/* 1036 * i n q _ n a m e _ f o r _ e r r o r s 1037 * 1038 * Function: Returns the name of the file being processed. 1039 * 1040 * Outputs: name - the file name is copied through this. 1041 * 1042 */ 1043 1044void inq_name_for_errors 1045( 1046 char *name, 1047 size_t name_len 1048) 1049{ 1050 if (current_file) 1051 strlcpy(name, current_file, name_len); 1052 else 1053 *name = '\0'; 1054} 1055 1056/* preserve coding style vim: set tw=78 sw=4 ts=4: */ 1057