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/src/lib/cpp/src/typeinfo.cc – Rev 2

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 "implement.h"
32
#include "interface.h"
33
#include <cstdio>
34
#include <cstring>
35
#include <typeinfo>
36
using namespace std ;
37
 
38
 
39
/*
40
    CHECK FOR EQUAL TYPES
41
 
42
    This routine returns true if the types represented by t and s are
43
    equal.
44
*/
45
 
46
static int is_equal_type ( TYPE_INFO *t, TYPE_INFO *s )
47
{
48
    if ( t == s ) return ( 1 ) ;
49
    int c = t->code ;
50
    if ( c == s->code ) {
51
	// Type categories match
52
	switch ( c ) {
53
	    case RTTI_ptr :
54
	    case RTTI_ref :
55
	    case RTTI_ptr_mem :
56
	    case RTTI_array :
57
	    case RTTI_bitfield :
58
	    case RTTI_func :
59
	    case RTTI_c_func : {
60
		// Examine sub-types
61
		BASE_INFO *bt = t->base ;
62
		BASE_INFO *bs = s->base ;
63
		while ( bt && bs ) {
64
		    if ( bt->access != bs->access ) return ( 0 ) ;
65
		    if ( bt->virt != bs->virt ) return ( 0 ) ;
66
		    t = bt->rtti ;
67
		    s = bs->rtti ;
68
		    if ( !is_equal_type ( t, s ) ) return ( 0 ) ;
69
		    bt = bt->next ;
70
		    bs = bs->next ;
71
		}
72
		if ( bt || bs ) return ( 0 ) ;
73
		return ( 1 ) ;
74
	    }
75
	    case RTTI_class :
76
	    case RTTI_union :
77
	    case RTTI_enum : {
78
		// Examine type names
79
		if ( strcmp ( t->name, s->name ) == 0 ) return ( 1 ) ;
80
		break ;
81
	    }
82
	    default : {
83
		// Built-in types have unique representative
84
		break ;
85
	    }
86
	}
87
    }
88
    return ( 0 ) ;
89
}
90
 
91
 
92
/*
93
    CHECK FOR A BASE CLASS
94
 
95
    This routine returns 1 if the type represented by s is a base class
96
    of the type represented by t and 2 if the two types are actually
97
    equal.
98
*/
99
 
100
static int is_base_class ( TYPE_INFO *t, TYPE_INFO *s )
101
{
102
    if ( is_equal_type ( t, s ) ) return ( 2 ) ;
103
    if ( t->code == RTTI_class ) {
104
	for ( BASE_INFO *b = t->base ; b ; b = b->next ) {
105
	    // Check base classes
106
	    if ( is_base_class ( b->rtti, s ) ) return ( 1 ) ;
107
	}
108
    }
109
    return ( 0 ) ;
110
}
111
 
112
 
113
/*
114
    UNIQUE POINTERS
115
 
116
    The following unique pointers are used in do_base_cast.
117
*/
118
 
119
static void *error_ptr = ( void * ) &error_ptr ;
120
static void *null_ptr = ( void * ) &null_ptr ;
121
 
122
 
123
/*
124
    PERFORM A BASE CLASS CONVERSION
125
 
126
    This routine converts the pointer p from the type represented by t
127
    to the type represented by s.  The error pointer is returned for
128
    ambiguous conversions while a keeps track of the base class access.
129
*/
130
 
131
static void *do_base_cast ( void *p, TYPE_INFO *t, TYPE_INFO *s, int &a )
132
{
133
    void *r = NULL ;
134
    int acc = 0 ;
135
    if ( is_equal_type ( t, s ) ) {
136
	r = p ;
137
    } else {
138
	// Check base classes
139
	for ( BASE_INFO *b = t->base ; b ; b = b->next ) {
140
	    int c = b->access ;
141
	    void *q = p ;
142
	    if ( q != null_ptr ) {
143
		q = ( void * ) ( ( char * ) p + b->off ) ;
144
		if ( b->virt ) q = *( ( void ** ) q ) ;
145
	    }
146
	    q = do_base_cast ( q, b->rtti, s, c ) ;
147
	    if ( q ) {
148
		if ( r == NULL ) {
149
		    // First successful conversion
150
		    r = q ;
151
		    acc = c ;
152
		} else if ( r == q ) {
153
		    // Select most accessible successful conversion
154
		    if ( c < acc ) acc = c ;
155
		} else {
156
		    // Ambiguous conversion
157
		    r = error_ptr ;
158
		    return ( r ) ;
159
		}
160
	    }
161
	}
162
    }
163
    a += acc ;
164
    return ( r ) ;
165
}
166
 
