Main Page | Data Structures | File List | Data Fields | Globals

errhandler.c

Go to the documentation of this file.
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 

Generated on Fri Aug 18 14:03:39 2006 for Toke1.0 by  doxygen 1.4.4