Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
6 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
6 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:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 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;
6 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;
6 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 <signal.h>
63
#include "release.h"
64
#include "object.h"
65
#include "hash.h"
66
#include "index.h"
67
#include "lex.h"
68
#include "makefile.h"
69
#include "name.h"
70
#include "syntax.h"
71
#include "type.h"
72
#include "print.h"
73
#include "utility.h"
74
 
75
 
76
/*
6 7u83 77
 * INPUT AND OUTPUT DIRECTORIES
78
 *
79
 * The variable input_dir consists of a colon-separated list of directories
80
 * to be searched for input files.  output_incl_dir and output_src_dir
81
 * give respectively the output include and output source directories.
82
 * The lengths of these directory names (plus one) are also given.
83
 */
84
 
85
char *input_dir;
86
char *output_incl_dir;
87
char *output_src_dir;
88
int output_incl_len;
89
int output_src_len;
90
 
91
 
92
/*
2 7u83 93
    SIGNAL HANDLER
94
 
95
    This routine handles caught signals.
96
*/
97
 
6 7u83 98
static void
99
handler(int sig)
2 7u83 100
{
6 7u83 101
    char *s;
102
    hash_elem *e;
103
    IGNORE signal(SIGINT, SIG_IGN);
104
    switch (sig) {
105
	case SIGINT: s = "interrupt"; break;
106
	case SIGSEGV: s = "segmentation violation"; break;
107
	case SIGTERM: s = "termination signal"; break;
108
	default : s = "unknown signal"; break;
2 7u83 109
    }
6 7u83 110
    error(ERR_SERIOUS, "Caught %s", s);
111
    e = sort_hash(files);
112
    while (e) {
113
	object *p = e->obj;
114
	FILE *f = p->u.u_file;
115
	if (f) {
116
	    char *nm = p->name;
117
	    if (verbose) IGNORE printf("Removing %s ...\n", nm);
118
	    IGNORE fclose(f);
119
	    IGNORE remove(nm);
2 7u83 120
	}
6 7u83 121
	e = e->next;
2 7u83 122
    }
6 7u83 123
    exit(exit_status);
2 7u83 124
}
125
 
126
 
127
/*
128
    SEPARATE COMPILATION ROUTINE
129
 
130
    This routine performs the separate compilation of the set object p.
131
*/
132
 
6 7u83 133
static void
134
separate(object *p)
2 7u83 135
{
6 7u83 136
    info *i = p->u.u_info;
137
    static char *exec = null;
138
    if (i->subset || i->file == null) return;
139
    if (exec == null)exec = buffer + strlen(buffer);
140
    IGNORE sprintf(exec, "%s %s", i->api, i->file);
141
    if (verbose > 1) IGNORE printf("Executing '%s' ...\n", buffer);
142
    if (system(buffer)) {
143
	error(ERR_SERIOUS, "Separate compilation of %s failed", p->name);
2 7u83 144
    }
6 7u83 145
    return;
2 7u83 146
}
147
 
148
 
149
/*
150
    MARK A SET AS IMPLEMENTED
151
 
152
    This routine recursively marks all implemented subsets of p.
153
*/
154
 
6 7u83 155
static void
156
implement(object *p, int depth)
2 7u83 157
{
6 7u83 158
    object *q;
159
    info *i = p->u.u_info;
160
    if (i == null || i->implemented >= depth) return;
161
    i->implemented = depth;
162
    for (q = i->elements; q != null; q = q->next) {
163
	if (q->objtype == OBJ_IMPLEMENT) {
164
	    implement(q->u.u_obj, depth + 1);
2 7u83 165
	}
166
    }
6 7u83 167
    return;
2 7u83 168
}
169
 
170
 
171
/*
172
    MAIN ROUTINE
173
 
174
    This is the main routine which interprets the command-line options
175
    and calls the appropriate routines.
176
*/
177
 
