Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**** error.c --- Error reporting.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 **** Commentary:
36
 *
37
 * This file implements the error reporting facility specified in the file
38
 * "error.h".  See that file for more details.
39
 *
40
 **** Change Log:
41
 * $Log: error.c,v $
42
 * Revision 1.1.1.1  1998/01/17  15:57:42  release
43
 * First version to be checked into rolling release.
44
 *
45
 * Revision 1.2  1994/12/12  11:44:41  smf
46
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
47
 * OSSG C Coding Standards.
48
 *
49
 * Revision 1.1.1.1  1994/07/25  16:05:51  smf
50
 * Initial import of library shared files.
51
 *
52
**/
53
 
54
/****************************************************************************/
55
 
56
#include "error.h"
57
#include "syntax.h"
58
 
59
/*--------------------------------------------------------------------------*/
60
 
61
#define TAG_TABLE_SIZE (127)
62
#define ERROR_TABLE_SIZE (127)
63
#define STRING_TABLE_SIZE (127)
64
 
65
/*--------------------------------------------------------------------------*/
66
 
67
static ETagP		tag_table [TAG_TABLE_SIZE];
68
static ErrorP		error_table [ERROR_TABLE_SIZE];
69
static EStringP		string_table [STRING_TABLE_SIZE];
70
static CStringP		program_name         = NIL (CStringP);
71
static ErrorInitProcP	init_proc	     = NIL (ErrorInitProcP);
72
static ETagP		etag_program	     = NIL (ETagP);
73
static ETagP		etag_severity	     = NIL (ETagP);
74
static ETagP		etag_error_name      = NIL (ETagP);
75
static ETagP		etag_dollar	     = NIL (ETagP);
76
static ETagP		etag_ocb	     = NIL (ETagP);
77
static ETagP		etag_ccb	     = NIL (ETagP);
78
static ErrorListP	error_prefix	     = NIL (ErrorListP);
79
static ESeverityT	min_severity	     = ERROR_SEVERITY_ERROR;
80
static ESeverityT	max_reported	     = ERROR_SEVERITY_INFORMATION;
81
static EStringDataT	severity_data []     = {
82
    UB {"error severity information",	"Info"} UE,
83
    UB {"error severity warning",	"Warning"} UE,
84
    UB {"error severity error",		"Error"} UE,
85
    UB {"error severity fatal",		"Fatal"} UE,
86
    UB {"error severity internal",	"Internal"} UE,
87
    ERROR_END_STRING_LIST
88
};
89
 
90
/*--------------------------------------------------------------------------*/
91
 
92
static void
93
error_deallocate_error_list PROTO_N ((error_list))
94
			    PROTO_T (ErrorListP error_list)
95
{
96
    while (error_list) {
97
	ErrorListP tmp = error_list;
98
 
99
	if (error_list->tag == ERROR_TAG_STRING) {
100
	    nstring_destroy (&(error_list->u.string));
101
	}
102
	error_list = error_list->next;
103
	DEALLOCATE (tmp);
104
    }
105
}
106
 
107
static ErrorListP
108
error_parse_message PROTO_N ((message))
109
		    PROTO_T (CStringP message)
110
{
111
    ErrorListP  error_list;
112
    ErrorListP *error_list_next = &error_list;
113
    CStringP    message_copy    = cstring_duplicate (message);
114
    CStringP    scan            = message = message_copy;
115
 
116
    while (*scan) {
117
	if ((*scan ++ == '$') && (*scan == '{')) {
118
	    if (scan > (message + 1)) {
119
		ErrorListP tmp = ALLOCATE (ErrorListT);
120
 
121
		tmp->tag  = ERROR_TAG_STRING;
122
		scan [-1] = '\0';
123
		nstring_copy_cstring (&(tmp->u.string), message);
124
		*error_list_next = tmp;
125
		error_list_next  = &(tmp->next);
126
	    }
127
	    scan ++;
128
	    message = scan;
129
	    while (*scan != '}') {
130
		if ((*scan == '\0') || (*scan == '$') || (*scan == '{') ||
131
		    ((!syntax_is_printable (*scan)) && (*scan != ' '))) {
132
		    *error_list_next = NIL (ErrorListP);
133
		    error_deallocate_error_list (error_list);
134
		    return (NIL (ErrorListP));
135
		}
136
		scan ++;
137
	    }
138
	    if (scan ++ > message) {
139
		ErrorListP tmp = ALLOCATE (ErrorListT);
140
		CStringP   tag;
141
 
142
		tmp->tag   = ERROR_TAG_TAG;
143
		scan [-1]  = '\0';
144
		tag        = cstring_duplicate (message);
145
		tmp->u.tag = error_define_tag (tag);
146
		if (tmp->u.tag->name != tag) {
147
		    DEALLOCATE (tag);
148
		}
149
		*error_list_next = tmp;
150
		error_list_next  = &(tmp->next);
151
	    }
152
	    message = scan;
153
	}
154
    }
155
    if (scan > message) {
156
	ErrorListP tmp = ALLOCATE (ErrorListT);
157
 
158
	tmp->tag = ERROR_TAG_STRING;
159
	nstring_copy_cstring (&(tmp->u.string), message);
160
	*error_list_next = tmp;
161
	error_list_next  = &(tmp->next);
162
    }
163
    *error_list_next = NIL (ErrorListP);
164
    DEALLOCATE (message_copy);
165
    return (error_list);
166
}
167
 
168
static void
169
write_error_list PROTO_N ((ostream, error_list, error, proc, closure))
170
		 PROTO_T (OStreamP   ostream X
171
			  ErrorListP error_list X
172
			  ErrorP     error X
173
			  ErrorProcP proc X
174
			  GenericP   closure)
175
{
176
    while (error_list) {
177
	switch (error_list->tag) EXHAUSTIVE {
178
	  case ERROR_TAG_STRING:
179
	    write_nstring (ostream, &(error_list->u.string));
180
	    break;
181
	  case ERROR_TAG_TAG:
182
	    if (error_list->u.tag == etag_program) {
183
		write_cstring (ostream, program_name);
184
	    } else if (error_list->u.tag == etag_severity) {
185
		EStringP estring =
186
		    severity_data [(error->severity)].estring;
187
 
188
		write_cstring (ostream, error_string_contents (estring));
189
	    } else if (error_list->u.tag == etag_error_name) {
190
		write_cstring (ostream, error->name);
191
	    } else if (error_list->u.tag == etag_dollar) {
192
		write_char (ostream, '$');
193
	    } else if (error_list->u.tag == etag_ocb) {
194
		write_char (ostream, '{');
195
	    } else if (error_list->u.tag == etag_ccb) {
196
		write_char (ostream, '}');
197
	    } else if (proc) {
198
		((*proc) (ostream, error_list->u.tag, closure));
199
	    }
200
	    break;
201
	}
202
	error_list = error_list->next;
203
    }
204
}
205
 
206
static void
207
write_error_list_text PROTO_N ((ostream, error_list))
208
		      PROTO_T (OStreamP   ostream X
209
			       ErrorListP error_list)
210
{
211
    NStringP nstring;
212
    CStringP contents;
213
    unsigned length;
214
 
215
    write_char (ostream, '"');
216
    while (error_list) {
217
	switch (error_list->tag) EXHAUSTIVE {
218
	  case ERROR_TAG_STRING:
219
	    nstring  = &(error_list->u.string);
220
	    contents = nstring_contents (nstring);
221
	    length   = nstring_length (nstring);
222
 
223
	    while (length --) {
224
		switch (*contents) {
225
		  case '\n':
226
		    write_cstring (ostream, "\\n\\");
227
		    write_newline (ostream);
228
		    break;
229
		  case '"':
230
		    write_cstring (ostream, "\\\"");
231
		    break;
232
		  default:
233
		    ASSERT (*contents != '\0');
234
		    write_char (ostream, *contents);
235
		    break;
236
		}
237
		contents ++;
238
	    }
239
	    break;
240
	  case ERROR_TAG_TAG:
241
	    write_cstring (ostream, "${");
242
	    write_cstring (ostream, error_list->u.tag->name);
243
	    write_char (ostream, '}');
244
	    break;
245
	}
246
	error_list = error_list->next;
247
    }
248
    write_char (ostream, '"');
249
}
250
 