167
 
168
/*
169
    PERFORM AN UNAMBIGUOUS BASE CLASS CONVERSION
170
 
171
    This routine is identical to do_base_cast except that it returns the
172
    null pointer for ambiguous or inaccessible conversions.
173
*/
174
 
175
static void *do_valid_base_cast ( void *p, TYPE_INFO *t, TYPE_INFO *s )
176
{
177
    int acc = INFO_public ;
178
    p = do_base_cast ( p, t, s, acc ) ;
179
    if ( p == error_ptr || acc != INFO_public ) p = NULL ;
180
    return ( p ) ;
181
}
182
 
183
 
184
/*
185
    PERFORM A DYNAMIC CAST
186
 
187
    This routine is used to implement the dynamic cast construct.  p gives
188
    a pointer to the virtual function table pointer for the construct
189
    operand and s gives the type information for the target type.
190
*/
191
 
192
void *__TCPPLUS_dynamic_cast ( VTABLE **p, TYPE_INFO *s )
193
{
194
    void *r = NULL ;
195
    VTABLE *vptr = *p ;
196
    TYPE_INFO *t = vptr->extra.rtti ;
197
    int c = is_base_class ( t, s ) ;
198
    if ( c ) {
199
	// Perform the base class conversion
200
	r = ( void * ) p ;
201
	r = ( void * ) ( ( ( char * ) r ) + vptr->extra.off ) ;
202
	if ( c == 1 ) r = do_valid_base_cast ( r, t, s ) ;
203
    }
204
    return ( r ) ;
205
}
206
 
207
 
208
/*
209
    PERFORM AN EXCEPTION CATCH CONVERSION
210
 
211
    This routine checks whether an exception of type t can be caught
212
    by a handler of type s.  If so it applies any necessary conversions
213
    to the exception value p and returns the value.  Otherwise the
214
    null pointer is returned.  Note that any reference components will
215
    have been removed from s.  cn is true if all the qualifiers in
216
    a qualification conversion contain 'const'.  dpt keeps track of
217
    the depth of pointer conversions.
218
*/
219
 
220
void *__TCPPLUS_catch_cast
221
    ( void *p, TYPE_INFO *t, TYPE_INFO *s, int cn, int dpt )
222
{
223
    if ( p ) {
224
	if ( is_equal_type ( t, s ) ) {
225
	    // Exact match
226
	    return ( p ) ;
227
	}
228
	int c = t->code ;
229
	if ( c == s->code ) {
230
	    if ( c == RTTI_ptr || c == RTTI_ref ) {
231
		// Check for pointer conversions
232
		BASE_INFO *bt = t->base ;
233
		BASE_INFO *bs = s->base ;
234
		int at = bt->access ;
235
		int as = bs->access ;
236
		if ( at == as || ( cn && !( at & ~as ) ) ) {
237
		    // Qualifiers are alright
238
		    t = bt->rtti ;
239
		    s = bs->rtti ;
240
		    if ( dpt == 0 ) {
241
			if ( s->code == RTTI_void && c == RTTI_ptr ) {
242
			    switch ( t->code ) {
243
				case RTTI_func :
244
				case RTTI_c_func : {
245
				    // Can't convert function to 'void *'
246
				    break ;
247
				}
248
				default : {
249
				    // Can convert 't *' to 'void *'
250
				    return ( p ) ;
251
				}
252
			    }
253
			}
254
			int b = is_base_class ( t, s ) ;
255
			if ( b == 2 ) {
256
			    // Exact base class conversion
257
			    return ( p ) ;
258
			}
259
			if ( b == 1 ) {
260
			    // Base class conversion
261
			    void *q = *( ( void ** ) p ) ;
262
			    if ( q == NULL ) q = null_ptr ;
263
			    void *r = do_valid_base_cast ( q, t, s ) ;
264
			    if ( r ) {
265
				static void *buf = NULL ;
266
				if ( q == r ) return ( p ) ;
267
				buf = r ;
268
				return ( ( void * ) &buf ) ;
269
			    }
270
			}
271
		    }
272
		    if ( !( at & INFO_const ) ) cn = 0 ;
273
		    p = __TCPPLUS_catch_cast ( p, t, s, cn, dpt + 1 ) ;
274
		    return ( p ) ;
275
		}
276
 
277
	    } else if ( c == RTTI_ptr_mem ) {
278
		// Check for pointer to member conversion
279
		BASE_INFO *bt = t->base ;
280
		BASE_INFO *bs = s->base ;
281
		if ( is_equal_type ( bt->rtti, bs->rtti ) ) {
282
		    // Classes match
283
		    bt = bt->next ;
284
		    bs = bs->next ;
285
		    int at = bt->access ;
286
		    int as = bs->access ;
287
		    if ( at == as || ( cn && !( at & ~as ) ) ) {
288
			// Qualifiers are alright
289
			t = bt->rtti ;
290
			s = bs->rtti ;
291
			if ( !( at & INFO_const ) ) cn = 0 ;
292
			p = __TCPPLUS_catch_cast ( p, t, s, cn, dpt + 1 ) ;
293
			return ( p ) ;
294
		    }
295
		}
296
 
297
	    } else if ( c == RTTI_class ) {
298
		// Check for base class conversions
299
		if ( dpt == 0 ) {
300
		    int b = is_base_class ( t, s ) ;
301
		    if ( b == 2 ) {
302
			return ( p ) ;
303
		    }
304
		    if ( b == 1 ) {
305
			p = do_valid_base_cast ( p, t, s ) ;
306
			return ( p ) ;
307
		    }
308
		}
309
	    }
310
	}
311
    }
312
    return ( NULL ) ;
313
}
314
 
