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, 1998
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 <limits.h>
63
#include "system.h"
64
#include "version.h"
65
#include "c_types.h"
66
#include "error.h"
67
#include "catalog.h"
68
#include "basetype.h"
69
#include "buffer.h"
70
#include "capsule.h"
71
#include "compile.h"
72
#include "constant.h"
73
#include "debug.h"
74
#include "declare.h"
75
#include "exception.h"
76
#include "file.h"
77
#include "dump.h"
78
#include "hash.h"
79
#include "initialise.h"
80
#include "instance.h"
81
#include "inttype.h"
82
#include "lex.h"
83
#include "literal.h"
84
#include "load.h"
85
#include "macro.h"
86
#include "namespace.h"
87
#include "operator.h"
88
#include "option.h"
89
#include "overload.h"
90
#include "parse.h"
91
#include "predict.h"
92
#include "preproc.h"
93
#include "printf.h"
94
#include "redeclare.h"
95
#include "statement.h"
96
#include "syntax.h"
97
#include "table.h"
98
#include "template.h"
99
#include "tok.h"
100
#include "tokdef.h"
101
#include "typeid.h"
102
#include "unmangle.h"
103
#include "ustring.h"
104
#include "variable.h"
105
#include "xalloc.h"
106
 
107
 
7 7u83 108
/**
109
 * DEFAULT MACHINE OPTION
110
 *
111
 * This macro is used to determine the machine dependent options to be used.
112
 */
2 7u83 113
 
114
#ifndef FS_MACHINE
115
#ifdef FS_DOS
116
#define FS_MACHINE		"dos"
117
#else
118
#define FS_MACHINE		"unix"
119
#endif
120
#endif
121
 
122
 
123
/*
7 7u83 124
 * COMMAND-LINE FLAGS
125
 *
126
 * These flags may be set by command-line options to indicate various actions
127
 * to the compiler.
128
 */
2 7u83 129
 
7 7u83 130
static int builtin_asserts = 1;
131
static int builtin_macros = 1;
132
static int check_level = 0;
133
static int complete_program = 0;
134
static int have_startup = 0;
135
static int spec_linker = 0;
136
static int started_scope = 0;
137
static int output_last = 1;
138
static int unmangle_names = 0;
139
static int quit_immediately = 0;
140
static string dump_name = NULL;
141
static string dump_opt = NULL;
142
static string spec_name = NULL;
143
static string table_name = NULL;
2 7u83 144
 
145
 
146
/*
7 7u83 147
 * TABLE OF COMMAND-LINE ARGUMENTS
148
 *
149
 * This table describes all the command-line options. Each is given by an
150
 * option letter, followed by a flag indicating whether the option can be
151
 * split into two components, and a description of the second option
152
 * component.
153
 */
2 7u83 154
 
155
typedef struct {
7 7u83 156
    char opt;
157
    char space;
158
    CONST char *arg;
159
    CONST char *desc;
160
} PROGRAM_ARG;
2 7u83 161
 
7 7u83 162
static PROGRAM_ARG prog_args[] = {
2 7u83 163
    { 'A', 1, "<pre>(<tok>)", "assert a predicate" },
164
    { 'D', 1, "<mac>=<def>", "define a macro" },
165
    { 'E', 0, NULL, "preprocess input file only" },
166
    { 'F', 1, "<file>", "read list of options from file" },
167
    { 'H', 0, NULL, "report file inclusions" },
168
    { 'I', 1, "<dir>", "specify an include directory" },
169
    { 'M', 1, "<mach>", "machine dependent options" },
170
    { 'N', 1, "<name>:<dir>", "specify a named include directory" },
171
    { 'O', 0, NULL, "optimise output capsule" },
172
    { 'R', 0, NULL, "reverse order of files" },
173
    { 'S', 0, NULL, "spec file linker action" },
174
    { 'U', 1, "<mac>", "undefine a macro" },
175
    { 'V', 0, NULL, "enable verbose mode" },
176
    { 'W', 1, "<opt>", "enable warnings option" },
177
    { 'X', 0, NULL, "disable exception handling" },
178
    { 'Z', 1, "<number>", "set maximum number of errors" },
179
    { 'a', 0, NULL, "apply complete program checks" },
180
    { 'c', 0, NULL, "disable TDF output" },
181
    { 'd', 1, "<opt>=<file>", "dump symbol table" },
182
    { 'e', 1, "<file>", "add an end-up file" },
183
    { 'f', 1, "<file>", "add a start-up file" },
184
    { 'g', 0, "<level>", "enable diagnostics mode" },
185
    { 'h', 0, NULL, "print this help page" },
186
    { 'j', 1, "<opts>", "set TDF output options" },
187
    { 'm', 1, "<opts>", "set error printing options" },
188
    { 'n', 1, "<file>", "specify portability table" },
189
    { 'o', 1, "<output>", "specify output file" },
190
    { 'q', 0, NULL, "quit immediately" },
191
    { 'r', 1, "<file>", "specify error marker" },
192
    { 's', 1, "<file>", "specify spec output file" },
193
    { 't', 0, NULL, "output TDF token declarations" },
194
    { 'u', 0, NULL, "unmangle identifier names" },
195
    { 'v', 0, NULL, "print version number" },
196
    { 'w', 0, NULL, "disable all warnings" },
197
#ifdef DEBUG
198
    { 'x', 1, "<debug>", "debugging options" },
199
#endif
200
    { 'z', 0, NULL, "ignore compilation errors" },
201
    { '?', 0, NULL, "print this help page" },
202
    { '-', 0, NULL, "specify end of options" }
7 7u83 203
};
2 7u83 204
 