251
static void
252
write_error_table PROTO_N ((ostream))
253
		  PROTO_T (OStreamP ostream)
254
{
255
    unsigned i;
256
 
257
    for (i = 0; i < ERROR_TABLE_SIZE; i ++) {
258
	ErrorP error = error_table [i];
259
 
260
	while (error) {
261
	    write_char (ostream, '\'');
262
	    write_cstring (ostream, error->name);
263
	    write_char (ostream, '\'');
264
	    write_newline (ostream);
265
	    write_cstring (ostream, "    ");
266
	    write_error_list_text (ostream, error->error_list);
267
	    write_newline (ostream);
268
	    error = error->next;
269
	}
270
    }
271
}
272
 
273
static void
274
write_string_table PROTO_N ((ostream))
275
		   PROTO_T (OStreamP ostream)
276
{
277
    unsigned i;
278
 
279
    for (i = 0; i < STRING_TABLE_SIZE; i ++) {
280
	EStringP string = string_table [i];
281
 
282
	while (string) {
283
	    CStringP contents = string->contents;
284
 
285
	    write_char (ostream, '\'');
286
	    write_cstring (ostream, string->name);
287
	    write_char (ostream, '\'');
288
	    write_newline (ostream);
289
	    write_cstring (ostream, "    ");
290
	    write_char (ostream, '"');
291
	    while (*contents) {
292
		switch (*contents) {
293
		  case '\n':
294
		    write_cstring (ostream, "\\n\\");
295
		    write_newline (ostream);
296
		    break;
297
		  case '"':
298
		    write_cstring (ostream, "\\\"");
299
		    break;
300
		  default:
301
		    write_char (ostream, *contents);
302
		    break;
303
		}
304
		contents ++;
305
	    }
306
	    write_char (ostream, '"');
307
	    write_newline (ostream);
308
	    string = string->next;
309
	}
310
    }
311
}
312
 
313
/*--------------------------------------------------------------------------*/
314
 
315
void
316
error_init PROTO_N ((name, proc))
317
	   PROTO_T (CStringP       name X
318
		    ErrorInitProcP proc)
319
{
320
    static CStringP prefix = "${program name}: ${severity}: ";
321
 
322
    program_name = name;
323
    while (*name) {
324
	if (*name ++ == '/') {
325
	    program_name = name;
326
	}
327
    }
328
    init_proc       = proc;
329
    etag_program    = error_define_tag ("program name");
330
    etag_severity   = error_define_tag ("severity");
331
    etag_error_name = error_define_tag ("this error name");
332
    etag_dollar     = error_define_tag ("dollar");
333
    etag_ocb        = error_define_tag ("open brace");
334
    etag_ccb        = error_define_tag ("close brace");
335
    error_prefix    = error_parse_message (prefix);
336
    error_intern_strings (severity_data);
337
    ostream_buffer (ostream_error);
338
}
339
 
340
void
341
error_call_init_proc PROTO_Z ()
342
{
343
    if (init_proc) {
344
	(*init_proc) ();
345
	init_proc = NIL (ErrorInitProcP);
346
    }
347
}
348
 
349
ETagP
350
error_define_tag PROTO_N ((name))
351
		 PROTO_T (CStringP name)
352
{
353
    unsigned hash   = (cstring_hash_value (name) % TAG_TABLE_SIZE);
354
    ETagP   *entryp = &(tag_table [hash]);
355
    ETagP    entry;
356
 
357
    while ((entry = *entryp) != NIL (ETagP)) {
358
	if (cstring_equal (entry->name, name)) {
359
	    return (entry);
360
	}
361
	entryp = &(entry->next);
362
    }
363
    entry       = ALLOCATE (ETagT);
364
    entry->next = NIL (ETagP);
365
    entry->name = name;
366
    *entryp     = entry;
367
    return (entry);
368
}
369
 
370
ErrorP
371
error_define_error PROTO_N ((name, severity, message, data))
372
		   PROTO_T (CStringP   name X
373
			    ESeverityT severity X
374
			    CStringP   message X
375
			    GenericP   data)
