Subversion Repositories tendra.SVN

Rev

Rev 2 | 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 "c_types.h"
63
#include "hashid_ops.h"
64
#include "id_ops.h"
65
#include "tok_ops.h"
66
#include "error.h"
67
#include "catalog.h"
68
#include "option.h"
69
#include "char.h"
70
#include "declare.h"
71
#include "dump.h"
72
#include "file.h"
73
#include "lex.h"
74
#include "hash.h"
75
#include "macro.h"
76
#include "parse.h"
77
#include "pragma.h"
78
#include "predict.h"
79
#include "preproc.h"
80
#include "psyntax.h"
81
#include "redeclare.h"
82
#include "statement.h"
83
#include "symbols.h"
84
#include "tok.h"
85
#include "token.h"
86
#include "ustring.h"
87
#include "variable.h"
88
 
89
 
90
/*
91
    CHECK THAT PRAGMA SYNTAX AND MAIN SYNTAX ARE IN STEP
92
 
93
    By including both psyntax.h and syntax.h, the compiler will check
94
    that the lex_* macros defined in each are consistent.  Note that
95
    because the #pragma syntax is the same for both C and C++, this
96
    also checks the consistency of the C and C++ syntaxes.  This is only
97
    done in development mode.
98
*/
99
 
100
#ifdef DEBUG
101
#include "syntax.h"
102
#endif
103
 
104
 
105
/*
106
    READ A PREPROCESSING TOKEN
107
 
108
    This routine reads the next preprocessing token from the input file.
109
*/
110
 
7 7u83 111
static PPTOKEN *
112
get_token(void)
2 7u83 113
{
7 7u83 114
	PPTOKEN *p = new_pptok();
115
	int t = read_token();
116
	update_column();
117
	p->tok = t;
118
	p->pp_space = WHITE_SPACE;
119
	p->next = NULL;
120
	if (t <= LAST_COMPLEX_TOKEN) {
121
		token_parts(t, p);
122
	}
123
	return(p);
2 7u83 124
}
125
 
126
 
127
/*
128
    FIND A KEYWORD LEXICAL TOKEN NUMBER
129
 
130
    This routine finds the lexical token corresponding to the identifier id.
131
    If id does not represent an underlying keyword then an error is reported
132
    and lex_identifier is returned.
133
*/
134
 
7 7u83 135
int
136
find_keyword(IDENTIFIER id)
2 7u83 137
{
7 7u83 138
	HASHID nm = DEREF_hashid(id_name(id));
139
	int t = find_hashid(nm);
140
	if (t == lex_identifier) {
141
		report(preproc_loc, ERR_pragma_keyword_bad(nm));
142
	}
143
	return(t);
2 7u83 144
}
145
 
146
 
147
/*
148
    DEFINE A KEYWORD
149
 
150
    This routine defines id to be a keyword with lexical token number t.
151
    Certain language extensions are implemented by tokens disguised as
152
    keywords.
153
*/
154
 
7 7u83 155
void
156
define_keyword(IDENTIFIER id, int t)
2 7u83 157
{
7 7u83 158
	switch (t) {
159
	case lex_identifier: {
160
		break;
2 7u83 161
	}
7 7u83 162
	case lex_representation: {
163
		TOKEN tok = make_sort("ZZZ", 1);
164
		id = make_token_decl(tok, 0, id, id);
165
		token_interface(id, lex_no_Hdef);
166
		COPY_int(tok_proc_key(tok), t);
167
		break;
2 7u83 168
	}
7 7u83 169
	case lex_typeof: {
170
		TOKEN tok = make_sort("SE", 1);
171
		id = make_token_decl(tok, 0, id, id);
172
		token_interface(id, lex_no_Hdef);
173
		COPY_int(tok_proc_key(tok), t);
174
		break;
2 7u83 175
	}
7 7u83 176
	default: {
177
		HASHID nm = DEREF_hashid(id_name(id));
178
		IGNORE make_keyword(nm, t, NULL_id);
179
		break;
2 7u83 180
	}
7 7u83 181
	}
182
	return;
2 7u83 183
}
184
 
185
 
186
/*
187
    UNDEFINE A KEYWORD
188
 
189
    This routine undefines the keyword id.
190
*/
191
 
7 7u83 192
void
193
undef_keyword(IDENTIFIER id)
2 7u83 194
{
7 7u83 195
	unsigned tag;
196
	HASHID nm = DEREF_hashid(id_name(id));
197
	PTR(IDENTIFIER)ptr = hashid_id(nm);
198
	do {
199
		IDENTIFIER pid = DEREF_id(ptr);
200
		tag = TAG_id(pid);
201
		switch (tag) {
202
		case id_keyword_tag:
203
		case id_iso_keyword_tag:
204
		case id_reserved_tag:
205
			/* Undefine a keyword */
206
			if (do_keyword) {
207
				dump_undefine(pid, &preproc_loc, 1);
208
			}
209
			pid = DEREF_id(id_alias(pid));
210
			COPY_id(ptr, pid);
211
			COPY_id(hashid_cache(nm), NULL_id);
212
			return;
213
		}
214
		ptr = id_alias(pid);
215
	} while (tag != id_dummy_tag);
216
	return;
2 7u83 217
}
218
 
