Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
errors.cxx
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines