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
#define calculus_IO_ROUTINES
32
#include "config.h"
33
#include "calculus.h"
34
#include "error.h"
35
#include "extra.h"
36
#include "xalloc.h"
37
 
38
 
39
/*
40
    CHECK FOR CORRECT HEADERS
41
 
42
    The functions defined in this file give the implementations of various
43
    support functions used by the calculus implementation.  They should
44
    therefore be compiled with the calculus implementation rather than the
45
    specification.
46
*/
47
 
48
#if calculus_SPECIFICATION
49
!!!error Implementation specific functions compiled with token specifications
50
#endif
51
 
52
 
53
/*
54
    FREE OBJECTS
55
 
56
    These variables indicate the free calculi.  There is an array containing
57
    lists of small blocks, plus a single larger block.
58
*/
59
 
60
static calculus *free_calculi = NULL ;
61
static unsigned free_calculi_left = 0 ;
62
static calculus *free_calculus_array [] = {
63
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
64
    NULL, NULL, NULL
65
} ;
66
 
67
 
68
/*
69
    GENERATE A NEW OBJECT BLOCK
70
 
71
    This routine generates a new blcok of calculi of size sz.  Small blocks
72
    are allocated from the calculus array, others from the main calculus list.
73
*/
74
 
75
calculus *gen_calculus
76
    PROTO_N ( ( sz ) )
77
    PROTO_T ( unsigned sz )
78
{
79
    calculus *p ;
80
    unsigned n = sz ;
81
    ASSERT ( array_size ( free_calculus_array ) == calculus_GEN_MAX ) ;
82
    ASSERT ( n != 0 ) ;
83
 
84
    if ( n < calculus_GEN_MAX ) {
85
	/* Allocate from small block array */
86
	p = free_calculus_array [n] ;
87
	if ( p ) {
88
	    free_calculus_array [n] = TAIL_list ( p ) ;
89
	    return ( p ) ;
90
	}
91
    }
92
 
93
    /* Allocate from large block */
94
    if ( n > free_calculi_left ) {
95
	free_calculi_left = 1000 ;
96
	free_calculi = xmalloc_nof ( calculus, free_calculi_left ) ;
97
    }
98
    p = free_calculi ;
99
    free_calculi += sz ;
100
    free_calculi_left -= sz ;
101
    return ( p ) ;
102
}
103
 
104
 
105
/*
106
    DESTROY AN OBJECT BLOCK
107
 
108
    This routine destroys the block of calculi p of size sz.  Only small
109
    blocks are recycled.
110
*/
111
 
112
void destroy_calculus
113
    PROTO_N ( ( p, sz ) )
114
    PROTO_T ( calculus *p X unsigned sz )
115
{
116
    unsigned n = sz ;
117
    ASSERT ( n != 0 ) ;
118
    if ( p && n < calculus_GEN_MAX ) {
119
	TAIL_list ( p ) = free_calculus_array [n] ;
120
	free_calculus_array [n] = p ;
121
    }
122
    return ;
123
}
124
 
125
 
126
/*
127
    DUMMY OBJECT BLOCK DESTRUCTOR
128
 
129
    This routine is a dummy destructor which does nothing.
130
*/
131
 
132
void dummy_destroy_calculus
133
    PROTO_N ( ( p, sz ) )
134
    PROTO_T ( calculus *p X unsigned sz )
135
{
136
    UNUSED ( p ) ;
137
    UNUSED ( sz ) ;
138
    return ;
139
}
140
 
141
 
142
/*
143
    DESTROY A LIST OF OBJECT BLOCKS
144
 
145
    This routine destroys the list p of blocks of calculi of size sz.  The
146
    list is added to the appropriate entry of the free calculus array.
147
*/
148
 
149
void destroy_calculus_list
150
    PROTO_N ( ( p, sz ) )
151
    PROTO_T ( calculus *p X unsigned sz )
152
{
153
    unsigned n = sz + 1 ;
154
    if ( p && n < calculus_GEN_MAX ) {
155
	calculus *q = p ;
156
	while ( TAIL_list ( p ) ) p = TAIL_list ( p ) ;
157
	TAIL_list ( p ) = free_calculus_array [n] ;
158
	free_calculus_array [n] = q ;
159
    }
160
    return ;
161
}
162
 
163
 
164
/*
165
    FIND THE LENGTH OF A LIST
166
 
167
    This routine calculates the length of the list p.
168
*/
169
 
170
unsigned length_calculus_list
171
    PROTO_N ( ( p ) )
172
    PROTO_T ( calculus *p )
173
{
174
    calculus *q ;
175
    unsigned n = 0 ;
176
    for ( q = p ; q != NULL ; q = TAIL_list ( q ) ) n++ ;
177
    return ( n ) ;
178
}
179
 
180
 
181
/*
182
    REVERSE A LIST
183
 
184
    This routine reverses the order of the list p.
185
*/
186
 
187
calculus *reverse_calculus_list
188
    PROTO_N ( ( p ) )
189
    PROTO_T ( calculus *p )
190
{
191
    calculus *r = NULL ;
192
    calculus *q = p ;
193
    while ( q != NULL ) {
194
	calculus *nq = TAIL_list ( q ) ;
195
	TAIL_list ( q ) = r ;
196
	r = q ;
197
	q = nq ;
198
    }
199
    return ( r ) ;
200
}
201
 