219
 
220
/*
221
    RESCAN A PRAGMA STATEMENT
222
 
223
    The routine read_tendra replaces all identifier tokens within a '#pragma'
224
    command by their corresponding underlying keywords.  This routine restores
225
    these keywords, except that given by s, to identifiers.
226
*/
227
 
7 7u83 228
void
229
rescan_pragma(int s)
2 7u83 230
{
7 7u83 231
	PPTOKEN *p;
232
	for (p = crt_token; p != NULL; p = p->next) {
233
		int t = p->tok;
234
		if (t >= FIRST_KEYWORD && t <= LAST_KEYWORD && t != s) {
235
			p->tok = lex_identifier;
236
		}
2 7u83 237
	}
7 7u83 238
	return;
2 7u83 239
}
240
 
241
 
242
/*
243
    SET A TOKEN TO A KEYWORD
244
 
245
    This routine sets the preprocessing token p to the keyword corresponding
246
    to the lexical token number t.
247
*/
248
 
7 7u83 249
static void
250
set_token(PPTOKEN *p, int t)
2 7u83 251
{
7 7u83 252
	HASHID nm = KEYWORD(t);
253
	p->tok = t;
254
	p->pp_data.id.hash = nm;
255
	p->pp_data.id.use = DEREF_id(hashid_id(nm));
256
	return;
2 7u83 257
}
258
 
259
 
260
/*
261
    PATCH A PRAGMA STATEMENT
262
 
263
    This routine is used by the preprocessor to preserve a '#pragma'
264
    statement.  The arguments are as in parse_pragma.
265
*/
266
 
7 7u83 267
static void
268
patch_pragma(PPTOKEN *p, int tendra)
2 7u83 269
{
7 7u83 270
	p = clean_tok_list(p);
271
	switch (p->tok) {
272
	case lex_interface: {
273
		int t = crt_interface;
274
		if (t == lex_ignore && tendra) {
275
			t = lex_reject;
276
		}
277
		set_token(p, t);
278
		break;
2 7u83 279
	}
7 7u83 280
	case lex_member:
281
		if (!tendra) {
282
			if (p->next->tok == lex_definition) {
283
				set_token(p, lex_define_Hcap);
284
				set_token(p->next, lex_member_Hcap);
285
			}
2 7u83 286
		}
7 7u83 287
		break;
288
	case lex_promoted:
289
		if (!tendra) {
290
			set_token(p, lex_promote);
291
		}
292
		break;
293
	case lex_reject:
294
		if (!tendra) {
295
			set_token(p, lex_ignore);
296
		}
297
		break;
2 7u83 298
	}
7 7u83 299
	patch_preproc_dir(p);
300
	if (tendra) {
301
		p = patch_tokens(tendra);
302
		set_token(p, lex_tendra);
303
		if (tendra == 2)p->next->tok = lex_plus_Hplus;
2 7u83 304
	}
7 7u83 305
	return;
2 7u83 306
}
307
 
308
 
309
/*
310
    PARSE A PRAGMA STATEMENT
311
 
312
    This routine parses the '#pragma' statement given by the preprocessing
313
    tokens p.  tendra is 1 for '#pragma TenDRA' statements, 2 for '#pragma
314
    TenDRA++' statements, and 0 otherwise.
315
*/
316
 
7 7u83 317
static int
318
parse_pragma(PPTOKEN *p, int tendra)
2 7u83 319
{
7 7u83 320
	int nt;
321
	PPTOKEN *pt;
322
	PARSE_STATE s;
323
	int pp = preproc_only;
324
	int tok = lex_ignore_token;
2 7u83 325
 
7 7u83 326
	/* Parsing action */
327
	new_linkage = crt_linkage;
328
	save_state(&s, 0);
329
	init_parser(p);
330
	crt_loc = preproc_loc;
331
	crt_line_changed = 1;
332
	ADVANCE_LEXER;
333
	if (pp) {
334
		parse_preproc(&tok);
335
		if (tok != lex_ignore_token) {
336
			tok = lex_ignore_token;
337
			have_syntax_error = 1;
338
		}
339
	} else {
340
		parse_tendra(&tok);
2 7u83 341
	}
7 7u83 342
	nt = crt_lex_token;
343
	pt = crt_token;
344
	p = restore_parser();
2 7u83 345
 
7 7u83 346
	/* Check for end of input */
347
	switch (tok) {
348
	case lex_set:
349
	case lex_unused: {
350
		/* Patch inset pragma statements */
351
		PPTOKEN *q = clean_tok_list(p);
352
		PPTOKEN *r = new_pptok();
353
		p = q;
354
		p->tok = tok;
355
		while (q->tok != lex_newline) {
356
			q = q->next;
357
		}
358
		q->tok = lex_inset_Hend;
359
		r->tok = lex_newline;
360
		r->next = q->next;
361
		q->next = r;
362
		patch_preproc_dir(p);
363
		tok = lex_inset_Hstart;
364
		p = NULL;
365
		break;
2 7u83 366
	}
7 7u83 367
	default:
368
		/* Should have reached the end of the line */
369
		if (nt != lex_newline && !have_syntax_error) {
370
			ERROR err = ERR_lex_parse(pt);
371
			err = concat_error(err, ERR_cpp_end(lex_pragma));
372
			report(preproc_loc, err);
373
		}
374
		break;
2 7u83 375
	}
376
 
7 7u83 377
	/* Preprocessing action */
378
	if (pp) {
379
		patch_pragma(p, tendra);
380
		tok = lex_hash_Hpragma;
381
	} else {
382
		free_tok_list(p);
383
	}
384
	restore_state(&s);
385
	crt_linkage = new_linkage;
386
	return(tok);
2 7u83 387
}
388
 
