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
#if FS_STDARG
33
#include <stdarg.h>
34
#else
35
#include <varargs.h>
36
#endif
37
#include "types.h"
38
#include "read_types.h"
39
#include "analyser.h"
40
#include "fetch.h"
41
#include "file.h"
42
#include "table.h"
43
#include "utility.h"
44
#include "write.h"
45
extern char *progname ;
46
extern char *capname ;
47
extern int decode_status ;
48
extern int have_version ;
49
 
50
 
51
/*
52
    ARE INPUT AND OUTPUT TEXT OR CODE?
53
 
54
    The form of any error message depends on whether the input file
55
    is text or code.
56
*/
57
 
58
boolean text_input = 1 ;
59
boolean text_output = 0 ;
60
 
61
 
62
/*
63
    EXIT STATUS
64
 
65
    The overall exit status of the program.
66
*/
67
 
68
int exit_status = EXIT_SUCCESS ;
69
 
70
 
71
/*
72
    REPORT A FATAL ERROR
73
 
74
    The error s is reported and the program exits.
75
*/
76
 
77
void fatal_error
78
    PROTO_V ( ( char *s, ... ) ) /* VARARGS */
79
{
80
    va_list args ;
81
#if FS_STDARG
82
    va_start ( args, s ) ;
83
#else
84
    char *s ;
85
    va_start ( args ) ;
86
    s = va_arg ( args, char * ) ;
87
#endif
88
    if ( progname ) IGNORE fprintf ( stderr, "%s: ", progname ) ;
89
    IGNORE fprintf ( stderr, "Error: " ) ;
90
    IGNORE vfprintf ( stderr, s, args ) ;
91
    IGNORE fprintf ( stderr, ".\n" ) ;
92
    va_end ( args ) ;
93
    exit ( EXIT_FAILURE ) ;
94
}
95
 
96
 
97
/*
98
    IS AN INPUT ERROR FATAL?
99
 
100
    Not all input errors cause an immediate exit.  These should set
101
    is_fatal to false before calling input_error.
102
*/
103
 
104
boolean is_fatal = 1 ;
105
 
106
 
107
/*
108
    REPORT AN INPUT ERROR
109
 
110
    The input error s is reported and the program exits.
111
*/
112
 
113
void input_error
114
    PROTO_V ( ( char *s, ... ) ) /* VARARGS */
115
{
116
    va_list args ;
117
#if FS_STDARG
118
    va_start ( args, s ) ;
119
#else
120
    char *s ;
121
    va_start ( args ) ;
122
    s = va_arg ( args, char * ) ;
123
#endif
124
    if ( progname ) IGNORE fprintf ( stderr, "%s: ", progname ) ;
125
    IGNORE fprintf ( stderr, "Error: " ) ;
126
    IGNORE vfprintf ( stderr, s, args ) ;
127
    if ( input_file ) {
128
	IGNORE fprintf ( stderr, ", %s", input_file ) ;
129
	if ( text_input ) {
130
	    IGNORE fprintf ( stderr, ", line %ld", line_no ) ;
131
	} else {
132
	    long b = input_posn () ;
133
	    if ( capname ) {
134
		IGNORE fprintf ( stderr, ", capsule %s", capname ) ;
135
	    }
136
	    switch ( decode_status ) {
137
		case 0 : {
138
		    IGNORE fprintf ( stderr, " (at outermost level)" ) ;
139
		    break ;
140
		}
141
		case 1 : {
142
		    IGNORE fprintf ( stderr, " (in linking information)" ) ;
143
		    break ;
144
		}
145
		case 2 : {
146
		    IGNORE fprintf ( stderr, " (in unit body)" ) ;
147
		    break ;
148
		}
149
	    }
150
	    IGNORE fprintf ( stderr, ", byte %ld, bit %ld", b / 8, b % 8 ) ;
151
	    if ( decode_status == 0 ) {
152
		IGNORE fprintf ( stderr, " (Illegal TDF capsule?)" ) ;
153
	    }
154
	    if ( decode_status >= 1 && !have_version ) {
155
		IGNORE fprintf ( stderr, " (TDF version error?)" ) ;
156
	    }
157
	}
158
    }
159
    IGNORE fprintf ( stderr, ".\n" ) ;
160
    va_end ( args ) ;
161
    if ( is_fatal ) {
162
	if ( text_output ) {
163
	    sort_all () ;
164
	    print_capsule () ;
165
	    IGNORE fputs ( "# TERMINATED ON INPUT ERROR\n", output ) ;
166
	}
167
	exit ( EXIT_FAILURE ) ;
168
    }
169
    is_fatal = 1 ;
170
    exit_status = EXIT_FAILURE ;
171
    return ;
172
}
173
 
174
 
175
/*
176
    ISSUE A WARNING
177
 
178
    The warning message s is printed.
179
*/
180
 
181
void warning
182
    PROTO_V ( ( char *s, ... ) ) /* VARARGS */
183
{
184
    va_list args ;
185
#if FS_STDARG
186
    va_start ( args, s ) ;
187
#else
188
    char *s ;
189
    va_start ( args ) ;
190
    s = va_arg ( args, char * ) ;
191
#endif
192
    if ( progname ) IGNORE fprintf ( stderr, "%s: ", progname ) ;
193
    IGNORE fprintf ( stderr, "Warning: " ) ;
194
    IGNORE vfprintf ( stderr, s, args ) ;
195
    IGNORE fprintf ( stderr, ".\n" ) ;
196
    va_end ( args ) ;
197
    return ;
198
}
199
 
