Subversion Repositories tendra.SVN

Rev

Rev 7 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "object.h"
63
#include "hash.h"
7 7u83 64
#include "index.h"
2 7u83 65
#include "name.h"
66
#include "type.h"
67
#include "print.h"
68
#include "utility.h"
69
 
70
 
71
/*
72
    FLAGS
73
 
74
    These flags are used to indicate various output states indicated by
75
    preprocessing directives.  A value of 1 is the default (which
76
    actually means that the condition is false), 2 means that the given
77
    statement is true, and 0 means that its negation is true.
78
*/
79
 
7 7u83 80
static int building_libs = 1;
81
static int commented_out = 1;
2 7u83 82
 
83
 
84
/*
85
    FIELD SEPARATOR
86
 
87
    The field separator for the machine processable index.  This
88
    separator can be changed, but no command line option is provided to
89
    do this as '$' seems ideal.
90
*/
91
 
7 7u83 92
static char field_sep = '$';
2 7u83 93
 
94
 
95
/*
96
    PRINT FIELD SEPARATOR
97
 
98
    Routine to print field separator of the machine processable index.
99
*/
100
 
7 7u83 101
#define print_field_sep()	IGNORE putchar(field_sep)
2 7u83 102
 
103
 
104
/*
105
    PRINT FIELD
106
 
107
    Routine to print field and separator of the machine processable index.
108
*/
109
 
7 7u83 110
static void
111
print_field(char *s)
2 7u83 112
{
7 7u83 113
    IGNORE printf("%s%c", s, field_sep);
114
    return;
2 7u83 115
}
116
 
117
 
118
/*
119
    PRINT ESCAPED FIELD
120
 
121
    Routine to print field without separator of the machine processable
122
    index, escaping characters that could confuse output processing tools.
123
*/
124
 
7 7u83 125
static void
126
print_escape(char *s)
2 7u83 127
{
7 7u83 128
    int c;
129
    while ((c = *s++)!= '\0') {
130
	if (c == field_sep) {
131
	    IGNORE printf("\\F");
132
	} else if (c == '\n') {
133
	    IGNORE printf("\\n");
134
	} else if (c == '\\') {
135
	    IGNORE printf("\\\\");
2 7u83 136
	} else {
7 7u83 137
	    IGNORE putchar(c);
2 7u83 138
	}
139
    }
7 7u83 140
    return;
2 7u83 141
}
142
 
143
 
144
/*
145
    PRINT VALUE FIELD
146
 
147
    Routine to print the final value field of the machine processable index.
148
*/
149
 
7 7u83 150
static void
151
print_value(char *s)
2 7u83 152
{
7 7u83 153
    print_field_sep();
154
    print_escape(s);
155
    IGNORE putchar('\n');
156
    return;
2 7u83 157
}
158
 
159
 
160
/*
161
    PRINT EMPTY VALUE FIELD
162
 
163
    Routine to print the final empty value field of the machine processable
164
    index.
165
*/
166
 
7 7u83 167
static void
168
print_no_value(void)
2 7u83 169
{
7 7u83 170
    IGNORE printf("%c\n", field_sep);
171
    return;
2 7u83 172
}
173
 
174
 
175
/*
176
    PRINT SORT, INFO AND TYPE FIELDS
177
 
178
    Routine to print sort, info and type fields of the machine processable
179
    index.
180
*/
181
 
7 7u83 182
static void
183
print_sit_v(char *s, char *i, type *t, char *nm)
2 7u83 184
{
7 7u83 185
    IGNORE printf("%s%c%s%c", s, field_sep, i, field_sep);
186
    IGNORE print_type(stdout, t, nm, 0);
187
    return;
2 7u83 188
}
189
 
190
 
191
/*
192
    PRINT SORT AND TYPE FIELDS
193
 
194
    Routine to print sort, empty info, and type fields of the machine
195
    processable index.
196
*/
197
 
7 7u83 198
static void
199
print_st_v(char *s, type *t, char *nm)
2 7u83 200
{
7 7u83 201
    print_sit_v(s, "", t, nm);
202
    return;
2 7u83 203
}
204
 
205
 
206
/*
207
    PRINT SORT AND INFO FIELDS
208
 
209
    Routine to print sort, info, and empty type fields of the machine
210
    processable index.
211
*/
212
 