389
 
390
/*
391
    SKIP TO NEXT COLON
392
 
393
    This routine scans along the list of preprocessing tokens p until it
394
    finds the first colon.  It then returns the following token.  The null
395
    token is returned if there is no colon in p.
396
*/
397
 
7 7u83 398
static PPTOKEN *
399
skip_to_colon(PPTOKEN *p)
2 7u83 400
{
7 7u83 401
	while (p) {
402
		PPTOKEN *q = p->next;
403
		if (p->tok == lex_colon) {
404
			return(q);
405
		}
406
		p = q;
407
	}
408
	return(NULL);
2 7u83 409
}
410
 
411
 
412
/*
413
    MARK A TOKEN PARAMETER
414
 
415
    This routine marks the TDF token parameter given by the preprocessing
416
    tokens p.  This consists of an optional 'TAG' followed by an identifier,
417
    which is optional if n is false.  Macro expansion of this identifier
418
    is inhibited.  Macro is true if the identifier is declared in the
419
    token namespace.
420
*/
421
 
7 7u83 422
static PPTOKEN *
423
mark_tdf_param(PPTOKEN *p, int n, int macro)
2 7u83 424
{
7 7u83 425
	if (p && p->tok == lex_identifier) {
426
		int t = find_hashid(p->pp_data.id.hash);
427
		if (t == lex_tag_Hcap) {
428
			if (p->next && p->next->tok == lex_identifier) {
429
				/* Have 'TAG id' */
430
				p->tok = t;
431
				p = p->next;
432
				p->pp_data.id.use = NULL_id;
433
			} else {
434
				/* Have 'TAG' */
435
				if (n == 0) {
436
					/* Interpret as 'TAG' */
437
					p->tok = t;
438
				} else {
439
					/* Interpret as 'id' where id = TAG */
440
					p->pp_data.id.use = NULL_id;
441
				}
442
			}
2 7u83 443
		} else {
7 7u83 444
			/* Have 'id' */
445
			if (macro && preproc_only) {
446
				/* Mark macro names when preprocessing */
447
				HASHID nm = p->pp_data.id.hash;
448
				unsigned c = check_macro(nm, 0);
449
				IDENTIFIER id =
450
				    underlying_id(p->pp_data.id.use);
451
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
452
				ds |= dspec_token;
453
				COPY_dspec(id_storage(id), ds);
454
				if (c == PP_TRUE) {
455
					/* Token previously defined as macro */
456
					PPTOKEN *q;
457
					token_macro = DEREF_id(hashid_id(nm));
458
					IGNORE patch_cond(lex_hash_Hop,
459
							  lex_define);
460
					q = patch_tokens(2);
461
					q->tok = lex_builtin_Hfile;
462
					q->next->tok = lex_hash_Hop;
463
				}
464
			}
465
			p->pp_data.id.use = NULL_id;
2 7u83 466
		}
7 7u83 467
		return(p->next);
2 7u83 468
	}
7 7u83 469
	if (n) {
470
		return(NULL);
471
	}
472
	return(p);
2 7u83 473
}
474
 
475
 
476
/*
477
    MARK A TOKEN PROGRAM PARAMETER
478
 
479
    This routine marks the TDF token program parameter given by the
480
    preprocessing tokens p.
481
*/
482
 
7 7u83 483
static PPTOKEN *
484
mark_prog_param(PPTOKEN *p)
2 7u83 485
{
7 7u83 486
	if (p && p->tok == lex_identifier) {
487
		int t = find_hashid(p->pp_data.id.hash);
488
		switch (t) {
489
		case lex_exp_Hcap:
490
		case lex_nat_Hcap:
491
		case lex_int_Hcap:
492
		case lex_stmt_Hcap:
493
		case lex_proc_Hcap:
494
			/* Have the form 'EXP id' etc */
495
			p->tok = t;
496
			p = p->next;
497
			if (p) {
498
				p = p->next;
2 7u83 499
			}
7 7u83 500
			return(p);
501
		case lex_type_Hcap: {
502
			/* Have the form 'TYPE t' */
503
			int depth = 0;
504
			p->tok = t;
505
			while (p) {
506
				/* Step over type */
507
				switch (p->tok) {
508
				case lex_open_Hround:
509
				case lex_open_Hsquare_H1:
510
				case lex_open_Hsquare_H2:
511
					depth++;
512
					break;
513
				case lex_close_Hround:
514
				case lex_close_Hsquare_H1:
515
				case lex_close_Hsquare_H2:
516
					if (depth > 0) {
517
						depth--;
518
					}
519
					break;
520
				case lex_comma:
521
					if (depth == 0) {
522
						return(p);
523
					}
524
					break;
525
				case lex_close_Hbrace_H1:
526
				case lex_close_Hbrace_H2:
527
					return(p);
528
				}
529
				p = p->next;
2 7u83 530
			}
7 7u83 531
			break;
532
		}
533
		case lex_member_Hcap:
534
			/* Have the form 'MEMBER t : id' */
535
			p->tok = t;
536
			p = skip_to_colon(p->next);
537
			if (p) {
538
				p = p->next;
2 7u83 539
			}
7 7u83 540
			return(p);
2 7u83 541
		}
542
	}
7 7u83 543
	return(NULL);
2 7u83 544
}
545
 
