Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5-amd64/src/producers/common/obj_c/c_class.c – Rev 6

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