7 7u83 213
static void
214
print_si_v(char *s, char *i)
2 7u83 215
{
7 7u83 216
    IGNORE printf("%s%c%s%c", s, field_sep, i, field_sep);
217
    return;
2 7u83 218
}
219
 
220
 
221
/*
222
    PRINT SORT FIELD
223
 
224
    Routine to print sort, empty info, and empty type fields of the
225
    machine processable index.
226
*/
227
 
7 7u83 228
static void
229
print_s_v(char *s)
2 7u83 230
{
7 7u83 231
    IGNORE printf("%s%c%c", s, field_sep, field_sep);
232
    return;
2 7u83 233
}
234
 
235
 
236
/*
237
    PRINT SORT, INFO, TYPE AND EMPTY VALUE FIELDS
238
 
239
    Routine to print sort, info, type and empty value fields of the
240
    machine processable index.
241
*/
242
 
7 7u83 243
static void
244
print_sit(char *s, char *i, type *t, char *nm)
2 7u83 245
{
7 7u83 246
    print_sit_v(s, i, t, nm);
247
    print_no_value();
248
    return;
2 7u83 249
}
250
 
251
 
252
/*
253
    PRINT SORT, TYPE AND EMPTY VALUE FIELDS
254
 
255
    Routine to print sort, empty info, type and empty value fields of the
256
    machine processable index.
257
*/
258
 
7 7u83 259
static void
260
print_st(char *s, type *t, char *nm)
2 7u83 261
{
7 7u83 262
    print_st_v(s, t, nm);
263
    print_no_value();
264
    return;
2 7u83 265
}
266
 
267
 
268
/*
269
    PRINT SORT, INFO AND EMPTY VALUE FIELDS
270
 
271
    Routine to print sort, info, empty type and empty value fields of the
272
    machine processable index.
273
*/
274
 
7 7u83 275
static void
276
print_si(char *s, char *i)
2 7u83 277
{
7 7u83 278
    print_si_v(s, i);
279
    print_no_value();
280
    return;
2 7u83 281
}
282
 
283
 
284
/*
285
    PRINT SORT AND EMPTY VALUE FIELDS
286
 
287
    Routine to print sort, empty info, empty type and empty value fields
288
    of the machine processable index.
289
*/
290
 
7 7u83 291
static void
292
print_s(char *s)
2 7u83 293
{
7 7u83 294
    print_s_v(s);
295
    print_no_value();
296
    return;
2 7u83 297
}
298
 
299
 
300
/*
301
    IF STACK STATE
302
 
303
    This stack is used to keep track of the current +IF conditions.
304
*/
305
 
7 7u83 306
static object **if_stack = 0;
307
static int if_stack_sz = 0;
308
static int if_stack_index = 0;
2 7u83 309
 
310
 
311
/*
312
    STACK AN IF COMMAND OBJECT
313
 
314
    Routine to stack an object representing +IFxxx or +ELSE.
315
*/
316
 
7 7u83 317
static void
318
stack_if(object *p)
2 7u83 319
{
7 7u83 320
    if (if_stack_index == if_stack_sz) {
321
	if_stack_sz += 16;
322
	if_stack = realloc_nof(if_stack, object *, if_stack_sz);
2 7u83 323
    }
7 7u83 324
    if_stack [ if_stack_index ] = p;
325
    if_stack_index++;
326
    return;
2 7u83 327
}
328
 
329
 
330
/*
331
    UNSTACK AN IF COMMAND OBJECT
332
 
333
    Routine to unstack an object representing +IFxxx or +ELSE.
334
*/
335
 
7 7u83 336
static object *
337
unstack_if(void)
2 7u83 338
{
7 7u83 339
    return(if_stack [ --if_stack_index ]);
2 7u83 340
}
341
 
342
 
343
/*
344
    PRINT IF NESTING
345
 
346
    Routine to print the currently stacked +IFxxx and +ELSE nesting.
347
*/
348
 