546
 
547
/*
548
    MARK A PRAGMA TOKEN STATEMENT
549
 
550
    The macro expansion of '#pragma token' statements is rather complex.
551
    The token syntax skeleton is not subject to macro expansion, while
552
    any types etc. involved in the specification are.  This routine marks
553
    the skeleton keywords in the list of preprocessing tokens p, returning
554
    the token immediately following the token specification.  It also sets
555
    macro to true if the declared token lies in the macro namespace.
556
*/
557
 
7 7u83 558
static PPTOKEN *
559
mark_tdf_token(PPTOKEN *p, int *macro)
2 7u83 560
{
7 7u83 561
	if (p == NULL) {
562
		return(NULL);
563
	}
564
	if (p->tok == lex_identifier) {
565
		int t = find_hashid(p->pp_data.id.hash);
566
		switch (t) {
567
		case lex_exp_Hcap:
568
			/* Expression token specifiers */
569
			*macro = 1;
570
			p->tok = t;
571
			p = p->next;
572
			if (p->tok == lex_identifier) {
573
				/* Check for lvalue or rvalue qualifier */
574
				t = find_hashid(p->pp_data.id.hash);
575
				if (t == lex_lvalue || t == lex_rvalue ||
576
				    t == lex_const) {
577
					p->tok = t;
578
				}
579
				p = p->next;
580
			}
581
			if (p->tok == lex_colon) {
582
				/* Step over type name */
583
				p = skip_to_colon(p->next);
584
			}
585
			return(p);
2 7u83 586
 
7 7u83 587
		case lex_func_Hcap:
588
			/* Function token specifiers */
589
			*macro = 1;
590
			p->tok = t;
591
			p = skip_to_colon(p->next);
592
			return(p);
2 7u83 593
 
7 7u83 594
		case lex_member_Hcap:
595
			/* Member token specifiers */
596
			p->tok = t;
597
			p = p->next;
598
			if (p->tok == lex_identifier) {
599
				/* Check for access specifier */
600
				t = find_hashid(p->pp_data.id.hash);
601
				if (t == lex_public || t == lex_protected ||
602
				    t == lex_private) {
603
					p->tok = t;
604
					p = p->next;
605
				}
606
			}
607
			p = skip_to_colon(p);
608
			p = skip_to_colon(p);
609
			return(p);
2 7u83 610
 
7 7u83 611
		case lex_proc_Hcap:
612
			/* Procedure token specifiers */
613
			*macro = 1;
614
			p->tok = t;
615
			p = p->next;
616
			if (p == NULL) {
617
				return(NULL);
2 7u83 618
			}
7 7u83 619
			t = p->tok;
620
			if (t == lex_open_Hbrace_H1 ||
621
			    t == lex_open_Hbrace_H2) {
622
				/* General procedure parameters */
623
				p = p->next;
624
				for (;;) {
625
					if (p == NULL) {
626
						break;
627
					}
628
					t = p->tok;
629
					if (t == lex_or_H1) {
630
						p = p->next;
631
						break;
632
					}
633
					p = mark_tdf_token(p, macro);
634
					p = mark_tdf_param(p, 1, 0);
635
					if (p == NULL) {
636
						break;
637
					}
638
					if (p->tok == lex_comma)p = p->next;
639
				}
640
				for (;;) {
641
					if (p == NULL) {
642
						break;
643
					}
644
					t = p->tok;
645
					if (t == lex_close_Hbrace_H1 ||
646
					    t == lex_close_Hbrace_H2) {
647
						p = p->next;
648
						break;
649
					}
650
					p = mark_prog_param(p);
651
					if (p == NULL) {
652
						break;
653
					}
654
					if (p->tok == lex_comma)p = p->next;
655
				}
656
			} else if (t == lex_open_Hround) {
657
				/* Simple procedure parameters */
658
				p = p->next;
659
				for (;;) {
660
					if (p == NULL) {
661
						break;
662
					}
663
					t = p->tok;
664
					if (t == lex_close_Hround) {
665
						p = p->next;
666
						break;
667
					}
668
					p = mark_tdf_token(p, macro);
669
					p = mark_tdf_param(p, 0, 0);
670
					if (p == NULL) {
671
						break;
672
					}
673
					if (p->tok == lex_comma) {
674
						p = p->next;
675
					}
676
				}
2 7u83 677
			}
7 7u83 678
			p = mark_tdf_token(p, macro);
679
			return(p);
680
 
681
		case lex_variety_Hcap:
682
			/* Integral type token specifiers */
683
			p->tok = t;
684
			p = p->next;
685
			if (p->tok == lex_identifier) {
686
				/* Check for signed or unsigned qualifier */
687
				t = find_hashid(p->pp_data.id.hash);
688
				if (t == lex_signed || t == lex_unsigned) {
689
					p->tok = t;
690
					p = p->next;
691
				}
2 7u83 692
			}
7 7u83 693
			return(p);
2 7u83 694
 
7 7u83 695
		case lex_nat_Hcap:
696
		case lex_int_Hcap:
697
		case lex_stmt_Hcap:
698
			/* Simple token specifiers */
699
			*macro = 1;
700
			p->tok = t;
701
			return(p->next);
702
 
703
		case lex_arith_Hcap:
704
		case lex_class_Hcap:
705
		case lex_float_Hcap:
706
		case lex_scalar_Hcap:
707
		case lex_struct_Hcap:
708
		case lex_type_Hcap:
709
		case lex_union_Hcap:
710
			/* Type token specifiers */
711
			p->tok = t;
712
			return(p->next);
2 7u83 713
		}
714
	}
7 7u83 715
	return(p->next);
2 7u83 716
}
717
 
718
 
719
/*
720
    READ AN EXTERNAL TOKEN NAME
721
 
722
    This routine processes an external token name.  This consists of a
723
    hash symbol, pointed to by p, followed a list of preprocessing
724
    tokens.  Note that the result is an extended identifier, unless it
725
    is a simple identifier.
726
*/
727
 
7 7u83 728
static PPTOKEN *
729
quote_token_name(PPTOKEN *p)
2 7u83 730
{
7 7u83 731
	PPTOKEN *q = p->next;
732
	if (q != NULL) {
733
		/* All following tokens are quoted */
734
		string s;
735
		unsigned long sp = q->pp_space;
736
		IGNORE quote_tok_list(q, 0, char_quote);
737
		free_tok_list(q);
738
		q = new_pptok();
739
		q->pp_space = sp;
740
		q->next = NULL;
741
		s = token_buff.start;
742
		if (ustrseq(s, "-")) {
743
			/* Special form '-' */
744
			q->tok = lex_minus;
745
		} else {
746
			/* Create an identifier */
747
			unsigned long h = hash(s);
748
			token_hashid = lookup_name(s, h, 1, lex_unknown);
749
			q->tok = lex_identifier;
750
			token_parts(lex_identifier, q);
751
		}
752
		p->next = q;
753
		p = q;
2 7u83 754
	}
7 7u83 755
	return(p);
2 7u83 756
}
757
 
758
 
759
/*
760
    READ A PRAGMA TOKEN STATEMENT
761
 
762
    This routine processes a '#pragma token' statement.  p gives the first
763
    preprocessing token (i.e. 'token').  tendra is as in parse_pragma.
764
*/
765
 
7 7u83 766
static int
767
read_tdf_token(PPTOKEN *p, int tendra)
2 7u83 768
{
7 7u83 769
	/* Read and macro expand the rest of the line */
770
	int t;
771
	PPTOKEN *q = p;
772
	while (q->next)q = q->next;
773
	if (q->tok != lex_newline) {
774
		int macro = 0;
775
		PPTOKEN *r = read_line(lex_ignore_token, lex_ignore_token);
776
		if (r) {
777
			r->pp_space = WHITE_SPACE;
778
		}
779
		q->next = r;
780
		r = mark_tdf_token(r, &macro);
781
		r = mark_tdf_param(r, 1, macro);
782
		while (r) {
783
			/* Find token name */
784
			t = r->tok;
785
			if (t == lex_hash_H1 || t == lex_hash_H2) {
786
				q = quote_token_name(r);
787
				break;
788
			}
789
			q = r;
790
			r = r->next;
791
		}
792
 
793
		/* Add newline token */
794
		while (q->next) {
795
			q = q->next;
796
		}
797
		q->next = new_pptok();
798
		q->next->tok = lex_newline;
799
		q->next->next = NULL;
2 7u83 800
	}
7 7u83 801
	q = expand_tok_list(p);
802
	free_tok_list(p);
2 7u83 803
 
7 7u83 804
	/* Parse the line */
805
	in_token_decl = 1;
806
	decl_loc = preproc_loc;
807
	t = parse_pragma(q, tendra);
808
	in_token_decl = 0;
809
	return(t);
2 7u83 810
}
811
 
812
 
813
/*
814
    READ A PRAGMA TENDRA STATEMENT
815
 
816
    This routine processes a '#pragma TenDRA' statement, returning the
817
    corresponding lexical token.  One or two tokens from the line will
818
    have already been read into p.  tendra is as in parse_pragma.
819
*/
820
 
7 7u83 821
static int
822
read_tendra(PPTOKEN *p, int tendra)
2 7u83 823
{
7 7u83 824
	/* Read and macro expand the rest of the line */
825
	PPTOKEN *q = p;
826
	while (q->next) {
827
		q = q->next;
828
	}
829
	if (q->tok != lex_newline) {
830
		PPTOKEN *r = read_line(lex_ignore_token, lex_newline);
831
		if (r) {
832
			r->pp_space = WHITE_SPACE;
833
		}
834
		q->next = r;
835
	}
836
	q = expand_tok_list(p);
837
	free_tok_list(p);
838
	p = q;
2 7u83 839
 
7 7u83 840
	/* Replace any identifiers by keywords */
841
	for (q = p; q != NULL; q = q->next) {
842
		int t = q->tok;
843
		if (t == lex_identifier) {
844
			t = find_hashid(q->pp_data.id.hash);
845
			q->tok = t;
846
		}
2 7u83 847
	}
848
 
7 7u83 849
	/* Parse the line */
850
	return(parse_pragma(p, tendra));
2 7u83 851
}
852
 
