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
#define calculus_IO_ROUTINES
32
#include "config.h"
33
#include "read.h"
34
#include "calculus.h"
35
#include "common.h"
36
#include "error.h"
37
#include "output.h"
38
#include "xalloc.h"
39
 
40
 
41
/*
42
    BITMASKS
43
 
44
    This array gives the masks for each bit value.
45
*/
46
 
47
unsigned long bitmask [ CHAR_BIT ] ;
48
 
49
 
50
/*
51
    INITIALISE MASKS
52
 
53
    This routine initialises the array of bitmasks.  This is done
54
    dynamically rather than statically in case CHAR_BIT is not 8.
55
*/
56
 
57
void init_bitmask
58
    PROTO_Z ()
59
{
60
    int i ;
61
    for ( i = 0 ; i < CHAR_BIT ; i++ ) bitmask [i] = MASK ( i ) ;
62
    return ;
63
}
64
 
65
 
66
/*
67
    INPUT FILE
68
 
69
    These variables describe the input file.  There is a one byte input
70
    buffer.
71
*/
72
 
73
static FILE *input_file ;
74
static unsigned long input_buff = 0 ;
75
static int input_bits = 0 ;
76
 
77
 
78
/*
79
    READ A NUMBER OF BITS
80
 
81
    This routine reads the next n bits from the input file.
82
*/
83
 
84
static unsigned long read_bits
85
    PROTO_N ( ( n ) )
86
    PROTO_T ( int n )
87
{
88
    int b = input_bits ;
89
    unsigned long m = input_buff ;
90
    unsigned long r = 0 ;
91
    while ( n ) {
92
	if ( b == 0 ) {
93
	    /* Read next byte */
94
	    int c = getc ( input_file ) ;
95
	    if ( c == EOF ) {
96
		error ( ERROR_FATAL, "Premature end of file" ) ;
97
	    } else {
98
		m = ( ( ( unsigned long ) c ) & MASK ( CHAR_BIT ) ) ;
99
	    }
100
	    b = CHAR_BIT ;
101
	}
102
	if ( n >= b ) {
103
	    r = ( r << b ) | m ;
104
	    n -= b ;
105
	    b = 0 ;
106
	} else {
107
	    int c = b - n ;
108
	    r = ( r << n ) | ( m >> c ) ;
109
	    m &= bitmask [c] ;
110
	    n = 0 ;
111
	    b = c ;
112
	}
113
    }
114
    input_bits = b ;
115
    input_buff = m ;
116
    return ( r ) ;
117
}
118
 
119
 
120
/*
121
    READ AN INTEGER
122
 
123
    This routine reads an integer from the input file.  This is encoded
124
    as a sequence of octal digits with a marker bit for the end of the
125
    number.
126
*/
127
 
128
static unsigned long read_int
129
    PROTO_Z ()
130
{
131
    unsigned long r = 0, d ;
132
    while ( d = read_bits ( 4 ), ( d & 0x08 ) == 0 ) {
133
	r = ( r << 3 ) | d ;
134
    }
135
    r = ( r << 3 ) | ( d & 0x07 ) ;
136
    return ( r ) ;
137
}
138
 
139
 
140
/*
141
    READ A STRING
142
 
143
    This routine reads an integer from the input file.  This is encoded
144
    as the string length followed by the characters comprising the
145
    string (8 bits each).
146
*/
147
 
148
static char *read_string
149
    PROTO_Z ()
150
{
151
    unsigned long i, n = read_int () ;
152
    char *s = xstr ( ( long ) ( n + 1 ) ) ;
153
    for ( i = 0 ; i < n ; i++ ) {
154
	s [i] = ( char ) read_bits ( 8 ) ;
155
    }
156
    s [n] = 0 ;
157
    return ( s ) ;
158
}
159
 
160
 
161
/*
162
    READ A FILENAME
163
 
164
    File names are just strings, however they are buffered to save
165
    space.
166
*/
167
 
168
static char *read_filename
169
    PROTO_Z ()