6 7u83 178
int
179
main(int argc, char **argv)
2 7u83 180
{
6 7u83 181
    int a;
182
    char *env;
183
    char *dir = ".";
184
    char *api = null;
185
    char *file = null;
186
    char *subset = null;
187
    object *commands = null;
188
    FILE *preproc_file = null;
189
    int show_index = 0;
190
    boolean check_only = 0;
191
    boolean preproc_input = 0;
192
    boolean separate_files = 0;
2 7u83 193
 
194
    /* Initialisation */
6 7u83 195
    line_no = 1;
196
    filename = "built-in definitions";
197
    init_hash();
198
    init_keywords();
199
    init_types();
200
    filename = "command line";
201
    IGNORE signal(SIGINT, handler);
202
    IGNORE signal(SIGSEGV, handler);
203
    IGNORE signal(SIGTERM, handler);
2 7u83 204
 
205
    /* Read system variables */
6 7u83 206
    env = getenv(INPUT_ENV);
207
    if (env)input_dir = string_copy(env);
208
    env = getenv(OUTPUT_ENV);
209
    if (env) {
210
	output_incl_dir = string_printf("%s/include", env);
211
	output_incl_len = (int)strlen(output_incl_dir) + 1;
212
	output_src_dir = string_printf("%s/src", env);
213
	output_src_len = (int)strlen(output_src_dir) + 1;
2 7u83 214
    }
6 7u83 215
    env = getenv(INCLUDE_ENV);
216
    if (env) {
217
	output_incl_dir = string_copy(env);
218
	output_incl_len = (int)strlen(output_incl_dir) + 1;
2 7u83 219
    }
6 7u83 220
    env = getenv(SRC_ENV);
221
    if (env) {
222
	output_src_dir = string_copy(env);
223
	output_src_len = (int)strlen(output_src_dir) + 1;
2 7u83 224
    }
6 7u83 225
    env = getenv(COPYRIGHT_ENV);
226
    if (env)copyright = string_copy(env);
2 7u83 227
 
228
    /* Process options */
6 7u83 229
    for (a = 1; a < argc; a++) {
230
	char *arg = argv [a];
231
	line_no = a;
232
	if (arg [0] == '-') {
233
	    if (arg [1] == 'I') {
234
		dir = string_printf("%s:%s", dir, arg + 2);
235
	    } else if (arg [1] == 'O') {
236
		output_incl_dir = arg + 2;
237
		output_incl_len = (int)strlen(arg + 2) + 1;
238
	    } else if (arg [1] == 'S') {
239
		output_src_dir = arg + 2;
240
		output_src_len = (int)strlen(arg + 2) + 1;
241
	    } else if (arg [1] == 'C') {
242
		copyright = arg + 2;
2 7u83 243
	    } else {
6 7u83 244
		char *s;
245
		for (s = arg + 1; *s; s++) {
246
		    switch (*s) {
247
			case 'a': separate_files = 0; break;
248
			case 'c': check_only = 1; break;
249
			case 'd': restrict_depth = 0; break;
250
			case 'e': preproc_file = stdout; break;
251
			case 'f': force_output = 1; break;
252
			case 'i': show_index = 1; break;
253
			case 'l': local_input = 1; break;
254
			case 'm': show_index = 2; break;
255
			case 'n': progdate = date_stamp(argv [0]); break;
256
			case 'p': preproc_input = 1; break;
257
			case 'r': restrict_use = 1; break;
258
			case 's': separate_files = 1; break;
259
			case 't': allow_long_long = 1; break;
260
			case 'u': unique_names = 1; break;
261
			case 'v': verbose++; break;
262
			case 'w': warnings = 0; break;
263
			case 'V': {
264
			    error(ERR_INFO, "Version: %s (release %s)",
265
				    progvers, RELEASE);
266
			    break;
2 7u83 267
			}
268
			default : {
6 7u83 269
			    error(ERR_WARNING, "Unknown option, -%c", *s);
270
			    break;
2 7u83 271
			}
272
		    }
273
		}
274
	    }
275
	} else {
6 7u83 276
	    if (api == null) {
277
		api = arg;
278
	    } else if (file == null) {
279
		file = arg;
280
	    } else if (subset == null) {
281
		subset = arg;
2 7u83 282
	    } else {
6 7u83 283
		error(ERR_WARNING, "Too many arguments");
2 7u83 284
	    }
285
	}
286
    }
21 7u83 287
 
6 7u83 288
    if (local_input) {
289
	if (subset)error(ERR_WARNING, "Too many arguments");
290
	subset = file;
291
	file = api;
292
	api = LOCAL_API;
2 7u83 293
    }
21 7u83 294
    if (api == null)
295
	error(ERR_FATAL, "Not enough arguments");
6 7u83 296
    input_dir = string_printf("%s:%s", dir, input_dir);
2 7u83 297
 
21 7u83 298
    if (output_src_len==0 || output_incl_len==0){
299
	error(ERR_FATAL, "No output directories specified");	    
300
    }
301
 
6 7u83 302
    if (preproc_input) {
2 7u83 303
	/* Open preprocessed input */
6 7u83 304
	if (file != null)error(ERR_WARNING, "Too many arguments");
305
	preproc_file = fopen(api, "r");
306
	filename = api;
307
	line_no = 1;
308
	if (preproc_file == null) {
309
	    error(ERR_FATAL, "Can't open input file");
2 7u83 310
	}
311
    } else {
312
	/* Find the temporary file */
6 7u83 313
	int n;
314
	if (preproc_file == null) {
315
	    preproc_file = tmpfile();
316
	    if (preproc_file == null) {
317
		error(ERR_FATAL, "Can't open temporary file");
2 7u83 318
	    }
319
	}
320
	/* Do the preprocessing */
6 7u83 321
	preproc(preproc_file, api, file, subset);
322
	n = no_errors;
323
	if (n) {
324
	    filename = null;
325
	    error(ERR_FATAL, "%d error(s) in preprocessor phase", n);
2 7u83 326
	}
6 7u83 327
	if (preproc_file == stdout)exit(exit_status);
328
	filename = "temporary file";
329
	line_no = 1;
2 7u83 330
    }
331
 
332
    /* Deal with separate compilation */
6 7u83 333
    if (separate_files) {
334
	int n;
335
	hash_elem *e;
336
	char *s = buffer;
337
	IGNORE sprintf(s, "%s ", argv [0]);
338
	for (a = 1; a < argc; a++) {
339
	    char *arg = argv [a];
340
	    if (arg [0] == '-') {
341
		s = s + strlen(s);
342
		IGNORE sprintf(s, "%s ", arg);
2 7u83 343
	    }
344
	}
6 7u83 345
	s = s + strlen(s);
346
	IGNORE strcpy(s, "-ac ");
347
	filename = null;
348
	e = sort_hash(subsets);
349
	while (e) {
350
	    separate(e->obj);
351
	    e = e->next;
2 7u83 352
	}
6 7u83 353
	n = no_errors;
354
	if (n) {
355
	    error(ERR_FATAL, "%d error(s) in separate compilation", n);
2 7u83 356
	}
6 7u83 357
	exit(exit_status);
2 7u83 358
    }
359
 
360
    /* Process the input */
6 7u83 361
    input_file = preproc_file;
362
    input_pending = LEX_EOF;
363
    rewind(input_file);
364
    ADVANCE_LEXER;
365
    read_spec(&commands);
366
    if (no_errors) {
367
	filename = null;
368
	error(ERR_FATAL, "%d error(s) in analyser phase", no_errors);
2 7u83 369
    }
370
 
371
    /* Perform the output */
6 7u83 372
    if (!check_only) {
373
	filename = null;
374
	if (commands && commands->objtype == OBJ_SET) {
375
	    implement(commands->u.u_obj, 1);
376
	    if (show_index == 0) {
377
		print_set(commands, 0);
378
		print_set(commands, 1);
379
		if (file == null) {
380
		    hash_elem *e = sort_hash(subsets);
381
		    print_makefile(api, e, 0);
382
		    print_makefile(api, e, 1);
2 7u83 383
		}
384
	    } else {
6 7u83 385
		if (show_index == 1) {
386
		    print_index(commands);
2 7u83 387
		} else {
6 7u83 388
		    print_machine_index(commands);
2 7u83 389
		}
390
	    }
391
	}
392
    }
6 7u83 393
    return(exit_status);
2 7u83 394
}