7 7u83 349
static void
350
print_if_nest(void)
2 7u83 351
{
7 7u83 352
    int i;
353
    for (i = 0; i < if_stack_index; i++) {
354
	char code;
355
	object *p = if_stack [ i ];
356
	char *c = p->name;
2 7u83 357
 
7 7u83 358
	if (i > 0)print_escape(";");
359
	if (i + 1 < if_stack_index &&
360
	  if_stack [ i + 1 ]->u.u_num == CMD_ELSE) {
361
	    IGNORE printf("e");
362
	    i++;
2 7u83 363
	}
7 7u83 364
	switch (p->u.u_num)EXHAUSTIVE {
365
	    case CMD_IF: code = 'i'; break;
366
	    case CMD_IFDEF: code = 'd'; break;
367
	    case CMD_IFNDEF: code = 'n'; break;
2 7u83 368
	}
7 7u83 369
	IGNORE printf("%c", code);
370
	print_escape(":");
371
	print_escape(c);
2 7u83 372
    }
7 7u83 373
    return;
2 7u83 374
}
375
 
376
 
377
/*
378
    PRINT A MACHINE PROCESSABLE ITEM INDEX
379
 
380
    This routine prints the index item indicated by the token object p.
381
    u gives the token status, a the current file name, and e is used in
382
    enumeration items.  The output is in fields suitable for machine
383
    processing by tools such as 'awk'.
384
*/
385
 
