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