1 : /*
2 : * OpenBIOS - free your system!
3 : * ( FCode tokenizer )
4 : *
5 : * This program is part of a free implementation of the IEEE 1275-1994
6 : * Standard for Boot (Initialization Configuration) Firmware.
7 : *
8 : * Copyright (C) 2001-2005 Stefan Reinauer, <stepan@openbios.org>
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; version 2 of the License.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program; if not, write to the Free Software
21 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
22 : *
23 : */
24 :
25 : /* **************************************************************************
26 : *
27 : * Error-Handler for Tokenizer
28 : *
29 : * Controls printing of various classes of errors
30 : *
31 : * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
32 : * Module Author: David L. Paktor dlpaktor@us.ibm.com
33 : *
34 : **************************************************************************** */
35 :
36 : /* **************************************************************************
37 : *
38 : * Functions Exported:
39 : * init_error_handler Initialize the error-counts,
40 : * announce the file names.
41 : * tokenization_error Handle an error of the given class,
42 : * print the given message in the
43 : * standard format.
44 : * started_at Supplemental message, giving a back-reference
45 : * to the "starting" point of a compound
46 : * error, including last-colon identification.
47 : * just_started_at Supplemental back-reference to "starting" point
48 : * of compound error, but without last-colon
49 : * identification.
50 : * where_started Supplemental message, giving a more terse back-
51 : * -reference to "start" of compound-error.
52 : * just_where_started Supplemental message, more terse back-reference,
53 : * without last-colon identification.
54 : * in_last_colon Supplemental back-reference message,
55 : * identifying last Colon-definition.
56 : * safe_malloc malloc with built-in failure test.
57 : * error_summary Summarize final error-message status
58 : * before completing tokenization.
59 : *
60 : **************************************************************************** */
61 :
62 :
63 : /* **************************************************************************
64 : *
65 : * We will define a set of bit-valued error-types and a
66 : * global bit-mask. Each error-message will be associated
67 : * with one of the bit-valued error-types. The bit-mask,
68 : * which will be set by a combination of defaults and user
69 : * inputs (mainly command-line arguments), will control
70 : * whether an error-message of any given type is printed.
71 : *
72 : * Another bit-mask variable will accumulate the error-
73 : * types that occur within any given run; at the end of
74 : * the run, it will be examined to determine if the run
75 : * failed, i.e., if the output should be suppressed.
76 : *
77 : **************************************************************************** */
78 :
79 : /* **************************************************************************
80 : *
81 : * Error-types fall into the following broad categories:
82 : * FATAL Cause to immediately stop activity
83 : * TKERROR Sufficient to make the run a failure,
84 : * but not to stop activity.
85 : * WARNING Not necessarily an error, but something
86 : * to avoid. E.g., it might rely on
87 : * assumptions that are not necessarily
88 : * what the user/programmer wants. Or:
89 : * It's a deprecated feature, or one
90 : * that might be incompatible with
91 : * other standard tokenizers.
92 : * INFO Nothing is changed in processing, but
93 : * an advisory is still in order.
94 : * MESSAGE Message generated by the user. (Complete;
95 : * new-line will be added by display routine.)
96 : * P_MESSAGE Partial Message -- Instigated by user, but
97 : * pre-formatted and not complete. New-line
98 : * will be added by follow-up routine.
99 : *
100 : **************************************************************************** */
101 :
102 : #include <stdio.h>
103 : #include <stdarg.h>
104 : #include <stdlib.h>
105 : #include <string.h>
106 : #include <errno.h>
107 :
108 : #include "types.h"
109 : #include "toke.h"
110 : #include "stream.h"
111 : #include "errhandler.h"
112 : #include "scanner.h"
113 :
114 : /* **************************************************************************
115 : *
116 : * Global Variables Imported
117 : * iname Name of file currently being processed
118 : * lineno Current line-number being processed
119 : * noerrors "Ignore Errors" flag, set by "-i" switch
120 : * opc FCode Output Buffer Position Counter
121 : * verbose If true, enable Advisory Messages
122 : *
123 : **************************************************************************** */
124 :
125 : /* **************************************************************************
126 : *
127 : * Internal Static Variables
128 : * print_msg Whether beginning of a message was printed;
129 : * therefore, whether to print the rest.
130 : * errs_to_print Error Verbosity Mask. Bits set correspond
131 : * to message-types that will be printed
132 : * May be altered by Command-Line switches.
133 : * err_types_found Accumulated Error-types. Bits
134 : * set correspond to error-types
135 : * that have occurred.
136 : * message_dest Message Dest'n. Usually ERRMSG_DESTINATION
137 : * (stdout) except when we need to switch.
138 : * err_count Count of Error Messages
139 : * warn_count Count of Warning Messages
140 : * info_count Count of "Advisory" Messages
141 : * user_msg_count Count of User-generated Messages
142 : * fatal_err_exit Exit code to be used for "Fatal" error.
143 : * This is a special accommodation
144 : * for the safe_malloc routine.
145 : *
146 : **************************************************************************** */
147 :
148 : static bool print_msg ;
149 : static int errs_to_print = ( FATAL | TKERROR | WARNING |
150 : MESSAGE | P_MESSAGE | FORCE_MSG ) ;
151 : static int err_types_found = 0 ;
152 : static int err_count = 0 ;
153 : static int warn_count = 0 ;
154 : static int info_count = 0 ;
155 : static int user_msg_count = 0 ;
156 : static int fatal_err_exit = -1 ;
157 : static FILE *message_dest; /* Would like to init to ERRMSG_DESTINATION
158 : * here, but the compiler complains...
159 : */
160 :
161 : /* **************************************************************************
162 : *
163 : * Internal Static Constant Structure
164 : * err_category Correlate each error-type code with its
165 : * Counter-variable and the printable
166 : * form of its name.
167 : * num_categories Number of entries in the err_category table
168 : *
169 : **************************************************************************** */
170 :
171 : typedef struct {
172 : int type_bit ; /* Error-type single-bit code */
173 : char *category_name ; /* Printable-name base */
174 : char *single ; /* Suffix to print singular of name */
175 : char *plural ; /* Suffix to print plural of name */
176 : int *counter ; /* Associated Counter-variable */
177 : bool new_line ; /* Whether to print new-line at end */
178 : } err_category ;
179 :
180 : static const err_category error_categories[] = {
181 : /* FATAL must be the first entry in the table. */
182 : /* No plural is needed; only one is allowed.... */
183 : { FATAL, "Fatal Error", "", "", &err_count , TRUE },
184 :
185 : { TKERROR, "Error" , "", "s", &err_count , FALSE },
186 : { WARNING, "Warning" , "", "s", &warn_count , FALSE },
187 : { INFO, "Advisor" , "y", "ies", &info_count , FALSE },
188 : { MESSAGE , "Message" , "", "s", &user_msg_count , TRUE },
189 : { P_MESSAGE , "Message" , "", "s", &user_msg_count , FALSE }
190 : };
191 :
192 : static const int num_categories =
193 : ( sizeof(error_categories) / sizeof(err_category) );
194 :
195 :
196 : #ifdef NEEDS_STRUPR
197 :
198 : /* **************************************************************************
199 : *
200 : * Function name: toup
201 : * Synopsis: Support function for strupper
202 : * Converts one character
203 : *
204 : * Inputs:
205 : * Parameters:
206 : * chr_ptr Pointer to the character
207 : *
208 : * Outputs:
209 : * Returned Value: None
210 : * Supplied Pointers:
211 : * The character pointed to is changed
212 : *
213 : * Process Explanation:
214 : * Because this fills in a lack in the host system, we cannot
215 : * rely on the functions islower or toupper , which are
216 : * usually built-in but might be similarly missing.
217 : *
218 : **************************************************************************** */
219 :
220 : static void toup( char *chr_ptr)
221 11222 : {
222 11222 : const unsigned char upcas_diff = ( 'a' - 'A' );
223 11222 : if ( ( *chr_ptr >= 'a' ) && ( *chr_ptr <= 'z' ) )
224 : {
225 9053 : *chr_ptr -= upcas_diff ;
226 : }
227 11222 : }
228 :
229 : /* **************************************************************************
230 : *
231 : * Function name: strupper
232 : * Synopsis: Replacement for strupr on systems that don't
233 : * seem to have it. A necessary hack.
234 : *
235 : * Inputs:
236 : * Parameters:
237 : * strung Pointer to the string to be changed
238 : *
239 : * Outputs:
240 : * Returned Value: Same pointer that was passed in
241 : * Supplied Pointers:
242 : * The string pointed to will be converted to upper case
243 : *
244 : * Process Explanation:
245 : * Because it fills in a lack in the host system, this routine
246 : * does not rely on the functions islower or toupper
247 : * which are usually built-in but might be missing.
248 : *
249 : **************************************************************************** */
250 :
251 : char *strupper( char *strung)
252 1477 : {
253 : char *strindx;
254 12699 : for (strindx = strung; *strindx != 0; strindx++)
255 : {
256 11222 : toup( strindx);
257 : }
258 1477 : return strung;
259 : }
260 :
261 : /* **************************************************************************
262 : *
263 : * If strupr is missing, it's a good bet that so is strlwr
264 : *
265 : **************************************************************************** */
266 :
267 : /* **************************************************************************
268 : *
269 : * Function name: tolow
270 : * Synopsis: Support function for strlower
271 : * Converts one character
272 : *
273 : * Inputs:
274 : * Parameters:
275 : * chr_ptr Pointer to the character
276 : *
277 : * Outputs:
278 : * Returned Value: None
279 : * Supplied Pointers:
280 : * The character pointed to is changed
281 : *
282 : * Process Explanation:
283 : * Because this fills in a lack in the host system, we cannot
284 : * rely on the functions isupper or tolower , which are
285 : * usually built-in but might be similarly missing.
286 : *
287 : **************************************************************************** */
288 :
289 : static void tolow( char *chr_ptr)
290 178 : {
291 178 : const unsigned char lowcas_diff = ( 'A' - 'a' );
292 178 : if ( ( *chr_ptr >= 'A' ) && ( *chr_ptr <= 'Z' ) )
293 : {
294 38 : *chr_ptr -= lowcas_diff ;
295 : }
296 178 : }
297 :
298 : /* **************************************************************************
299 : *
300 : * Function name: strlower
301 : * Synopsis: Replacement for strlwr on systems that don't
302 : * seem to have it. A necessary hack.
303 : *
304 : * Inputs:
305 : * Parameters:
306 : * strung Pointer to the string to be changed
307 : *
308 : * Outputs:
309 : * Returned Value: Same pointer that was passed in
310 : * Supplied Pointers:
311 : * The string pointed to will be converted to lower case
312 : *
313 : * Process Explanation:
314 : * Because it fills in a lack in the host system, this routine
315 : * does not rely on the functions isupper or tolower
316 : * which are usually built-in but might be missing.
317 : *
318 : **************************************************************************** */
319 :
320 : char *strlower( char *strung)
321 15 : {
322 : char *strindx;
323 193 : for (strindx = strung; *strindx != 0; strindx++)
324 : {
325 178 : tolow( strindx);
326 : }
327 15 : return strung;
328 : }
329 :
330 :
331 : #endif /* NEEDS_STRUPR */
332 :
333 : /* **************************************************************************
334 : *
335 : * Function name: init_error_handler
336 : * Synopsis: Initialize the error-handler before starting a
337 : * new tokenization; both the aspects that will
338 : * persist across the entire run and those that
339 : * need to be reset, such as error-counts.
340 : *
341 : * Inputs:
342 : * Parameters: NONE
343 : * Global Variables:
344 : * verbose Set by "-v" switch
345 : * Macro:
346 : * ERRMSG_DESTINATION Error message destination;
347 : * (Set by development-time switch)
348 : * FFLUSH_STDOUT Flush STDOUT if err-msg-dest is STDERR
349 : *
350 : * Outputs:
351 : * Returned Value: NONE
352 : * Global Variables:
353 : * errs_to_print Add the INFO bit if verbose is set
354 : * Local Static Variables:
355 : * message_dest Point it at ERRMSG_DESTINATION (stderr)
356 : * Reset the following to zero:
357 : * err_types_found Accumulated Error-types.
358 : * err_count Count of Error Messages
359 : * warn_count Count of Warning Messages
360 : * info_count Count of "Advisory" Messages
361 : * user_msg_count Count of User-generated Messages
362 : * Other Exotic Effects:
363 : * Flush stdout if Error message destination is not stdout, to
364 : * avoid collisions with stderr once Error Messaging begins.
365 : *
366 : * Extraneous Remarks:
367 : * This needs to be done before attempting to read the input file,
368 : * so that any Messages that occur there can be properly counted.
369 : *
370 : **************************************************************************** */
371 :
372 : void init_error_handler( void)
373 171 : {
374 171 : message_dest = ERRMSG_DESTINATION;
375 171 : if ( verbose ) errs_to_print |= INFO ;
376 171 : err_types_found = 0 ;
377 171 : err_count = 0 ;
378 171 : warn_count = 0 ;
379 171 : info_count = 0 ;
380 171 : user_msg_count = 0 ;
381 171 : FFLUSH_STDOUT
382 171 : }
383 :
384 : /* **************************************************************************
385 : *
386 : * Function name: tokenization_error
387 : * Synopsis: Handle an error of the given class,
388 : * print the given message in the standard format.
389 : *
390 : * Inputs:
391 : * Parameters:
392 : * err_type int One of the bit-valued error-types
393 : * The remaining parameters are a format string and corresponding
394 : * data objects such as would be sent to printf()
395 : * Global Variables:
396 : * errs_to_print Error Verbosity Mask.
397 : * iname Name of file currently being processed
398 : * lineno Current line-number being processed
399 : * fatal_err_exit Exit code for "Fatal" error, if applicable.
400 : * Macro:
401 : * ERRMSG_DESTINATION Error message destination;
402 : * (Development-time switch)
403 : * Note: Whether this routine will or will not supply a new-line
404 : * at the end of the printout depends on the category of the
405 : * message. The new-line is included for a FATAL or a User-
406 : * Generated Message, and excluded for the rest. For those,
407 : * the calling routine must be responsible for including a
408 : * new-line at the end of the format string or for otherwise
409 : * finishing the line, as by calling started_at()
410 : *
411 : * Outputs:
412 : * Returned Value: NONE
413 : * Local Static Variables:
414 : * err_types_found Accumulated Error-types.
415 : * print_msg Whether this message was printed;
416 : * may be used by started_at()
417 : * One of the following Category Counters
418 : * will be incremented, as applicable:
419 : * err_count
420 : * warn_count
421 : * info_count
422 : * user_msg_count
423 : * Printout: Directed to stdout or stderr
424 : * (see definition of ERRMSG_DESTINATION)
425 : *
426 : * Error Detection:
427 : * Err_type not in list
428 : * Print special message; treat cause as an Error.
429 : * Force printout.
430 : *
431 : * Process Explanation:
432 : * Accumulated the Error-type into err_types_found
433 : * Identify the Error-Category:
434 : * Check the Error-Type against the bit-code.
435 : * The Error-type may have more than one bit set,
436 : * but if it matches the Category bit-code, it's it.
437 : * If it doesn't match any Error-Category bit-code, print
438 : * a special message and treat it as an ERROR code.
439 : * Check the Error-Type against the Error Verbosity Mask;
440 : * If it has a bit set, print the Error-Category, together
441 : * with the source-file name and line number, and
442 : * the rest of the message as supplied.
443 : * The table that translates the Error-type into a printable
444 : * Error-Category string also identifies the applicable
445 : * Category Counter; increment it.
446 : * Of course, there's no return from a FATAL error; it exits.
447 : *
448 : **************************************************************************** */
449 :
450 : void tokenization_error( int err_type, char* msg, ... )
451 3959 : {
452 : int indx ;
453 :
454 : /* Initial settings: treat as an Error. */
455 3959 : char *catgy_name = "Error";
456 3959 : char *catgy_suffx = "";
457 3959 : int *catgy_counter = &err_count;
458 3959 : bool print_new_line = FALSE;
459 :
460 : /* Accumulated the Error-type into err_types_found */
461 3959 : err_types_found |= err_type;
462 :
463 : /* Identify the Error-Category. */
464 14234 : for ( indx = 0 ; indx < num_categories ; indx ++ )
465 : {
466 14234 : if ( ( error_categories[indx].type_bit & err_type ) != 0 )
467 : {
468 3959 : catgy_name = error_categories[indx].category_name;
469 3959 : catgy_suffx = error_categories[indx].single;
470 3959 : catgy_counter = error_categories[indx].counter;
471 3959 : print_new_line = error_categories[indx].new_line;
472 3959 : break;
473 : }
474 : }
475 :
476 : /* Special message if err_type not in list; treat as an Error. */
477 3959 : if ( catgy_name == NULL )
478 : {
479 0 : fprintf(ERRMSG_DESTINATION,
480 : "Program error: Unknown Error-Type, 0x%08x. "
481 : " Will treat as Error.\n", err_type) ;
482 0 : err_types_found |= TKERROR;
483 0 : print_msg = TRUE ;
484 : } else {
485 : /* Check the Error-Type against the Error Verbosity Mask */
486 3959 : print_msg = BOOLVAL( ( errs_to_print & err_type ) != 0 );
487 : }
488 :
489 3959 : if ( print_msg )
490 : {
491 : va_list argp;
492 :
493 3933 : if ( iname != NULL )
494 : {
495 3889 : fprintf(ERRMSG_DESTINATION, "%s%s: File %s, Line %d. ",
496 : catgy_name, catgy_suffx, iname, lineno);
497 : }else{
498 : /* Don't print iname or lineno if no file opened. */
499 44 : fprintf(ERRMSG_DESTINATION, "%s%s: ",
500 : catgy_name, catgy_suffx);
501 : }
502 :
503 3933 : va_start(argp, msg);
504 3933 : vfprintf(ERRMSG_DESTINATION, msg, argp);
505 3933 : va_end(argp);
506 3933 : if ( print_new_line ) fprintf(ERRMSG_DESTINATION, "\n");
507 :
508 : /* Increment the category-counter. */
509 3933 : *catgy_counter += 1;
510 : }
511 3959 : if ( err_type == FATAL )
512 : {
513 1 : fprintf(ERRMSG_DESTINATION, "Tokenization terminating.\n");
514 1 : error_summary();
515 1 : exit ( fatal_err_exit );
516 : }
517 3958 : }
518 :
519 : /* **************************************************************************
520 : *
521 : * Function name: print_where_started
522 : * Synopsis: Supplemental message, following a tokenization_error,
523 : * giving a back-reference to the "start" point of
524 : * the compound-error being reported.
525 : * This is a retro-fit; it does the heavy lifting for
526 : * the routines started_at() , just_started_at() ,
527 : * where_started() , just_where_started() and
528 : * in_last_colon() .
529 : *
530 : * Inputs:
531 : * Parameters:
532 : * show_started Whether to print a phrase about "started"
533 : * show_that_st Whether to print "that started" as opposed
534 : * to " , which started"
535 : * saved_ifile File-name saved for "back-reference"
536 : * saved_lineno Line-number saved for "back-reference"
537 : * may_show_incolon Whether to allow a call to in_last_colon()
538 : * Needed to prevent infinite recursion...
539 : * Global Variables:
540 : * iname Name of file currently being processed
541 : * lineno Current line-number being processed
542 : * Local Static Variables:
543 : * print_msg Whether the beginning part of the message
544 : * was printed by tokenization_error()
545 : * message_dest Message Destination. Is ERRMSG_DESTINATION
546 : * (stdout) usually, except sometimes...
547 : *
548 : * Outputs:
549 : * Returned Value: None
550 : * Printout:
551 : * The remainder of a message: the location of a back-reference.
552 : * The phrase "that started" is switchable. This routine
553 : * will supply the leading space and a new-line; the routines
554 : * that call this can be used to finish the line.
555 : *
556 : * Process Explanation:
557 : * This routine is called immediately after tokenization_error()
558 : * If tokenization_error() didn't print, neither will we.
559 : * The residual state of print_msg will tell us that.
560 : * If the preceding message ended with something general about a
561 : * "Colon Definition" or "Device-Node" or the like, we want
562 : * the message to read: "that started on line ... [in file ...]"
563 : * If the end of the preceding message was something more specific,
564 : * we just want the message to read: "on line ... [in file ...]"
565 : * If the saved input file name doesn't match our current input
566 : * file name, we will print it and the saved line-number.
567 : * If the file name hasn't changed, we will print only the saved
568 : * line-number.
569 : * If neither is changed, there's no point in printing any of the
570 : * above-mentioned text.
571 : * If a Colon-definition is in progress, show its name and the
572 : * line on which it started. Protect against infinite loop!
573 : * End the line.
574 : *
575 : * Extraneous Remarks:
576 : * This is a retrofit. Earlier, it was just started_at() . Later,
577 : * I generated more specific messages, and needed a way to leave
578 : * out the "that started". I could, theoretically, have added
579 : * the extra parameter to started_at() , but by now there are
580 : * so many of calls to it that I'd rather leave them as is, and
581 : * just change the name of the routine in the few places that
582 : * need the terser form of the message.
583 : *
584 : **************************************************************************** */
585 :
586 : static void print_where_started( bool show_started,
587 : bool show_that_st,
588 : char * saved_ifile,
589 : unsigned int saved_lineno,
590 : bool may_show_incolon)
591 1033 : {
592 1033 : if ( print_msg )
593 : {
594 : bool fil_is_diff;
595 : bool lin_is_diff;
596 :
597 : /* File names are case-sensitive */
598 1033 : fil_is_diff = BOOLVAL(strcmp(saved_ifile, iname) != 0 );
599 1033 : lin_is_diff = BOOLVAL(saved_lineno != lineno );
600 1033 : if ( fil_is_diff || lin_is_diff )
601 : {
602 1010 : if ( show_started )
603 : {
604 624 : if ( show_that_st )
605 : {
606 444 : fprintf(message_dest, " that");
607 : }else{
608 180 : fprintf(message_dest, " , which");
609 : }
610 624 : fprintf(message_dest, " started");
611 : }
612 1010 : fprintf(message_dest, " on line %d", saved_lineno);
613 1010 : if ( fil_is_diff )
614 : {
615 20 : fprintf(message_dest, " of file %s", saved_ifile);
616 : }
617 : }
618 :
619 1033 : if ( may_show_incolon )
620 : {
621 538 : in_last_colon();
622 : }else{
623 495 : fprintf(message_dest, "\n");
624 : }
625 : }
626 1033 : }
627 :
628 : /* **************************************************************************
629 : *
630 : * Function name: started_at
631 : * Synopsis: Supplemental back-reference message,
632 : * with the "that started" phrase,
633 : * and with last-colon identification.
634 : *
635 : * Inputs:
636 : * Parameters:
637 : * saved_ifile File-name saved for "back-reference"
638 : * saved_lineno Line-number saved for "back-reference"
639 : *
640 : * Outputs:
641 : * Returned Value: None
642 : * Global Variables:
643 : * Printout:
644 : * The "...started at..." remainder of a message, giving a back-
645 : * -reference to the "start" point supplied in the params,
646 : * and the start of the current Colon-definition if one is
647 : * in effect.
648 : * Will supply a new-line and can be used to finish the line.
649 : *
650 : **************************************************************************** */
651 :
652 : void started_at( char * saved_ifile, unsigned int saved_lineno)
653 289 : {
654 289 : print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, TRUE);
655 289 : }
656 :
657 :
658 : /* **************************************************************************
659 : *
660 : * Function name: print_started_at
661 : * Synopsis: Same as started_at() except output will be directed
662 : * to stdout instead of to ERRMSG_DESTINATION
663 : *
664 : * Extraneous Remarks:
665 : * A retrofit. Can you tell?
666 : *
667 : **************************************************************************** */
668 :
669 : void print_started_at( char * saved_ifile, unsigned int saved_lineno)
670 83 : {
671 83 : message_dest = stdout;
672 83 : started_at( saved_ifile, saved_lineno);
673 83 : message_dest = ERRMSG_DESTINATION;
674 83 : }
675 :
676 :
677 : /* **************************************************************************
678 : *
679 : * Function name: just_started_at
680 : * Synopsis: Supplemental back-reference message,
681 : * with the "that started" phrase,
682 : * but without last-colon identification.
683 : *
684 : * Inputs:
685 : * Parameters:
686 : * saved_ifile File-name saved for "back-reference"
687 : * saved_lineno Line-number saved for "back-reference"
688 : *
689 : * Outputs:
690 : * Returned Value: None
691 : * Global Variables:
692 : * Printout:
693 : * The "...started at..." remainder of a message, giving a back-
694 : * -reference to the "start" point supplied in the params,
695 : * and no more.
696 : * Will supply a new-line and can be used to finish the line.
697 : *
698 : **************************************************************************** */
699 :
700 : void just_started_at( char * saved_ifile, unsigned int saved_lineno)
701 172 : {
702 172 : print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, FALSE);
703 172 : }
704 :
705 : /* **************************************************************************
706 : *
707 : * Function name: where_started
708 : * Synopsis: Supplemental back-reference message,
709 : * without the "that started" phrase,
710 : * but with last-colon identification.
711 : *
712 : * Inputs:
713 : * Parameters:
714 : * saved_ifile File-name saved for "back-reference"
715 : * saved_lineno Line-number saved for "back-reference"
716 : *
717 : * Outputs:
718 : * Returned Value: None
719 : * Global Variables:
720 : * Printout:
721 : * The remainder of a message, giving a back-reference to the
722 : * "start" point supplied in the parameters, and the start
723 : * of the current Colon-definition if one is in effect.
724 : * Will supply a new-line and can be used to finish the line.
725 : *
726 : **************************************************************************** */
727 :
728 : void where_started( char * saved_ifile, unsigned int saved_lineno)
729 249 : {
730 249 : print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, TRUE);
731 249 : }
732 :
733 : /* **************************************************************************
734 : *
735 : * Function name: just_where_started
736 : * Synopsis: Supplemental back-reference message,
737 : * without the "that started" phrase,
738 : * and without last-colon identification.
739 : *
740 : * Inputs:
741 : * Parameters:
742 : * saved_ifile File-name saved for "back-reference"
743 : * saved_lineno Line-number saved for "back-reference"
744 : *
745 : * Outputs:
746 : * Returned Value: None
747 : * Global Variables:
748 : * Printout:
749 : * The remainder of a message, giving a back-reference to the
750 : * "start" point supplied in the parameters, and no more.
751 : * Will supply a new-line and can be used to finish the line.
752 : *
753 : **************************************************************************** */
754 :
755 : void just_where_started( char * saved_ifile, unsigned int saved_lineno)
756 141 : {
757 141 : print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, FALSE);
758 141 : }
759 :
760 : /* **************************************************************************
761 : *
762 : * Function name: in_last_colon
763 : * Synopsis: Supplemental back-reference message, identifying
764 : * last Colon-definition if one is in effect.
765 : * Can be used to finish the line in either case.
766 : *
767 : * Inputs:
768 : * Parameters: NONE
769 : * Global Variables:
770 : * incolon TRUE if Colon-definition is in progress
771 : * last_colon_defname Name of last colon-definition
772 : * last_colon_filename File where last colon-def'n made
773 : * last_colon_lineno Line number of last colon-def'n
774 : * Local Static Variables:
775 : * print_msg Whether the beginning part of the message
776 : * was printed by tokenization_error()
777 : * message_dest Message Destination. Is ERRMSG_DESTINATION
778 : * (stdout) usually, except sometimes...
779 : *
780 : * Outputs:
781 : * Returned Value: NONE
782 : * Printout:
783 : * Remainder of a message:
784 : * "in definition of ... , which started ..."
785 : *
786 : * Process Explanation:
787 : * Because this routine does some of its own printing, it needs
788 : * to check the residual state of print_msg first.
789 : * The calling routine does not need to test incolon ; it can
790 : * call this to end the line in either case.
791 : *
792 : **************************************************************************** */
793 :
794 : void in_last_colon( void )
795 616 : {
796 616 : if ( print_msg )
797 : {
798 616 : if ( incolon )
799 : {
800 182 : fprintf( message_dest, " in definition of %s ",
801 : strupr( last_colon_defname) );
802 182 : print_where_started( TRUE, FALSE,
803 : last_colon_filename, last_colon_lineno, FALSE);
804 : }else{
805 434 : fprintf(message_dest, "\n");
806 : }
807 : }
808 616 : }
809 :
810 :
811 : /* **************************************************************************
812 : *
813 : * Function name: safe_malloc
814 : * Synopsis: malloc with built-in failure test.
815 : *
816 : * Inputs:
817 : * Parameters:
818 : * size size_t Size of memory-chunk to allocate
819 : * phrase char * Phrase to print after "... while "
820 : * in case of failure.
821 : *
822 : * Outputs:
823 : * Returned Value: Pointer to allocated memory
824 : * Global Variables:
825 : * fatal_err_exit On memory allocation failure, change
826 : * to a special system-defined value
827 : *
828 : * Error Detection:
829 : * On memory allocation failure, declare a FATAL error. Set up
830 : * for a special system-defined EXIT value that indicates
831 : * insufficient memory.
832 : *
833 : * Process Explanation:
834 : * It is the responsibility of the calling routine to be sure
835 : * the "phrase" is unique within the program. It is intended
836 : * as a debugging aid, to help localize the point of failure.
837 : *
838 : **************************************************************************** */
839 :
840 : _PTR safe_malloc( size_t size, char *phrase)
841 16897 : {
842 : _PTR retval ;
843 16897 : retval = malloc (size);
844 16897 : if ( !retval )
845 : {
846 0 : fatal_err_exit = -ENOMEM ;
847 0 : tokenization_error( FATAL, "Out of memory while %s.", phrase);
848 : }
849 16897 : return ( retval );
850 : }
851 :
852 : /* **************************************************************************
853 : *
854 : * Function name: error_summary
855 : * Synopsis: Summarize final error-message status
856 : * before completing tokenization.
857 : * Indicate if OK to produce output.
858 : *
859 : * Inputs:
860 : * Parameters: NONE
861 : * Global Variables:
862 : * noerrors "Ignore Errors" flag, set by "-i" switch
863 : * err_types_found Accumulated Error-types.
864 : * error_categories Table of Error-types, Message-Counters
865 : * and their printable names.
866 : * opc FCode Output Buffer Position Counter
867 : * (zero means there was no output).
868 : *
869 : * Outputs:
870 : * Returned Value: True = OK to produce output (But caller
871 : * must still verify non-zero opc)
872 : * Printout:
873 : * Various messages.
874 : *
875 : * Process Explanation:
876 : * The first entry in the error_categories table is FATAL
877 : * We won't need to print a tally of that...
878 : *
879 : **************************************************************************** */
880 :
881 : bool error_summary( void )
882 165 : {
883 : /* Bit-mask of error-types that require suppressing output */
884 : static const int suppress_mask = ( FATAL | TKERROR );
885 165 : bool retval = TRUE;
886 165 : bool suppressing = FALSE;
887 :
888 : /* There's no escaping a FATAL error */
889 165 : if ( ( err_types_found & FATAL ) != 0 )
890 : {
891 : /* FATAL error. Don't even bother with the tally. */
892 1 : suppressing = TRUE;
893 : } else {
894 :
895 164 : if ( opc == 0 )
896 : {
897 22 : printf ( "Nothing Tokenized");
898 : }else{
899 142 : printf ( "Tokenization Completed");
900 : }
901 :
902 164 : if ( err_types_found != 0 )
903 : {
904 : int indx;
905 164 : bool tally_started = FALSE ;
906 164 : printf (". ");
907 : /*
908 : * Print a tally of the error-types;
909 : * handle plurals and punctuation appropriately.
910 : */
911 : /* Start at indx = 1 to skip examining FATALs */
912 984 : for ( indx = 1; indx < num_categories ; indx ++ )
913 : {
914 820 : if ( *(error_categories[indx].counter) > 0 )
915 : {
916 413 : printf ("%s %d %s%s",
917 : tally_started ? "," : "" ,
918 : *(error_categories[indx].counter),
919 : error_categories[indx].category_name,
920 : *(error_categories[indx].counter) > 1 ?
921 : error_categories[indx].plural :
922 : error_categories[indx].single );
923 : /* Zero out the counter, to prevent displaying the
924 : * number of Messages twice, since it's shared
925 : * by the "Messages" and "P_Messages" categories.
926 : */
927 413 : *(error_categories[indx].counter) = 0;
928 413 : tally_started = TRUE;
929 : }
930 : }
931 : }
932 164 : printf (".\n");
933 :
934 164 : if ( ( err_types_found & suppress_mask ) != 0 )
935 : { /* Errors found. Not OK to produce output */
936 : /* Unless "Ignore Errors" flag set... */
937 82 : if ( INVERSE(noerrors) )
938 : {
939 17 : suppressing = TRUE;
940 : }else{
941 65 : if ( opc > 0 )
942 : {
943 64 : printf ("Error-detection over-ridden; "
944 : "producing binary output.\n");
945 : }
946 : }
947 : }
948 : }
949 165 : if ( suppressing )
950 : {
951 18 : retval = FALSE ;
952 18 : printf ("Suppressing binary output.\n");
953 : }
954 165 : return ( retval );
955 : }
956 :
|