7 7u83 386
static void
387
print_item_m(object *p, char *u, char *a, type *e)
2 7u83 388
{
7 7u83 389
    char *nm;
390
    char *ap;
391
    char *tnm = p->name;
392
    object *q = p->u.u_obj;
2 7u83 393
 
7 7u83 394
    if (q->objtype == OBJ_FIELD) {
395
	nm = q->u.u_field->fname;
2 7u83 396
    } else {
7 7u83 397
	nm = q->name;
2 7u83 398
    }
399
 
400
    /* Field 1: C_SYMBOL */
7 7u83 401
    print_field(nm);
2 7u83 402
 
403
    /* Field 2: TOKEN */
7 7u83 404
    print_field(tnm);
2 7u83 405
 
406
    /* Field 3: STATUS */
7 7u83 407
    IGNORE printf("%c%c", u [ 0 ], field_sep);
2 7u83 408
 
409
    /* Field 4: IF_NESTING */
7 7u83 410
    print_if_nest();
411
    print_field_sep();
2 7u83 412
 
413
    /* Field 5: API_LOCATION */
7 7u83 414
    for (ap = a; *ap && *ap != ':'; ap++)IGNORE putchar(*ap);
415
    print_field_sep();
2 7u83 416
 
417
    /* Field 6: FILE_LOCATION */
7 7u83 418
    if (*ap)ap++;
419
    for (; *ap && *ap != ':'; ap++)IGNORE putchar(*ap);
420
    print_field_sep();
2 7u83 421
 
422
    /* Field 7: LINE_LOCATION */
7 7u83 423
    IGNORE printf("%d%c", q->line_no, field_sep);
2 7u83 424
 
425
    /* Field 8: SUBSET_NESTING */
7 7u83 426
    if (*ap)IGNORE printf("%s", ap + 1);
427
    print_field_sep();
2 7u83 428
 
429
    /* Fields 9-12: SORT, INFO, TYPE, VALUE */
7 7u83 430
    switch (q->objtype) {
2 7u83 431
 
7 7u83 432
	case OBJ_CONST: {
433
	    print_st("const", q->u.u_type, null_str);
434
	    break;
2 7u83 435
	}
436
 
7 7u83 437
	case OBJ_ENUMVAL: {
438
	    print_field("enum_member");
439
	    print_type(stdout, e, null_str, 0);
440
	    print_field_sep();
441
	    if (q->u.u_str) {
442
		print_value(q->u.u_str);
2 7u83 443
	    } else {
7 7u83 444
		print_no_value();
2 7u83 445
	    }
7 7u83 446
	    break;
2 7u83 447
	}
448
 
7 7u83 449
	case OBJ_EXP: {
450
	    type *t = q->u.u_type;
451
	    char *s = (t->id == TYPE_LVALUE ? "lvalue" : "rvalue");
452
	    print_st(s, t, null_str);
453
	    break;
2 7u83 454
	}
455
 
7 7u83 456
	case OBJ_EXTERN: {
457
	    type *t = q->u.u_type;
458
	    if (t->id == TYPE_LVALUE)t = t->u.subtype;
459
	    if (t->id == TYPE_PROC) {
460
		print_sit("func", "extern", t, nm);
2 7u83 461
	    } else {
7 7u83 462
		print_st("extern", t, null_str);
2 7u83 463
	    }
7 7u83 464
	    break;
2 7u83 465
	}
466
 
7 7u83 467
	case OBJ_WEAK: {
468
	    type *t = q->u.u_type;
469
	    print_sit("func", "weak", t, nm);
470
	    break;
2 7u83 471
	}
472
 
7 7u83 473
	case OBJ_DEFINE: {
474
	    char *s = q->u.u_str;
475
	    if (*s == '(') {
476
		print_field("define");
477
		print_field("param");
478
		for (; *s && *s != ')'; s++) {
479
		    IGNORE putchar(*s);
2 7u83 480
		}
7 7u83 481
		if (*s == ')')s++;
482
		IGNORE printf(")");
2 7u83 483
	    } else {
7 7u83 484
		print_s_v("define");
2 7u83 485
	    }
7 7u83 486
	    while (*s == ' ')s++;
487
	    print_value(s);
488
	    break;
2 7u83 489
	}
490
 
7 7u83 491
	case OBJ_DEFMIN: {
492
	    char *s = q->u.u_str;
493
	    if (*s == '(') {
494
		print_field("defmin");
495
		print_field("param");
496
		for (; *s && *s != ')'; s++) {
497
		    IGNORE putchar(*s);
498
		}
499
		if (*s == ')')s++;
500
		IGNORE printf(")");
501
	    } else {
502
		print_s_v("defmin");
503
	    }
504
	    while (*s == ' ')s++;
505
	    print_value(s);
506
	    break;
2 7u83 507
	}
508
 
7 7u83 509
	case OBJ_FIELD: {
510
	    field *f = q->u.u_field;
511
	    print_field("member");
512
	    print_type(stdout, f->stype, null_str, 0);
513
	    print_field_sep();
514
	    print_type(stdout, f->ftype, null_str, 0);
515
	    print_no_value();
516
	    break;
2 7u83 517
	}
518
 
7 7u83 519
	case OBJ_FUNC: {
520
	    print_st("func", q->u.u_type, nm);
521
	    break;
2 7u83 522
	}
523
 
7 7u83 524
	case OBJ_MACRO: {
525
	    print_st("macro", q->u.u_type, nm);
526
	    break;
2 7u83 527
	}
528
 
7 7u83 529
	case OBJ_NAT: {
530
	    print_s("nat");
531
	    break;
532
	}
533
 
534
	case OBJ_STATEMENT: {
535
	    type *t = q->u.u_type;
536
	    if (t) {
537
		print_sit("statement", "param", t, null_str);
2 7u83 538
	    } else {
7 7u83 539
		print_s("statement");
2 7u83 540
	    }
7 7u83 541
	    break;
2 7u83 542
	}
543
 
7 7u83 544
	case OBJ_TOKEN: {
545
	    print_s_v("token");
546
	    print_value(q->u.u_str);
547
	    break;
2 7u83 548
	}
549
 
7 7u83 550
	case OBJ_TYPE: {
551
	    type *t = q->u.u_type;
552
	    int i = t->id;
553
	    switch (i) {
2 7u83 554
 
7 7u83 555
		case TYPE_DEFINED: {
556
		    print_st("typedef", t->v.next, null_str);
557
		    break;
2 7u83 558
		}
559
 
7 7u83 560
		case TYPE_GENERIC: {
561
		    print_s("opaque");
562
		    break;
2 7u83 563
		}
564
 
7 7u83 565
		case TYPE_INT: {
566
		    print_s("integral");
567
		    break;
2 7u83 568
		}
569
 
7 7u83 570
		case TYPE_SIGNED: {
571
		    print_s("signed_integral");
572
		    break;
2 7u83 573
		}
574
 
7 7u83 575
		case TYPE_UNSIGNED: {
576
		    print_s("unsigned_integral");
577
		    break;
2 7u83 578
		}
579
 
7 7u83 580
		case TYPE_PROMOTE: {
581
		    print_field("promotion");
582
		    print_type(stdout, t->v.next, null_str, 0);
583
		    print_field_sep();
584
		    print_no_value();
585
		    break;
2 7u83 586
		}
587
 
7 7u83 588
		case TYPE_FLOAT: {
589
		    print_s("floating");
590
		    break;
2 7u83 591
		}
592
 
7 7u83 593
		case TYPE_ARITH: {
594
		    print_s("arithmetic");
595
		    break;
2 7u83 596
		}
597
 
7 7u83 598
		case TYPE_SCALAR: {
599
		    print_s("scalar");
600
		    break;
2 7u83 601
		}
602
 
7 7u83 603
		case TYPE_STRUCT:
604
		case TYPE_STRUCT_TAG:
605
		case TYPE_UNION:
606
		case TYPE_UNION_TAG:
607
		case TYPE_ENUM:
608
		case TYPE_ENUM_TAG: {
609
		    char *s;
610
		    type *en = null;
611
		    object *r = t->v.obj2;
612
		    char *inf = (r ? "exact" : "");
613
		    switch (i)EXHAUSTIVE {
614
			case TYPE_STRUCT: s = "struct"; break;
615
			case TYPE_STRUCT_TAG: s = "struct_tag"; break;
616
			case TYPE_UNION: s = "union"; break;
617
			case TYPE_UNION_TAG: s = "union_tag"; break;
618
			case TYPE_ENUM: s = "enum"; en = t; break;
619
			case TYPE_ENUM_TAG: s = "enum_tag"; en = t; break;
2 7u83 620
		    }
7 7u83 621
		    print_si(s, inf);
622
		    while (r) {
623
			print_item_m(r, u, a, en);
624
			r = r->next;
2 7u83 625
		    }
7 7u83 626
		    break;
2 7u83 627
		}
628
 
629
		default : {
7 7u83 630
		    error(ERR_INTERNAL, "Unknown type identifier, '%d'", i);
631
		    break;
2 7u83 632
		}
633
	    }
7 7u83 634
	    break;
2 7u83 635
	}
636
 
637
	default : {
7 7u83 638
	    error(ERR_INTERNAL, "Unknown object type, '%d'", q->objtype);
639
	    break;
2 7u83 640
	}
641
    }
7 7u83 642
    return;
2 7u83 643
}
644
 