7 7u83 205
#define no_prog_args	array_size(prog_args)
2 7u83 206
 
207
 
7 7u83 208
/**
209
 * PRINT PROGRAM USAGE
210
 *
211
 * This routine prints the program usage to the file f.
212
 */
2 7u83 213
 
7 7u83 214
static void
215
report_usage(FILE *f)
2 7u83 216
{
7 7u83 217
    int i;
218
    fprintf_v(f, "Usage: %s [options] [input] [output]\n", progname);
219
    for (i = 0; i < no_prog_args; i++) {
220
	char opt = prog_args[i].opt;
221
	CONST char *arg = prog_args[i].arg;
222
	CONST char *desc = prog_args[i].desc;
223
	if (arg == NULL) arg = "\t";
224
	if (desc == NULL) desc = "(not documented)";
225
	fprintf_v(f, " -%c%s\t%s\n", opt, arg, desc);
2 7u83 226
    }
7 7u83 227
    fputc_v('\n', f);
228
    return;
2 7u83 229
}
230
 
231
 
7 7u83 232
/**
233
 * SET MACHINE DEPENDENT FLAGS
234
 *
235
 * This routine sets the machine dependent options for the machine described
236
 * by mach. The routine returns false for an unknown machine descriptor.
237
 */
2 7u83 238
 
7 7u83 239
static int
240
set_machine(CONST char *mach)
2 7u83 241
{
7 7u83 242
    if (streq(mach, "dos")) {
243
	allow_dos_newline = 1;
244
	good_fseek = 0;
245
	binary_mode = 1;
246
	file_sep = '\\';
247
	drive_sep = ':';
248
	return(1);
2 7u83 249
    }
7 7u83 250
    if (streq(mach, "unix")) {
251
	allow_dos_newline = 0;
252
	good_fseek = 1;
253
	binary_mode = 0;
254
	file_sep = '/';
255
	drive_sep = 0;
256
	return(1);
2 7u83 257
    }
7 7u83 258
    return(0);
2 7u83 259
}
260
 
261
 
7 7u83 262
/**
263
 * PRE-SET A COMPILE-TIME OPTION
264
 *
265
 * This routine pre-sets the value of option A to be B.
266
 */
2 7u83 267
 
7 7u83 268
#define preset(A, B)\
269
    OPT_CATALOG[A].def[0] = (B);\
270
    OPT_CATALOG[A].def[1] = (B)
2 7u83 271
 
272
 
7 7u83 273
/**
274
 * READ AN ARGUMENT FROM A FILE
275
 *
276
 * This routine reads a command-line argument from the file f into the buffer
277
 * s of length n, returning the result.
278
 */
2 7u83 279
 
7 7u83 280
static char *
281
read_arg(FILE *f, char *s, int n)
2 7u83 282
{
7 7u83 283
    char *p = fgets(s, n, f);
284
    if (p) {
285
	char c = *p;
286
	if (c == '#' || c == '\n') {
2 7u83 287
	    /* Ignore empty lines and comments */
7 7u83 288
	    p = read_arg(f, s, n);
2 7u83 289
	} else {
290
	    /* Remove terminal newline */
7 7u83 291
	    char *q = strrchr(p, '\n');
292
	    if (q) *q = 0;
2 7u83 293
	}
294
    }
7 7u83 295
    return(p);
2 7u83 296
}
297
 