170
{
171
    char *s ;
172
    static char *last_filename = "????" ;
173
    if ( read_bits ( 1 ) ) {
174
	s = last_filename ;
175
    } else {
176
	s = read_string () ;
177
	last_filename = s ;
178
    }
179
    return ( s ) ;
180
}
181
 
182
 
183
/*
184
    AUTOMATICALLY GENERATED DISK READING ROUTINES
185
 
186
    The main disk reading routines are automatically generated.  The
187
    various macros are used to customise these routines.
188
*/
189
 
190
#define READ_BITS( N )		( ( unsigned ) read_bits ( N ) )
191
#define READ_ALIAS()		( ( unsigned ) read_int () )
192
#define READ_DIM()		( ( unsigned ) read_int () )
193
#define READ_int()		( ( int ) read_int () )
194
#define READ_number()		( ( number ) read_int () )
195
#define READ_string()		read_string ()
196
#define READ_name_string()	read_filename ()
197
#define READ_zero_int()		0
198
 
199
#include "read_def.h"
200
 
201
 
202
/*
203
    READ AN INPUT FILE
204
 
205
    This routine reads an algebra from the input file nm.
206
*/
207
 
208
void read_file
209
    PROTO_N ( ( nm ) )
210
    PROTO_T ( char *nm )
211
{
212
    char *s ;
213
 
214
    /* Open file */
215
    crt_line_no = -1 ;
216
    crt_file_name = nm ;
217
    input_file = fopen ( nm, "rb" ) ;
218
    if ( input_file == NULL ) {
219
	error ( ERROR_SERIOUS, "Can't open input file, '%s'", nm ) ;
220
	return ;
221
    }
222
    init_bitmask () ;
223
    input_buff = 0 ;
224
    input_bits = 0 ;
225
 
226
    /* Confirm file header */
227
    s = READ_string () ;
228
    if ( !streq ( s, calculus_NAME ) ) {
229
	error ( ERROR_FATAL, "Invalid file header identifier" ) ;
230
    }
231
    s = READ_string () ;
232
    if ( !streq ( s, calculus_VERSION ) ) {
233
	error ( ERROR_FATAL, "Invalid file header version, '%s'", s ) ;
234
    }
235
 
236
    /* Read the algebra */
237
    algebra->name = READ_string () ;
238
    algebra->major_no = READ_int () ;
239
    algebra->minor_no = READ_int () ;
240
    algebra->types = READ_list_ptr_type () ;
241
    clear_calculus_alias () ;
242
 
243
    /* Extract lists of primitives etc */
244
    LOOP_TYPE {
245
	TYPE_P t = CRT_TYPE ;
246
	TYPE t0 = DEREF_type ( t ) ;
247
	switch ( TAG_type ( t0 ) ) {
248
	    case type_primitive_tag : {
249
		PRIMITIVE_P p = DEREF_ptr ( type_primitive_prim ( t0 ) ) ;
250
		CONS_ptr ( p, algebra->primitives, algebra->primitives ) ;
251
		break ;
252
	    }
253
	    case type_ident_tag : {
254
		IDENTITY_P p = DEREF_ptr ( type_ident_id ( t0 ) ) ;
255
		CONS_ptr ( p, algebra->identities, algebra->identities ) ;
256
		break ;
257
	    }
258
	    case type_enumeration_tag : {
259
		ENUM_P p = DEREF_ptr ( type_enumeration_en ( t0 ) ) ;
260
		CONS_ptr ( p, algebra->enumerations, algebra->enumerations ) ;
261
		break ;
262
	    }
263
	    case type_structure_tag : {
264
		STRUCTURE_P p = DEREF_ptr ( type_structure_struc ( t0 ) ) ;
265
		CONS_ptr ( p, algebra->structures, algebra->structures ) ;
266
		break ;
267
	    }
268
	    case type_onion_tag : {
269
		UNION_P p = DEREF_ptr ( type_onion_un ( t0 ) ) ;
270
		CONS_ptr ( p, algebra->unions, algebra->unions ) ;
271
		break ;
272
	    }
273
	}
274
    }
275
 
276
    /* Close file */
277
    fclose_v ( input_file ) ;
278
    return ;
279
}