Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | 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 "c_types.h"
33
#include "error.h"
34
#include "xalloc.h"
35
 
36
 
37
/*
38
    CHECK FOR CORRECT HEADERS
39
 
40
    The functions defined in this file give the implementations of various
41
    support functions used by the c_class implementation.  They should
42
    therefore be compiled with the c_class implementation rather than the
43
    specification.
44
*/
45
 
46
#if c_class_SPECIFICATION
47
FAIL_COMPILER ( Implementation functions compiled with token specifications )
48
#endif
49
 
50
 
51
/*
52
    FREE OBJECTS
53
 
54
    These variables indicate the free c_classes.  There is an array
55
    containing lists of small blocks, plus a single larger block.
56
*/
57
 
58
#define SMALL_BLOCK		24
59
#define ALLOC_BLOCK		2048
60
 
61
#if ( c_class_GEN_MAX > SMALL_BLOCK )
62
FAIL_COMPILER ( Free block array is too small )
63
#endif
64
 
65
static c_class *free_c_classes = NULL ;
66
static unsigned free_c_classes_left = 0 ;
67
unsigned total_c_classes = 0 ;
68
 
69
static c_class *free_c_class_array [ SMALL_BLOCK ] = {
70
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
71
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
72
} ;
73
 
74
 
75
/*
76
    GENERATE A NEW OBJECT BLOCK
77
 
78
    This routine generates a new block of c_classes of size sz.  Small
79
    blocks are allocated from the c_class array, others from the main
80
    c_class list.
81
*/
82
 
83
c_class *gen_c_class
84
    PROTO_N ( ( sz ) )
85
    PROTO_T ( unsigned sz )
86
{
87
    c_class *p ;
88
    unsigned n = sz ;
89
    if ( n < SMALL_BLOCK ) {
90
	/* Allocate from small block array */
91
	if ( n == 0 ) return ( NULL ) ;
92
	p = free_c_class_array [n] ;
93
	if ( p ) {
94
	    free_c_class_array [n] = TAIL_list ( p ) ;
95
	    return ( p ) ;
96
	}
97
    }
98
    if ( n > free_c_classes_left ) {
99
	/* Allocate new blocks */
100
	unsigned m = ALLOC_BLOCK ;
101
	if ( n > m ) m = n ;
102
	free_c_classes = xmalloc_nof ( c_class, m ) ;
103
	free_c_classes_left = m ;
104
    }
105
    p = free_c_classes ;
106
    free_c_classes += n ;
107
    free_c_classes_left -= n ;
108
    return ( p ) ;
109
}
110
 
111
 
112
/*
113
    MARK AN OBJECT AS FREE
114
 
115
    This routine is used in the object destruction routines to mark an
116
    object as having been freed.  This only has any effect in conjunction
117
    with the debugging routine below.
118
*/
119
 
120
#ifdef RUNTIME
121
#define clean_c_class( P, Z )\
122
    {\
123
	ASSERT ( TYPEID ( P ) != TYPEID_free ) ;\
124
	TYPEID ( P ) = TYPEID_free ;\
125
	total_c_classes -= ( Z ) ;\
126
    }
127
#else
128
#define clean_c_class( P, Z )	/* empty */
129
#endif
130
 
131
 
132
/*
133
    GENERATE A NEW OBJECT BLOCK (DEBUG VERSION)
134
 
135
    This routine is identical to gen_c_class except that it includes the
136
    run-time type information t in the allocated block.
137
*/
138
 
139
#ifdef RUNTIME
140
 
141
c_class *debug_c_class
142
    PROTO_N ( ( sz, t ) )
143
    PROTO_T ( unsigned sz X unsigned t )