298
 
7 7u83 299
/**
300
 * PROCESS A LIST OF ARGUMENTS
301
 *
302
 * This routine is called by main to process the command-line arguments given
303
 * by argc and argv. It returns a list of strings giving the input and output
304
 * files.
305
 */
2 7u83 306
 
7 7u83 307
static LIST(string)
308
process_args(int argc, char **argv)
2 7u83 309
{
7 7u83 310
    char opt = 0;
311
    FILE *f = NULL;
312
    char buff[1000];
313
    int allow_opt = 1;
314
    string output = NULL;
315
    LIST(string)files = NULL_list(string);
2 7u83 316
 
317
    /* Set development default options */
318
#ifdef DEBUG
7 7u83 319
    output_tokdec = 1;
2 7u83 320
#endif
321
 
322
    /* Scan through the arguments */
7 7u83 323
    for (; ;) {
324
	char *arg = NULL;
325
	if (f != NULL) {
2 7u83 326
	    /* Get next option from file */
7 7u83 327
	    arg = read_arg(f, buff,(int)sizeof(buff));
328
	    if (arg == NULL) {
2 7u83 329
		/* End of file reached */
7 7u83 330
		fclose_v(f);
331
		f = NULL;
2 7u83 332
	    }
333
	}
7 7u83 334
	if (arg == NULL && argc) {
2 7u83 335
	    /* Get next option from array */
7 7u83 336
	    arg = *(argv++);
337
	    argc--;
2 7u83 338
	}
7 7u83 339
	if (arg == NULL) {
2 7u83 340
	    /* No more options */
7 7u83 341
	    break;
2 7u83 342
	}
7 7u83 343
	if (opt == 0) {
2 7u83 344
	    /* Find option letter */
7 7u83 345
	    if (arg[0] == '-' && allow_opt) {
346
		opt = arg[1];
347
		if (opt) arg += 2;
2 7u83 348
	    }
349
	}
7 7u83 350
	if (opt == 0) {
2 7u83 351
	    /* Input or output file 'arg' */
7 7u83 352
	    string uarg = xustrcpy(ustrlit(arg));
353
	    CONS_string(uarg, files, files);
2 7u83 354
 
355
	} else {
356
	    /* Command-line options */
7 7u83 357
	    int i;
358
	    int known = 0;
359
	    char next_opt = 0;
2 7u83 360
 
361
	    /* Search through options */
7 7u83 362
	    for (i = 0; i < no_prog_args; i++) {
363
		if (opt == prog_args[i].opt) {
364
		    if (prog_args[i].arg) {
2 7u83 365
			/* Complex options */
7 7u83 366
			if (arg[0] == 0 && prog_args[i].space) {
367
			    next_opt = opt;
368
			    known = 1;
2 7u83 369
			} else {
7 7u83 370
			    known = 2;
2 7u83 371
			}
372
		    } else {
373
			/* Simple options */
7 7u83 374
			if (arg[0] == 0) {
375
			    known = 2;
376
			    break;
2 7u83 377
			}
378
		    }
379
		}
380
	    }
381
 
382
	    /* Deal with complete options */
7 7u83 383
	    if (known == 2) {
384
		string uarg = ustrlit(arg);
385
		switch (opt) {
2 7u83 386
 
7 7u83 387
		    case 'A': {
2 7u83 388
			/* Assertion */
7 7u83 389
			BUFFER *bf = &internal_buff;
390
			if (streq(arg, "-")) {
391
			    builtin_asserts = 0;
392
			    break;
2 7u83 393
			}
7 7u83 394
			bfprintf(bf, "#assert %x\n", arg);
395
			preset(OPT_ppdir_assert, OPTION_ALLOW);
396
			preset(OPT_ppdir_unassert, OPTION_ALLOW);
397
			preset(OPT_ppdir_assert_ignore, OPTION_OFF);
398
			preset(OPT_ppdir_unassert_ignore, OPTION_OFF);
399
			have_startup = 1;
400
			break;
2 7u83 401
		    }
402
 
7 7u83 403
		    case 'D': {
2 7u83 404
			/* Macro definition */
7 7u83 405
			char c;
406
			CONST char *def = "1";
407
			BUFFER *bf = &internal_buff;
408
			bfprintf(bf, "#define ");
409
			while (c = *(arg++), c != 0) {
410
			    if (c == '=') {
411
				def = arg;
412
				break;
2 7u83 413
			    }
7 7u83 414
			    bfputc(bf,(int)c);
2 7u83 415
			}
7 7u83 416
			bfprintf(bf, " %x\n", def);
417
			have_startup = 1;
418
			break;
2 7u83 419
		    }
420
 
7 7u83 421
		    case 'E': {
2 7u83 422
			/* Preprocessor option */
7 7u83 423
			preproc_only = 1;
424
			break;
2 7u83 425
		    }
426
 
7 7u83 427
		    case 'F': {
2 7u83 428
			/* Open option file */
7 7u83 429
			if (f != NULL) {
430
			    CONST char *err = "Nested option files";
431
			    error(ERROR_WARNING, err);
432
			    break;
2 7u83 433
			}
7 7u83 434
			f = fopen(arg, "r");
435
			if (f == NULL) {
436
			    CONST char *err = "Can't open option file '%s'";
437
			    error(ERROR_WARNING, err, arg);
2 7u83 438
			}
7 7u83 439
			break;
2 7u83 440
		    }
441
 
7 7u83 442
		    case 'H': {
2 7u83 443
			/* Inclusion reporting option */
7 7u83 444
			preset(OPT_include_verbose, OPTION_WARN);
445
			break;
2 7u83 446
		    }
447
 
7 7u83 448
		    case 'I': {
2 7u83 449
			/* Include file search directory */
7 7u83 450
			uarg = xustrcpy(uarg);
451
			add_directory(uarg, NULL_string);
452
			break;
2 7u83 453
		    }
454
 
7 7u83 455
		    case 'M': {
2 7u83 456
			/* Machine dependent options */
7 7u83 457
			known = set_machine(arg);
458
			break;
2 7u83 459
		    }
460
 
7 7u83 461
		    case 'N': {
2 7u83 462
			/* Named include file search directory */
7 7u83 463
			string dir;
464
			uarg = xustrcpy(uarg);
465
			dir = ustrchr(uarg, ':');
466
			if (dir == NULL) {
467
			    CONST char *err = "Bad '-%c' option";
468
			    error(ERROR_WARNING, err, opt);
469
			    add_directory(uarg, NULL_string);
2 7u83 470
			} else {
7 7u83 471
			    *dir = 0;
472
			    add_directory(dir + 1, uarg);
2 7u83 473
			}
7 7u83 474
			break;
2 7u83 475
		    }
476
 
7 7u83 477
		    case 'O': {
2 7u83 478
			/* Optimisation mode */
7 7u83 479
			output_inline = 1;
480
			output_unused = 0;
481
			break;
2 7u83 482
		    }
483
 
7 7u83 484
		    case 'R': {
2 7u83 485
			/* Reverse order of files */
7 7u83 486
			output_last = 0;
487
			break;
2 7u83 488
		    }
489
 
7 7u83 490
		    case 'S': {
2 7u83 491
			/* Spec linker option */
7 7u83 492
			spec_linker = 1;
493
			break;
2 7u83 494
		    }
495
 
7 7u83 496
		    case 'U': {
2 7u83 497
			/* Macro undefinition */
7 7u83 498
			BUFFER *bf = &internal_buff;
499
			if (streq(arg, "-")) {
500
			    builtin_macros = 0;
501
			    break;
2 7u83 502
			}
7 7u83 503
			bfprintf(bf, "#undef %x\n", arg);
504
			have_startup = 1;
505
			break;
2 7u83 506
		    }
507
 
7 7u83 508
		    case 'V': {
2 7u83 509
			/* Switch on verbose mode */
7 7u83 510
			verbose = 1;
511
			break;
2 7u83 512
		    }
513
 
7 7u83 514
		    case 'W': {
2 7u83 515
			/* Switch on checks */
7 7u83 516
			char c;
517
			CONST char *sev = "warning";
518
			BUFFER *bf = &internal_buff;
519
			if (streq(arg, "all")) {
520
			    check_level = 1;
521
			    break;
2 7u83 522
			}
7 7u83 523
			if (!started_scope) {
524
			    bfprintf(bf, "#pragma TenDRA begin\n");
525
			    started_scope = 1;
2 7u83 526
			}
7 7u83 527
			bfprintf(bf, "#pragma TenDRA option \"");
528
			while (c = *(arg++), c != 0) {
529
			    if (c == '=') {
530
				sev = arg;
531
				break;
2 7u83 532
			    }
7 7u83 533
			    bfputc(bf,(int)c);
2 7u83 534
			}
7 7u83 535
			bfprintf(bf, "\" %x\n", sev);
536
			have_startup = 1;
537
			break;
2 7u83 538
		    }
539
 
7 7u83 540
		    case 'X': {
2 7u83 541
			/* Disable exception handling */
7 7u83 542
			output_except = 0;
543
			break;
2 7u83 544
		    }
545
 
7 7u83 546
		    case 'Z': {
2 7u83 547
			/* Set maximum number of errors */
7 7u83 548
			BUFFER *bf = &internal_buff;
549
			if (!started_scope) {
550
			    bfprintf(bf, "#pragma TenDRA begin\n");
551
			    started_scope = 1;
2 7u83 552
			}
7 7u83 553
			bfprintf(bf, "#pragma TenDRA set error limit");
554
			bfprintf(bf, " %x\n", uarg);
555
			have_startup = 1;
556
			break;
2 7u83 557
		    }
558
 
7 7u83 559
		    case 'a': {
2 7u83 560
			/* Complete program checks */
7 7u83 561
			complete_program = 1;
562
			break;
2 7u83 563
		    }
564
 
7 7u83 565
		    case 'c': {
2 7u83 566
			/* Disable TDF output */
7 7u83 567
			output_capsule = 0;
568
			break;
2 7u83 569
		    }
570
 
7 7u83 571
		    case 'd': {
2 7u83 572
			/* Dump file */
7 7u83 573
			string dump;
574
			uarg = xustrcpy(uarg);
575
			dump = ustrchr(uarg, '=');
576
			if (dump == NULL) {
577
			    CONST char *err = "Bad '-%c' option";
578
			    error(ERROR_WARNING, err, opt);
579
			    break;
2 7u83 580
			}
7 7u83 581
			if (dump_name) {
582
			    CONST char *err = "Multiple dump files";
583
			    error(ERROR_WARNING, err);
2 7u83 584
			}
7 7u83 585
			dump_opt = uarg;
586
			dump_name = dump + 1;
587
			break;
2 7u83 588
		    }
589
 
7 7u83 590
		    case 'e': {
2 7u83 591
			/* End-up file */
7 7u83 592
			LIST(string)p;
593
			uarg = xustrcpy(uarg);
594
			CONS_string(uarg, NULL_list(string), p);
595
			endup_files = APPEND_list(endup_files, p);
596
			have_startup = 1;
597
			break;
2 7u83 598
		    }
599
 
7 7u83 600
		    case 'f': {
2 7u83 601
			/* Start-up file */
7 7u83 602
			LIST(string)p;
603
			uarg = xustrcpy(uarg);
604
			CONS_string(uarg, NULL_list(string), p);
605
			startup_files = APPEND_list(startup_files, p);
606
			have_startup = 1;
607
			break;
2 7u83 608
		    }
609
 
7 7u83 610
		    case 'g': {
2 7u83 611
			/* Diagnostics mode */
7 7u83 612
			if (uarg[0] == 0) {
613
			    output_diag = DIAG_VERSION;
614
			} else if (uarg[1] == 0) {
615
			    switch (uarg[0]) {
616
				case '0': output_diag = 0; break;
617
				case '1': output_diag = 1; break;
618
				case '2': output_diag = 2; break;
619
				default : known = 0; break;
2 7u83 620
			    }
621
			} else {
7 7u83 622
			    known = 0;
2 7u83 623
			}
7 7u83 624
			break;
2 7u83 625
		    }
626
 
7 7u83 627
		    case 'h':
628
		    case '?': {
2 7u83 629
			/* Help option */
7 7u83 630
			report_usage(error_file);
631
			break;
2 7u83 632
		    }
633
 
7 7u83 634
		    case 'j': {
2 7u83 635
			/* Output options */
7 7u83 636
			output_option(uarg);
637
			break;
2 7u83 638
		    }
639
 
7 7u83 640
		    case 'm': {
2 7u83 641
			/* Error options */
7 7u83 642
			error_option(uarg);
643
			break;
2 7u83 644
		    }
645
 
7 7u83 646
		    case 'n': {
2 7u83 647
			/* Portability table */
7 7u83 648
			if (table_name) {
649
			    CONST char *err = "Multiple portability tables";
650
			    error(ERROR_WARNING, err);
2 7u83 651
			}
7 7u83 652
			table_name = xustrcpy(uarg);
653
			break;
2 7u83 654
		    }
655
 
7 7u83 656
		    case 'o': {
2 7u83 657
			/* Output file */
7 7u83 658
			if (output) {
659
			    CONST char *err = "Multiple output files";
660
			    error(ERROR_WARNING, err);
2 7u83 661
			}
7 7u83 662
			output = xustrcpy(uarg);
663
			break;
2 7u83 664
		    }
665
 
7 7u83 666
		    case 'q': {
2 7u83 667
			/* Quit immediately */
7 7u83 668
			quit_immediately = 1;
669
			break;
2 7u83 670
		    }
671
 
7 7u83 672
		    case 'r': {
2 7u83 673
			/* Error marker file */
7 7u83 674
			output_name[OUTPUT_ERROR] = xustrcpy(uarg);
675
			break;
2 7u83 676
		    }
677
 
7 7u83 678
		    case 's': {
2 7u83 679
			/* Spec output file */
7 7u83 680
			if (spec_name) {
681
			    CONST char *err = "Multiple spec output files";
682
			    error(ERROR_WARNING, err);
2 7u83 683
			}
7 7u83 684
			spec_name = xustrcpy(uarg);
685
			break;
2 7u83 686
		    }
687
 
7 7u83 688
		    case 't': {
2 7u83 689
			/* Output TDF token declarations */
7 7u83 690
			output_tokdec = 1;
691
			break;
2 7u83 692
		    }
693
 
7 7u83 694
		    case 'u': {
2 7u83 695
			/* Unmangle an identifier name */
7 7u83 696
			unmangle_names = 1;
697
			break;
2 7u83 698
		    }
699
 
7 7u83 700
		    case 'v': {
2 7u83 701
			/* Print version number */
7 7u83 702
			string v = report_version(1);
703
			fprintf_v(error_file, "%s\n\n", strlit(v));
704
			break;
2 7u83 705
		    }
706
 
7 7u83 707
		    case 'w': {
2 7u83 708
			/* Suppress all warnings */
7 7u83 709
			preset(OPT_warning, OPTION_OFF);
710
			check_level = 0;
711
			break;
2 7u83 712
		    }
713
 
7 7u83 714
		    case 'z': {
2 7u83 715
			/* Ignore compilation errors */
7 7u83 716
			preset(OPT_error, OPTION_WARN);
717
			max_errors = ULONG_MAX;
718
			break;
2 7u83 719
		    }
720
 
7 7u83 721
		    case '-': {
2 7u83 722
			/* Last option */
7 7u83 723
			allow_opt = 0;
724
			break;
2 7u83 725
		    }
726
 
727
#ifdef DEBUG
7 7u83 728
		    case 'x': {
2 7u83 729
			/* Debug options */
7 7u83 730
			debug_option(arg);
731
			quit_immediately = 1;
732
			break;
2 7u83 733
		    }
734
#endif
735
		}
736
	    }
737
 
738
	    /* Deal with unknown options */
7 7u83 739
	    if (known == 0) {
740
		CONST char *err = "Unknown option, '-%c%s'";
741
		error(ERROR_WARNING, err, opt, arg);
2 7u83 742
	    }
7 7u83 743
	    opt = next_opt;
2 7u83 744
	}
745
    }
7 7u83 746
    if (opt) {
747
	CONST char *err = "Incomplete option, '-%c'";
748
	error(ERROR_WARNING, err, opt);
2 7u83 749
    }
750
 
751
    /* Examine list of files */
7 7u83 752
    if (IS_NULL_list(files)) {
753
	CONS_string(NULL, NULL_list(string), files);
2 7u83 754
    }
7 7u83 755
    if (output || IS_NULL_list(TAIL_list(files))) {
756
	CONS_string(output, files, files);
757
	output_last = 1;
2 7u83 758
    }
7 7u83 759
    files = REVERSE_list(files);
760
    return(files);
2 7u83 761
}
762
 
