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
/*
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 "ascii.h"
33
#include "types.h"
34
#include "basic.h"
35
#include "capsule.h"
36
#include "file.h"
37
#include "sort.h"
38
#include "tdf.h"
39
#include "tree.h"
40
#include "utility.h"
41
 
42
 
43
/*
44
    READ AN EXTENDED NUMBER FROM THE INPUT FILE
45
 
46
    This routine reads n bits.  If these are nonzero they give the result.
47
    Otherwise the result is ( 2^n - 1 ) plus the next extended number.
48
*/
49
 
50
long fetch_extn
51
    PROTO_N ( ( n ) )
52
    PROTO_T ( int n )
53
{
54
    long r = 0, s ;
55
    while ( s = fetch ( n ), s == 0 ) r += ( ( 1 << n ) - 1 ) ;
56
    return ( r + s ) ;
57
}
58
 
59
 
60
/*
61
    READ A TDF INTEGER FROM THE INPUT FILE
62
 
63
    This routine reads a TDF integer from the input file, returning
64
    the result as a long.  Any overflow is ignored.  A TDF integer
65
    is encoded as a series of 4 bit chunks, the least significant
66
    three of which represent an octal digit, and the most significant
67
    of which is a flag which is set to mark the last digit.
68
*/
69
 
70
long tdf_int
71
    PROTO_Z ()
72
{
73
    long dig ;
74
    long num = 0 ;
75
    if ( read_error ) return ( 0 ) ;
76
    do {
77
	dig = fetch ( 4 ) ;
78
	num = 8 * num + ( dig & 7 ) ;
79
    } while ( !( dig & 8 ) ) ;
80
    return ( num ) ;
81
}
82
 
83
 
84
/*
85
    BUFFER FOR LARGE TDF INTEGERS
86
 
87
    Larger TDF integers are stored as strings of octal digits.  This
88
    buffer is used to hold them temporarily.  tdf_int_digits gives
89
    the number of octal digits read.
90
*/
91
 
92
int tdf_int_digits ;
93
static char tdf_int_buff [1000] ;
94
 
95
 
96
/*
97
    READ A TDF INTEGER AS A STRING OF OCTAL DIGITS
98
 
99
    A TDF integer is read into the buffer tdf_int_buff, with its length being
100
    recorded in tdf_int_digits.
101
*/
102
 
103
char *tdf_int_str
104
    PROTO_Z ()
105
{
106
    long dig ;
107
    int i = 0 ;
108
    int reported = 0 ;
109
    if ( read_error ) {
110
	/* allow for recovery */
111
	tdf_int_digits = 1 ;
112
	return ( "0" ) ;
113
    }
114
    do {
115
	dig = fetch ( 4 ) ;
116
	if ( i < 1000 ) {
117
	    tdf_int_buff [i] = charact ( dig & 7 ) ;
118
	    i++ ;
119
	} else {
120
	    if ( !reported ) input_error ( "Numeric overflow" ) ;
121
	    reported = 1 ;
122
	}
123
    } while ( !( dig & 8 ) ) ;
124
    tdf_int_buff [i] = 0 ;
125
    tdf_int_digits = i ;
126
    return ( tdf_int_buff ) ;
127
}
128
 
129
 
130
/*
131
    READ AN 8-BIT STRING
132
 
133
    Only strings consisting of 8-bit characters are actually dealt with
134
    at the moment.  This routine decodes such a string of length n,
135
    translating any unprintable characters into escape sequences.
136
*/
137
 
138
string get_string
139
    PROTO_N ( ( n, sz ) )
140
    PROTO_T ( long n X long sz )
141
{
142
    long i ;
143
    string s ;
144
    char buff [5000] ;
145
    char *p = buff ;
146
    for ( i = 0 ; i < n ; i++ ) {
147
	int c = ( int ) fetch ( ( int ) sz ) ;
148
	if ( printable ( c ) ) {
149
	    if ( c == SLASH || c == QUOTE ) *( p++ ) = SLASH ;
150
	    *( p++ ) = ( char ) c ;
151
	} else {
152
	    *( p++ ) = SLASH ;
153
	    if ( c == NEWLINE ) {
154
		*( p++ ) = 'n' ;
155
	    } else if ( c == TAB ) {
156
		*( p++ ) = 't' ;
157
	    } else {
158
		*( p++ ) = charact ( c / 64 ) ;
159
		*( p++ ) = charact ( ( c % 64 ) / 8 ) ;
160
		*( p++ ) = charact ( c % 8 ) ;
161
	    }
162
	}
163
    }
164
    *( p++ ) = 0 ;
165
    n = ( int ) ( p - buff ) ;
166
    s = alloc_nof ( char, n ) ;
167
    IGNORE memcpy ( s, buff, ( size_t ) n ) ;
168
    return ( s ) ;
169
}
170
 
