Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * 05-Sep-89 - Original Version 00042 * 24-Jan-91 - Copied for TP/Muse 00043 * 26-May-91 - Integrated Josie functionality 00044 * 13-Nov-92 - Integrated Josie/92 functionality 00045 * 00046 * Description: 00047 * 00048 * This module implements the core of the microcode compiler error 00049 * reporting mechanism, i.e. that part which is not specific to the 00050 * host program. Host program-specific portions are done elsewhere to 00051 * allow reuse of this module in the linker and librarian (or other 00052 * as-yet-unknown tools). 00053 * 00054 * The host program-specific facilities should be provided in a file 00055 * satisfying the interface defined in err_host.h. They will include 00056 * the actual phase and error descriptor table and a routine for 00057 * formatting error message parameters which are not one of the simple 00058 * types supported in this module. This module should provide the 00059 * external interface to all other users, however. 00060 * 00061 * ==================================================================== 00062 * ==================================================================== 00063 */ 00064 00065 #define USE_STANDARD_TYPES 00066 #include <stdarg.h> 00067 #include <stdlib.h> 00068 #include <unistd.h> 00069 #include <sys/types.h> 00070 #include <signal.h> 00071 #include <ctype.h> 00072 #include <string.h> 00073 00074 #ifdef _SGI_SGI 00075 #define _LANGUAGE_C /* work around system header bug */ 00076 extern "C" { 00077 #include <sys/fpu.h> /* we don't have a C++ sys/fpu.h */ 00078 } 00079 #undef _LANGUAGE_C 00080 #include <sys/syssgi.h> 00081 #endif 00082 00083 #include <errno.h> 00084 #include <cmplrs/rcodes.h> 00085 #include "defs.h" 00086 #ifdef AWAITING_NEWCOMP /* needed? */ 00087 #include "config.h" 00088 #endif /* AWAITING_NEWCOMP */ 00089 #define IN_ERRORS_C 00090 #include "errors.h" 00091 #undef IN_ERRORS_C 00092 #include "err_host.h" 00093 #include "erglob.h" 00094 #include "file_util.h" 00095 #include "tracing.h" 00096 #include "glob.h" 00097 #include "errdesc.h" 00098 #include "vstring.h" 00099 00100 #ifdef MONGOOSE_BE 00101 #include "wn.h" 00102 #include "wn_map.h" 00103 #include "ir_reader.h" 00104 #endif 00105 00106 00107 /* ==================================================================== 00108 * 00109 * Global Data 00110 * 00111 * ==================================================================== 00112 */ 00113 00114 INT Min_Error_Severity = ES_ADVISORY; /* report advisory msgs or worse */ 00115 INT Conformance_Level = ES_IGNORE; /* ignore conformance error */ 00116 00117 /* Compiler error location: */ 00118 static const char *Compiler_File = NULL;/* errors.c internal use only */ 00119 static INT Compiler_Line = 0; /* errors.c internal use only */ 00120 00121 /* Error file support: */ 00122 static FILE *Error_File = NULL; /* File descriptor */ 00123 static const char *Error_File_Name = NULL; /* Error file name */ 00124 00125 /* Trace file support: */ 00126 static FILE *Trace_File = NULL; /* File descriptor */ 00127 00128 /* Source file location: */ 00129 static char source_file_name[256]; 00130 static char *Source_File_Name = &source_file_name[0]; 00131 static INT Source_Line = ERROR_LINE_UNKNOWN; /* Line number */ 00132 00133 /* Current compiler/tool phase: */ 00134 static const char *Current_Phase = NULL; 00135 00136 /* Error counts: */ 00137 static INT Error_Counts[ES_MAX+1]; 00138 static INT Error_Count = 0; /* Number of all errors */ 00139 static BOOL Phase_Error = FALSE; /* ES_ERRPHASE or worse seen */ 00140 static INT Max_Errors = 100; /* Maximum errors allowed */ 00141 00142 static BOOL Had_Compiler_Error = FALSE; 00143 00144 /* ==================================================================== 00145 * 00146 * Severity Description Table 00147 * 00148 * ==================================================================== 00149 */ 00150 00151 /* Severity descriptors: */ 00152 typedef struct { 00153 INT level; /* Severity level */ 00154 char symbol[5]; /* Symbol used to prefix messages */ 00155 const char *name; /* Name used in message headers */ 00156 } SEVERITY_DESCRIPTOR; 00157 00158 static SEVERITY_DESCRIPTOR Severities[] = { 00159 {ES_IGNORE, "??? ", "Ignore"}, 00160 {ES_ADVISORY, "--- ", "Advisory"}, 00161 {ES_WARNING, "!!! ", "Warning"}, 00162 {ES_CONFORMANCE, "!!! ", "Conformance warning"}, 00163 {ES_ERRBENIGN, "### ", "Error"}, 00164 {ES_ERRPHASE, "### ", "Error"}, 00165 {ES_ERRABORT, "### ", "Error"} 00166 }; 00167 00168 /* Access functions: */ 00169 #define SEV_level(n) (Severities[n].level) 00170 #define SEV_symbol(n) (Severities[n].symbol) 00171 #define SEV_name(n) (Severities[n].name) 00172 00173 /* ==================================================================== 00174 * 00175 * Error message descriptors 00176 * 00177 * ==================================================================== 00178 */ 00179 00180 #ifdef MONGOOSE_BE 00181 #include "err_host.tab" /* for error tables */ 00182 #else /* MONGOOSE_BE */ 00183 /* these table pointers get pointed at the client's tables */ 00184 static ERROR_DESC_TABLE *Phases = NULL; 00185 static const char **host_errlist = NULL; 00186 #endif /* MONGOOSE_BE */ 00187 00188 /* The access functions: */ 00189 #define Phase_Num(n) (Phases[n].phase) 00190 #define Phase_List(n) (Phases[n].descriptors) 00191 #define Phase_Name(n) (Phases[n].name) 00192 00193 /* WOFF handling */ 00194 static char dont_print[RAG_EN_LAST-RAG_EN_FIRST+1]; 00195 #define Dont_Print_Warning(i) dont_print[i-RAG_EN_FIRST] 00196 00197 #define Heed_Woff(rag_errnum, severity) \ 00198 (Dont_Print_Warning(rag_errnum) && (severity < ES_ERRBENIGN) ) 00199 00200 extern void Rag_Handle_Woff_Args(char *wstring); 00201 00202 /* ==================================================================== 00203 * 00204 * Catch_Signal 00205 * 00206 * Catch a signal that's been raised. Print a message to stdout, call 00207 * the Signal_Cleanup routine defined in err_host.h, and generate a 00208 * fatal error message. 00209 * 00210 * ==================================================================== 00211 */ 00212 00213 static void 00214 catch_signal (INT sig, INT error_num) 00215 { 00216 signal ( sig, SIG_DFL ); 00217 00218 00219 switch (sig) { 00220 case SIGBUS: 00221 case SIGSEGV: 00222 if (error_num == ENXIO || error_num == ENOSPC) { 00223 /* special case for I/O error on mmapped object: report as an 00224 ordinary fatal error */ 00225 Fatal_Error ("I/O error in mmapped object: %s", strerror(error_num)); 00226 } 00227 } 00228 00229 printf ( "Signal: %s", StrSignal(sig) ); 00230 fflush ( stdout ); 00231 printf ( " in %s phase.\n", Current_Phase ); 00232 00233 Signal_Cleanup ( sig ); /* Must be provided in err_host */ 00234 if ( sig == SIGHUP || sig == SIGINT || sig == SIGTERM ) { 00235 kill ( getpid(), sig); /* pass signal on to driver */ 00236 /*NOTREACHED*/ 00237 exit(RC_INTERNAL_ERROR); 00238 } 00239 signal ( SIGILL, SIG_DFL ); 00240 signal ( SIGBUS, SIG_DFL ); 00241 ErrMsgLine ( EC_Signal, ERROR_LINE_UNKNOWN, 00242 StrSignal(sig), Current_Phase ); 00243 /*NOTREACHED*/ 00244 exit(RC_INTERNAL_ERROR); 00245 } 00246 00247 00248 /* ==================================================================== 00249 * 00250 * Handle_Signals 00251 * 00252 * Initialize signal handling. 00253 * Also set FP_PRECISE mode and no FLUSH_ZERO to handle denorm values. 00254 * 00255 * ==================================================================== 00256 */ 00257 00258 inline static void 00259 setup_signal_handler (int s) 00260 { 00261 if (signal (s, SIG_IGN) != SIG_IGN) 00262 00263 // Solaris CC workaround 00264 // std:: is added before signal() when reinterpret_cast is present. 00265 #ifdef _SOLARIS_SOLARIS 00266 std::signal (s, reinterpret_cast <void (*)(int)> (catch_signal)); 00267 #else 00268 signal (s, reinterpret_cast <void (*)(int)> (catch_signal)); 00269 #endif 00270 } 00271 00272 00273 void 00274 Handle_Signals ( void ) 00275 { 00276 setup_signal_handler (SIGHUP); 00277 setup_signal_handler (SIGINT); 00278 setup_signal_handler (SIGQUIT); 00279 setup_signal_handler (SIGILL); 00280 setup_signal_handler (SIGTRAP); 00281 setup_signal_handler (SIGABRT); // SIGABRT replaces SIGIOT 00282 #if !defined(__linux__) 00283 setup_signal_handler (SIGEMT); 00284 #endif 00285 setup_signal_handler (SIGFPE); 00286 setup_signal_handler (SIGBUS); 00287 setup_signal_handler (SIGSEGV); 00288 setup_signal_handler (SIGTERM); 00289 00290 #if defined(__sgi) 00291 syssgi(SGI_SET_FP_PRECISE, 1); 00292 set_fpc_csr(get_fpc_csr() & ~FPCSR_FLUSH_ZERO); 00293 syssgi(SGI_SET_FP_PRESERVE, 1); 00294 #endif 00295 00296 00297 } 00298 00299 /* ==================================================================== 00300 * 00301 * Set_Error_File 00302 * 00303 * Prepare to write error messages to the given file, using the given 00304 * file number. If there is an open error file, close it. If the 00305 * given file exists, delete it. Note that the error file is not 00306 * opened here. 00307 * 00308 * ==================================================================== 00309 */ 00310 00311 void 00312 Set_Error_File ( const char *fname ) 00313 { 00314 /* Close any open error file: */ 00315 if ( Error_File ) { 00316 fclose ( Error_File ); 00317 Error_File = NULL; /* So we don't try to write messages to it */ 00318 } 00319 00320 /* Delete the indicated file if it exists: */ 00321 Error_File_Name = fname; 00322 if ( Is_File(Error_File_Name) ) { 00323 unlink ( Error_File_Name ); 00324 } 00325 } 00326 00327 00328 /* ==================================================================== 00329 * 00330 * Init_Error_File 00331 * 00332 * Prepare the error file for writing, i.e. open it if it's not open. 00333 * Return TRUE iff successful. 00334 * 00335 * ==================================================================== 00336 */ 00337 00338 static BOOL 00339 Init_Error_File (void) 00340 { 00341 if ( Error_File != NULL ) return TRUE; /* Already open */ 00342 if ( Error_File_Name != NULL ) { 00343 Error_File = fopen ( Error_File_Name, "a" ); 00344 if ( Error_File == NULL ) return FALSE; 00345 if ( Same_File (Error_File, stderr) ) { 00346 fclose ( Error_File ); 00347 Error_File = NULL; 00348 Error_File_Name = NULL; 00349 return FALSE; 00350 } 00351 return TRUE; 00352 } 00353 return FALSE; /* No error file specified */ 00354 } 00355 00356 /* ==================================================================== 00357 * 00358 * Set_Error_Trace 00359 * 00360 * Prepare to write error messages to the trace file, using the given 00361 * stream descriptor. If the trace file is the same as stderr, 00362 * suppress error output via the trace file. 00363 * 00364 * ==================================================================== 00365 */ 00366 00367 void 00368 Set_Error_Trace ( FILE *stream ) 00369 { 00370 if ( Same_File (stream, stderr) ) 00371 Trace_File = NULL; 00372 else 00373 Trace_File = stream; 00374 } 00375 00376 /* ==================================================================== 00377 * 00378 * Set_Error_Source 00379 * 00380 * Note the current source file name for subsequent error messages. 00381 * 00382 * ==================================================================== 00383 */ 00384 00385 void 00386 Set_Error_Source ( const char *filename ) 00387 { 00388 if ( filename == NULL ) { 00389 Source_File_Name = NULL; 00390 } else { 00391 Source_File_Name = &source_file_name[0]; 00392 strcpy ( Source_File_Name, filename ); 00393 } 00394 } 00395 00396 00397 #ifdef MONGOOSE_BE 00398 /* ==================================================================== 00399 * 00400 * Set_Error_Srcpos 00401 * 00402 * Set Source_Line and Source_File from SRCPOS 00403 * 00404 * ==================================================================== 00405 */ 00406 00407 void 00408 Set_Error_Srcpos ( SRCPOS srcpos ) 00409 { 00410 const char *fname = NULL; 00411 const char *dname; 00412 00413 Set_Error_Line(Srcpos_To_Line(srcpos)); 00414 IR_Srcpos_Filename(srcpos, &fname, &dname); 00415 Set_Error_Source(fname); 00416 } 00417 #endif 00418 00419 00420 /* ==================================================================== 00421 * 00422 * Set_Error_Line 00423 * 00424 * Note the current source line number for subsequent error messages. 00425 * 00426 * ==================================================================== 00427 */ 00428 00429 void 00430 Set_Error_Line ( INT lineno ) 00431 { 00432 Source_Line = lineno; 00433 } 00434 00435 00436 /* ==================================================================== 00437 * 00438 * Set_Error_Phase / Get_Error_Phase 00439 * 00440 * Note the current phase name for subsequent compiler error messages. 00441 * 00442 * ==================================================================== 00443 */ 00444 00445 void 00446 Set_Error_Phase ( const char *phase ) 00447 { 00448 Current_Phase = phase; 00449 #ifdef BACK_END 00450 if (Get_Trace(TP_MISC, 4)) { 00451 fprintf(stderr, "Entering PU %s phase %s\n", 00452 Cur_PU_Name ? Cur_PU_Name : "(None)", phase); 00453 fprintf(TFile, "Entering PU %s phase %s\n", 00454 Cur_PU_Name ? Cur_PU_Name : "(None)", phase); 00455 } 00456 #endif 00457 switch (phase[0]) { 00458 case 'A': 00459 if (strcmp(phase, "Alias Analysis") == 0) 00460 Set_Current_Phase_Number(TP_ALIAS); 00461 else if (strcmp(phase, "Assembly") == 0) 00462 Set_Current_Phase_Number(TP_EMIT); 00463 break; 00464 00465 case 'C': 00466 if (strcmp(phase, "Code Generation") == 0) 00467 Set_Current_Phase_Number(TP_CGEXP); 00468 break; 00469 00470 case 'H': 00471 if (strcmp(phase, "Hyperblock formation") == 0) 00472 Set_Current_Phase_Number(TP_HBF); 00473 break; 00474 case 'G': 00475 if (strcmp(phase, "Global Live Range Analysis") == 0) 00476 Set_Current_Phase_Number(TP_FIND_GLOB); 00477 else if (strcmp(phase, "Global Code Motion") == 0) 00478 Set_Current_Phase_Number(TP_GCM); 00479 break; 00480 00481 case 'O': 00482 if (strcmp(phase, "Optimizer") == 0) 00483 Set_Current_Phase_Number(TP_WOPT1); 00484 break; 00485 00486 case 'P': 00487 if (strcmp(phase, "Pre-Optimizer") == 0) 00488 Set_Current_Phase_Number(TP_GLOBOPT); 00489 break; 00490 00491 case 'R': 00492 if (strcmp(phase, "Reading IR file") == 0) 00493 Set_Current_Phase_Number(TP_IR_READ); 00494 else if (strcmp(phase, "Reorder Blocks") == 0) 00495 Set_Current_Phase_Number(TP_FLOWOPT); 00496 else if (strcmp(phase, "Register Allocation") == 0) 00497 Set_Current_Phase_Number(TP_GRA); 00498 break; 00499 00500 case 'S': 00501 if (strcmp(phase, "Software Pipelining") == 0) 00502 Set_Current_Phase_Number(TP_SWPIPE); 00503 break; 00504 case 'T': 00505 if (strcmp(phase, "Tree-Height Reduction") == 0) 00506 Set_Current_Phase_Number(TP_THR); 00507 break; 00508 } 00509 00510 } 00511 00512 const char * 00513 Get_Error_Phase ( void ) 00514 { 00515 return Current_Phase; 00516 } 00517 00518 /* ==================================================================== 00519 * 00520 * Get_Error_Count 00521 * 00522 * Determine the number of errors and warnings reported to this point 00523 * (since the last initialization). Return whether compilation should 00524 * stop after this phase. 00525 * 00526 * ==================================================================== 00527 */ 00528 00529 BOOL 00530 Get_Error_Count ( INT *ErrCount, INT *WarnCount ) 00531 { 00532 *ErrCount = Error_Count; 00533 *WarnCount = Error_Counts[ES_WARNING]; 00534 return Phase_Error; 00535 } 00536 00537 00538 /* ==================================================================== 00539 * 00540 * Init_Error_Handler 00541 * 00542 * Initialize the error message handler's internal data structures, 00543 * either at the beginning of compilation, or between source files. 00544 * 00545 * ==================================================================== 00546 */ 00547 00548 void 00549 Init_Error_Handler ( INT Max_Errors_Allowed ) 00550 { 00551 INT i; 00552 00553 /* Initialize error counts: */ 00554 Max_Errors = Max_Errors_Allowed; 00555 Phase_Error = FALSE; 00556 Error_Count = 0; 00557 for ( i=0; i<=ES_MAX; i++ ) { 00558 Error_Counts[i] = 0; 00559 } 00560 00561 /* Initialize error file state: */ 00562 if ( Error_File ) { 00563 fclose ( Error_File ); 00564 } 00565 Error_File = NULL; 00566 Error_File_Name = NULL; 00567 00568 /* Initialize current position: */ 00569 Source_File_Name = NULL; 00570 Source_Line = ERROR_LINE_UNKNOWN; 00571 Current_Phase = NULL; 00572 } 00573 00574 /* ==================================================================== 00575 * 00576 * Find_Error_Desc 00577 * 00578 * Description 00579 * 00580 * ==================================================================== 00581 */ 00582 00583 static ERROR_DESC * 00584 Find_Error_Desc ( INT ecode ) 00585 { 00586 INT phase = ecode/1000; 00587 INT i; 00588 ERROR_DESC *edesc; 00589 00590 /* Find the right list, i.e. from the matching phase: */ 00591 for ( i=0; Phase_Num(i) != -1; i++ ) { 00592 if ( Phase_Num(i) == phase ) { 00593 /* This is the right list -- find the error code: */ 00594 for ( edesc = Phase_List(i); ED_code(edesc) != -1; edesc++ ) { 00595 if ( ED_code(edesc) == ecode ) return edesc; 00596 } 00597 break; /* Not found */ 00598 } 00599 } 00600 00601 /* We didn't find it -- return the global unknown error code: */ 00602 return Find_Error_Desc ( EC_Undef_Code ); 00603 } 00604 00605 /* ==================================================================== 00606 * 00607 * Emit_Message 00608 * 00609 * Write a two-line message to stderr and to the error and trace files 00610 * if enabled. If Compiler_File is not NULL, report the compiler 00611 * location as well. 00612 * 00613 * ==================================================================== 00614 */ 00615 00616 static void 00617 Emit_Message ( 00618 char *hmsg, /* Header line of message */ 00619 char *emsg ) /* Error line of message */ 00620 { 00621 char msg[512]; 00622 BOOL report_location = FALSE; 00623 00624 /* Report the assertion failure location: */ 00625 if ( Compiler_File != NULL ) { 00626 sprintf ( msg, "\n### Assertion failure at line %d of %s:\n", 00627 Compiler_Line, Compiler_File ); 00628 fputs ( msg, stderr ); 00629 Compiler_File = NULL; 00630 report_location = TRUE; 00631 } 00632 00633 /* Write to standard error first: */ 00634 fputs ( hmsg, stderr ); 00635 fputs ( emsg, stderr ); 00636 fflush ( stderr ); 00637 00638 /* Then write to error file if enabled: */ 00639 if ( Init_Error_File() ) { 00640 if ( report_location ) fputs ( msg, Error_File ); 00641 fputs ( hmsg, Error_File ); 00642 fputs ( emsg, Error_File ); 00643 fflush ( Error_File ); 00644 } 00645 00646 /* Finally write to trace file: */ 00647 if ( Trace_File != NULL ) { 00648 if ( report_location ) fputs ( msg, Trace_File ); 00649 fputs ( hmsg, Trace_File ); 00650 fputs ( emsg, Trace_File ); 00651 fflush ( Trace_File ); 00652 } 00653 } 00654 00655 /* ==================================================================== 00656 * 00657 * ErrMsg_Report 00658 * 00659 * Report an error at the given line number. 00660 * 00661 * ==================================================================== 00662 */ 00663 00664 static void 00665 ErrMsg_Report_Nonuser ( ERROR_DESC *edesc, INT ecode, INT line, 00666 const char *file, va_list vp ) 00667 { 00668 INT dlevel = ED_severity(edesc); /* Declared severity */ 00669 INT mlevel = dlevel; /* Mapped severity */ 00670 char hmsg[512]; 00671 vstring emsg; 00672 INTPS mparm[MAX_ERR_PARMS]; 00673 00674 /* Formatting buffer: */ 00675 # define BUFLEN 512 00676 INT loc; 00677 static char buf[BUFLEN]; 00678 char *result; 00679 INT kind; 00680 00681 INT pnum; 00682 INTPS parm; 00683 00684 /* Count error: */ 00685 ++Error_Counts[dlevel]; 00686 if ( dlevel >= ES_ERROR ) ++Error_Count; 00687 if ( dlevel >= ES_ERRPHASE) Phase_Error = TRUE; 00688 00689 /* Convert conformance error severity level: */ 00690 if ( dlevel == ES_CONFORMANCE ) mlevel = Conformance_Level; 00691 00692 /* Filter out errors with severity lower than threshhold: */ 00693 if ( mlevel < Min_Error_Severity ) return; 00694 if (Heed_Woff( ED_rag_errnum(edesc) , mlevel)) return; 00695 00696 /* Prepare header line: */ 00697 if ( ! ED_continuation(edesc) ) { 00698 loc = sprintf ( &hmsg[0], "%s%s%s", SEV_symbol(mlevel), 00699 ED_unknown(edesc) ? "Unknown Compiler " : 00700 (ED_compiler(edesc) ? "Compiler " : ""), 00701 SEV_name(mlevel) ); 00702 if ( line != ERROR_LINE_UNKNOWN ) { 00703 loc += sprintf ( &hmsg[loc], " at line %d", line ); 00704 } 00705 if ( file != NULL && *file != 0 ) { 00706 loc += sprintf ( &hmsg[loc], " in file %s", file ); 00707 } 00708 #ifndef METAKAP 00709 if ( Cur_PU_Name != NULL ) { 00710 loc += sprintf ( &hmsg[loc], " (user routine '%s')", Cur_PU_Name ); 00711 } 00712 if ( ED_compiler(edesc) && Current_Phase != NULL ) { 00713 loc += sprintf ( &hmsg[loc], " during %s phase", Current_Phase ); 00714 } 00715 #endif /* METAKAP */ 00716 sprintf ( &hmsg[loc], ":\n" ); 00717 } else { 00718 hmsg[0] = 0; 00719 } 00720 00721 /* Prepare message parameters: */ 00722 loc = 0; 00723 for ( pnum = 0; pnum < MAX_ERR_PARMS; pnum++ ) { 00724 00725 /* If this is the unknown error message, make ecode first parm: */ 00726 if ( ED_unknown(edesc) ) { 00727 mparm[0] = (INTPS) ecode; 00728 break; 00729 } 00730 00731 /* If this is beyond the required parameters, we're done: */ 00732 if ( pnum >= ED_parms(edesc) ) break; 00733 00734 /* Otherwise base processing on descriptor's type: */ 00735 switch ( kind = ED_kind(edesc,pnum) ) { 00736 /* The following parameter kinds are standard and require no 00737 * host program-specific data structures to interpret: 00738 */ 00739 case ET_UNKNOWN: mparm[pnum] = 0; 00740 break; 00741 00742 case ET_INT: mparm[pnum] = (INTPS) va_arg ( vp, INTSC ); 00743 break; 00744 00745 case ET_INT32: mparm[pnum] = (INTPS) va_arg ( vp, mINT32 ); 00746 break; 00747 00748 case ET_INT64: /* will output as a string */ 00749 result = &buf[++loc]; 00750 loc += sprintf ( &buf[loc], "%lld", 00751 va_arg(vp,INT64) ); 00752 mparm[pnum] = (INTPS) result; 00753 break; 00754 00755 case ET_STRING: mparm[pnum] = (INTPS) va_arg ( vp, char * ); 00756 break; 00757 00758 case ET_FLOAT: result = &buf[++loc]; 00759 loc += sprintf ( &buf[loc], "%6e", 00760 *(va_arg(vp,float *)) ); 00761 mparm[pnum] = (INTPS) result; 00762 break; 00763 00764 case ET_DOUBLE: result = &buf[++loc]; 00765 loc += sprintf ( &buf[loc], "%14e", 00766 *(va_arg(vp,double *)) ); 00767 mparm[pnum] = (INTPS) result; 00768 break; 00769 00770 case ET_POINTER: result = &buf[++loc]; 00771 loc += sprintf ( &buf[loc], "%#8lX", 00772 (INTPS) va_arg(vp,char *) ); 00773 mparm[pnum] = (INTPS) result; 00774 break; 00775 00776 case ET_SYSERR: parm = (INTPS) va_arg(vp,int); 00777 if (parm < 0) { 00778 mparm[pnum] = (INTPS) host_errlist[-parm]; 00779 } else { 00780 mparm[pnum] = (INTPS) strerror(parm); 00781 } 00782 break; 00783 00784 /* The default case takes care of all host program-specific 00785 * parameter kinds, which must be pointers: 00786 */ 00787 default: result = Host_Format_Parm ( kind, va_arg(vp,char *) ); 00788 /* Copy the string from the result into buffer: */ 00789 ++loc; 00790 strncpy ( &buf[loc], result, BUFLEN-loc ); 00791 result = &buf[loc]; 00792 loc += strlen (result); 00793 mparm[pnum] = (INTPS) result; 00794 break; 00795 } 00796 00797 } 00798 00799 /* Prepare main error message: */ 00800 emsg = vstr_begin(512); 00801 emsg = vstr_concat (emsg, SEV_symbol(mlevel)); 00802 loc = vstr_sprintf (&emsg, vstr_len(emsg), ED_format(edesc), mparm[0], 00803 mparm[1], mparm[2], mparm[3], mparm[4], mparm[5] ); 00804 emsg = vstr_concat (emsg, "\n"); 00805 00806 /* Produce the message: */ 00807 Emit_Message ( hmsg, vstr_str(emsg) ); 00808 vstr_end(emsg); 00809 00810 if (ED_compiler(edesc)) Had_Compiler_Error = TRUE; 00811 00812 /* Abort at highest severity level: */ 00813 if ( mlevel >= ES_ERRABORT ) { 00814 Signal_Cleanup( 0 ); 00815 if ( ecode == EC_Signal ) kill ( getpid(), SIGILL ); 00816 exit(RC_INTERNAL_ERROR); 00817 } 00818 00819 /* If we've seen too many errors, abort: */ 00820 if ( Error_Count > Max_Errors ) { 00821 ErrMsgLine ( EC_Too_Many, ERROR_LINE_UNKNOWN, Error_Count ); 00822 /* Won't return */ 00823 } 00824 00825 return; 00826 } 00827 00828 00829 static void 00830 ErrMsg_Report_User (ERROR_DESC *edesc, INT ecode, INT line, 00831 const char *file, va_list vp ) 00832 { 00833 INT dlevel = ED_severity(edesc); /* Declared severity */ 00834 INT mlevel = dlevel; /* Mapped severity */ 00835 char hmsg[512]; 00836 vstring emsg; 00837 INTPS mparm[MAX_ERR_PARMS]; 00838 00839 /* Formatting buffer: */ 00840 # define BUFLEN 512 00841 INT loc; 00842 static char buf[BUFLEN]; 00843 char *result; 00844 INT kind; 00845 00846 INT pnum; 00847 INTPS parm; 00848 00849 /* Count error: */ 00850 ++Error_Counts[dlevel]; 00851 if ( dlevel >= ES_ERROR ) ++Error_Count; 00852 if ( dlevel >= ES_ERRPHASE) Phase_Error = TRUE; 00853 00854 /* Convert conformance error severity level: */ 00855 if ( dlevel == ES_CONFORMANCE ) mlevel = Conformance_Level; 00856 00857 /* Filter out errors with severity lower than threshhold: */ 00858 if ( mlevel < Min_Error_Severity ) return; 00859 if (Heed_Woff( ED_rag_errnum(edesc) , mlevel)) return; 00860 00861 /* Prepare header line: */ 00862 if ( ! ED_continuation(edesc) ) { 00863 if ( file != NULL && *file != 0 && line != ERROR_LINE_UNKNOWN ) { 00864 loc = sprintf ( &hmsg[0], "\"%s\", line %d: ", file, line ); 00865 } 00866 else if ( file != NULL && *file != 0 ) { 00867 loc = sprintf ( &hmsg[0], "\"%s\": ", file ); 00868 } 00869 else if ( line != ERROR_LINE_UNKNOWN ) { 00870 loc = sprintf ( &hmsg[0], "line %d: ", line ); 00871 } 00872 else { 00873 loc = 0; 00874 } 00875 sprintf ( &hmsg[loc], "%s%s: ", 00876 ED_unknown(edesc) ? "unknown compiler " 00877 : (ED_compiler(edesc) ? "compiler " : ""), 00878 SEV_name(mlevel) ); 00879 } else { 00880 hmsg[0] = 0; 00881 } 00882 00883 loc = 0; 00884 /* Prepare message parameters: */ 00885 for ( pnum = 0; pnum < MAX_ERR_PARMS; pnum++ ) { 00886 /* If this is beyond the required parameters, we're done: */ 00887 if ( pnum >= ED_parms(edesc) ) break; 00888 00889 /* Otherwise base processing on descriptor's type: */ 00890 switch ( kind = ED_kind(edesc,pnum) ) { 00891 /* The following parameter kinds are standard and require no 00892 * host program-specific data structures to interpret: 00893 */ 00894 case ET_UNKNOWN: mparm[pnum] = 0; 00895 break; 00896 00897 case ET_INT: mparm[pnum] = (INTPS) va_arg ( vp, INTSC ); 00898 break; 00899 00900 case ET_INT32: mparm[pnum] = (INTPS) va_arg ( vp, mINT32 ); 00901 break; 00902 00903 case ET_INT64: /* will output as a string */ 00904 result = &buf[++loc]; 00905 loc += sprintf ( &buf[loc], "%lld", 00906 va_arg(vp,INT64) ); 00907 mparm[pnum] = (INTPS) result; 00908 break; 00909 00910 case ET_STRING: mparm[pnum] = (INTPS) va_arg ( vp, char * ); 00911 break; 00912 00913 case ET_FLOAT: result = &buf[++loc]; 00914 loc += sprintf ( &buf[loc], "%6e", 00915 *(va_arg(vp,float *)) ); 00916 mparm[pnum] = (INTPS) result; 00917 break; 00918 00919 case ET_DOUBLE: result = &buf[++loc]; 00920 loc += sprintf ( &buf[loc], "%14e", 00921 *(va_arg(vp,double *)) ); 00922 mparm[pnum] = (INTPS) result; 00923 break; 00924 00925 case ET_POINTER: result = &buf[++loc]; 00926 loc += sprintf ( &buf[loc], "%#8lX", 00927 (INTPS) va_arg(vp,char *) ); 00928 mparm[pnum] = (INTPS) result; 00929 break; 00930 00931 case ET_SYSERR: parm = (INTPS) va_arg(vp,int); 00932 if (parm < 0) { 00933 mparm[pnum] = (INTPS) host_errlist[-parm]; 00934 } else { 00935 mparm[pnum] = (INTPS) strerror(parm); 00936 } 00937 break; 00938 00939 /* The default case takes care of all host program-specific 00940 * parameter kinds, which must be pointers: 00941 */ 00942 default: result = Host_Format_Parm ( kind, va_arg(vp,char *) ); 00943 /* Copy the string from the result into buffer: */ 00944 ++loc; 00945 strncpy ( &buf[loc], result, BUFLEN-loc ); 00946 result = &buf[loc]; 00947 loc += strlen (result); 00948 mparm[pnum] = (INTPS) result; 00949 break; 00950 } 00951 00952 } 00953 00954 /* Prepare main error message: */ 00955 emsg = vstr_begin(512); 00956 loc = vstr_sprintf (&emsg, 0, ED_format(edesc), mparm[0], mparm[1], 00957 mparm[2], mparm[3], mparm[4], mparm[5] ); 00958 emsg = vstr_concat (emsg, "\n"); 00959 00960 /* TODO: user error messages usually have a second line that is a copy of */ 00961 /* the source line, and a third line with blanks and a ^ pointing to the */ 00962 /* character of interest. We are not printing that out. The easiest */ 00963 /* way to remedy that would be to fopen the file and find the desired line */ 00964 /* (fgets()). It's feasible, but if there are lots of warnings and errors */ 00965 /* it becomes O(n^2) in the number of characters, which may or may not be */ 00966 /* a problem. By reading the file the first time this is called with a */ 00967 /* given file name, and keeping an extensible array (or even linked list) */ 00968 /* of offsets to the beginnings of lines, we could access the file */ 00969 /* efficiently enough. A minor headache. */ 00970 00971 /* Produce the message: */ 00972 Emit_Message ( hmsg, vstr_str(emsg) ); 00973 vstr_end(emsg); 00974 00975 if (ED_compiler(edesc)) Had_Compiler_Error = TRUE; 00976 00977 /* Abort at highest severity level: */ 00978 if ( mlevel >= ES_ERRABORT ) { 00979 Signal_Cleanup( 0 ); 00980 if ( ecode == EC_Signal ) kill ( getpid(), SIGILL ); 00981 exit(RC_NORECOVER_USER_ERROR); 00982 } 00983 00984 /* If we've seen too many errors, abort: */ 00985 if ( Error_Count > Max_Errors ) { 00986 ErrMsgLine ( EC_Too_Many, ERROR_LINE_UNKNOWN, Error_Count ); 00987 /* Won't return */ 00988 } 00989 00990 return; 00991 } 00992 00993 static void 00994 ErrMsg_Report ( INT ecode, INT line, const char *file, va_list vp ) 00995 { 00996 ERROR_DESC *edesc = Find_Error_Desc (ecode); 00997 00998 if ( ED_user(edesc) ) 00999 ErrMsg_Report_User ( edesc, ecode, line, file, vp ); 01000 else 01001 ErrMsg_Report_Nonuser ( edesc, ecode, line, file, vp ); 01002 } 01003 01004 /* ==================================================================== 01005 * 01006 * ErrMsg / ErrMsgLine / ErrMsgSrcpos 01007 * 01008 * Report an error at the current (passed) line number. 01009 * 01010 * ==================================================================== 01011 */ 01012 01013 void 01014 ErrMsg ( INT ecode, ... ) 01015 { 01016 va_list vp; 01017 01018 va_start ( vp, ecode); 01019 ErrMsg_Report ( ecode, Source_Line, Source_File_Name, vp ); 01020 va_end ( vp ); 01021 } 01022 01023 /* ================================================================= */ 01024 01025 void 01026 ErrMsgLine ( INT ecode, INT line, ... ) 01027 { 01028 va_list vp; 01029 01030 va_start ( vp, line ); 01031 ErrMsg_Report ( ecode, line, Source_File_Name, vp ); 01032 va_end ( vp ); 01033 } 01034 01035 01036 #ifdef MONGOOSE_BE 01037 /* ================================================================= */ 01038 01039 void 01040 ErrMsgSrcpos ( INT ecode, SRCPOS srcpos, ... ) 01041 { 01042 INT32 line = Srcpos_To_Line(srcpos); 01043 const char *fname = NULL; 01044 const char *dname; 01045 01046 va_list vp; 01047 va_start ( vp, srcpos ); 01048 01049 IR_Srcpos_Filename(srcpos, &fname, &dname); 01050 ErrMsg_Report ( ecode, line, fname, vp ); 01051 va_end ( vp ); 01052 } 01053 #endif 01054 01055 /* ==================================================================== 01056 * 01057 * Abort_Compiler_Location 01058 * 01059 * An assertion failure is in progress. Receive the compiler file 01060 * and line number for later reporting. 01061 * 01062 * This replaces in line assignments to global variables in the 01063 * assertion. The problem with that way of doing things is that it 01064 * can cause lint (other checkers?) to complain when assertions are 01065 * included in access macros and used in contexts with undefined 01066 * order of evaluation. For example: 01067 * 01068 * if ( ND_fld(x) == ND_fld(y) ) 01069 * 01070 * would cause a lint warning with Is_True_On. 01071 * 01072 * ==================================================================== 01073 */ 01074 01075 void Abort_Compiler_Location ( 01076 const char * file_name, 01077 INT line_number ) 01078 { 01079 Compiler_File = file_name; 01080 Compiler_Line = line_number; 01081 } 01082 01083 /* ==================================================================== 01084 * 01085 * Fail_Assertion 01086 * 01087 * An assertion has failed -- report the fact. 01088 * 01089 * ==================================================================== 01090 */ 01091 01092 void 01093 Fail_Assertion ( INT ecode, ... ) 01094 { 01095 va_list vp; 01096 01097 va_start ( vp, ecode); 01098 ErrMsg_Report ( ecode, Source_Line, Source_File_Name, vp ); 01099 va_end ( vp ); 01100 } 01101 01102 /* ==================================================================== 01103 * 01104 * Fail_FmtAssertion 01105 * 01106 * A FmtAssertion has failed -- report the fact. 01107 * 01108 * Report a failure with the given printf format and parameters to the 01109 * error file(s), and then abort. 01110 * 01111 * ==================================================================== 01112 */ 01113 01114 void 01115 Fail_FmtAssertion ( const char *fmt, ... ) 01116 { 01117 va_list vp; 01118 01119 INT dlevel = ES_ERRABORT; /* Severity level */ 01120 INT mlevel = dlevel; 01121 char hmsg[512], emsg[512]; 01122 INT loc; 01123 01124 /* Count error: */ 01125 ++Error_Counts[dlevel]; 01126 01127 /* Prepare header line: */ 01128 loc = sprintf ( &hmsg[0], "%s%s%s", SEV_symbol(mlevel), 01129 "Compiler ", SEV_name(mlevel) ); 01130 if ( Source_File_Name != NULL && *Source_File_Name != 0 ) { 01131 loc += sprintf ( &hmsg[loc], " in file %s", Source_File_Name ); 01132 } 01133 if ( Current_Phase != NULL ) { 01134 loc += sprintf ( &hmsg[loc], " during %s phase", Current_Phase ); 01135 } 01136 sprintf ( &hmsg[loc], ":\n" ); 01137 01138 /* Prepare main error message: */ 01139 va_start ( vp, fmt ); 01140 loc = sprintf ( &emsg[0], "%s", SEV_symbol(mlevel) ); 01141 loc += vsprintf ( &emsg[loc], fmt, vp ); 01142 sprintf ( &emsg[loc], "\n" ); 01143 va_end ( vp ); 01144 01145 /* Report the error: */ 01146 Emit_Message ( hmsg, emsg ); 01147 01148 /* Abort: */ 01149 Signal_Cleanup( 0 ); 01150 exit(RC_INTERNAL_ERROR); 01151 } 01152 01153 /* ==================================================================== 01154 * 01155 * Fatal_Error 01156 * 01157 * A Require has failed -- report the fact. 01158 * 01159 * Report a failure with the given printf format and parameters to the 01160 * error file(s), and then abort. This routine is similar to 01161 * Fail_FmtAssertion, but reports a user error instead of a compiler 01162 * error. 01163 * 01164 * ==================================================================== 01165 */ 01166 01167 void 01168 Fatal_Error ( const char *fmt, ... ) 01169 { 01170 va_list vp; 01171 INT dlevel = ES_ERRABORT; /* Severity level */ 01172 INT mlevel = dlevel; 01173 char hmsg[512], emsg[512]; 01174 INT loc; 01175 01176 /* Count error: */ 01177 ++Error_Counts[dlevel]; 01178 01179 /* Prepare header line: */ 01180 loc = sprintf ( &hmsg[0], "%s%s", SEV_symbol(mlevel), 01181 SEV_name(mlevel) ); 01182 if ( Source_File_Name != NULL && *Source_File_Name != 0 ) { 01183 loc += sprintf ( &hmsg[loc], " in file %s", Source_File_Name ); 01184 } 01185 if ( Current_Phase != NULL ) { 01186 loc += sprintf ( &hmsg[loc], " during %s phase", Current_Phase ); 01187 } 01188 sprintf ( &hmsg[loc], ":\n" ); 01189 01190 /* Prepare main error message: */ 01191 va_start ( vp, fmt ); 01192 loc = sprintf ( &emsg[0], "%s", SEV_symbol(mlevel) ); 01193 loc += vsprintf ( &emsg[loc], fmt, vp ); 01194 sprintf ( &emsg[loc], "\n" ); 01195 va_end ( vp ); 01196 01197 /* Report the error: */ 01198 Emit_Message ( hmsg, emsg ); 01199 01200 /* Abort: */ 01201 Signal_Cleanup( 0 ); 01202 exit(RC_INTERNAL_ERROR); 01203 } 01204 01205 /* ==================================================================== 01206 * 01207 * Rag_Handle_Woff_Args 01208 * 01209 * Process a -woff argument: Mark the given error codes to be ignored. 01210 * Ignore bad/illegal values. 01211 * 01212 * ==================================================================== 01213 */ 01214 01215 extern void Rag_Handle_Woff_Args ( char *wstring ) 01216 { 01217 INT i=0; 01218 INT inp_size = strlen(wstring); 01219 INT msgnum1, msgnum2; 01220 01221 /* check that argument string is correct and set woff */ 01222 while ( i < inp_size ) { 01223 /* get next warning number */ 01224 if ( isdigit ( wstring[i] ) ) { 01225 /* get first number of the range */ 01226 msgnum1 = atoi(&wstring[i]); 01227 while ( isdigit ( wstring[++i] ) ); 01228 /* get second number of the range */ 01229 if ((wstring[i] == '-') && isdigit(wstring[++i])) { 01230 msgnum2 = atoi(&wstring[i]); 01231 while ( isdigit ( wstring[++i] ) ); 01232 } else { 01233 msgnum2 = msgnum1; 01234 } 01235 01236 msgnum1 = MAX ( msgnum1, RAG_EN_FIRST ); 01237 msgnum2 = MIN ( msgnum2, RAG_EN_LAST ); 01238 /* set the warning within the range (inclusive) */ 01239 for (; msgnum1 <= msgnum2; msgnum1++) 01240 Dont_Print_Warning(msgnum1) = TRUE; 01241 } 01242 01243 /* skip past next comma */ 01244 while ( i < inp_size && wstring[i++] != ',' ) {}; 01245 01246 } /* while i < inp_size */ 01247 } 01248 01249 static INT Current_Phase_Number = 0; 01250 01251 void 01252 Set_Current_Phase_Number( INT phase ) 01253 { 01254 Current_Phase_Number = phase; 01255 } 01256 01257 INT 01258 Get_Current_Phase_Number( void ) 01259 { 01260 return Current_Phase_Number; 01261 } 01262 01263 01264 #ifndef MONGOOSE_BE 01265 /* ==================================================================== 01266 * 01267 * Set_Error_Tables 01268 * 01269 * Error table initialization. All users of this package must call 01270 * this routine before emitting any error messages. 01271 * 01272 * ==================================================================== 01273 */ 01274 01275 extern void Set_Error_Tables( 01276 ERROR_DESC_TABLE *edt, 01277 const char *errlist[] ) 01278 { 01279 Phases = edt; 01280 host_errlist = errlist; 01281 } 01282 #endif /* MONGOOSE_BE */ 01283 01284 extern void 01285 Set_Error_Descriptor (INT phase, ERROR_DESC *descriptor) 01286 { 01287 register INT i = 0; 01288 01289 while (Phases[i].phase != -1) { 01290 if (Phases[i].phase == phase) { 01291 Phases[i].descriptors = descriptor; 01292 return; 01293 } 01294 i++; 01295 } 01296 01297 FmtAssert (FALSE, ("Error Phase %d not initialized", phase)); 01298 } /* Set_Error_Descriptor */ 01299 01300 /* ==================================================================== 01301 * 01302 * DevWarn 01303 * 01304 * See interface description 01305 * 01306 * ==================================================================== 01307 */ 01308 01309 #if Is_True_On 01310 static BOOL dev_warn_enabled = TRUE; 01311 #else 01312 static BOOL dev_warn_enabled = FALSE; 01313 #endif 01314 01315 extern void 01316 DevWarn( const char *fmt, ... ) 01317 { 01318 va_list args; 01319 01320 va_start ( args, fmt ); 01321 01322 const char *phase_name = (Current_Phase != NULL) ? Current_Phase : "unknown phase"; 01323 01324 if ( dev_warn_enabled ) { 01325 /* Write to standard error first: */ 01326 fprintf ( stderr, "!!! DevWarn during %s: ", phase_name ); 01327 vfprintf ( stderr, fmt, args ); 01328 fprintf ( stderr, "\n" ); 01329 fflush ( stderr ); 01330 } 01331 01332 /* Then write to error file if enabled: */ 01333 if ( Init_Error_File() ) { 01334 fprintf ( Error_File, "!!! DevWarn during %s: ", phase_name ); 01335 vfprintf ( Error_File, fmt, args ); 01336 fprintf ( Error_File, "\n" ); 01337 fflush ( Error_File ); 01338 } 01339 01340 /* Finally write to trace file: */ 01341 if ( Trace_File != NULL ) { 01342 fprintf ( Trace_File, "!!! DevWarn during %s: ", phase_name ); 01343 vfprintf ( Trace_File, fmt, args ); 01344 fprintf ( Trace_File, "\n" ); 01345 fflush ( Trace_File ); 01346 } 01347 01348 va_end(args); 01349 } 01350 01351 /* ==================================================================== 01352 * 01353 * DevWarn_limit_search 01354 * 01355 * For use only by Count_Limit_DevWarn. Ultimately this linear search 01356 * should probably be replaced by a faster hash lookup. 01357 * 01358 * ==================================================================== 01359 */ 01360 typedef struct { 01361 const char *fname; 01362 UINT line; 01363 UINT count; 01364 } LIMIT_STRUCT; 01365 01366 static LIMIT_STRUCT * 01367 DevWarn_limit_search(const char *const src_fname, 01368 const UINT src_line) 01369 { 01370 static LIMIT_STRUCT *dw_ls_buf = NULL; 01371 static UINT dw_ls_buf_siz = 0; 01372 static UINT dw_ls_num = 0; 01373 static LIMIT_STRUCT dummy_ls = { NULL, 0, 0 }; // In case of realloc failure 01374 UINT i; 01375 01376 for (i = 0; i < dw_ls_num; i++) { 01377 if (dw_ls_buf[i].line == src_line && 01378 (dw_ls_buf[i].fname == src_fname || /* speed hack */ 01379 (strcmp(dw_ls_buf[i].fname, src_fname) == 0))) { 01380 return dw_ls_buf + i; 01381 } 01382 } 01383 01384 /* Didn't find the entry we're looking for. We're going to have to 01385 * add an entry. 01386 */ 01387 if (dw_ls_num >= dw_ls_buf_siz) { 01388 UINT new_ls_buf_siz; 01389 LIMIT_STRUCT *new_ls_buf; 01390 01391 /* Expand the buffer of LIMIT_STRUCTs if possible. If not 01392 * possible, return value points to a LIMIT_STRUCT that always 01393 * says we should emit the error message. 01394 */ 01395 if (dw_ls_buf_siz == 0) { 01396 new_ls_buf_siz = 1024; 01397 } 01398 else { 01399 new_ls_buf_siz = dw_ls_buf_siz * 2; 01400 } 01401 new_ls_buf = (LIMIT_STRUCT *) 01402 realloc(dw_ls_buf, new_ls_buf_siz * sizeof(LIMIT_STRUCT)); 01403 if (new_ls_buf != NULL) { 01404 dw_ls_buf = new_ls_buf; 01405 dw_ls_buf_siz = new_ls_buf_siz; 01406 } 01407 else { 01408 /* realloc() failed. 01409 */ 01410 dummy_ls.count = 0; 01411 return &dummy_ls; 01412 } 01413 } 01414 01415 dw_ls_buf[dw_ls_num].line = src_line; 01416 dw_ls_buf[dw_ls_num].fname = src_fname; 01417 dw_ls_buf[dw_ls_num].count = 0; 01418 01419 return dw_ls_buf + (dw_ls_num++); 01420 } 01421 01422 /* ==================================================================== 01423 * 01424 * Count_Limit_DevWarn 01425 * 01426 * For use through Lmt_DevWarn macro; see interface description 01427 * 01428 * ==================================================================== 01429 */ 01430 01431 extern BOOL 01432 Count_Limit_DevWarn(const char *const src_fname, 01433 const UINT src_line, 01434 const UINT limit) 01435 { 01436 /* Check conditions used by DevWarn that result in output. If 01437 * DevWarn will not generate output, don't bother wasting time or 01438 * memory in DevWarn_limit_search. 01439 */ 01440 if (!(dev_warn_enabled || Init_Error_File() || Trace_File != NULL)) { 01441 return TRUE; 01442 } 01443 01444 LIMIT_STRUCT *s = DevWarn_limit_search(src_fname, src_line); 01445 s->count++; 01446 if (s->count == limit) { 01447 DevWarn("Count limit reached on the following DevWarn:"); 01448 } 01449 return s->count <= limit; 01450 } 01451 01452 /* ==================================================================== 01453 * 01454 * DevWarn_Toggle 01455 * 01456 * See interface description 01457 * 01458 * ==================================================================== 01459 */ 01460 extern void 01461 DevWarn_Toggle(void) 01462 { 01463 dev_warn_enabled = ! dev_warn_enabled; 01464 } 01465 01466 extern BOOL 01467 Had_Internal_Error (void) 01468 { 01469 return Had_Compiler_Error; 01470 } 01471 01472 /* ==================================================================== 01473 * 01474 * Handling Errors from Signals 01475 * 01476 * ==================================================================== 01477 */ 01478 01479 #if defined(__sgi) 01480 // On some versions of IRIX, namespace std will not be defined. We 01481 // need at least a definition of 'std' so that the IRIX compiler won't 01482 // complain when it sees the 'using' below. 01483 namespace std { } 01484 #endif 01485 01486 // StrSignal: See interface description 01487 extern const char* StrSignal(int sig) 01488 { 01489 // eraxxon: As of now, there is no portable method for collecting 01490 // string representations of signal errors. Many platforms define 01491 // an external array indexed by error number such as _sys_siglist[]. 01492 // There has been some attempt at sanitizing this into a call to 01493 // 'strsignal()' but this is not yet widely available. Sigh. 01494 01495 // ------------------------------------------------------- 01496 01497 // The following platforms access via an accursed array of char* 01498 // defined in <signal.h> 01499 char** my_sys_siglist = NULL; 01500 #if defined(__sgi) 01501 # define I_USE_THE_CRUSTY_SYS_SIGLIST_ARRAY 1 01502 using namespace std; 01503 my_sys_siglist = (char**)_sys_siglist; 01504 #elif defined(__MACH__) /* MacOS */ 01505 # define I_USE_THE_CRUSTY_SYS_SIGLIST_ARRAY 1 01506 my_sys_siglist = (char**)sys_siglist; 01507 #elif defined(__digital__) 01508 # define I_USE_THE_CRUSTY_SYS_SIGLIST_ARRAY 1 01509 my_sys_siglist = (char**)__sys_siglist; 01510 #endif 01511 01512 // Other platforms use strsignal() from <string.h>: Linux, cygwin, 01513 // Solaris 01514 01515 // ------------------------------------------------------- 01516 01517 #if defined(I_USE_THE_CRUSTY_SYS_SIGLIST_ARRAY) 01518 // The code originally used sys_siglist[] directly, without 01519 // checking for bad indices or copying the string to a static 01520 // buffer. So we just simulate that behavior. 01521 return my_sys_siglist[sig]; 01522 #else 01523 return strsignal(sig); 01524 #endif 01525 } 01526