763
 
7 7u83 764
/**
765
 * INITIALISE FILE LOCATIONS
766
 *
767
 * This routine initialises the standard file locations.
768
 */
2 7u83 769
 
7 7u83 770
static void
771
init_loc(void)
2 7u83 772
{
7 7u83 773
    IGNORE set_crt_loc(ustrlit("<builtin-in>"), 1);
774
    builtin_loc = crt_loc;
775
    IGNORE set_crt_loc(ustrlit("<command-line>"), 1);
776
    preproc_loc = crt_loc;
777
    decl_loc = crt_loc;
778
    stmt_loc = crt_loc;
779
    return;
2 7u83 780
}
781
 
782
 
7 7u83 783
/**
784
 * PERFORM LANGUAGE DEPENDENT INITIALISATION
785
 *
786
 * This routine performs any language dependent initialisation not covered in
787
 * the main initialisation routines. Note that the default language is C++.
788
 */
2 7u83 789
 
7 7u83 790
static void
791
init_lang(int c)
2 7u83 792
{
7 7u83 793
    if (c) {
794
	crt_linkage = dspec_c;
795
	set_std_namespace(NULL_id);
2 7u83 796
    }
7 7u83 797
    init_tok(c);
798
    return;
2 7u83 799
}
800
 
801
 