645
 
646
/*
647
    PRINT AN INDEX ITEM
648
 
649
    This routine prints the index item indicated by the token object p.
650
    u gives the token status, a the current file name, and e is used in
651
    enumeration items.  The output is in a humun readable format.
652
*/
653
 
7 7u83 654
static void
655
print_item_h(object *p, char *u, char *a, type *e)
2 7u83 656
{
7 7u83 657
    char *tnm = p->name;
658
    object *q = p->u.u_obj;
659
    char *nm = q->name;
660
    IGNORE printf("TOKEN: %s\n", tnm);
661
    IGNORE printf("STATUS: %s", u);
662
    if (building_libs == 0)IGNORE printf(" (not library building)");
663
    if (building_libs == 2)IGNORE printf(" (library building only)");
664
    IGNORE printf("\nDEFINED: %s, line %d\n", a, q->line_no);
665
    IGNORE printf("INFO: ");
666
    if (commented_out == 2)IGNORE printf("(commented out) ");
2 7u83 667
 
7 7u83 668
    switch (q->objtype) {
2 7u83 669
 
7 7u83 670
	case OBJ_CONST: {
671
	    IGNORE printf("%s is a constant expression of type ", nm);
672
	    print_type(stdout, q->u.u_type, null_str, 0);
673
	    IGNORE printf("\n\n");
674
	    break;
2 7u83 675
	}
676
 
7 7u83 677
	case OBJ_ENUMVAL: {
678
	    IGNORE printf("%s is a member of the enumeration type ", nm);
679
	    print_type(stdout, e, null_str, 0);
680
	    IGNORE printf("\n\n");
681
	    break;
2 7u83 682
	}
683
 
7 7u83 684
	case OBJ_EXP: {
685
	    IGNORE printf("%s is an expression of type ", nm);
686
	    print_type(stdout, q->u.u_type, null_str, 0);
687
	    IGNORE printf("\n\n");
688
	    break;
2 7u83 689
	}
690
 
7 7u83 691
	case OBJ_EXTERN: {
692
	    type *t = q->u.u_type;
693
	    if (t->id == TYPE_LVALUE)t = t->u.subtype;
694
	    IGNORE printf("%s is an external ", nm);
695
	    if (t->id == TYPE_PROC) {
696
		IGNORE printf("function with prototype ");
697
		print_type(stdout, t, nm, 0);
2 7u83 698
	    } else {
7 7u83 699
		IGNORE printf("expression with type ");
700
		print_type(stdout, t, null_str, 0);
2 7u83 701
	    }
7 7u83 702
	    IGNORE printf("\n\n");
703
	    break;
2 7u83 704
	}
705
 
7 7u83 706
	case OBJ_WEAK: {
707
	    type *t = q->u.u_type;
708
	    IGNORE printf("%s is an external ", nm);
709
	    IGNORE printf("function with weak prototype ");
710
	    print_type(stdout, t, nm, 0);
711
	    IGNORE printf("\n\n");
712
	    break;
2 7u83 713
	}
714
 
7 7u83 715
	case OBJ_DEFINE: {
716
	    char *s = q->u.u_str;
717
	    IGNORE printf("%s is a macro ", nm);
718
	    if (*s == '(') {
719
		IGNORE printf("with arguments ");
720
		for (; *s && *s != ')'; s++) {
721
		    IGNORE putchar(*s);
2 7u83 722
		}
7 7u83 723
		if (*s == ')')s++;
724
		IGNORE printf(") ");
2 7u83 725
	    }
7 7u83 726
	    while (*s == ' ')s++;
727
	    IGNORE printf("defined to be %s\n\n", s);
728
	    break;
2 7u83 729
	}
730
 
7 7u83 731
	case OBJ_DEFMIN: {
732
	    char *s = q->u.u_str;
733
	    IGNORE printf("%s is a macro ", nm);
734
	    if (*s == '(') {
735
		IGNORE printf("with arguments ");
736
		for (; *s && *s != ')'; s++) {
737
		    IGNORE putchar(*s);
738
		}
739
		if (*s == ')')s++;
740
		IGNORE printf(") ");
741
	    }
742
	    while (*s == ' ')s++;
743
	    IGNORE printf("defined to be minimum %s\n\n", s);
744
	    break;
2 7u83 745
	}
746
 
7 7u83 747
	case OBJ_FIELD: {
748
	    field *f = q->u.u_field;
749
	    IGNORE printf("%s is a field selector of ", f->fname);
750
	    print_type(stdout, f->stype, null_str, 0);
751
	    IGNORE printf(" of type ");
752
	    print_type(stdout, f->ftype, null_str, 0);
753
	    IGNORE printf("\n\n");
754
	    break;
2 7u83 755
	}
756
 
7 7u83 757
	case OBJ_FUNC: {
758
	    IGNORE printf("%s is a function with prototype ", nm);
759
	    print_type(stdout, q->u.u_type, nm, 0);
760
	    IGNORE printf("\n\n");
761
	    break;
2 7u83 762
	}
763
 
7 7u83 764
	case OBJ_MACRO: {
765
	    IGNORE printf("%s is a macro with prototype ", nm);
766
	    print_type(stdout, q->u.u_type, nm, 0);
767
	    IGNORE printf("\n\n");
768
	    break;
2 7u83 769
	}
770
 
7 7u83 771
	case OBJ_NAT: {
772
	    IGNORE printf("%s is a constant integer\n\n", nm);
773
	    break;
774
	}
775
 
776
	case OBJ_STATEMENT: {
777
	    type *t = q->u.u_type;
778
	    IGNORE printf("%s is a statement", nm);
779
	    if (t) {
780
		IGNORE printf(" with arguments");
781
		print_type(stdout, t, null_str, 0);
2 7u83 782
	    }
7 7u83 783
	    IGNORE printf("\n\n");
784
	    break;
2 7u83 785
	}
786
 
7 7u83 787
	case OBJ_TOKEN: {
788
	    IGNORE printf("%s is a complex token\n\n", nm);
789
	    break;
2 7u83 790
	}
791
 
7 7u83 792
	case OBJ_TYPE: {
793
	    type *t = q->u.u_type;
794
	    int i = t->id;
795
	    print_type(stdout, t, null_str, 0);
796
	    switch (i) {
2 7u83 797
 
7 7u83 798
		case TYPE_DEFINED: {
799
		    IGNORE printf(" is a type defined to be ");
800
		    print_type(stdout, t->v.next, null_str, 0);
801
		    IGNORE printf("\n\n");
802
		    break;
2 7u83 803
		}
804
 
7 7u83 805
		case TYPE_GENERIC: {
806
		    IGNORE printf(" is a type\n\n");
807
		    break;
2 7u83 808
		}
809
 
7 7u83 810
		case TYPE_INT: {
811
		    IGNORE printf(" is an integral type\n\n");
812
		    break;
2 7u83 813
		}
814
 
7 7u83 815
		case TYPE_SIGNED: {
816
		    IGNORE printf(" is a signed integral type\n\n");
817
		    break;
2 7u83 818
		}
819
 
7 7u83 820
		case TYPE_UNSIGNED: {
821
		    IGNORE printf(" is an unsigned integral type\n\n");
822
		    break;
2 7u83 823
		}
824
 
7 7u83 825
		case TYPE_PROMOTE: {
826
		    IGNORE printf(" is the integral promotion of ");
827
		    print_type(stdout, t->v.next, null_str, 0);
828
		    IGNORE printf("\n\n");
829
		    break;
2 7u83 830
		}
831
 
7 7u83 832
		case TYPE_FLOAT: {
833
		    IGNORE printf(" is a floating type\n\n");
834
		    break;
2 7u83 835
		}
836
 
7 7u83 837
		case TYPE_ARITH: {
838
		    IGNORE printf(" is an arithmetic type\n\n");
839
		    break;
2 7u83 840
		}
841
 
7 7u83 842
		case TYPE_SCALAR: {
843
		    IGNORE printf(" is a scalar type\n\n");
844
		    break;
2 7u83 845
		}
846
 
7 7u83 847
		case TYPE_STRUCT:
848
		case TYPE_STRUCT_TAG:
849
		case TYPE_UNION:
850
		case TYPE_UNION_TAG: {
851
		    char *n;
852
		    object *r = t->v.obj2;
853
		    switch (i)EXHAUSTIVE {
854
			case TYPE_STRUCT: n = "structure"; break;
855
			case TYPE_STRUCT_TAG: n = "structure"; break;
856
			case TYPE_UNION: n = "union"; break;
857
			case TYPE_UNION_TAG: n = "union"; break;
2 7u83 858
		    }
7 7u83 859
		    if (r == null) {
860
			IGNORE printf(" is an inexact %s type\n\n", n);
2 7u83 861
		    } else {
7 7u83 862
			IGNORE printf(" is an exact %s type\n\n", n);
863
			while (r) {
864
			    print_item_h(r, u, a,(type *)null);
865
			    r = r->next;
2 7u83 866
			}
867
		    }
7 7u83 868
		    break;
2 7u83 869
		}
870
 
7 7u83 871
		case TYPE_ENUM:
872
		case TYPE_ENUM_TAG: {
873
		    object *r = t->v.obj2;
874
		    IGNORE printf(" is an enumeration type\n\n");
875
		    while (r) {
876
			print_item_h(r, u, a, t);
877
			r = r->next;
2 7u83 878
		    }
7 7u83 879
		    break;
2 7u83 880
		}
881
 
882
		default : {
7 7u83 883
		    IGNORE printf(" is a type\n\n");
884
		    error(ERR_INTERNAL, "Unknown type identifier, '%d'", i);
885
		    break;
2 7u83 886
		}
887
	    }
7 7u83 888
	    break;
2 7u83 889
	}
890
 
891
	default : {
7 7u83 892
	    error(ERR_INTERNAL, "Unknown object type, '%d'", q->objtype);
893
	    break;
2 7u83 894
	}
895
    }
7 7u83 896
    return;
2 7u83 897
}
898
 