171
 
172
/*
173
    DECODE A TDF STRING
174
 
175
    A TDF string is read and returned.  This consists of the number
176
    of bits per character and the string length followed by the
177
    appropriate number of characters.  If the character size is not 8
178
    or the string is too long, it is deemed to be unprintable.
179
*/
180
 
181
string de_tdfstring
182
    PROTO_Z ()
183
{
184
    string s ;
185
    long sz = tdf_int () ;
186
    long n = tdf_int () ;
187
    if ( sz == 8 && n < 1000 ) {
188
	s = get_string ( n, sz ) ;
189
    } else {
190
	skip_bits ( ( long ) ( n * sz ) ) ;
191
	s = "<UNPRINTABLE>" ;
192
    }
193
    return ( s ) ;
194
}
195
 
196
 
197
/*
198
    DECODE AN ALIGNED TDF STRING
199
 
200
    This routine is identical to that above except that there are a
201
    couple of alignments.  This is used by de_extern_name.
202
*/
203
 
204
string de_tdfstring_align
205
    PROTO_Z ()
206
{
207
    string s ;
208
    long sz = tdf_int () ;
209
    long n = tdf_int () ;
210
    byte_align () ;
211
    if ( sz == 8 && n < 1000 ) {
212
	s = get_string ( n, sz ) ;
213
    } else {
214
	skip_bits ( ( long ) ( n * sz ) ) ;
215
	s = "<UNPRINTABLE>" ;
216
    }
217
    byte_align () ;
218
    return ( s ) ;
219
}
220
 
221
 
222
/*
223
    DECODE A UNIQUE IDENTIFIER
224
 
225
    A unique consists of an array of strings.  The end of the array is marked
226
    by a null string.
227
*/
228
 
229
unique de_unique
230
    PROTO_Z ()
231
{
232
    long i, n ;
233
    unique u ;
234
    n = tdf_int () ;
235
    u = alloc_nof ( string, n + 1 ) ;
236
    for ( i = 0 ; i < n ; i++ ) u [i] = de_tdfstring_align () ;
237
    u [n] = null ;
238
    return ( u ) ;
239
}
240
 
241
 
242
/*
243
    DECODE AN EXTERNAL NAME
244
 
245
    A number of bits are read and, according to their value, either a
246
    string or a unique is decoded.
247
*/
248
 
249
external de_extern_name
250
    PROTO_Z ()
251
{
252
    external e ;
253
    long n = de_external () ;
254
    byte_align () ;
255
    switch ( n ) {
256
	case external_string_extern : {
257
	    e.simple = 1 ;
258
	    e.val.str = de_tdfstring_align () ;
259
	    break ;
260
	}
261
	case external_unique_extern : {
262
	    e.simple = 0 ;
263
	    e.val.uniq = de_unique () ;
264
	    break ;
265
	}
266
	case external_chain_extern : {
267
	    e.simple = 1 ;
268
	    e.val.str = de_tdfstring_align () ;
269
	    IGNORE tdf_int () ;
270
	    break ;
271
	}
272
	default : {
273
	    e.simple = 1 ;
274
	    e.val.str = "<ERROR>" ;
275
	    break ;
276
	}
277
    }
278
    return ( e ) ;
279
}
280
 
281
 
282
/*
283
    ARRAY OF FOREIGN SORTS
284
 
285
    Foreign sorts are identified by means of strings.  This array gives all
286
    the foreign sorts known to the program.
287
*/
288
 
289
int do_foreign_sorts = 0 ;
290
long no_foreign_sorts = 0 ;
291
sortid *foreign_sorts = null ;
292
static long fs_size = 0 ;
293
 
294
 
295
/*
296
    ADD A FOREIGN SORT
297
 
298
    The foreign sort with name nm, foreign name fnm and decode letter c is
299
    added to the array of foreign sorts.
300
*/
301
 
