Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

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