144
{
145
    c_class *p ;
146
    unsigned n = sz ;
147
    total_c_classes += n ;
148
    if ( n < SMALL_BLOCK ) {
149
	/* Allocate from small block array */
150
	if ( n == 0 ) return ( NULL ) ;
151
	p = free_c_class_array [n] ;
152
	if ( p ) {
153
	    free_c_class_array [n] = TAIL_list ( p ) ;
154
	    ASSERT ( TYPEID ( p ) == TYPEID_free ) ;
155
	    TYPEID ( p ) = t ;
156
	    return ( p ) ;
157
	}
158
    }
159
    n += 1 ;
160
    if ( n > free_c_classes_left ) {
161
	/* Allocate new blocks */
162
	unsigned m = ALLOC_BLOCK ;
163
	if ( n > m ) m = n ;
164
	free_c_classes = xmalloc_nof ( c_class, m ) ;
165
	free_c_classes_left = m ;
166
    }
167
    p = free_c_classes + 1 ;
168
    TYPEID ( p ) = t ;
169
    free_c_classes += n ;
170
    free_c_classes_left -= n ;
171
    return ( p ) ;
172
}
173
 
174
#endif /* RUNTIME */
175
 
176
 
177
/*
178
    DESTROY AN OBJECT BLOCK
179
 
180
    This routine destroys the block of c_classes p of size sz.
181
*/
182
 
183
void destroy_c_class
184
    PROTO_N ( ( p, sz ) )
185
    PROTO_T ( c_class *p X unsigned sz )
186
{
187
    if ( p ) {
188
	unsigned n = sz ;
189
	c_class **r = free_c_class_array ;
190
	if ( n < SMALL_BLOCK ) r += n ;
191
	clean_c_class ( p, n ) ;
192
	TAIL_list ( p ) = *r ;
193
	*r = p ;
194
    }
195
    return ;
196
}
197
 
198
 
199
/*
200
    DUMMY OBJECT BLOCK DESTRUCTOR
201
 
202
    This routine is a dummy destructor which does nothing.
203
*/
204
 
205
void dummy_destroy_c_class
206
    PROTO_N ( ( p, sz ) )
207
    PROTO_T ( c_class *p X unsigned sz )
208
{
209
    UNUSED ( p ) ;
210
    UNUSED ( sz ) ;
211
    return ;
212
}
213
 
214
 
215
/*
216
    DESTROY A LIST OF OBJECT BLOCKS
217
 
218
    This routine destroys the list p of blocks of c_classes of size sz.
219
    The list is added to the appropriate entry of the free c_class array.
220
*/
221
 
222
void destroy_c_class_list
223
    PROTO_N ( ( p, sz ) )
224
    PROTO_T ( c_class *p X unsigned sz )
225
{
226
    if ( p ) {
227
	c_class *q = p ;
228
	unsigned n = sz + 1 ;
229
	c_class **r = free_c_class_array ;
230
	if ( n < SMALL_BLOCK ) r += n ;
231
	while ( TAIL_list ( p ) ) {
232
	    clean_c_class ( p, n ) ;
233
	    p = TAIL_list ( p ) ;
234
	}
235
	clean_c_class ( p, n ) ;
236
	TAIL_list ( p ) = *r ;
237
	*r = q ;
238
    }
239
    return ;
240
}
241
 
242
 
243
/*
244
    FIND THE LENGTH OF A LIST
245
 
246
    This routine calculates the length of the list p.
247
*/
248
 
249
unsigned length_c_class_list
250
    PROTO_N ( ( p ) )
251
    PROTO_T ( c_class *p )
252
{
253
    unsigned n = 0 ;
254
    c_class *q = p ;
255
    while ( q ) {
256
	n++ ;
257
	q = TAIL_list ( q ) ;
258
    }
259
    return ( n ) ;
260
}
261
 
262
 
263
/*
264
    REVERSE A LIST
265
 
266
    This routine reverses the order of the list p.
267
*/
268
 
269
c_class *reverse_c_class_list
270
    PROTO_N ( ( p ) )
271
    PROTO_T ( c_class *p )
272
{
273
    c_class *r = NULL ;
274
    c_class *q = p ;
275
    while ( q ) {
276
	c_class *nq = TAIL_list ( q ) ;
277
	TAIL_list ( q ) = r ;
278
	r = q ;
279
	q = nq ;
280
    }
281
    return ( r ) ;
282
}
283
 
284
 
285
/*
286
    APPEND TWO LISTS
287
 
288
    This routine appends the lists of c_class blocks p and q.
289
*/
290
 
291
c_class *append_c_class_list
292
    PROTO_N ( ( p, q ) )
293
    PROTO_T ( c_class *p X c_class *q )
