Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
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 <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
/*
7 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
 
7 7u83 98
static void
99
handler(int sig)
2 7u83 100
{
7 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
    }
7 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
	}
7 7u83 121
	e = e->next;
2 7u83 122
    }
7 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
 
7 7u83 133
static void
134
separate(object *p)
2 7u83 135
{
7 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
    }
7 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
 
7 7u83 155
static void
156
implement(object *p, int depth)
2 7u83 157
{
7 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
    }
7 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
 
7 7u83 178
int
179
main(int argc, char **argv)
2 7u83 180
{
7 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 */
7 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 */
7 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
    }
7 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
    }
7 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
    }
7 7u83 225
    env = getenv(COPYRIGHT_ENV);
226
    if (env)copyright = string_copy(env);
2 7u83 227
 
228
    /* Process options */
7 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 {
7 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 : {
7 7u83 269
			    error(ERR_WARNING, "Unknown option, -%c", *s);
270
			    break;
2 7u83 271
			}
272
		    }
273
		}
274
	    }
275
	} else {
7 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 {
7 7u83 283
		error(ERR_WARNING, "Too many arguments");
2 7u83 284
	    }
285
	}
286
    }
7 7u83 287
    if (local_input) {
288
	if (subset)error(ERR_WARNING, "Too many arguments");
289
	subset = file;
290
	file = api;
291
	api = LOCAL_API;
2 7u83 292
    }
7 7u83 293
    if (api == null)error(ERR_FATAL, "Not enough arguments");
294
    input_dir = string_printf("%s:%s", dir, input_dir);
2 7u83 295
 
7 7u83 296
    if (preproc_input) {
2 7u83 297
	/* Open preprocessed input */
7 7u83 298
	if (file != null)error(ERR_WARNING, "Too many arguments");
299
	preproc_file = fopen(api, "r");
300
	filename = api;
301
	line_no = 1;
302
	if (preproc_file == null) {
303
	    error(ERR_FATAL, "Can't open input file");
2 7u83 304
	}
305
    } else {
306
	/* Find the temporary file */
7 7u83 307
	int n;
308
	if (preproc_file == null) {
309
	    preproc_file = tmpfile();
310
	    if (preproc_file == null) {
311
		error(ERR_FATAL, "Can't open temporary file");
2 7u83 312
	    }
313
	}
314
	/* Do the preprocessing */
7 7u83 315
	preproc(preproc_file, api, file, subset);
316
	n = no_errors;
317
	if (n) {
318
	    filename = null;
319
	    error(ERR_FATAL, "%d error(s) in preprocessor phase", n);
2 7u83 320
	}
7 7u83 321
	if (preproc_file == stdout)exit(exit_status);
322
	filename = "temporary file";
323
	line_no = 1;
2 7u83 324
    }
325
 
326
    /* Deal with separate compilation */
7 7u83 327
    if (separate_files) {
328
	int n;
329
	hash_elem *e;
330
	char *s = buffer;
331
	IGNORE sprintf(s, "%s ", argv [0]);
332
	for (a = 1; a < argc; a++) {
333
	    char *arg = argv [a];
334
	    if (arg [0] == '-') {
335
		s = s + strlen(s);
336
		IGNORE sprintf(s, "%s ", arg);
2 7u83 337
	    }
338
	}
7 7u83 339
	s = s + strlen(s);
340
	IGNORE strcpy(s, "-ac ");
341
	filename = null;
342
	e = sort_hash(subsets);
343
	while (e) {
344
	    separate(e->obj);
345
	    e = e->next;
2 7u83 346
	}
7 7u83 347
	n = no_errors;
348
	if (n) {
349
	    error(ERR_FATAL, "%d error(s) in separate compilation", n);
2 7u83 350
	}
7 7u83 351
	exit(exit_status);
2 7u83 352
    }
353
 
354
    /* Process the input */
7 7u83 355
    input_file = preproc_file;
356
    input_pending = LEX_EOF;
357
    rewind(input_file);
358
    ADVANCE_LEXER;
359
    read_spec(&commands);
360
    if (no_errors) {
361
	filename = null;
362
	error(ERR_FATAL, "%d error(s) in analyser phase", no_errors);
2 7u83 363
    }
364
 
365
    /* Perform the output */
7 7u83 366
    if (!check_only) {
367
	filename = null;
368
	if (commands && commands->objtype == OBJ_SET) {
369
	    implement(commands->u.u_obj, 1);
370
	    if (show_index == 0) {
371
		print_set(commands, 0);
372
		print_set(commands, 1);
373
		if (file == null) {
374
		    hash_elem *e = sort_hash(subsets);
375
		    print_makefile(api, e, 0);
376
		    print_makefile(api, e, 1);
2 7u83 377
		}
378
	    } else {
7 7u83 379
		if (show_index == 1) {
380
		    print_index(commands);
2 7u83 381
		} else {
7 7u83 382
		    print_machine_index(commands);
2 7u83 383
		}
384
	    }
385
	}
386
    }
7 7u83 387
    return(exit_status);
2 7u83 388
}