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