853
 
854
/*
855
    READ A PRAGMA INTERFACE STATEMENT
856
 
857
    This routine processes a '#pragma interface' statement, returning the
858
    corresponding lexical token.  One or two tokens from the line will
859
    have already been read into p.  tendra is as in parse_pragma.
860
*/
861
 
7 7u83 862
static int
863
read_interface(PPTOKEN *p, int tendra)
2 7u83 864
{
7 7u83 865
	/* Read and macro expand the rest of the line */
866
	int tok;
867
	int nl = 0;
868
	PPTOKEN *q = p;
869
	PPTOKEN *r = p;
870
	while (q->next)q = q->next;
871
	if (q->tok != lex_newline) {
872
		PPTOKEN *s = read_line(lex_ignore_token, lex_ignore_token);
873
		if (s) {
874
			s->pp_space = WHITE_SPACE;
875
		}
876
		q->next = s;
877
		nl = 1;
2 7u83 878
	}
7 7u83 879
	for (q = p; q != NULL; q = q->next) {
880
		/* Suppress expansion of 'TAG' */
881
		int t = q->tok;
882
		if (t == lex_identifier) {
883
			t = find_hashid(q->pp_data.id.hash);
884
			if (t == lex_tag_Hcap) {
885
				q->tok = t;
886
			}
887
		} else if (t == lex_hash_H1 || t == lex_hash_H2) {
888
			r = quote_token_name(q);
889
			break;
890
		}
891
		r = q;
892
	}
2 7u83 893
 
7 7u83 894
	/* Add newline token */
895
	if (nl) {
896
		while (r->next)r = r->next;
897
		r->next = new_pptok();
898
		r->next->tok = lex_newline;
899
		r->next->next = NULL;
900
	}
2 7u83 901
 
7 7u83 902
	/* Parse the line */
903
	tok = parse_pragma(p, tendra);
904
	return(tok);
2 7u83 905
}
906
 
907
 
908
/*
909
    PROCESS A NON-TENDRA PRAGMA STATEMENT
910
 
911
    This routine processes a '#pragma' statement in which there is no
912
    TenDRA keyword, or such a keyword is optional.  The argument p gives
913
    the first preprocessing token of the statement, while tendra is as
914
    in parse_pragma.  The corresponding lexical token value is returned
915
    if the statement is recognised, otherwise lex_unknown is returned.
916
    The non-TenDRA and TenDRA forms may differ as follows:
917
 
918
	token				TenDRA token
919
	extend interface		TenDRA extend
920
	implement interface		TenDRA implement
921
	define				TenDRA define
922
	no_def				TenDRA no_def
923
	ignore				TenDRA reject
924
	interface			TenDRA interface
925
	promote				TenDRA promoted
926
	compute promote			TenDRA compute promote (?)
927
	integer literal			TenDRA integer literal
928
	external volatile		TenDRA external volatile
929
	DEFINE MEMBER			TenDRA member definition
930
*/
931
 