376
{
377
    ErrorListP error_list = error_parse_message (message);
378
    unsigned   hash       = (cstring_hash_value (name) % ERROR_TABLE_SIZE);
379
    ErrorP    *entryp     = &(error_table [hash]);
380
    ErrorP     entry;
381
 
382
    while ((entry = *entryp) != NIL (ErrorP)) {
383
	ASSERT (!cstring_equal (entry->name, name));
384
	entryp = &(entry->next);
385
    }
386
    ASSERT (error_list);
387
    entry             = ALLOCATE (ErrorT);
388
    entry->next       = NIL (ErrorP);
389
    entry->name       = name;
390
    entry->severity   = severity;
391
    entry->error_list = error_list;
392
    entry->data       = data;
393
    *entryp           = entry;
394
    return (entry);
395
}
396
 
397
void
398
error_intern_tags PROTO_N ((vector))
399
		  PROTO_T (ETagDataP vector)
400
{
401
    while (vector->name) {
402
	ETagP tag = error_define_tag (vector->name);
403
 
404
	vector->tag = tag;
405
	vector ++;
406
    }
407
}
408
 
409
void
410
error_intern_errors PROTO_N ((vector))
411
		    PROTO_T (ErrorDataP vector)
412
{
413
    while (vector->s.name) {
414
	ErrorP error = error_define_error (vector->s.name, vector->s.severity,
415
					   vector->s.message, vector->s.data);
416
 
417
	vector->error = error;
418
	vector ++;
419
    }
420
}
421
 
422
ErrorStatusT
423
error_redefine_error PROTO_N ((name, message))
424
		     PROTO_T (CStringP name X
425
			      CStringP message)
426
{
427
    error_call_init_proc ();
428
    {
429
	unsigned hash  = (cstring_hash_value (name) % ERROR_TABLE_SIZE);
430
	ErrorP   entry = (error_table [hash]);
431
 
432
	while (entry) {
433
	    if (cstring_equal (entry->name, name)) {
434
		ErrorListP error_list = error_parse_message (message);
435
 
436
		if (error_list == NIL (ErrorListP)) {
437
		    return (ERROR_STATUS_BAD_MESSAGE);
438
		}
439
		error_deallocate_error_list (entry->error_list);
440
		entry->error_list = error_list;
441
		return (ERROR_STATUS_SUCCESS);
442
	    }
443
	    entry = entry->next;
444
	}
445
	return (ERROR_STATUS_BAD_ERROR);
446
    }
447
}
448
 
449
ErrorP
450
error_lookup_error PROTO_N ((name))
451
		   PROTO_T (CStringP name)
452
{
453
    error_call_init_proc ();
454
    {
455
	unsigned hash  = (cstring_hash_value (name) % ERROR_TABLE_SIZE);
456
	ErrorP   entry = (error_table [hash]);
457
 
458
	while (entry) {
459
	    if (cstring_equal (entry->name, name)) {
460
		return (entry);
461
	    }
462
	    entry = entry->next;
463
	}
464
	return (NIL (ErrorP));
465
    }
466
}
467
 
468
GenericP
469
error_data PROTO_N ((error))
470
	   PROTO_T (ErrorP error)
471
{
472
    return (error->data);
473
}
474
 
475
void
476
error_report PROTO_N ((error, proc, closure))
477
	     PROTO_T (ErrorP     error X
478
		      ErrorProcP proc X
479
		      GenericP   closure)
480
{
481
    if ((error->severity) >= min_severity) {
482
	write_error_list (ostream_error, error_prefix, error, NIL (ErrorProcP),
483
			  NIL (GenericP));
484
	write_error_list (ostream_error, error->error_list, error, proc,
485
			  closure);
486
	write_newline (ostream_error);
487
	ostream_flush (ostream_error);
488
    }
489
    if ((error->severity) > max_reported) {
490
	max_reported = error->severity;
491
    }
492
    if ((error->severity) >= ERROR_SEVERITY_FATAL) {
493
	if (error->severity == ERROR_SEVERITY_INTERNAL) {
494
	    abort ();
495
	    UNREACHED;
496
	}
497
	exit (EXIT_FAILURE);
498
	UNREACHED;
499
    }
500
}
501
 
502
void
503
error_set_min_report_severity PROTO_N ((severity))
504
			      PROTO_T (ESeverityT severity)