294
{
295
    c_class *r = p ;
296
    if ( r == NULL ) return ( q ) ;
297
    while ( TAIL_list ( r ) ) r = TAIL_list ( r ) ;
298
    TAIL_list ( r ) = q ;
299
    return ( p ) ;
300
}
301
 
302
 
303
/*
304
    FIND THE LAST MEMBER OF A LIST
305
 
306
    This routine returns the last member of the list of c_class blocks p.
307
*/
308
 
309
c_class *end_c_class_list
310
    PROTO_N ( ( p ) )
311
    PROTO_T ( c_class *p )
312
{
313
    c_class *r = p ;
314
    if ( r == NULL ) return ( NULL ) ;
315
    while ( TAIL_list ( r ) ) r = TAIL_list ( r ) ;
316
    return ( r ) ;
317
}
318
 
319
 
320
/*
321
    GENERIC EMPTY VECTOR
322
 
323
    This c_class represents the generic empty vector.  It is only defined
324
    if vector operations have been enabled.  Note that the element field
325
    of a vector is not be NULL, even if the vector is empty.
326
*/
327
 
328
#ifdef VEC
329
static c_class dummy_elem ;
330
c_class_VEC empty_c_class_vec = { 0, { &dummy_elem, &dummy_elem } } ;
331
#endif
332
 
333
 
334
#ifdef c_class_IO_ROUTINES
335
 
336
/*
337
    ALIASING VARIABLES
338
 
339
    These variables give respectively the current alias number and the
340
    list of all aliases.
341
*/
342
 
343
unsigned crt_c_class_alias = 0 ;
344
static c_class *crt_alias_list = NULL ;
345
 
346
 
347
/*
348
    SET AN ALIAS
349
 
350
    This routine sets up an alias of p to n.
351
*/
352
 
353
void set_c_class_alias
354
    PROTO_N ( ( p, n ) )
355
    PROTO_T ( c_class *p X unsigned n )
356
{
357
    c_class *q = GEN_c_class ( 2, TYPEID_list ) ;
358
    TAIL_list ( q ) = crt_alias_list ;
359
    HEAD_list ( q )->ag_ptr = p ;
360
    ASSERT ( p != NULL ) ;
361
    p->ag_tag = n ;
362
    crt_alias_list = q ;
363
    return ;
364
}
365
 
366
 
367
/*
368
    FIND AN ALIAS
369
 
370
    This routine searches for alias number n.
371
*/
372
 
373
c_class *find_c_class_alias
374
    PROTO_N ( ( n ) )
375
    PROTO_T ( unsigned n )
376
{
377
    c_class *p = crt_alias_list ;
378
    while ( p ) {
379
	c_class *q = HEAD_list ( p )->ag_ptr ;
380
	if ( q->ag_tag == n ) return ( q ) ;
381
	p = TAIL_list ( p ) ;
382
    }
383
    error ( ERROR_INTERNAL, "Can't find alias %u", n ) ;
384
    return ( NULL ) ;
385
}
386
 
387
 
388
/*
389
    CLEAR ALL ALIASES
390
 
391
    This routine clears all aliases.  Each alias in the list is reset to
392
    zero, and the list itself is freed.
393
*/
394
 
395
void clear_c_class_alias
396
    PROTO_Z ()
397
{
398
    c_class *p = crt_alias_list ;
399
    c_class *q = NULL ;
400
    while ( p ) {
401
	HEAD_list ( p )->ag_ptr->ag_tag = 0 ;
402
	q = p ;
403
	p = TAIL_list ( p ) ;
404
    }
405
    if ( q ) {
406
	TAIL_list ( q ) = free_c_class_array [2] ;
407
	free_c_class_array [2] = crt_alias_list ;
408
    }
409
    crt_c_class_alias = 0 ;
410
    crt_alias_list = NULL ;
411
    return ;
412
}
413
 
414
#endif /* c_class_IO_ROUTINES */
415
 
416
 
417
/*
418
    ASSERTION ROUTINES
419
 
420
    These routine implement the assertion checks.
421
*/
422
 
423
#ifdef ASSERTS
424
#define assert_c_class	assertion
425
#include "assert_def.h"
426
#endif