7 7u83 932
static int
933
read_non_tendra(PPTOKEN *p, int tendra)
2 7u83 934
{
7 7u83 935
	if (p->tok == lex_identifier) {
936
		int t = find_hashid(p->pp_data.id.hash);
937
		switch (t) {
2 7u83 938
 
7 7u83 939
		case lex_token:
940
			/* Token syntax */
941
			p->tok = t;
942
			return(read_tdf_token(p, tendra));
2 7u83 943
 
7 7u83 944
		case lex_extend:
945
		case lex_implement: {
946
			/* Interface inclusion */
947
			int pp;
948
			if (!tendra) {
949
				/* Need 'interface' for non-TenDRA form */
950
				PPTOKEN *q = get_token();
951
				p->next = q;
952
				if (q->tok == lex_identifier) {
953
					int s = find_hashid(q->pp_data.id.hash);
954
					if (s != lex_interface) {
955
						break;
956
					}
957
				}
2 7u83 958
			}
7 7u83 959
			pp = read_include(1, lex_pragma);
960
			if (pp == lex_included) {
961
				/* Update current interface flag */
962
				if (t == lex_implement) {
963
					crt_interface = lex_define;
964
				} else {
965
					if (crt_interface != lex_no_Hdef) {
966
						crt_interface = lex_ignore;
967
					}
968
				}
969
			}
970
			return(pp);
2 7u83 971
		}
972
 
7 7u83 973
		case lex_define:
974
		case lex_no_Hdef:
975
		case lex_interface:
976
			/* Interface listing */
977
			p->tok = t;
978
			return(read_interface(p, tendra));
2 7u83 979
 
7 7u83 980
		case lex_reject:
981
			/* Interface listing (TenDRA form) */
982
			if (tendra) {
983
				p->tok = t;
984
				return(read_interface(p, tendra));
985
			}
986
			break;
2 7u83 987
 
7 7u83 988
		case lex_ignore:
989
			/* Interface listing (non-TenDRA form) */
990
			if (!tendra) {
991
				p->tok = lex_reject;
992
				return(read_interface(p, tendra));
993
			}
994
			break;
2 7u83 995
 
7 7u83 996
		case lex_undef: {
997
			/* Token undefining */
998
			PPTOKEN *q = get_token();
999
			p->next = q;
1000
			if (q->tok == lex_identifier) {
1001
				int s = find_hashid(q->pp_data.id.hash);
1002
				if (s == lex_token) {
1003
					p->tok = t;
1004
					q->tok = s;
1005
					return(read_interface(p, tendra));
1006
				}
1007
			}
1008
			break;
2 7u83 1009
		}
1010
 
7 7u83 1011
		case lex_promote:
1012
			/* Promotion specification (non-TenDRA form) */
1013
			if (!tendra) {
1014
				set_token(p, lex_promoted);
1015
				return(read_tendra(p, tendra));
1016
			}
1017
			break;
2 7u83 1018
 
7 7u83 1019
		case lex_promoted:
1020
			/* Promotion specification (TenDRA form) */
1021
			if (tendra) {
1022
				set_token(p, lex_promoted);
1023
				return(read_tendra(p, tendra));
1024
			}
1025
			break;
2 7u83 1026
 
7 7u83 1027
		case lex_compute: {
1028
			/* Computed promotion specification */
1029
			PPTOKEN *q = get_token();
1030
			p->next = q;
1031
			if (q->tok == lex_identifier) {
1032
				int s = find_hashid(q->pp_data.id.hash);
1033
				if (s == lex_promote) {
1034
					set_token(p, t);
1035
					set_token(q, s);
1036
					return(read_tendra(p, tendra));
1037
				}
1038
			}
1039
			break;
2 7u83 1040
		}
1041
 
7 7u83 1042
		case lex_integer: {
1043
			/* Integer literal specification */
1044
			PPTOKEN *q = get_token();
1045
			p->next = q;
1046
			if (q->tok == lex_identifier) {
1047
				int s = find_hashid(q->pp_data.id.hash);
1048
				if (s == lex_lit) {
1049
					set_token(p, t);
1050
					set_token(q, s);
1051
					return(read_tendra(p, tendra));
1052
				}
1053
			}
1054
			break;
2 7u83 1055
		}
1056
 
7 7u83 1057
		case lex_define_Hcap:
1058
			/* Member definition (non-TenDRA form) */
1059
			if (!tendra) {
1060
				PPTOKEN *q = get_token();
1061
				p->next = q;
1062
				if (q->tok == lex_identifier) {
1063
					int s = find_hashid(q->pp_data.id.hash);
1064
					if (s == lex_member_Hcap) {
1065
						set_token(p, lex_member);
1066
						set_token(q, lex_definition);
1067
						return(read_tendra(p, tendra));
1068
					}
1069
				}
2 7u83 1070
			}
7 7u83 1071
			break;
2 7u83 1072
 
7 7u83 1073
		case lex_member:
1074
			/* Member definition (TenDRA form) */
1075
			if (tendra) {
1076
				PPTOKEN *q = get_token();
1077
				p->next = q;
1078
				if (q->tok == lex_identifier) {
1079
					int s = find_hashid(q->pp_data.id.hash);
1080
					if (s == lex_definition) {
1081
						set_token(p, lex_member);
1082
						set_token(q, lex_definition);
1083
						return(read_tendra(p, tendra));
1084
					}
1085
				}
2 7u83 1086
			}
7 7u83 1087
			break;
2 7u83 1088
 
7 7u83 1089
		case lex_accept:
1090
			/* Conversion tokens (non-TenDRA form) */
1091
			if (!tendra) {
1092
				PPTOKEN *q = get_token();
1093
				p->next = q;
1094
				if (q->tok == lex_ellipsis) {
1095
					return(read_tendra(p, tendra));
1096
				}
1097
				if (q->tok == lex_identifier) {
1098
					int s = find_hashid(q->pp_data.id.hash);
1099
					if (s == lex_conversion) {
1100
						return(read_tendra(p, tendra));
1101
					}
1102
				}
2 7u83 1103
			}
7 7u83 1104
			break;
2 7u83 1105
 
7 7u83 1106
		case lex_external:
1107
			/* External volatility (non-TenDRA form) */
1108
			if (!tendra) {
1109
				PPTOKEN *q = get_token();
1110
				p->next = q;
1111
				if (q->tok == lex_identifier) {
1112
					int s = find_hashid(q->pp_data.id.hash);
1113
					if (s == lex_volatile) {
1114
						return(read_tendra(p, tendra));
1115
					}
1116
				}
2 7u83 1117
			}
7 7u83 1118
			break;
1119
 
1120
		case lex_preserve:
1121
			/* Preserve statics (non-TenDRA form) */
1122
			return(read_tendra(p, tendra));
2 7u83 1123
		}
1124
	}
7 7u83 1125
	return(lex_unknown);
2 7u83 1126
}
1127
 
1128
 