202
 
203
/*
204
    APPEND TWO LISTS
205
 
206
    This routine appends the lists of calculus blocks p and q.
207
*/
208
 
209
calculus *append_calculus_list
210
    PROTO_N ( ( p, q ) )
211
    PROTO_T ( calculus *p X calculus *q )
212
{
213
    calculus *r = p ;
214
    if ( r == NULL ) return ( q ) ;
215
    while ( TAIL_list ( r ) ) r = TAIL_list ( r ) ;
216
    TAIL_list ( r ) = q ;
217
    return ( p ) ;
218
}
219
 
220
 
221
/*
222
    FIND THE LAST MEMBER OF A LIST
223
 
224
    This routine returns the last member of the list of calculus blocks p.
225
*/
226
 
227
calculus *end_calculus_list
228
    PROTO_N ( ( p ) )
229
    PROTO_T ( calculus *p )
230
{
231
    calculus *r = p ;
232
    if ( r == NULL ) return ( NULL ) ;
233
    while ( TAIL_list ( r ) ) r = TAIL_list ( r ) ;
234
    return ( r ) ;
235
}
236
 
237
 
238
/*
239
    EMPTY VECTOR
240
 
241
    This calculus represents the generic empty vector.  It is only defined
242
    if vector operations have been enabled.  Note that the element field
243
    of a vector is not be NULL, even if the vector is empty.
244
*/
245
 
246
#ifdef VEC
247
static calculus dummy_elem ;
248
calculus_VEC empty_calculus_vec = { 0, { &dummy_elem, &dummy_elem } } ;
249
#endif
250
 
251
 
252
/*
253
    ALIASING VARIABLES
254
 
255
    These variables give respectively the current alias number and the
256
    list of all aliases.
257
*/
258
 
259
unsigned crt_calculus_alias = 0 ;
260
static calculus *crt_alias_list = NULL ;
261
 
262
 
263
/*
264
    SET AN ALIAS
265
 
266
    This routine sets up an alias of p to n.
267
*/
268
 
269
void set_calculus_alias
270
    PROTO_N ( ( p, n ) )
271
    PROTO_T ( calculus *p X unsigned n )
272
{
273
    calculus *q ;
274
    ASSERT ( p != NULL ) ;
275
    q = gen_calculus ( ( unsigned ) 2 ) ;
276
    TAIL_list ( q ) = crt_alias_list ;
277
    HEAD_list ( q )->ag_ptr = p ;
278
    p->ag_tag = n ;
279
    crt_alias_list = q ;
280
    return ;
281
}
282
 
283
 
284
/*
285
    FIND AN ALIAS
286
 
287
    This routine searches for alias number n.
288
*/
289
 
290
calculus *find_calculus_alias
291
    PROTO_N ( ( n ) )
292
    PROTO_T ( unsigned n )
293
{
294
    calculus *p = crt_alias_list ;
295
    while ( p != NULL ) {
296
	calculus *q = HEAD_list ( p )->ag_ptr ;
297
	if ( q->ag_tag == n ) return ( q ) ;
298
	p = TAIL_list ( p ) ;
299
    }
300
    error ( ERROR_FATAL, "Can't find alias %u", n ) ;
301
    return ( NULL ) ;
302
}
303
 
304
 
305
/*
306
    CLEAR ALL ALIASES
307
 
308
    This routine clears all aliases.  Each alias in the list is reset to
309
    zero, and the list itself is freed.
310
*/
311
 
312
void clear_calculus_alias
313
    PROTO_Z ()
314
{
315
    calculus *p = crt_alias_list ;
316
    calculus *q = NULL ;
317
    while ( p != NULL ) {
318
	HEAD_list ( p )->ag_ptr->ag_tag = 0 ;
319
	q = p ;
320
	p = TAIL_list ( p ) ;
321
    }
322
    if ( q ) {
323
	TAIL_list ( q ) = free_calculus_array [2] ;
324
	free_calculus_array [2] = crt_alias_list ;
325
    }
326
    crt_calculus_alias = 0 ;
327
    crt_alias_list = NULL ;
328
    return ;
329
}
330
 
331
 
332
/*
333
    ADD TWO LISTS
334
 
335
    This routine copies the list of blocks of calculi p and adds the list
336
    q to the end.  sz gives the size of the blocks in the list.  This is
337
    used for the user defined tokens in extra.h.
338
*/
339
 
340
calculus *add_calculus_list
341
    PROTO_N ( ( p, q, sz ) )
342
    PROTO_T ( calculus *p X calculus *q X int sz )
343
{
344
    int i ;
345
    calculus *r ;
346
    if ( p == NULL ) return ( q ) ;
347
    r = gen_calculus ( ( unsigned ) ( sz + 1 ) ) ;
348
    for ( i = 1 ; i <= sz ; i++ ) r [i] = p [i] ;
349
    TAIL_list ( r ) = add_calculus_list ( TAIL_list ( p ), q, sz ) ;
350
    return ( r ) ;
351
}
352
 
353
 
354
/*
355
    ASSERTION ROUTINES
356
 
357
    These routine implement the assertion checks.
358
*/
359
 
360
#ifdef ASSERTS
361
#define assert_calculus assertion
362
#include "assert_def.h"
363
#endif