302
void add_foreign_sort
303
    PROTO_N ( ( nm, fnm, c ) )
304
    PROTO_T ( char *nm X char *fnm X int c )
305
{
306
    long n = no_foreign_sorts++ ;
307
    if ( n >= fs_size ) {
308
	fs_size += 20 ;
309
	foreign_sorts = realloc_nof ( foreign_sorts, sortid, fs_size ) ;
310
    }
311
    foreign_sorts [n].name = nm ;
312
    foreign_sorts [n].fname = fnm ;
313
    foreign_sorts [n].decode = ( char ) c ;
314
    foreign_sorts [n].res = ( sortname ) ( extra_sorts + n ) ;
315
    foreign_sorts [n].args = null ;
316
    return ;
317
}
318
 
319
 
320
/*
321
    DECODE A COMPLEX SORT AS A STRING
322
*/
323
 
324
static sortid de_complex_sort
325
    PROTO_N ( ( sn ) )
326
    PROTO_T ( sortname sn )
327
{
328
    sortid cs ;
329
    if ( sn == sort_token ) {
330
	long i, n ;
331
	sortid cp, cr ;
332
	char buff [1000] ;
333
	char *p = buff ;
334
 
335
	/* Decode result of token sort */
336
	cr = de_sort_name ( 0 ) ;
337
	cs.res = cr.res ;
338
	cr = de_complex_sort ( cs.res ) ;
339
 
340
	/* Start decoding token sort */
341
	cs.decode = 'T' ;
342
	check_list () ;
343
	n = tdf_int () ;
344
	cs.args = alloc_nof ( char, n + 1 ) ;
345
	IGNORE strcpy ( p, "TOKEN(" ) ;
346
	p = p + strlen ( p ) ;
347
 
348
	/* Decode arguments of token sort */
349
	for ( i = 0 ; i < n ; i++ ) {
350
	    cp = de_sort_name ( 0 ) ;
351
	    cp = de_complex_sort ( cp.res ) ;
352
	    if ( i ) *( p++ ) = ',' ;
353
	    IGNORE strcpy ( p, cp.name ) ;
354
	    p = p + strlen ( p ) ;
355
	    cs.args [i] = cp.decode ;
356
	}
357
	cs.args [n] = 0 ;
358
	IGNORE strcpy ( p, ")->" ) ;
359
	p = p + strlen ( p ) ;
360
 
361
	/* Copy token sort */
362
	IGNORE strcpy ( p, cr.name ) ;
363
	p = alloc_nof ( char, ( int ) strlen ( buff ) + 1 ) ;
364
	IGNORE strcpy ( p, buff ) ;
365
	cs.name = p ;
366
    } else {
367
	/* Non-token sorts are simple */
368
	cs = find_sort ( sn ) ;
369
    }
370
    return ( cs ) ;
371
}
372
 
373
 
374
/*
375
    DECODE A SORTNAME
376
 
377
    A value representing a sort is read and returned.  If expand is true
378
    then the parameters and result of any high-level sort are read but
379
    discarded.
380
*/
381
 
382
sortid de_sort_name
383
    PROTO_N ( ( expand ) )
384
    PROTO_T ( int expand )
385
{
386
    sortname sn = ( sortname ) de_sortname () ;
387
    if ( sn == sort_token && expand ) {
388
	return ( de_complex_sort ( sn ) ) ;
389
    }
390
    if ( sn == sort_foreign ) {
391
	long i ;
392
	string nm ;
393
#if string_ext
394
	long n = fetch_extn ( string_bits ) ;
395
#else
396
	long n = fetch ( string_bits ) ;
397
#endif
398
	if ( n != string_make_string ) {
399
	    input_error ( "Unknown foreign sort" ) ;
400
	}
401
	nm = de_tdfstring () ;
402
	for ( i = 0 ; i < no_foreign_sorts ; i++ ) {
403
	    if ( streq ( nm, foreign_sorts [i].fname ) ) {
404
		return ( foreign_sorts [i] ) ;
405
	    }
406
	}
407
	add_foreign_sort ( nm, nm, 'F' ) ;
408
	return ( foreign_sorts [i] ) ;
409
    }
410
    return ( find_sort ( sn ) ) ;
411
}