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
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#include <signal.h>
33
#include "release.h"
34
#include "object.h"
35
#include "hash.h"
36
#include "index.h"
37
#include "lex.h"
38
#include "makefile.h"
39
#include "name.h"
40
#include "syntax.h"
41
#include "type.h"
42
#include "print.h"
43
#include "utility.h"
44
 
45
 
46
/*
47
    SIGNAL HANDLER
48
 
49
    This routine handles caught signals.
50
*/
51
 
52
static void handler
53
    PROTO_N ( ( sig ) )
54
    PROTO_T ( int sig )
55
{
56
    char *s ;
57
    hash_elem *e ;
58
    IGNORE signal ( SIGINT, SIG_IGN ) ;
59
    switch ( sig ) {
60
	case SIGINT : s = "interrupt" ; break ;
61
	case SIGSEGV : s = "segmentation violation" ; break ;
62
	case SIGTERM : s = "termination signal" ; break ;
63
	default : s = "unknown signal" ; break ;
64
    }
65
    error ( ERR_SERIOUS, "Caught %s", s ) ;
66
    e = sort_hash ( files ) ;
67
    while ( e ) {
68
	object *p = e->obj ;
69
	FILE *f = p->u.u_file ;
70
	if ( f ) {
71
	    char *nm = p->name ;
72
	    if ( verbose ) error ( ERR_INFO, "Removing %s ...", nm ) ;
73
	    IGNORE fclose ( f ) ;
74
	    IGNORE remove ( nm ) ;
75
	}
76
	e = e->next ;
77
    }
78
    exit ( exit_status ) ;
79
}
80
 
81
 
82
/*
83
    SEPARATE COMPILATION ROUTINE
84
 
85
    This routine performs the separate compilation of the set object p.
86
*/
87
 
88
static void separate
89
    PROTO_N ( ( p ) )
90
    PROTO_T ( object *p )
91
{
92
    info *i = p->u.u_info ;
93
    static char *exec = null ;
94
    if ( i->subset || i->file == null ) return ;
95
    if ( exec == null ) exec = buffer + strlen ( buffer ) ;
96
    IGNORE sprintf ( exec, "%s %s", i->api, i->file ) ;
97
    if ( verbose > 1 ) error ( ERR_INFO, "Executing '%s' ...", buffer ) ;
98
    if ( system ( buffer ) ) {
99
	error ( ERR_SERIOUS, "Separate compilation of %s failed", p->name ) ;
100
    }
101
    return ;
102
}
103
 
104
 
105
/*
106
    MARK A SET AS IMPLEMENTED
107
 
108
    This routine recursively marks all implemented subsets of p.
109
*/
110
 
111
static void implement
112
    PROTO_N ( ( p, depth ) )
113
    PROTO_T ( object *p X int depth )
114
{
115
    object *q ;
116
    info *i = p->u.u_info ;
117
    if ( i == null || i->implemented >= depth ) return ;
118
    i->implemented = depth ;
119
    for ( q = i->elements ; q != null ; q = q->next ) {
120
	if ( q->objtype == OBJ_IMPLEMENT ) {
121
	    implement ( q->u.u_obj, depth + 1 ) ;
122
	}
123
    }
124
    return ;
125
}
126
 
127
 
128
/*
129
    MAIN ROUTINE
130
 
131
    This is the main routine which interprets the command-line options
132
    and calls the appropriate routines.
133
*/
134
 
135
int main
136
    PROTO_N ( ( argc, argv ) )
137
    PROTO_T ( int argc X char **argv )