200
 
201
/*
202
    ALLOCATE A SECTION OF MEMORY
203
 
204
    This routine allocates n bytes of memory.
205
*/
206
 
207
pointer xalloc
208
    PROTO_N ( ( n ) )
209
    PROTO_T ( int n )
210
{
211
    pointer ptr ;
212
    if ( n == 0 ) return ( null ) ;
213
    ptr = ( pointer ) malloc ( ( size_t ) n ) ;
214
    if ( ptr == null ) {
215
	if ( !text_input && decode_status == 0 ) {
216
	    fatal_error ( "Memory allocation error (Illegal TDF capsule?)" ) ;
217
	}
218
	fatal_error ( "Memory allocation error" ) ;
219
    }
220
    return ( ptr ) ;
221
}
222
 
223
 
224
/*
225
    REALLOCATE A SECTION OF MEMORY
226
 
227
    This routine reallocates n bytes of memory for the pointer p.
228
*/
229
 
230
pointer xrealloc
231
    PROTO_N ( ( p, n ) )
232
    PROTO_T ( pointer p X int n )
233
{
234
    pointer ptr ;
235
    if ( n == 0 ) return ( null ) ;
236
    if ( p == null ) return ( xalloc ( n ) ) ;
237
    ptr = ( pointer ) realloc ( p, ( size_t ) n ) ;
238
    if ( ptr == null ) fatal_error ( "Memory allocation error" ) ;
239
    return ( ptr ) ;
240
}
241
 
242
 
243
/*
244
    MAKE A COPY OF A STRING
245
 
246
    This routine makes a permanent copy of the string s of length n.
247
*/
248
 
249
char *string_copy
250
    PROTO_N ( ( s, n ) )
251
    PROTO_T ( char *s X int n )
252
{
253
    int m = ( n + 1 ) * ( int ) sizeof ( char ) ;
254
    char *p = ( char * ) xalloc ( m ) ;
255
    IGNORE strncpy ( p, s, ( size_t ) n ) ;
256
    p [n] = 0 ;
257
    return ( p ) ;
258
}
259
 
260
 
261
/*
262
    MAKE A TEMPORARY COPY OF A STRING
263
 
264
    This routine copies a string into a temporary buffer.
265
*/
266
 
267
char *temp_copy
268
    PROTO_N ( ( s ) )
269
    PROTO_T ( char *s )
270
{
271
    static char *buff = null ;
272
    static int bufflen = 0 ;
273
    int n = ( int ) strlen ( s ) + 1 ;
274
    if ( n >= bufflen ) {
275
	bufflen = n + 100 ;
276
	buff = ( char * ) xrealloc ( ( pointer ) buff, bufflen ) ;
277
    }
278
    IGNORE strcpy ( buff, s ) ;
279
    return ( buff ) ;
280
}
281
 
282
 
283
/*
284
    CONVERT AN UNSIGNED LONG TO OCTAL
285
 
286
    The result is returned as a string of octal digits.
287
*/
288
 
289
char *ulong_to_octal
290
    PROTO_N ( ( n ) )
291
    PROTO_T ( unsigned long n )
292
{
293
    int i = 99 ;
294
    char buff [100] ;
295
    if ( n == 0 ) return ( "0" ) ;
296
    buff [i] = 0 ;
297
    while ( n ) {
298
	buff [ --i ] = ( char ) ( '0' + ( n & 7 ) ) ;
299
	n >>= 3 ;
300
    }
301
    return ( string_copy ( buff + i, 99 - i ) ) ;
302
}
303
 
304
 
305
/*
306
    CONVERT AN OCTAL STRING TO AN UNSIGNED LONG
307
 
308
    Any overflow is ignored (but see below).
309
*/
310
 
311
unsigned long octal_to_ulong
312
    PROTO_N ( ( num ) )
313
    PROTO_T ( char *num )
314
{
315
    unsigned long n = 0 ;
316
    for ( ; *num ; num++ ) {
317
	n = ( n << 3 ) + ( unsigned long ) ( *num - '0' ) ;
318
    }
319
    return ( n ) ;
320
}
321
 
322
 
323
/*
324
    DOES THE GIVEN OCTAL STRING FIT INTO AN UNSIGNED LONG?
325
 
326
    The number of binary digits needed to represent the octal number
327
    is calculated and compared against the number of bits in an
328
    unsigned long, minus sz (to allow for a sign bit).
329
*/
330
 
331
boolean fits_ulong
332
    PROTO_N ( ( num, sz ) )
333
    PROTO_T ( char *num X int sz )
334
{
335
    int n = 3 * ( int ) strlen ( num ) ;
336
    int m = BYTESIZE * ( int ) sizeof ( unsigned long ) - sz ;
337
    switch ( *num ) {
338
	case '0' : n -= 3 ; break ;
339
	case '1' : n -= 2 ; break ;
340
	case '2' : n -= 1 ; break ;
341
	case '3' : n -= 1 ; break ;
342
    }
343
    if ( n <= m ) return ( 1 ) ;
344
    return ( 0 ) ;
345
}