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
toup(char * chr_ptr)238 static void toup( char *chr_ptr)
239 {
240 const unsigned char upcas_diff = ( 'a' - 'A' );
241 if ( ( *chr_ptr >= 'a' ) && ( *chr_ptr <= 'z' ) )
242 {
243 *chr_ptr -= upcas_diff ;
244 }
245 }
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
strupper(char * strung)269 char *strupper( char *strung)
270 {
271 char *strindx;
272 for (strindx = strung; *strindx != 0; strindx++)
273 {
274 toup( strindx);
275 }
276 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
tolow(char * chr_ptr)307 static void tolow( char *chr_ptr)
308 {
309 const unsigned char lowcas_diff = ( 'A' - 'a' );
310 if ( ( *chr_ptr >= 'A' ) && ( *chr_ptr <= 'Z' ) )
311 {
312 *chr_ptr -= lowcas_diff ;
313 }
314 }
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
strlower(char * strung)338 char *strlower( char *strung)
339 {
340 char *strindx;
341 for (strindx = strung; *strindx != 0; strindx++)
342 {
343 tolow( strindx);
344 }
345 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
init_error_handler(void)389 void init_error_handler( void)
390 {
391 int indx ;
392
393 message_dest = ERRMSG_DESTINATION;
394 if ( verbose ) errs_to_print |= INFO ;
395 err_types_found = 0 ;
396
397 /* Start at indx = 1 to skip resetting FATALs */
398 for ( indx = 1; indx < num_categories ; indx ++ )
399 {
400 *(error_categories[indx].counter) = 0 ;
401 }
402
403 FFLUSH_STDOUT
404 }
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
tokenization_error(int err_type,char * msg,...)482 void tokenization_error( int err_type, char* msg, ... )
483 {
484 int indx ;
485
486 /* Initial settings: treat as an Error. */
487 char *catgy_name = "Error";
488 char *catgy_suffx = "";
489 int *catgy_counter = &err_count;
490 bool print_new_line = FALSE;
491
492 /* Accumulated the Error-type into err_types_found */
493 err_types_found |= err_type;
494
495 /* Identify the Error-Category. */
496 for ( indx = 0 ; indx < num_categories ; indx ++ )
497 {
498 if ( ( error_categories[indx].type_bit & err_type ) != 0 )
499 {
500 catgy_name = error_categories[indx].category_name;
501 catgy_suffx = error_categories[indx].single;
502 catgy_counter = error_categories[indx].counter;
503 print_new_line = error_categories[indx].new_line;
504 break;
505 }
506 }
507
508 /* Special message if err_type not in list; treat as an Error. */
509 if ( catgy_name == NULL )
510 {
511 fprintf(ERRMSG_DESTINATION,
512 "Program error: Unknown Error-Type, 0x%08x. "
513 " Will treat as Error.\n", err_type) ;
514 err_types_found |= TKERROR;
515 print_msg = TRUE ;
516 } else {
517 /* Check the Error-Type against the Error Verbosity Mask */
518 print_msg = BOOLVAL( ( errs_to_print & err_type ) != 0 );
519 }
520
521 if ( print_msg )
522 {
523 va_list argp;
524
525 fprintf(ERRMSG_DESTINATION, "%s%s: ",
526 catgy_name, catgy_suffx);
527 if ( iname != NULL )
528 {
529 /* Don't print iname or lineno if no file opened. */
530 fprintf(ERRMSG_DESTINATION, "File %s, Line %d. ",
531 iname, lineno);
532 }
533 if ( opc > 0 )
534 {
535 /* Don't print Output Position if no output started. */
536 fprintf(ERRMSG_DESTINATION, "(Output Position = %d). ", opc);
537 }
538 if ( pci_hdr_end_ob_off > 0 )
539 {
540 /* Don't print PCI-Block Position if no PCI-Block in effect. */
541 fprintf(ERRMSG_DESTINATION, "(PCI-Block Position = %d). ",
542 opc - pci_hdr_end_ob_off );
543 }
544
545 va_start(argp, msg);
546 vfprintf(ERRMSG_DESTINATION, msg, argp);
547 va_end(argp);
548 if ( print_new_line ) fprintf(ERRMSG_DESTINATION, "\n");
549
550 /* Increment the category-counter. */
551 *catgy_counter += 1;
552 }
553 if ( err_type == FATAL )
554 {
555 fprintf(ERRMSG_DESTINATION, "Tokenization terminating.\n");
556 error_summary();
557 exit ( fatal_err_exit );
558 }
559 }
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
print_where_started(bool show_started,bool show_that_st,char * saved_ifile,unsigned int saved_lineno,bool may_show_incolon)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 {
634 if ( print_msg )
635 {
636 bool fil_is_diff;
637 bool lin_is_diff;
638
639 /* File names are case-sensitive */
640 fil_is_diff = BOOLVAL(strcmp(saved_ifile, iname) != 0 );
641 lin_is_diff = BOOLVAL(saved_lineno != lineno );
642 if ( fil_is_diff || lin_is_diff )
643 {
644 if ( show_started )
645 {
646 if ( show_that_st )
647 {
648 fprintf(message_dest, " that");
649 }else{
650 fprintf(message_dest, " , which");
651 }
652 fprintf(message_dest, " started");
653 }
654 fprintf(message_dest, " on line %d", saved_lineno);
655 if ( fil_is_diff )
656 {
657 fprintf(message_dest, " of file %s", saved_ifile);
658 }
659 }
660
661 if ( may_show_incolon )
662 {
663 in_last_colon( TRUE );
664 }else{
665 fprintf(message_dest, "\n");
666 }
667 }
668 }
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
started_at(char * saved_ifile,unsigned int saved_lineno)694 void started_at( char * saved_ifile, unsigned int saved_lineno)
695 {
696 print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, TRUE);
697 }
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
print_started_at(char * saved_ifile,unsigned int saved_lineno)711 void print_started_at( char * saved_ifile, unsigned int saved_lineno)
712 {
713 message_dest = stdout;
714 started_at( saved_ifile, saved_lineno);
715 message_dest = ERRMSG_DESTINATION;
716 }
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
just_started_at(char * saved_ifile,unsigned int saved_lineno)742 void just_started_at( char * saved_ifile, unsigned int saved_lineno)
743 {
744 print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, FALSE);
745 }
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
where_started(char * saved_ifile,unsigned int saved_lineno)770 void where_started( char * saved_ifile, unsigned int saved_lineno)
771 {
772 print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, TRUE);
773 }
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
just_where_started(char * saved_ifile,unsigned int saved_lineno)797 void just_where_started( char * saved_ifile, unsigned int saved_lineno)
798 {
799 print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, FALSE);
800 }
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
in_last_colon(bool say_in)839 void in_last_colon( bool say_in )
840 {
841 if ( print_msg )
842 {
843 if ( incolon || ( ! say_in ) )
844 {
845 fprintf( message_dest, "%s definition of %s ", say_in ? " in" : "",
846 strupr( last_colon_defname) );
847 print_where_started( TRUE, FALSE,
848 last_colon_filename, last_colon_lineno, FALSE);
849 }else{
850 fprintf(message_dest, "\n");
851 }
852 }
853 }
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
safe_malloc(size_t size,char * phrase)885 _PTR safe_malloc( size_t size, char *phrase)
886 {
887 _PTR retval ;
888 retval = malloc (size);
889 if ( !retval )
890 {
891 fatal_err_exit = -ENOMEM ;
892 tokenization_error( FATAL, "Out of memory while %s.", phrase);
893 }
894 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
error_summary(void)926 bool error_summary( void )
927 {
928 /* Bit-mask of error-types that require suppressing output */
929 static const int suppress_mask = ( FATAL | TKERROR );
930 bool retval = TRUE;
931 bool suppressing = FALSE;
932
933 /* There's no escaping a FATAL error */
934 if ( ( err_types_found & FATAL ) != 0 )
935 {
936 /* FATAL error. Don't even bother with the tally. */
937 suppressing = TRUE;
938 } else {
939
940 if ( opc == 0 )
941 {
942 printf ( "Nothing Tokenized");
943 }else{
944 printf ( "Tokenization Completed");
945 }
946
947 if ( err_types_found != 0 )
948 {
949 int indx;
950 bool tally_started = FALSE ;
951 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 for ( indx = 1; indx < num_categories ; indx ++ )
958 {
959 if ( *(error_categories[indx].counter) > 0 )
960 {
961 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 *(error_categories[indx].counter) = 0;
973 tally_started = TRUE;
974 }
975 }
976 }
977 printf (".\n");
978
979 if ( ( err_types_found & suppress_mask ) != 0 )
980 { /* Errors found. Not OK to produce output */
981 /* Unless "Ignore Errors" flag set... */
982 if ( INVERSE(noerrors) )
983 {
984 suppressing = TRUE;
985 }else{
986 if ( opc > 0 )
987 {
988 printf ("Error-detection over-ridden; "
989 "producing binary output.\n");
990 }
991 }
992 }
993 }
994 if ( suppressing )
995 {
996 retval = FALSE ;
997 printf ("Suppressing binary output.\n");
998 }
999 return ( retval );
1000 }
1001
1002