00001 /* 00002 * OpenBIOS - free your system! 00003 * ( FCode tokenizer ) 00004 * 00005 * This program is part of a free implementation of the IEEE 1275-1994 00006 * Standard for Boot (Initialization Configuration) Firmware. 00007 * 00008 * Copyright (C) 2001-2005 Stefan Reinauer, <stepan@openbios.org> 00009 * 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; version 2 of the License. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA 00022 * 00023 */ 00024 00025 /* ************************************************************************** 00026 * 00027 * Error-Handler for Tokenizer 00028 * 00029 * Controls printing of various classes of errors 00030 * 00031 * (C) Copyright 2005 IBM Corporation. All Rights Reserved. 00032 * Module Author: David L. Paktor dlpaktor@us.ibm.com 00033 * 00034 **************************************************************************** */ 00035 00036 /* ************************************************************************** 00037 * 00038 * Functions Exported: 00039 * init_error_handler Initialize the error-counts, 00040 * announce the file names. 00041 * tokenization_error Handle an error of the given class, 00042 * print the given message in the 00043 * standard format. 00044 * started_at Supplemental message, giving a back-reference 00045 * to the "starting" point of a compound 00046 * error, including last-colon identification. 00047 * just_started_at Supplemental back-reference to "starting" point 00048 * of compound error, but without last-colon 00049 * identification. 00050 * where_started Supplemental message, giving a more terse back- 00051 * -reference to "start" of compound-error. 00052 * just_where_started Supplemental message, more terse back-reference, 00053 * without last-colon identification. 00054 * in_last_colon Supplemental back-reference message, 00055 * identifying last Colon-definition. 00056 * safe_malloc malloc with built-in failure test. 00057 * error_summary Summarize final error-message status 00058 * before completing tokenization. 00059 * 00060 **************************************************************************** */ 00061 00062 00063 /* ************************************************************************** 00064 * 00065 * We will define a set of bit-valued error-types and a 00066 * global bit-mask. Each error-message will be associated 00067 * with one of the bit-valued error-types. The bit-mask, 00068 * which will be set by a combination of defaults and user 00069 * inputs (mainly command-line arguments), will control 00070 * whether an error-message of any given type is printed. 00071 * 00072 * Another bit-mask variable will accumulate the error- 00073 * types that occur within any given run; at the end of 00074 * the run, it will be examined to determine if the run 00075 * failed, i.e., if the output should be suppressed. 00076 * 00077 **************************************************************************** */ 00078 00079 /* ************************************************************************** 00080 * 00081 * Error-types fall into the following broad categories: 00082 * FATAL Cause to immediately stop activity 00083 * TKERROR Sufficient to make the run a failure, 00084 * but not to stop activity. 00085 * WARNING Not necessarily an error, but something 00086 * to avoid. E.g., it might rely on 00087 * assumptions that are not necessarily 00088 * what the user/programmer wants. Or: 00089 * It's a deprecated feature, or one 00090 * that might be incompatible with 00091 * other standard tokenizers. 00092 * INFO Nothing is changed in processing, but 00093 * an advisory is still in order. 00094 * MESSAGE Message generated by the user. (Complete; 00095 * new-line will be added by display routine.) 00096 * P_MESSAGE Partial Message -- Instigated by user, but 00097 * pre-formatted and not complete. New-line 00098 * will be added by follow-up routine. 00099 * 00100 **************************************************************************** */ 00101 00102 #include <stdio.h> 00103 #include <stdarg.h> 00104 #include <stdlib.h> 00105 #include <string.h> 00106 #include <errno.h> 00107 00108 #include "types.h" 00109 #include "toke.h" 00110 #include "stream.h" 00111 #include "errhandler.h" 00112 #include "scanner.h" 00113 00114 /* ************************************************************************** 00115 * 00116 * Global Variables Imported 00117 * iname Name of file currently being processed 00118 * lineno Current line-number being processed 00119 * noerrors "Ignore Errors" flag, set by "-i" switch 00120 * opc FCode Output Buffer Position Counter 00121 * verbose If true, enable Advisory Messages 00122 * 00123 **************************************************************************** */ 00124 00125 /* ************************************************************************** 00126 * 00127 * Internal Static Variables 00128 * print_msg Whether beginning of a message was printed; 00129 * therefore, whether to print the rest. 00130 * errs_to_print Error Verbosity Mask. Bits set correspond 00131 * to message-types that will be printed 00132 * May be altered by Command-Line switches. 00133 * err_types_found Accumulated Error-types. Bits 00134 * set correspond to error-types 00135 * that have occurred. 00136 * message_dest Message Dest'n. Usually ERRMSG_DESTINATION 00137 * (stdout) except when we need to switch. 00138 * err_count Count of Error Messages 00139 * warn_count Count of Warning Messages 00140 * info_count Count of "Advisory" Messages 00141 * user_msg_count Count of User-generated Messages 00142 * fatal_err_exit Exit code to be used for "Fatal" error. 00143 * This is a special accommodation 00144 * for the safe_malloc routine. 00145 * 00146 **************************************************************************** */ 00147 00148 static bool print_msg ; 00149 static int errs_to_print = ( FATAL | TKERROR | WARNING | 00150 MESSAGE | P_MESSAGE | FORCE_MSG ) ; 00151 static int err_types_found = 0 ; 00152 static int err_count = 0 ; 00153 static int warn_count = 0 ; 00154 static int info_count = 0 ; 00155 static int user_msg_count = 0 ; 00156 static int fatal_err_exit = -1 ; 00157 static FILE *message_dest; /* Would like to init to ERRMSG_DESTINATION 00158 * here, but the compiler complains... 00159 */ 00160 00161 /* ************************************************************************** 00162 * 00163 * Internal Static Constant Structure 00164 * err_category Correlate each error-type code with its 00165 * Counter-variable and the printable 00166 * form of its name. 00167 * num_categories Number of entries in the err_category table 00168 * 00169 **************************************************************************** */ 00170 00171 typedef struct { 00172 int type_bit ; /* Error-type single-bit code */ 00173 char *category_name ; /* Printable-name base */ 00174 char *single ; /* Suffix to print singular of name */ 00175 char *plural ; /* Suffix to print plural of name */ 00176 int *counter ; /* Associated Counter-variable */ 00177 bool new_line ; /* Whether to print new-line at end */ 00178 } err_category ; 00179 00180 static const err_category error_categories[] = { 00181 /* FATAL must be the first entry in the table. */ 00182 /* No plural is needed; only one is allowed.... */ 00183 { FATAL, "Fatal Error", "", "", &err_count , TRUE }, 00184 00185 { TKERROR, "Error" , "", "s", &err_count , FALSE }, 00186 { WARNING, "Warning" , "", "s", &warn_count , FALSE }, 00187 { INFO, "Advisor" , "y", "ies", &info_count , FALSE }, 00188 { MESSAGE , "Message" , "", "s", &user_msg_count , TRUE }, 00189 { P_MESSAGE , "Message" , "", "s", &user_msg_count , FALSE } 00190 }; 00191 00192 static const int num_categories = 00193 ( sizeof(error_categories) / sizeof(err_category) ); 00194 00195 00196 #ifdef NEEDS_STRUPR 00197 00198 /* ************************************************************************** 00199 * 00200 * Function name: toup 00201 * Synopsis: Support function for strupper 00202 * Converts one character 00203 * 00204 * Inputs: 00205 * Parameters: 00206 * chr_ptr Pointer to the character 00207 * 00208 * Outputs: 00209 * Returned Value: None 00210 * Supplied Pointers: 00211 * The character pointed to is changed 00212 * 00213 * Process Explanation: 00214 * Because this fills in a lack in the host system, we cannot 00215 * rely on the functions islower or toupper , which are 00216 * usually built-in but might be similarly missing. 00217 * 00218 **************************************************************************** */ 00219 00220 static void toup( char *chr_ptr) 00221 { 00222 const unsigned char upcas_diff = ( 'a' - 'A' ); 00223 if ( ( *chr_ptr >= 'a' ) && ( *chr_ptr <= 'z' ) ) 00224 { 00225 *chr_ptr -= upcas_diff ; 00226 } 00227 } 00228 00229 /* ************************************************************************** 00230 * 00231 * Function name: strupper 00232 * Synopsis: Replacement for strupr on systems that don't 00233 * seem to have it. A necessary hack. 00234 * 00235 * Inputs: 00236 * Parameters: 00237 * strung Pointer to the string to be changed 00238 * 00239 * Outputs: 00240 * Returned Value: Same pointer that was passed in 00241 * Supplied Pointers: 00242 * The string pointed to will be converted to upper case 00243 * 00244 * Process Explanation: 00245 * Because it fills in a lack in the host system, this routine 00246 * does not rely on the functions islower or toupper 00247 * which are usually built-in but might be missing. 00248 * 00249 **************************************************************************** */ 00250 00251 char *strupper( char *strung) 00252 { 00253 char *strindx; 00254 for (strindx = strung; *strindx != 0; strindx++) 00255 { 00256 toup( strindx); 00257 } 00258 return strung; 00259 } 00260 00261 /* ************************************************************************** 00262 * 00263 * If strupr is missing, it's a good bet that so is strlwr 00264 * 00265 **************************************************************************** */ 00266 00267 /* ************************************************************************** 00268 * 00269 * Function name: tolow 00270 * Synopsis: Support function for strlower 00271 * Converts one character 00272 * 00273 * Inputs: 00274 * Parameters: 00275 * chr_ptr Pointer to the character 00276 * 00277 * Outputs: 00278 * Returned Value: None 00279 * Supplied Pointers: 00280 * The character pointed to is changed 00281 * 00282 * Process Explanation: 00283 * Because this fills in a lack in the host system, we cannot 00284 * rely on the functions isupper or tolower , which are 00285 * usually built-in but might be similarly missing. 00286 * 00287 **************************************************************************** */ 00288 00289 static void tolow( char *chr_ptr) 00290 { 00291 const unsigned char lowcas_diff = ( 'A' - 'a' ); 00292 if ( ( *chr_ptr >= 'A' ) && ( *chr_ptr <= 'Z' ) ) 00293 { 00294 *chr_ptr -= lowcas_diff ; 00295 } 00296 } 00297 00298 /* ************************************************************************** 00299 * 00300 * Function name: strlower 00301 * Synopsis: Replacement for strlwr on systems that don't 00302 * seem to have it. A necessary hack. 00303 * 00304 * Inputs: 00305 * Parameters: 00306 * strung Pointer to the string to be changed 00307 * 00308 * Outputs: 00309 * Returned Value: Same pointer that was passed in 00310 * Supplied Pointers: 00311 * The string pointed to will be converted to lower case 00312 * 00313 * Process Explanation: 00314 * Because it fills in a lack in the host system, this routine 00315 * does not rely on the functions isupper or tolower 00316 * which are usually built-in but might be missing. 00317 * 00318 **************************************************************************** */ 00319 00320 char *strlower( char *strung) 00321 { 00322 char *strindx; 00323 for (strindx = strung; *strindx != 0; strindx++) 00324 { 00325 tolow( strindx); 00326 } 00327 return strung; 00328 } 00329 00330 00331 #endif /* NEEDS_STRUPR */ 00332 00333 /* ************************************************************************** 00334 * 00335 * Function name: init_error_handler 00336 * Synopsis: Initialize the error-handler before starting a 00337 * new tokenization; both the aspects that will 00338 * persist across the entire run and those that 00339 * need to be reset, such as error-counts. 00340 * 00341 * Inputs: 00342 * Parameters: NONE 00343 * Global Variables: 00344 * verbose Set by "-v" switch 00345 * Macro: 00346 * ERRMSG_DESTINATION Error message destination; 00347 * (Set by development-time switch) 00348 * FFLUSH_STDOUT Flush STDOUT if err-msg-dest is STDERR 00349 * 00350 * Outputs: 00351 * Returned Value: NONE 00352 * Global Variables: 00353 * errs_to_print Add the INFO bit if verbose is set 00354 * Local Static Variables: 00355 * message_dest Point it at ERRMSG_DESTINATION (stderr) 00356 * Reset the following to zero: 00357 * err_types_found Accumulated Error-types. 00358 * err_count Count of Error Messages 00359 * warn_count Count of Warning Messages 00360 * info_count Count of "Advisory" Messages 00361 * user_msg_count Count of User-generated Messages 00362 * Other Exotic Effects: 00363 * Flush stdout if Error message destination is not stdout, to 00364 * avoid collisions with stderr once Error Messaging begins. 00365 * 00366 * Extraneous Remarks: 00367 * This needs to be done before attempting to read the input file, 00368 * so that any Messages that occur there can be properly counted. 00369 * 00370 **************************************************************************** */ 00371 00372 void init_error_handler( void) 00373 { 00374 message_dest = ERRMSG_DESTINATION; 00375 if ( verbose ) errs_to_print |= INFO ; 00376 err_types_found = 0 ; 00377 err_count = 0 ; 00378 warn_count = 0 ; 00379 info_count = 0 ; 00380 user_msg_count = 0 ; 00381 FFLUSH_STDOUT 00382 } 00383 00384 /* ************************************************************************** 00385 * 00386 * Function name: tokenization_error 00387 * Synopsis: Handle an error of the given class, 00388 * print the given message in the standard format. 00389 * 00390 * Inputs: 00391 * Parameters: 00392 * err_type int One of the bit-valued error-types 00393 * The remaining parameters are a format string and corresponding 00394 * data objects such as would be sent to printf() 00395 * Global Variables: 00396 * errs_to_print Error Verbosity Mask. 00397 * iname Name of file currently being processed 00398 * lineno Current line-number being processed 00399 * fatal_err_exit Exit code for "Fatal" error, if applicable. 00400 * Macro: 00401 * ERRMSG_DESTINATION Error message destination; 00402 * (Development-time switch) 00403 * Note: Whether this routine will or will not supply a new-line 00404 * at the end of the printout depends on the category of the 00405 * message. The new-line is included for a FATAL or a User- 00406 * Generated Message, and excluded for the rest. For those, 00407 * the calling routine must be responsible for including a 00408 * new-line at the end of the format string or for otherwise 00409 * finishing the line, as by calling started_at() 00410 * 00411 * Outputs: 00412 * Returned Value: NONE 00413 * Local Static Variables: 00414 * err_types_found Accumulated Error-types. 00415 * print_msg Whether this message was printed; 00416 * may be used by started_at() 00417 * One of the following Category Counters 00418 * will be incremented, as applicable: 00419 * err_count 00420 * warn_count 00421 * info_count 00422 * user_msg_count 00423 * Printout: Directed to stdout or stderr 00424 * (see definition of ERRMSG_DESTINATION) 00425 * 00426 * Error Detection: 00427 * Err_type not in list 00428 * Print special message; treat cause as an Error. 00429 * Force printout. 00430 * 00431 * Process Explanation: 00432 * Accumulated the Error-type into err_types_found 00433 * Identify the Error-Category: 00434 * Check the Error-Type against the bit-code. 00435 * The Error-type may have more than one bit set, 00436 * but if it matches the Category bit-code, it's it. 00437 * If it doesn't match any Error-Category bit-code, print 00438 * a special message and treat it as an ERROR code. 00439 * Check the Error-Type against the Error Verbosity Mask; 00440 * If it has a bit set, print the Error-Category, together 00441 * with the source-file name and line number, and 00442 * the rest of the message as supplied. 00443 * The table that translates the Error-type into a printable 00444 * Error-Category string also identifies the applicable 00445 * Category Counter; increment it. 00446 * Of course, there's no return from a FATAL error; it exits. 00447 * 00448 **************************************************************************** */ 00449 00450 void tokenization_error( int err_type, char* msg, ... ) 00451 { 00452 int indx ; 00453 00454 /* Initial settings: treat as an Error. */ 00455 char *catgy_name = "Error"; 00456 char *catgy_suffx = ""; 00457 int *catgy_counter = &err_count; 00458 bool print_new_line = FALSE; 00459 00460 /* Accumulated the Error-type into err_types_found */ 00461 err_types_found |= err_type; 00462 00463 /* Identify the Error-Category. */ 00464 for ( indx = 0 ; indx < num_categories ; indx ++ ) 00465 { 00466 if ( ( error_categories[indx].type_bit & err_type ) != 0 ) 00467 { 00468 catgy_name = error_categories[indx].category_name; 00469 catgy_suffx = error_categories[indx].single; 00470 catgy_counter = error_categories[indx].counter; 00471 print_new_line = error_categories[indx].new_line; 00472 break; 00473 } 00474 } 00475 00476 /* Special message if err_type not in list; treat as an Error. */ 00477 if ( catgy_name == NULL ) 00478 { 00479 fprintf(ERRMSG_DESTINATION, 00480 "Program error: Unknown Error-Type, 0x%08x. " 00481 " Will treat as Error.\n", err_type) ; 00482 err_types_found |= TKERROR; 00483 print_msg = TRUE ; 00484 } else { 00485 /* Check the Error-Type against the Error Verbosity Mask */ 00486 print_msg = BOOLVAL( ( errs_to_print & err_type ) != 0 ); 00487 } 00488 00489 if ( print_msg ) 00490 { 00491 va_list argp; 00492 00493 if ( iname != NULL ) 00494 { 00495 fprintf(ERRMSG_DESTINATION, "%s%s: File %s, Line %d. ", 00496 catgy_name, catgy_suffx, iname, lineno); 00497 }else{ 00498 /* Don't print iname or lineno if no file opened. */ 00499 fprintf(ERRMSG_DESTINATION, "%s%s: ", 00500 catgy_name, catgy_suffx); 00501 } 00502 00503 va_start(argp, msg); 00504 vfprintf(ERRMSG_DESTINATION, msg, argp); 00505 va_end(argp); 00506 if ( print_new_line ) fprintf(ERRMSG_DESTINATION, "\n"); 00507 00508 /* Increment the category-counter. */ 00509 *catgy_counter += 1; 00510 } 00511 if ( err_type == FATAL ) 00512 { 00513 fprintf(ERRMSG_DESTINATION, "Tokenization terminating.\n"); 00514 error_summary(); 00515 exit ( fatal_err_exit ); 00516 } 00517 } 00518 00519 /* ************************************************************************** 00520 * 00521 * Function name: print_where_started 00522 * Synopsis: Supplemental message, following a tokenization_error, 00523 * giving a back-reference to the "start" point of 00524 * the compound-error being reported. 00525 * This is a retro-fit; it does the heavy lifting for 00526 * the routines started_at() , just_started_at() , 00527 * where_started() , just_where_started() and 00528 * in_last_colon() . 00529 * 00530 * Inputs: 00531 * Parameters: 00532 * show_started Whether to print a phrase about "started" 00533 * show_that_st Whether to print "that started" as opposed 00534 * to " , which started" 00535 * saved_ifile File-name saved for "back-reference" 00536 * saved_lineno Line-number saved for "back-reference" 00537 * may_show_incolon Whether to allow a call to in_last_colon() 00538 * Needed to prevent infinite recursion... 00539 * Global Variables: 00540 * iname Name of file currently being processed 00541 * lineno Current line-number being processed 00542 * Local Static Variables: 00543 * print_msg Whether the beginning part of the message 00544 * was printed by tokenization_error() 00545 * message_dest Message Destination. Is ERRMSG_DESTINATION 00546 * (stdout) usually, except sometimes... 00547 * 00548 * Outputs: 00549 * Returned Value: None 00550 * Printout: 00551 * The remainder of a message: the location of a back-reference. 00552 * The phrase "that started" is switchable. This routine 00553 * will supply the leading space and a new-line; the routines 00554 * that call this can be used to finish the line. 00555 * 00556 * Process Explanation: 00557 * This routine is called immediately after tokenization_error() 00558 * If tokenization_error() didn't print, neither will we. 00559 * The residual state of print_msg will tell us that. 00560 * If the preceding message ended with something general about a 00561 * "Colon Definition" or "Device-Node" or the like, we want 00562 * the message to read: "that started on line ... [in file ...]" 00563 * If the end of the preceding message was something more specific, 00564 * we just want the message to read: "on line ... [in file ...]" 00565 * If the saved input file name doesn't match our current input 00566 * file name, we will print it and the saved line-number. 00567 * If the file name hasn't changed, we will print only the saved 00568 * line-number. 00569 * If neither is changed, there's no point in printing any of the 00570 * above-mentioned text. 00571 * If a Colon-definition is in progress, show its name and the 00572 * line on which it started. Protect against infinite loop! 00573 * End the line. 00574 * 00575 * Extraneous Remarks: 00576 * This is a retrofit. Earlier, it was just started_at() . Later, 00577 * I generated more specific messages, and needed a way to leave 00578 * out the "that started". I could, theoretically, have added 00579 * the extra parameter to started_at() , but by now there are 00580 * so many of calls to it that I'd rather leave them as is, and 00581 * just change the name of the routine in the few places that 00582 * need the terser form of the message. 00583 * 00584 **************************************************************************** */ 00585 00586 static void print_where_started( bool show_started, 00587 bool show_that_st, 00588 char * saved_ifile, 00589 unsigned int saved_lineno, 00590 bool may_show_incolon) 00591 { 00592 if ( print_msg ) 00593 { 00594 bool fil_is_diff; 00595 bool lin_is_diff; 00596 00597 /* File names are case-sensitive */ 00598 fil_is_diff = BOOLVAL(strcmp(saved_ifile, iname) != 0 ); 00599 lin_is_diff = BOOLVAL(saved_lineno != lineno ); 00600 if ( fil_is_diff || lin_is_diff ) 00601 { 00602 if ( show_started ) 00603 { 00604 if ( show_that_st ) 00605 { 00606 fprintf(message_dest, " that"); 00607 }else{ 00608 fprintf(message_dest, " , which"); 00609 } 00610 fprintf(message_dest, " started"); 00611 } 00612 fprintf(message_dest, " on line %d", saved_lineno); 00613 if ( fil_is_diff ) 00614 { 00615 fprintf(message_dest, " of file %s", saved_ifile); 00616 } 00617 } 00618 00619 if ( may_show_incolon ) 00620 { 00621 in_last_colon(); 00622 }else{ 00623 fprintf(message_dest, "\n"); 00624 } 00625 } 00626 } 00627 00628 /* ************************************************************************** 00629 * 00630 * Function name: started_at 00631 * Synopsis: Supplemental back-reference message, 00632 * with the "that started" phrase, 00633 * and with last-colon identification. 00634 * 00635 * Inputs: 00636 * Parameters: 00637 * saved_ifile File-name saved for "back-reference" 00638 * saved_lineno Line-number saved for "back-reference" 00639 * 00640 * Outputs: 00641 * Returned Value: None 00642 * Global Variables: 00643 * Printout: 00644 * The "...started at..." remainder of a message, giving a back- 00645 * -reference to the "start" point supplied in the params, 00646 * and the start of the current Colon-definition if one is 00647 * in effect. 00648 * Will supply a new-line and can be used to finish the line. 00649 * 00650 **************************************************************************** */ 00651 00652 void started_at( char * saved_ifile, unsigned int saved_lineno) 00653 { 00654 print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, TRUE); 00655 } 00656 00657 00658 /* ************************************************************************** 00659 * 00660 * Function name: print_started_at 00661 * Synopsis: Same as started_at() except output will be directed 00662 * to stdout instead of to ERRMSG_DESTINATION 00663 * 00664 * Extraneous Remarks: 00665 * A retrofit. Can you tell? 00666 * 00667 **************************************************************************** */ 00668 00669 void print_started_at( char * saved_ifile, unsigned int saved_lineno) 00670 { 00671 message_dest = stdout; 00672 started_at( saved_ifile, saved_lineno); 00673 message_dest = ERRMSG_DESTINATION; 00674 } 00675 00676 00677 /* ************************************************************************** 00678 * 00679 * Function name: just_started_at 00680 * Synopsis: Supplemental back-reference message, 00681 * with the "that started" phrase, 00682 * but without last-colon identification. 00683 * 00684 * Inputs: 00685 * Parameters: 00686 * saved_ifile File-name saved for "back-reference" 00687 * saved_lineno Line-number saved for "back-reference" 00688 * 00689 * Outputs: 00690 * Returned Value: None 00691 * Global Variables: 00692 * Printout: 00693 * The "...started at..." remainder of a message, giving a back- 00694 * -reference to the "start" point supplied in the params, 00695 * and no more. 00696 * Will supply a new-line and can be used to finish the line. 00697 * 00698 **************************************************************************** */ 00699 00700 void just_started_at( char * saved_ifile, unsigned int saved_lineno) 00701 { 00702 print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, FALSE); 00703 } 00704 00705 /* ************************************************************************** 00706 * 00707 * Function name: where_started 00708 * Synopsis: Supplemental back-reference message, 00709 * without the "that started" phrase, 00710 * but with last-colon identification. 00711 * 00712 * Inputs: 00713 * Parameters: 00714 * saved_ifile File-name saved for "back-reference" 00715 * saved_lineno Line-number saved for "back-reference" 00716 * 00717 * Outputs: 00718 * Returned Value: None 00719 * Global Variables: 00720 * Printout: 00721 * The remainder of a message, giving a back-reference to the 00722 * "start" point supplied in the parameters, and the start 00723 * of the current Colon-definition if one is in effect. 00724 * Will supply a new-line and can be used to finish the line. 00725 * 00726 **************************************************************************** */ 00727 00728 void where_started( char * saved_ifile, unsigned int saved_lineno) 00729 { 00730 print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, TRUE); 00731 } 00732 00733 /* ************************************************************************** 00734 * 00735 * Function name: just_where_started 00736 * Synopsis: Supplemental back-reference message, 00737 * without the "that started" phrase, 00738 * and without last-colon identification. 00739 * 00740 * Inputs: 00741 * Parameters: 00742 * saved_ifile File-name saved for "back-reference" 00743 * saved_lineno Line-number saved for "back-reference" 00744 * 00745 * Outputs: 00746 * Returned Value: None 00747 * Global Variables: 00748 * Printout: 00749 * The remainder of a message, giving a back-reference to the 00750 * "start" point supplied in the parameters, and no more. 00751 * Will supply a new-line and can be used to finish the line. 00752 * 00753 **************************************************************************** */ 00754 00755 void just_where_started( char * saved_ifile, unsigned int saved_lineno) 00756 { 00757 print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, FALSE); 00758 } 00759 00760 /* ************************************************************************** 00761 * 00762 * Function name: in_last_colon 00763 * Synopsis: Supplemental back-reference message, identifying 00764 * last Colon-definition if one is in effect. 00765 * Can be used to finish the line in either case. 00766 * 00767 * Inputs: 00768 * Parameters: NONE 00769 * Global Variables: 00770 * incolon TRUE if Colon-definition is in progress 00771 * last_colon_defname Name of last colon-definition 00772 * last_colon_filename File where last colon-def'n made 00773 * last_colon_lineno Line number of last colon-def'n 00774 * Local Static Variables: 00775 * print_msg Whether the beginning part of the message 00776 * was printed by tokenization_error() 00777 * message_dest Message Destination. Is ERRMSG_DESTINATION 00778 * (stdout) usually, except sometimes... 00779 * 00780 * Outputs: 00781 * Returned Value: NONE 00782 * Printout: 00783 * Remainder of a message: 00784 * "in definition of ... , which started ..." 00785 * 00786 * Process Explanation: 00787 * Because this routine does some of its own printing, it needs 00788 * to check the residual state of print_msg first. 00789 * The calling routine does not need to test incolon ; it can 00790 * call this to end the line in either case. 00791 * 00792 **************************************************************************** */ 00793 00794 void in_last_colon( void ) 00795 { 00796 if ( print_msg ) 00797 { 00798 if ( incolon ) 00799 { 00800 fprintf( message_dest, " in definition of %s ", 00801 strupr( last_colon_defname) ); 00802 print_where_started( TRUE, FALSE, 00803 last_colon_filename, last_colon_lineno, FALSE); 00804 }else{ 00805 fprintf(message_dest, "\n"); 00806 } 00807 } 00808 } 00809 00810 00811 /* ************************************************************************** 00812 * 00813 * Function name: safe_malloc 00814 * Synopsis: malloc with built-in failure test. 00815 * 00816 * Inputs: 00817 * Parameters: 00818 * size size_t Size of memory-chunk to allocate 00819 * phrase char * Phrase to print after "... while " 00820 * in case of failure. 00821 * 00822 * Outputs: 00823 * Returned Value: Pointer to allocated memory 00824 * Global Variables: 00825 * fatal_err_exit On memory allocation failure, change 00826 * to a special system-defined value 00827 * 00828 * Error Detection: 00829 * On memory allocation failure, declare a FATAL error. Set up 00830 * for a special system-defined EXIT value that indicates 00831 * insufficient memory. 00832 * 00833 * Process Explanation: 00834 * It is the responsibility of the calling routine to be sure 00835 * the "phrase" is unique within the program. It is intended 00836 * as a debugging aid, to help localize the point of failure. 00837 * 00838 **************************************************************************** */ 00839 00840 _PTR safe_malloc( size_t size, char *phrase) 00841 { 00842 _PTR retval ; 00843 retval = malloc (size); 00844 if ( !retval ) 00845 { 00846 fatal_err_exit = -ENOMEM ; 00847 tokenization_error( FATAL, "Out of memory while %s.", phrase); 00848 } 00849 return ( retval ); 00850 } 00851 00852 /* ************************************************************************** 00853 * 00854 * Function name: error_summary 00855 * Synopsis: Summarize final error-message status 00856 * before completing tokenization. 00857 * Indicate if OK to produce output. 00858 * 00859 * Inputs: 00860 * Parameters: NONE 00861 * Global Variables: 00862 * noerrors "Ignore Errors" flag, set by "-i" switch 00863 * err_types_found Accumulated Error-types. 00864 * error_categories Table of Error-types, Message-Counters 00865 * and their printable names. 00866 * opc FCode Output Buffer Position Counter 00867 * (zero means there was no output). 00868 * 00869 * Outputs: 00870 * Returned Value: True = OK to produce output (But caller 00871 * must still verify non-zero opc) 00872 * Printout: 00873 * Various messages. 00874 * 00875 * Process Explanation: 00876 * The first entry in the error_categories table is FATAL 00877 * We won't need to print a tally of that... 00878 * 00879 **************************************************************************** */ 00880 00881 bool error_summary( void ) 00882 { 00883 /* Bit-mask of error-types that require suppressing output */ 00884 static const int suppress_mask = ( FATAL | TKERROR ); 00885 bool retval = TRUE; 00886 bool suppressing = FALSE; 00887 00888 /* There's no escaping a FATAL error */ 00889 if ( ( err_types_found & FATAL ) != 0 ) 00890 { 00891 /* FATAL error. Don't even bother with the tally. */ 00892 suppressing = TRUE; 00893 } else { 00894 00895 if ( opc == 0 ) 00896 { 00897 printf ( "Nothing Tokenized"); 00898 }else{ 00899 printf ( "Tokenization Completed"); 00900 } 00901 00902 if ( err_types_found != 0 ) 00903 { 00904 int indx; 00905 bool tally_started = FALSE ; 00906 printf (". "); 00907 /* 00908 * Print a tally of the error-types; 00909 * handle plurals and punctuation appropriately. 00910 */ 00911 /* Start at indx = 1 to skip examining FATALs */ 00912 for ( indx = 1; indx < num_categories ; indx ++ ) 00913 { 00914 if ( *(error_categories[indx].counter) > 0 ) 00915 { 00916 printf ("%s %d %s%s", 00917 tally_started ? "," : "" , 00918 *(error_categories[indx].counter), 00919 error_categories[indx].category_name, 00920 *(error_categories[indx].counter) > 1 ? 00921 error_categories[indx].plural : 00922 error_categories[indx].single ); 00923 /* Zero out the counter, to prevent displaying the 00924 * number of Messages twice, since it's shared 00925 * by the "Messages" and "P_Messages" categories. 00926 */ 00927 *(error_categories[indx].counter) = 0; 00928 tally_started = TRUE; 00929 } 00930 } 00931 } 00932 printf (".\n"); 00933 00934 if ( ( err_types_found & suppress_mask ) != 0 ) 00935 { /* Errors found. Not OK to produce output */ 00936 /* Unless "Ignore Errors" flag set... */ 00937 if ( INVERSE(noerrors) ) 00938 { 00939 suppressing = TRUE; 00940 }else{ 00941 if ( opc > 0 ) 00942 { 00943 printf ("Error-detection over-ridden; " 00944 "producing binary output.\n"); 00945 } 00946 } 00947 } 00948 } 00949 if ( suppressing ) 00950 { 00951 retval = FALSE ; 00952 printf ("Suppressing binary output.\n"); 00953 } 00954 return ( retval ); 00955 } 00956