315
 
316
/*
317
    PRINT RUN-TIME TYPE INFORMATION
318
 
319
    This routine prints the run-time type information t with access a
320
    and virtual qualifier v at an indentation of i.
321
*/
322
 
323
static void print_type_info ( TYPE_INFO *t, char *a, char *v, int i )
324
{
325
    for ( int j = 0 ; j < i ; j++ ) fputc ( ' ', stdout ) ;
326
    printf ( "%s%s%s", a, v, t->name ) ;
327
    BASE_INFO *b = t->base ;
328
    if ( b && t->code == RTTI_class ) {
329
	printf ( " = {\n" ) ;
330
	while ( b ) {
331
	    switch ( b->access ) {
332
		case INFO_public : a = "public " ; break ;
333
		case INFO_protected : a = "protected " ; break ;
334
		case INFO_private : a = "private " ; break ;
335
	    }
336
	    v = const_cast < char * > ( b->virt ? "virtual " : "" ) ;
337
	    print_type_info ( b->rtti, a, v, i + 4 ) ;
338
	    b = b->next ;
339
	}
340
	for ( int j = 0 ; j < i ; j++ ) fputc ( ' ', stdout ) ;
341
	fputc ( '}', stdout ) ;
342
    }
343
    printf ( " ;\n" ) ;
344
    return ;
345
}
346
 
347
 
348
/*
349
    PRINT RUN-TIME TYPE INFORMATION FOR AN OBJECT
350
 
351
    This routine prints the run-time type information for an object given
352
    a pointer to its virtual function table.
353
*/
354
 
355
void __TCPPLUS_type_info ( VTABLE *p )
356
{
357
    if ( p ) {
358
	TYPE_INFO *t = p->extra.rtti ;
359
	print_type_info ( t, "", "", 0 ) ;
360
    }
361
    return ;
362
}
363
 
364
 
365
/*
366
    MEMBER FUNCTIONS FOR TYPE_INFO CLASS
367
 
368
    These routines give the member functions for the type_info class.  They
369
    exploit the layout equivalent of a type_info and a TYPE_INFO.
370
*/
371
 
372
type_info::type_info ( const type_info &rhs )
373
{
374
    __code = rhs.__code ;
375
    __name = rhs.__name ;
376
    __base = rhs.__base ;
377
    return ;
378
}
379
 
380
type_info &type_info::operator= ( const type_info &rhs )
381
{
382
    __code = rhs.__code ;
383
    __name = rhs.__name ;
384
    __base = rhs.__base ;
385
    return ( *this ) ;
386
}
387
 
388
type_info::~type_info ()
389
{
390
    return ;
391
}
392
 
393
bool type_info::operator== ( const type_info &rhs ) const
394
{
395
    return ( is_equal_type ( ( TYPE_INFO * ) this, ( TYPE_INFO * ) &rhs ) ) ;
396
}
397
 
398
bool type_info::operator!= ( const type_info &rhs ) const
399
{
400
    return ( !( *this == rhs ) ) ;
401
}
402
 
403
bool type_info::before ( const type_info &rhs ) const
404
{
405
    return ( strcmp ( __name, rhs.__name ) < 0 ) ;
406
}
407
 
408
const char *type_info::name () const
409
{
410
    return ( __name ) ;
411
}