899
 
900
/*
901
    PRINT INDEX USING PRINT ITEM FUNCTION
902
 
903
    This routine prints an index of the set object input using fn.
904
*/
905
 
7 7u83 906
typedef void (*index_func)(object *, char *, char *, type *);
2 7u83 907
 
7 7u83 908
static void
909
print_index_with(object *input, index_func fn)
2 7u83 910
{
7 7u83 911
    object *p = input->u.u_obj;
912
    info *i = p->u.u_info;
913
    char *a = p->name;
914
    char *u = (i->implemented ? "implemented" : "used");
915
    for (p = i->elements; p != null; p = p->next) {
916
	switch (p->objtype) {
2 7u83 917
 
7 7u83 918
	    case OBJ_IF: {
2 7u83 919
		/* Deal with preprocessing directives */
7 7u83 920
		char *c = p->name;
921
		if (fn == print_item_m) {
922
		    switch (p->u.u_num) {
923
			case CMD_IF:
924
			case CMD_IFDEF:
925
			case CMD_IFNDEF:
926
			case CMD_ELSE: {
927
			    stack_if (p);
928
			    break;
2 7u83 929
			}
7 7u83 930
			case CMD_ENDIF: {
931
			    if (unstack_if () ->u.u_num == CMD_ELSE) {
932
				IGNORE unstack_if ();
2 7u83 933
			    }
7 7u83 934
			    break;
2 7u83 935
			}
936
		    }
7 7u83 937
		} else if (streq(c, BUILDING_MACRO)) {
2 7u83 938
		    /* Check for the building_libs macro */
7 7u83 939
		    switch (p->u.u_num) {
940
			case CMD_IF:
941
			case CMD_IFDEF: {
942
			    building_libs = 2;
943
			    break;
2 7u83 944
			}
7 7u83 945
			case CMD_IFNDEF: {
946
			    building_libs = 0;
947
			    break;
2 7u83 948
			}
7 7u83 949
			case CMD_ELSE: {
950
			    building_libs = 2 - building_libs;
951
			    break;
2 7u83 952
			}
7 7u83 953
			case CMD_ENDIF: {
954
			    building_libs = 1;
955
			    break;
2 7u83 956
			}
957
		    }
958
		} else {
959
		    /* Check for integers */
7 7u83 960
		    int n = 0;
961
		    while (*c == '-')c++;
962
		    while (*c >= '0' && *c <= '9') {
963
			n = 10 * n + (*c - '0');
964
			c++;
2 7u83 965
		    }
7 7u83 966
		    if (*c == 0) {
967
			switch (p->u.u_num) {
968
			    case CMD_IF: {
969
				commented_out = (n ? 0 : 2);
970
				break;
2 7u83 971
			    }
7 7u83 972
			    case CMD_ELSE: {
973
				commented_out = 2 - commented_out;
974
				break;
2 7u83 975
			    }
7 7u83 976
			    case CMD_ENDIF: {
977
				commented_out = 1;
978
				break;
2 7u83 979
			    }
980
			}
981
		    }
982
		}
7 7u83 983
		break;
2 7u83 984
	    }
985
 
7 7u83 986
	    case OBJ_SET: {
2 7u83 987
		/* Deal with subsets */
7 7u83 988
		print_index_with(p, fn);
989
		break;
2 7u83 990
	    }
991
 
7 7u83 992
	    case OBJ_TOKEN: {
2 7u83 993
		/* Deal with tokens */
7 7u83 994
		if (i->implemented || !restrict_use) {
995
		   (*fn)(p, u, a,(type *)null);
2 7u83 996
		}
7 7u83 997
		break;
2 7u83 998
	    }
999
	}
1000
    }
7 7u83 1001
    return;
2 7u83 1002
}
1003
 
1004
 
1005
/*
1006
    PRINT MACHINE PROCESSABLE INDEX
1007
 
1008
    This routine prints an index intended for machine processing of the
1009
    set object input.
1010
*/
1011
 
7 7u83 1012
void
1013
print_machine_index(object *input)
2 7u83 1014
{
7 7u83 1015
    print_index_with(input, print_item_m);
1016
    return;
2 7u83 1017
}
1018
 
1019
 
1020
/*
1021
    PRINT INDEX
1022
 
1023
    This routine prints an index intended for human readers of the set
1024
    object input.
1025
*/
1026
 
7 7u83 1027
void
1028
print_index(object *input)
2 7u83 1029
{
7 7u83 1030
    print_index_with(input, print_item_h);
1031
    return;
2 7u83 1032
}