00001 /* 00002 * Copyright (c) 2006 Beijing SimpLight Nanoelectornics, Ltd. 00003 * All rights reserved. 00004 */ 00005 00006 /* 00007 Copyright (C) 2005, 2006. Free Software Foundation, Inc. 00008 00009 This program is free software; you can redistribute it and/or modify it 00010 under the terms of version 2 of the GNU General Public License as 00011 published by the Free Software Foundation. 00012 00013 This program is distributed in the hope that it would be useful, but 00014 WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 00017 Further, this software is distributed without any warranty that it is 00018 free of the rightful claim of any third person regarding infringement 00019 or the like. Any license provided herein, whether implied or 00020 otherwise, applies only to this software file. Patent licenses, if 00021 any, provided herein do not apply to combinations of this program with 00022 other software, or any other product whatsoever. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with this program; if not, write the Free Software Foundation, Inc., 59 00026 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00027 */ 00028 00029 #ifndef _MESSG_H_ 00030 #define _MESSG_H_ 00031 00032 #ifdef __cplusplus 00033 extern "C" { 00034 #endif 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * Module: messg.h 00040 * 00041 * Description: 00042 * 00043 * This file defines the external interface to a general-purpose message 00044 * reporting mechanism for compilers. Its objectives are: 00045 * 00046 * 1) To provide a simple error reporting in the source (i.e. minimal 00047 * code), with adequate options to fully describe the message. 00048 * 00049 * 2) To require minimal effort to modify the message's description and 00050 * handling. This implies central descriptors driving the error 00051 * handling, especially to deal with frequent reuse of error 00052 * information (e.g. "Illegal access"). 00053 * 00054 * ==================================================================== 00055 * 00056 * The Message Reporting Interface 00057 * 00058 * In order to make use of an already-defined error message, the 00059 * interface defined consists of the following calls: 00060 * 00061 * void ErrMsg ( 00062 * INT Error_Code, 00063 * ... 00064 * ) 00065 * 00066 * produces the error message associated with Error_Code, with 00067 * up to six parameters. Error_Code and parameters will be 00068 * discussed further below. The error is presumed to result from 00069 * the current file and line number (discussed below), where the 00070 * current line number will generally be undefined for non-front 00071 * end passes. 00072 * 00073 * 00074 * void Assert ( 00075 * BOOL condition, 00076 * ( INT Error_Code, ... ) 00077 * ) 00078 * 00079 * checks for truth of the condition and, if false, invokes the 00080 * equivalent of ErrMsg to report an (presumably) error. The 00081 * extra set of parentheses is necessary to allow cpp to process 00082 * the call with arbitrary parameter count -- the condition is 00083 * checked in-line. Note that we assume that calls to Assert 00084 * will be kept in production code. 00085 * 00086 * BOOL IsTrue ( 00087 * BOOL condition, 00088 * ( const char *Format_String, ... ) 00089 * ) 00090 * 00091 * Similar to Assert, but performs a check expected to be removed (using 00092 * cpp) in production code. Also, notice that a format string is given 00093 * instead of an error code. Because these checks will be removed from 00094 * producetion code, we decided that consistency of error reporting was 00095 * less important than ease of use (in this case). 00096 * 00097 * void FmtAssert ( 00098 * BOOL condition, 00099 * ( const char *Format_String, ... ) 00100 * ) 00101 * 00102 * 00103 * Just like IsTrue, except will check in the production mode as 00104 * well as during development. 00105 * 00106 * 00107 * void Verifiy ( 00108 * BOOL condition, 00109 * ( const char *Format_String, ... ) 00110 * ) 00111 * 00112 * Just like FmtAssert, except will not abort regardless of condition. 00113 * 00114 * 00115 * WARNING: The parameter lists for the above are currently are limited to 6 00116 * parameters after the error code or format string. 00117 * 00118 * void DevWarn ( const char *Format_String, ... ) 00119 * 00120 * Issue a warning to stderr only when executed in a compiler built for 00121 * development (not in MR'ed compilers). This is a good thing to use if 00122 * you have an unexpected condition from which there is a valid (though 00123 * perhaps suboptimal) recovery. For example: 00124 * 00125 * if ( Unexpected_Condition_That_Precludes_Optimization() ) { 00126 * DevWarn("Can't optimize because I was a hopeless loser"); 00127 * Generate_Code(); 00128 * } 00129 * else { 00130 * Optimize(); 00131 * Generate_Code(); 00132 * } 00133 * 00134 * The warnings are issued by default if the errors package is built with 00135 * horrible Is_True_On; otherwise, they are not issued. This behavior can 00136 * be changed with: 00137 * 00138 * void DevWarn_Toggle ( void ) 00139 * 00140 * If the current behavior of DevWarn is to print the warnings, calling 00141 * this supresses the warnings. If the current behavior is to supress 00142 * the warnings, calling this will enable printing them. 00143 * 00144 * Lmt_DevWarn(const UINT limit, args) 00145 * 00146 * This is a macro designed to suppress printing of DevWarn 00147 * messages that get repeated a lot. At most limit copies of the 00148 * DevWarn message will be printed; args is the parenthesized 00149 * argument list for the function DevWarn(). In the present 00150 * implementation, the position (file, line) in the compiler 00151 * source is presumed to identify the message. For example, if 00152 * you are a hopeless loser hundreds of times per compilation, 00153 * and you feel a need to tolerate this situation for a time, and 00154 * you don't wish to see hundreds of copies of the "hopeless 00155 * loser" DevWarn message every time you compile, you might use: 00156 * 00157 * if ( Unexpected_Condition_That_Precludes_Simulation() ) { 00158 * Lmt_DevWarn(5, 00159 * "Can't simulate because I was a hopeless loser"); 00160 * Exec_Code(); 00161 * } 00162 * else { 00163 * Read_Object(); 00164 * Exec_Code(); 00165 * } 00166 * 00167 * In this example, you will see the "hopeless loser" DevWarn 00168 * message at most five times per compilation. 00169 * 00170 * 00171 * Note that a number of predefined error codes are available, 00172 * including one which allows arbitrary formatting. See erglob.h. 00173 * 00174 * The parameters passed to the error reporting routines must match the 00175 * message descriptor for the error code; they are used to provide 00176 * values inserted in the message. The parameters are passed in a form 00177 * which allows them to be passed further without type knowledge, with 00178 * only the assumption that standard integers and pointers are the same 00179 * size. The following possibilities are currently supported: 00180 * 00181 * ET_INT: Generic scaled integer: size of host register (INTSC). 00182 * ET_INT32: 32-bit integer. 00183 * ET_INT64: 64-bit integer. 00184 * ET_FLOAT: Pointer to a standard float number. 00185 * ET_POINTER: Arbitrary pointer, printed as a hex number. 00186 * ET_STRING: Pointer to a standard C string. 00187 * ET_SYSERR: Unix error number. 00188 * ET_STRTAB: Pointer to a string table entry. 00189 * ET_SYMTAB: Pointer to a symbol table entry. 00190 * 00191 * ==================================================================== 00192 * 00193 * Error Code Definition 00194 * 00195 * In order to define a new error code for use, its value must be 00196 * defined in one of the error code header files erXXX.h, and a message 00197 * descriptor added to the descriptor file erXXX.desc. For the 00198 * compiler, the possibilities for these files are: 00199 * 00200 * erglob: Global error codes, common to both simulator, debugger,... 00201 * other tools. 00202 * ersim: Simulator error codes. 00203 * erdbg: Debugger error codes. 00204 * erhost: Host system error codes. 00205 * erobj: Object reader error codes. 00206 * 00207 * The message descriptors provide a printf format for the 00208 * message and parameter types from the above list. They also specify 00209 * a severity level, one of: 00210 * 00211 * IGNORE: To be ignored by the error message generator. 00212 * MESSAGE: For user information/message only; not usually an 00213 * indication of a problem. 00214 * WARNING: A likely problem, but not a definite error. 00215 * ERROR: Minimum error severity level. All errors at or 00216 * above this level continue without exiting. 00217 * FATAL: Error: abort processing after minimal cleanup. 00218 * 00219 * The descriptor also identifies user vs. compiler errors. 00220 * See the discussion in erglob.desc for more detail. 00221 * 00222 * ==================================================================== 00223 * 00224 * In addition, if tracing is enabled, it is useful to have a copy of 00225 * all error messages embedded in the trace file. This is enabled by 00226 * the call: 00227 * 00228 * Set_Error_Trace ( FILE *stream ); 00229 * 00230 * The trace file is assumed to have been opened elsewhere before any 00231 * error message is reported. Note that, if tracing is directed to 00232 * the same file as stderr (e.g. the terminal), the extra copy will 00233 * be suppressed. Error message emission to the trace file is 00234 * disabled by setting the file descriptor to NULL. 00235 * 00236 * Finally, as early as possible during processing, signal catching 00237 * with associated cleanup may be enabled by calling: 00238 * 00239 * Handle_Signals (); 00240 * 00241 * ==================================================================== 00242 * ==================================================================== 00243 */ 00244 00245 #include "workaround.h" 00246 #include <stdio.h> 00247 00248 extern void Abort_Location ( 00249 char* file_name, 00250 INT line_number 00251 ); 00252 extern void Fail_Assertion ( INT ecode, ... ); 00253 extern void Fail_App_Assertion ( const char *fmt, ... ); 00254 extern void Fail_FmtAssertion ( const char *fmt, ... ); 00255 extern void Verify_Cond( const char *fmt, ... ); 00256 extern void Fatal_Error ( const char *fmt, ... ); 00257 extern void Handle_Signals ( void ); 00258 extern void Signal_Cleanup (INT sig); 00259 extern void Abort(); 00260 extern void ErrMsg(INT, ...); 00261 extern void WarnMsg(INT, ...); 00262 extern void FatalMsg(INT, ...); 00263 00264 #define VERBOSE_0 0 // dump all message 00265 #define VERBOSE_1 1 // dump detailed message 00266 #define VERBOSE_2 2 // dump flow message 00267 #define VERBOSE_3 3 // dump important messages such initialization and exiting 00268 #define VERBOSE_4 4 00269 #define VERBOSE_5 5 00270 #define VERBOSE_6 6 00271 #define VERBOSE_7 7 00272 00273 extern INT get_verbose_level(void); 00274 extern INT *get_verbose_level_ptr(void); 00275 extern void set_verbose_level(INT level); 00276 extern void vmsg( INT verbose_level, const char *fmt, ... ); 00277 00278 /* ==================================================================== 00279 * 00280 * Internal Assertion Checking: These routines are invoked via macros 00281 * defined below, and should not be called directly, as their 00282 * interfaces are allowed to change. 00283 * 00284 * ==================================================================== 00285 */ 00286 00287 /* Unconditional assertion checking with error code: */ 00288 #define Assert(Cond,ParmList) \ 00289 ( Cond ? (void) 1 : (Abort_Location(__FILE__, __LINE__), Fail_Assertion ParmList ) ) 00290 00291 /* Unconditional assertion checking with printf format: */ 00292 #define FmtAssert(Cond,ParmList) \ 00293 ( Cond ? (void) 1 : ( Abort_Location ( __FILE__, __LINE__ ), Fail_FmtAssertion ParmList) ) 00294 00295 /* Unconditional assertion checking with printf format, process will not be terminated: */ 00296 #define AppAssert(Cond,ParmList) \ 00297 ( Cond ? (void) 1 : ( Abort_Location ( __FILE__, __LINE__ ), Fail_App_Assertion ParmList) ) 00298 00299 /* Unconditional verification checking with printf format, execution continues: */ 00300 #define Verify(Cond,ParmList) \ 00301 ( Cond ? (void) 1 : ( Abort_Location ( __FILE__, __LINE__ ), Verify_Cond ParmList) ) 00302 00303 /* Check assertion only if Is_True_On flag is set: */ 00304 #ifdef Is_True_On 00305 # define IsTrue FmtAssert 00306 # define IsTrueApp AppAssert 00307 # define Is_True FmtAssert 00308 #else 00309 # define IsTrue(a, b) ((void) 1) 00310 # define Is_True(a, b) ((void) 1) 00311 # define IsTrueApp(a, b) ((void) 1) 00312 #endif 00313 00314 #ifndef _ERROR_ALL_FATAL 00315 #define _ERROR_ALL_FATAL 0 00316 #endif 00317 00318 #if _ERROR_ALL_FATAL 00319 #define ERR_SIM_FATAL IsTrue 00320 #define ERR_APP_FATAL IsTrue 00321 #else 00322 #define ERR_SIM_FATAL IsTrue 00323 #define ERR_APP_FATAL IsTrueApp 00324 #endif 00325 00326 /* If NEED_LONG_JMP is defined, only SimFatal will cause immediate exit. */ 00327 #define SimFatal(a, b) { ERR_SIM_FATAL(a, b); } 00328 #define AppFatal(a,b) { ERR_APP_FATAL(a, b); } 00329 00330 #define MAX_ERR_NUM 100 00331 00332 extern void DevWarn( const char* FormatString,... ) 00333 #ifdef __GNUC__ 00334 __attribute__((format(printf,1,2))) 00335 #endif 00336 ; 00337 #if 0 // not used for now 00338 extern void DevWarn_Toggle( void ); 00339 00340 extern BOOL Count_Limit_DevWarn( const UINT limit ); 00341 00342 #define Lmt_DevWarn(limit, args) \ 00343 ( Count_Limit_DevWarn(limit) ? DevWarn args : (void) 1 ) 00344 #endif 00345 00346 #if 1 00347 00348 /* ==================================================================== 00349 * 00350 * Message Reporting Management and Interface 00351 * 00352 * ==================================================================== 00353 */ 00354 00355 /* The maximum number of message parameters. This value cannot be 00356 * changed (increased) without changing MAX_MSG_PARMS and the file messg.tab 00357 */ 00358 #define MAX_MSG_PARMS 4 00359 /* Define the type used by messages */ 00360 typedef UINT16 Msg_Idx; 00361 enum Msg_Type { IGNORE=0, MESSAGE=1, WARNING=2, ERROR=3, FATAL=4, MSG_TYPE_SIZE=4 }; 00362 00363 00364 class Msg_Dsc { 00365 public: 00366 char *_messg; 00367 INT8 _code; 00368 INT8 _parms; // number of parms 00369 INT8 _kinds[MAX_MSG_PARMS]; 00370 INT8 Parms(void) const { return _parms; } 00371 INT8 Kinds(const INT i) const { return _kinds[i]; } 00372 char *Messg(void) const { return _messg; } 00373 INT8 Code(void) const { return _code; } 00374 void Print_Msg(FILE *f) { } 00375 }; 00376 00377 #include "messg.def" 00378 00379 #if 0 00380 class Msg { 00381 private: 00382 INT _size; // table size 00383 Msg_Type _type; 00384 Msg_Dsc *_tab; 00385 Msg(INT s, Msg_Type t, Msg_Dsc *m) { _size = s; _type = t; _tab = m; } 00386 public: 00387 Msg_Type Type(void) const { return _type; } 00388 INT Size(void) const { return _size; } 00389 void Print(FILE *file=stderr, Msg_Idx i=0) const { 00390 FmtAssert((i < Size()), ("Messg index out of range")); 00391 FmtAssert((i == _tab[i].Code()), ("Messg index inconsistent, table corrupted")); 00392 _tab[i].Print_Msg(file); 00393 } 00394 }; 00395 00396 class Warn : public Msg { 00397 private: 00398 void _print(FILE *file) const { fprintf(file, "# Warning # "); } 00399 public: 00400 Warn(); 00401 ~Warn(); 00402 void Print(FILE *file=stderr, const Msg_Idx i=0) const { _print(file), Msg::Print(file, i); } 00403 }; 00404 00405 class Error : public Msg { 00406 private: 00407 void _print(FILE *file) const { fprintf(file, "# Error # "); } 00408 public: 00409 Error(); 00410 ~Error(); 00411 void Print(FILE *file=stderr, const Msg_Idx i=0) const { _print(file), Msg::Print(file, i); } 00412 }; 00413 00414 class Fatal : public Msg { 00415 private: 00416 void _print(FILE *file) const { fprintf(file, "# Fatal # "); } 00417 public: 00418 Fatal(); 00419 ~Fatal(); 00420 void Print(FILE *file=stderr, const Msg_Idx i=0) const { _print(file), Msg::Print(file, i), Abort();} 00421 }; 00422 #endif 00423 00424 /* Include definitions specific to the host program: */ 00425 /* 00426 #include "err_host.h" 00427 */ 00428 00429 /* The following contains Unix error code after system call errors: */ 00430 #ifndef _ERRNO_H // for conflict with errno.h 00431 extern INT errno; // native build 00432 #endif 00433 00434 #define EC_Undef_Code 1 00435 #define EC_INTERNAL_ERROR 2 00436 #define EC_Signal 3 00437 #define EC_NORECOVER_USER_ERROR 4 00438 #define ERROR_LINE_UNKNOWN 0 00439 00440 /* Initialize signal catching: */ 00441 extern void Handle_Signals ( void ); 00442 00443 /* for debugging */ 00444 extern void Debug_Break ( char* ); 00445 /* ==================================================================== 00446 * 00447 * Miscellaneous 00448 * 00449 * ==================================================================== 00450 */ 00451 00452 /* had any internal errors */ 00453 extern BOOL Had_Internal_Error (void); 00454 #endif 00455 #ifdef __cplusplus 00456 } 00457 #endif 00458 00459 #endif /* _MESSG_H_ */
1.5.6