7 7u83 802
/**
803
 * CALL MAIN INITIALISATION ROUTINES
804
 *
805
 * This routine calls all the initialisation routines.
806
 */
2 7u83 807
 
7 7u83 808
static void
809
init_main(void)
2 7u83 810
{
811
    /* Set file locations */
7 7u83 812
    crt_loc = builtin_loc;
813
    decl_loc = builtin_loc;
814
    stmt_loc = builtin_loc;
815
    preproc_loc = builtin_loc;
2 7u83 816
 
817
    /* Initialise errors and options */
7 7u83 818
    init_hash();
819
    init_lang(LANGUAGE_C);
820
    init_catalog();
821
    init_option(check_level);
822
    if (output_diag) record_location = 1;
823
    init_dump(dump_name, dump_opt);
824
    if (do_header) dump_start(&crt_loc, NIL(INCL_DIR));
2 7u83 825
 
826
    /* Initialise macros and keywords */
7 7u83 827
    init_char();
828
    init_constant();
829
    init_keywords();
830
    init_macros(builtin_macros, builtin_asserts);
2 7u83 831
 
832
    /* Read the portability table */
7 7u83 833
    read_table(table_name);
2 7u83 834
 
835
    /* Initialise types and namespaces */
7 7u83 836
    init_namespace();
837
    push_namespace(global_namespace);
838
    init_types();
839
    init_literal();
840
    init_exception();
841
    init_printf();
842
    init_initialise();
843
    init_token_args();
844
    init_templates();
845
    if (do_header) dump_end(&crt_loc);
846
    return;
2 7u83 847
}
848
 