1129
/*
1130
    PROCESS A PRAGMA STATEMENT
1131
 
1132
    This routine analyses a '#pragma' statement, returning the corresponding
1133
    lexical token.  It is called from read_preproc_dir (q.v.) immediately
1134
    after the '#pragma' directive has been identified.  It is not called for
1135
    skipped '#pragma' directives.  The calling routine will skip to the end
1136
    of the preprocessing directive if necessary.
1137
*/
1138
 
7 7u83 1139
int
1140
read_pragma(void)
2 7u83 1141
{
7 7u83 1142
	int t;
1143
	PPTOKEN *p = get_token();
1144
	if (p->tok == lex_identifier) {
1145
		t = find_hashid(p->pp_data.id.hash);
1146
		switch (t) {
2 7u83 1147
 
7 7u83 1148
		case lex_tendra: {
1149
			/* Deal with '#pragma TenDRA' */
1150
			int tendra = 1;
1151
			p->next = free_tokens;
1152
			free_tokens = p;
1153
			p = get_token();
1154
			if (p->tok == lex_plus_Hplus) {
1155
				/* Allow for TenDRA++ */
2 7u83 1156
#if LANGUAGE_CPP
7 7u83 1157
				p->next = free_tokens;
1158
				free_tokens = p;
1159
				p = get_token();
1160
				tendra = 2;
2 7u83 1161
#else
7 7u83 1162
				return(lex_ignore_token);
2 7u83 1163
#endif
7 7u83 1164
			}
2 7u83 1165
 
7 7u83 1166
			/* Allow for optional TenDRA pragmas */
1167
			t = read_non_tendra(p, tendra);
1168
			if (t != lex_unknown) {
1169
				return(t);
1170
			}
2 7u83 1171
 
7 7u83 1172
			/* Deal with TenDRA pragmas */
1173
			t = read_tendra(p, tendra);
1174
			return(t);
2 7u83 1175
		}
1176
 
7 7u83 1177
		case lex_ident:
1178
			/* Deal with '#pragma ident' */
1179
			if (!option(OPT_ppdir_ident_ignore)) {
1180
				read_ident(lex_pragma);
1181
			}
1182
			return(lex_ignore_token);
1183
 
1184
		case lex_weak:
1185
			/* Deal with '#pragma weak' */
1186
			if (!option(OPT_ppdir_weak_ignore)) {
1187
				read_weak(lex_pragma);
1188
			}
1189
			return(lex_ignore_token);
2 7u83 1190
		}
1191
	}
1192
 
7 7u83 1193
	/* Deal with non-TenDRA pragmas */
1194
	t = read_non_tendra(p, 0);
1195
	if (t != lex_unknown) {
1196
		return(t);
1197
	}
2 7u83 1198
 
7 7u83 1199
	/* Report unknown pragmas */
1200
	free_tok_list(p);
1201
	report(preproc_loc, ERR_cpp_pragma_unknown(lex_pragma));
1202
	return(lex_ignore_token);
2 7u83 1203
}
1204
 
1205
 
1206
/*
1207
    ANALYSE A LINT COMMENT
1208
 
1209
    This routine analyses the comment built up in token_buff for lint
1210
    format comments.  These are interpreted locally.  This can go slightly
1211
    wrong with look-ahead, in which case the more structured keyword
1212
    approach should be used.  Other fairly standard lint comments include
1213
    VARARGS, LINTLIBRARY, CONSTANTCONDITION (CONSTCOND), EMPTY, LINTED,
1214
    PROTOLIB, PRINTFLIKE and SCANFLIKE.
1215
*/
1216
 
7 7u83 1217
int
1218
lint_comment(void)
2 7u83 1219
{
7 7u83 1220
	string t;
1221
	size_t sz;
1222
	character c;
1223
	string s = token_buff.start;
1224
	while (c = *s, is_white_char((unsigned long)c)) {
1225
		/* Step over initial white space */
1226
		s++;
2 7u83 1227
	}
7 7u83 1228
	t = s;
1229
	while (c = *s, is_alpha_char((unsigned long)c)) {
1230
		/* Scan to end of identifier */
1231
		s++;
2 7u83 1232
	}
7 7u83 1233
 
1234
	/* Check identifier */
1235
	sz = (size_t)(s - t);
1236
	switch (sz) {
1237
	case 8:
1238
		if (strncmp(strlit(t), "ARGSUSED", sz) == 0) {
1239
			/* Indicate unused variables */
1240
			suppress_variable = 1;
1241
		} else if (strncmp(strlit(t), "FALLTHRU", sz) == 0) {
1242
			/* Suppress fall through errors */
1243
			suppress_fall = 1;
1244
		}
1245
		break;
1246
	case 10:
1247
		if (strncmp(strlit(t), "NOTREACHED", sz) == 0) {
1248
			/* Suppress unreached code errors */
1249
			unreached_last = 1;
1250
		}
1251
		break;
1252
	case 11:
1253
		if (strncmp(strlit(t), "FALLTHROUGH", sz) == 0) {
1254
			/* Suppress fall through errors */
1255
			suppress_fall = 1;
1256
		}
1257
		break;
2 7u83 1258
	}
1259
 
7 7u83 1260
	/* Rest of comment is ignored */
1261
	return(lex_ignore_token);
2 7u83 1262
}