505
{
506
    min_severity = severity;
507
}
508
 
509
ESeverityT
510
error_get_min_report_severity PROTO_Z ()
511
{
512
    return (min_severity);
513
}
514
 
515
ESeverityT
516
error_max_reported_severity PROTO_Z ()
517
{
518
    return (max_reported);
519
}
520
 
521
void
522
error_set_severity_message PROTO_N ((severity, message))
523
			   PROTO_T (ESeverityT severity X
524
				    CStringP   message)
525
{
526
    severity_data [severity].estring->contents = message;
527
}
528
 
529
BoolT
530
error_set_prefix_message PROTO_N ((message))
531
			 PROTO_T (CStringP message)
532
{
533
    ErrorListP error_list = error_parse_message (message);
534
 
535
    if (error_list == NIL (ErrorListP)) {
536
	return (FALSE);
537
    }
538
    error_deallocate_error_list (error_prefix);
539
    error_prefix = error_list;
540
    return (TRUE);
541
}
542
 
543
EStringP
544
error_define_string PROTO_N ((name, contents))
545
		    PROTO_T (CStringP name X
546
			     CStringP contents)
547
{
548
    unsigned  hash   = (cstring_hash_value (name) % STRING_TABLE_SIZE);
549
    EStringP *entryp = &(string_table [hash]);
550
    EStringP  entry;
551
 
552
    while ((entry = *entryp) != NIL (EStringP)) {
553
	ASSERT (!cstring_equal (entry->name, name));
554
	entryp = &(entry->next);
555
    }
556
    entry           = ALLOCATE (EStringT);
557
    entry->next     = NIL (EStringP);
558
    entry->name     = name;
559
    entry->contents = contents;
560
    *entryp         = entry;
561
    return (entry);
562
}
563
 
564
void
565
error_intern_strings PROTO_N ((vector))
566
		     PROTO_T (EStringDataP vector)
567
{
568
    while (vector->s.name) {
569
	EStringP estring = error_define_string (vector->s.name,
570
						vector->s.contents);
571
 
572
	vector->estring = estring;
573
	vector ++;
574
    }
575
}
576
 
577
BoolT
578
error_redefine_string PROTO_N ((name, contents))
579
		      PROTO_T (CStringP name X
580
			       CStringP contents)
581
{
582
    unsigned hash  = (cstring_hash_value (name) % STRING_TABLE_SIZE);
583
    EStringP entry = (string_table [hash]);
584
 
585
    while (entry) {
586
	if (cstring_equal (entry->name, name)) {
587
	    entry->contents = contents;
588
	    return (TRUE);
589
	}
590
	entry = entry->next;
591
    }
592
    return (FALSE);
593
}
594
 
595
EStringP
596
error_lookup_string PROTO_N ((name))
597
		    PROTO_T (CStringP name)
598
{
599
    unsigned hash  = (cstring_hash_value (name) % STRING_TABLE_SIZE);
600
    EStringP entry = (string_table [hash]);
601
 
602
    while (entry) {
603
	if (cstring_equal (entry->name, name)) {
604
	    return (entry);
605
	}
606
	entry = entry->next;
607
    }
608
    return (NIL (EStringP));
609
}
610
 
611
CStringP
612
error_string_contents PROTO_N ((estring))
613
		      PROTO_T (EStringP estring)
614
{
615
    return (estring->contents);
616
}
617
 
618
void
619
write_error_file PROTO_N ((ostream))
620
		 PROTO_T (OStreamP ostream)
621
{
622
    error_call_init_proc ();
623
    write_cstring (ostream, "%prefix%");
624
    write_newline (ostream);
625
    write_cstring (ostream, "    ");
626
    write_error_list_text (ostream, error_prefix);
627
    write_newline (ostream);
628
    write_newline (ostream);
629
    write_cstring (ostream, "%errors%");
630
    write_newline (ostream);
631
    write_error_table (ostream);
632
    write_newline (ostream);
633
    write_cstring (ostream, "%strings%");
634
    write_newline (ostream);
635
    write_string_table (ostream);
636
}
637
 
638
/*
639
 * Local variables(smf):
640
 * eval: (include::add-path-entry "../os-interface" "../generated")
641
 * end:
642
**/