849
 
7 7u83 850
/**
851
 * CALL MAIN TERMINATION ROUTINES
852
 *
853
 * This routine frees any memory unneeded after the parsing routines.
854
 */
2 7u83 855
 
7 7u83 856
static void
857
term_main(void)
2 7u83 858
{
7 7u83 859
    free_candidates(&candidates);
860
    free_buffer(&field_buff);
861
    free_buffer(&token_buff);
862
    term_macros();
863
    term_input();
864
    term_catalog();
865
    term_itypes();
866
    return;
2 7u83 867
}
868
 
869
 
7 7u83 870
/**
871
 * CALL MAIN FILE PROCESSING ROUTINES
872
 *
873
 * This routine calls the main routines for processing the given list of
874
 * files. This will have at least two elements, the last of which is the
875
 * output file.
876
 */
2 7u83 877
 
7 7u83 878
static void
879
process_files(LIST(string)files)
2 7u83 880
{
881
    /* Find output file */
7 7u83 882
    int action;
883
    unsigned len;
884
    string output;
885
    PARSE_STATE st;
886
    unsigned max_len = 2;
887
    int mode = text_mode;
888
    LIST(string)input;
2 7u83 889
 
890
    /* Find output file */
7 7u83 891
    if (output_last) {
892
	LIST(string)end = END_list(files);
893
	output = DEREF_string(HEAD_list(end));
894
	input = files;
2 7u83 895
    } else {
7 7u83 896
	output = DEREF_string(HEAD_list(files));
897
	input = TAIL_list(files);
2 7u83 898
    }
7 7u83 899
    output_name[OUTPUT_TDF] = output;
900
    output_name[OUTPUT_SPEC] = spec_name;
2 7u83 901
 
902
    /* Find processing action */
7 7u83 903
    save_state(&st, 0);
904
    crt_state_depth = 0;
905
    if (spec_linker) {
2 7u83 906
	output_capsule = 0 ;	/* remove later */
7 7u83 907
	init_capsule();
908
	max_len = 0;
909
	action = 2;
910
    } else if (preproc_only) {
911
	output_name[OUTPUT_PREPROC] = output;
912
	output_tdf = 0;
913
	output_capsule = 0;
914
	action = 1;
2 7u83 915
    } else {
7 7u83 916
	init_capsule();
917
	action = 0;
2 7u83 918
    }
919
 
920
    /* Check number of input files */
7 7u83 921
    len = LENGTH_list(files);
922
    if (max_len && len > max_len) {
923
	CONST char *err = "Too many arguments (should have %u)";
924
	error(ERROR_WARNING, err, max_len);
925
	len = max_len;
2 7u83 926
    }
927
 
928
    /* Process start-up files in spec linker mode */
7 7u83 929
    if (action == 2) {
930
	if (have_startup) {
931
	    IGNORE open_input(mode);
932
	    crt_loc = builtin_loc;
933
	    input_name = NULL;
934
	    input_file = NULL;
935
	    process_file();
936
	    close_input();
2 7u83 937
	}
7 7u83 938
	mode = binary_mode;
2 7u83 939
    }
940
 
941
    /* Scan through input files */
7 7u83 942
    while (len >= 2) {
2 7u83 943
	/* Open input file */
7 7u83 944
	input_name = DEREF_string(HEAD_list(input));
945
	if (!open_input(mode)) {
946
	    fail(ERR_fail_input(input_name));
947
	    term_error(0);
948
	    return;
2 7u83 949
	}
7 7u83 950
	init_diag();
2 7u83 951
 
952
	/* Process input file */
7 7u83 953
	switch (action) {
954
	    case 0: {
2 7u83 955
		/* Parsing action */
7 7u83 956
		process_file();
957
		break;
2 7u83 958
	    }
7 7u83 959
	    case 1: {
2 7u83 960
		/* Preprocessing action */
7 7u83 961
		preprocess_file();
962
		break;
2 7u83 963
	    }
7 7u83 964
	    case 2: {
2 7u83 965
		/* Spec linker action */
7 7u83 966
		if (read_spec()) have_syntax_error = 1;
967
		no_declarations++;
968
		break;
2 7u83 969
	    }
970
	}
971
 
972
	/* Close input file */
7 7u83 973
	clear_decl_blocks();
974
	close_input();
975
	input = TAIL_list(input);
976
	len--;
2 7u83 977
    }
978
 
979
    /* Write output file */
7 7u83 980
    if (have_syntax_error) {
981
	suppress_variable = 2;
982
	no_declarations++;
2 7u83 983
    }
7 7u83 984
    init_diag();
985
    preproc_loc = crt_loc;
986
    restore_state(&st);
987
    if (action == 1) {
2 7u83 988
	/* Preprocessing action */
7 7u83 989
	term_option();
2 7u83 990
    } else {
991
	/* Compilation actions */
7 7u83 992
	external_declaration(NULL_exp, 0);
993
	clear_templates(2);
994
	term_main();
995
	IGNORE check_global(complete_program);
996
	term_option();
997
	compile_pending();
998
	write_capsule();
2 7u83 999
    }
7 7u83 1000
    return;
2 7u83 1001
}
1002
 
1003
 
1004
/*
7 7u83 1005
 * MAIN ROUTINE
1006
 *
1007
 * This is the main routine. It processes the command-line options, calls the
1008
 * initialisation routines and calls the main processing routine.
1009
 */
2 7u83 1010
 
7 7u83 1011
int
1012
main(int argc, char **argv)
2 7u83 1013
{
7 7u83 1014
    LIST(string)files;
1015
    set_progname(argv[0], PROG_VERSION);
1016
    IGNORE set_machine(FS_MACHINE);
1017
    init_loc();
1018
    files = process_args(argc - 1, argv + 1);
1019
    builtin_startup();
1020
    if (!quit_immediately) {
2 7u83 1021
	/* Process files */
7 7u83 1022
	init_main();
1023
	if (unmangle_names) {
1024
	    unmangle_list(files, stdout, 1);
2 7u83 1025
	} else {
7 7u83 1026
	    process_files(files);
1027
	    term_error(0);
2 7u83 1028
	}
1029
    }
7 7u83 1030
    return(exit_status);
2 7u83 1031
}