138
{
139
    int a ;
140
    char *env ;
141
    char *dir = "." ;
142
    char *api = null ;
143
    char *file = null ;
144
    char *subset = null ;
145
    object *commands = null ;
146
    FILE *preproc_file = null ;
147
    int show_index = 0 ;
148
    boolean check_only = 0 ;
149
    boolean preproc_input = 0 ;
150
    boolean separate_files = 0 ;
151
 
152
    /* Initialisation */
153
    line_no = 1 ;
154
    filename = "built-in definitions" ;
155
    init_hash () ;
156
    init_keywords () ;
157
    init_types () ;
158
    filename = "command line" ;
159
    IGNORE signal ( SIGINT, handler ) ;
160
    IGNORE signal ( SIGSEGV, handler ) ;
161
    IGNORE signal ( SIGTERM, handler ) ;
162
 
163
    /* Read system variables */
164
    env = getenv ( INPUT_ENV ) ;
165
    if ( env ) input_dir = string_copy ( env ) ;
166
    env = getenv ( OUTPUT_ENV ) ;
167
    if ( env ) {
168
	output_incl_dir = string_printf ( "%s/include", env ) ;
169
	output_incl_len = ( int ) strlen ( output_incl_dir ) + 1 ;
170
	output_src_dir = string_printf ( "%s/src", env ) ;
171
	output_src_len = ( int ) strlen ( output_src_dir ) + 1 ;
172
    }
173
    env = getenv ( INCLUDE_ENV ) ;
174
    if ( env ) {
175
	output_incl_dir = string_copy ( env ) ;
176
	output_incl_len = ( int ) strlen ( output_incl_dir ) + 1 ;
177
    }
178
    env = getenv ( SRC_ENV ) ;
179
    if ( env ) {
180
	output_src_dir = string_copy ( env ) ;
181
	output_src_len = ( int ) strlen ( output_src_dir ) + 1 ;
182
    }
183
    env = getenv ( COPYRIGHT_ENV ) ;
184
    if ( env ) copyright = string_copy ( env ) ;
185
 
186
    /* Process options */
187
    for ( a = 1 ; a < argc ; a++ ) {
188
	char *arg = argv [a] ;
189
	line_no = a ;
190
	if ( arg [0] == '-' ) {
191
	    if ( arg [1] == 'I' ) {
192
		dir = string_printf ( "%s:%s", dir, arg + 2 ) ;
193
	    } else if ( arg [1] == 'O' ) {
194
		output_incl_dir = arg + 2 ;
195
		output_incl_len = ( int ) strlen ( arg + 2 ) + 1 ;
196
	    } else if ( arg [1] == 'S' ) {
197
		output_src_dir = arg + 2 ;
198
		output_src_len = ( int ) strlen ( arg + 2 ) + 1 ;
199
	    } else if ( arg [1] == 'C' ) {
200
		copyright = arg + 2 ;
201
	    } else {
202
		char *s ;
203
		for ( s = arg + 1 ; *s ; s++ ) {
204
		    switch ( *s ) {
205
			case 'a' : separate_files = 0 ; break ;
206
			case 'c' : check_only = 1 ; break ;
207
			case 'd' : restrict_depth = 0 ; break ;
208
			case 'e' : preproc_file = stdout ; break ;
209
			case 'f' : force_output = 1 ; break ;
210
			case 'i' : show_index = 1 ; break ;
211
			case 'l' : local_input = 1 ; break ;
212
			case 'm' : show_index = 2 ; break ;
213
			case 'n' : progdate = date_stamp ( argv [0] ) ; break ;
214
			case 'p' : preproc_input = 1 ; break ;
215
			case 'r' : restrict_use = 1 ; break ;
216
			case 's' : separate_files = 1 ; break ;
217
			case 't' : allow_long_long = 1 ; break ;
218
			case 'u' : unique_names = 1 ; break ;
219
			case 'v' : verbose++ ; break ;
220
			case 'w' : warnings = 0 ; break ;
221
			case 'V' : {
222
			    error ( ERR_INFO, "Version: %s (release %s)",
223
				    progvers, RELEASE ) ;
224
			    break ;
225
			}
226
			default : {
227
			    error ( ERR_WARNING, "Unknown option, -%c", *s ) ;
228
			    break ;
229
			}
230
		    }
231
		}
232
	    }
233
	} else {
234
	    if ( api == null ) {
235
		api = arg ;
236
	    } else if ( file == null ) {
237
		file = arg ;
238
	    } else if ( subset == null ) {
239
		subset = arg ;
240
	    } else {
241
		error ( ERR_WARNING, "Too many arguments" ) ;
242
	    }
243
	}
244
    }
245
    if ( local_input ) {
246
	if ( subset ) error ( ERR_WARNING, "Too many arguments" ) ;
247
	subset = file ;
248
	file = api ;
249
	api = LOCAL_API ;
250
    }
251
    if ( api == null ) error ( ERR_FATAL, "Not enough arguments" ) ;
252
    input_dir = string_printf ( "%s:%s", dir, input_dir ) ;
253
 
254
    if ( preproc_input ) {
255
	/* Open preprocessed input */
256
	if ( file != null ) error ( ERR_WARNING, "Too many arguments" ) ;
257
	preproc_file = fopen ( api, "r" ) ;
258
	filename = api ;
259
	line_no = 1 ;
260
	if ( preproc_file == null ) {
261
	    error ( ERR_FATAL, "Can't open input file" ) ;
262
	}
263
    } else {
264
	/* Find the temporary file */
265
	int n ;
266
	if ( preproc_file == null ) {
267
	    preproc_file = tmpfile () ;
268
	    if ( preproc_file == null ) {
269
		error ( ERR_FATAL, "Can't open temporary file" ) ;
270
	    }
271
	}
272
	/* Do the preprocessing */
273
	preproc ( preproc_file, api, file, subset ) ;
274
	n = no_errors ;
275
	if ( n ) {
276
	    filename = null ;
277
	    error ( ERR_FATAL, "%d error(s) in preprocessor phase", n ) ;
278
	}
279
	if ( preproc_file == stdout ) exit ( exit_status ) ;
280
	filename = "temporary file" ;
281
	line_no = 1 ;
282
    }
283
 
284
    /* Deal with separate compilation */
285
    if ( separate_files ) {
286
	int n ;
287
	hash_elem *e ;
288
	char *s = buffer ;
289
	IGNORE sprintf ( s, "%s ", argv [0] ) ;
290
	for ( a = 1 ; a < argc ; a++ ) {
291
	    char *arg = argv [a] ;
292
	    if ( arg [0] == '-' ) {
293
		s = s + strlen ( s ) ;
294
		IGNORE sprintf ( s, "%s ", arg ) ;
295
	    }
296
	}
297
	s = s + strlen ( s ) ;
298
	IGNORE strcpy ( s, "-ac " ) ;
299
	filename = null ;
300
	e = sort_hash ( subsets ) ;
301
	while ( e ) {
302
	    separate ( e->obj ) ;
303
	    e = e->next ;
304
	}
305
	n = no_errors ;
306
	if ( n ) {
307
	    error ( ERR_FATAL, "%d error(s) in separate compilation", n ) ;
308
	}
309
	exit ( exit_status ) ;
310
    }
311
 
312
    /* Process the input */
313
    input_file = preproc_file ;
314
    input_pending = LEX_EOF ;
315
    rewind ( input_file ) ;
316
    ADVANCE_LEXER ;
317
    read_spec ( &commands ) ;
318
    if ( no_errors ) {
319
	filename = null ;
320
	error ( ERR_FATAL, "%d error(s) in analyser phase", no_errors ) ;
321
    }
322
 
323
    /* Perform the output */
324
    if ( !check_only ) {
325
	filename = null ;
326
	if ( commands && commands->objtype == OBJ_SET ) {
327
	    implement ( commands->u.u_obj, 1 ) ;
328
	    if ( show_index == 0 ) {
329
		print_set ( commands, 0 ) ;
330
		print_set ( commands, 1 ) ;
331
		if ( file == null ) {
332
		    hash_elem *e = sort_hash ( subsets ) ;
333
		    print_makefile ( api, e, 0 ) ;
334
		    print_makefile ( api, e, 1 ) ;
335
		}
336
	    } else {
337
		if ( show_index == 1 ) {
338
		    print_index ( commands ) ;
339
		} else {
340
		    print_machine_index ( commands ) ;
341
		}
342
	    }
343
	}
344
    }
345
    return ( exit_status ) ;
346
}