]>
Commit | Line | Data |
---|---|---|
c90f71dd RD |
1 | /******************************************************************************* |
2 | * Simplified Wrapper and Interface Generator (SWIG) | |
3 | * | |
4 | * Author : David Beazley | |
5 | * | |
6 | * Department of Computer Science | |
7 | * University of Chicago | |
8 | * 1100 E 58th Street | |
9 | * Chicago, IL 60637 | |
10 | * beazley@cs.uchicago.edu | |
11 | * | |
12 | * Please read the file LICENSE for the copyright and terms by which SWIG | |
13 | * can be used and distributed. | |
14 | *******************************************************************************/ | |
15 | ||
16 | /*********************************************************************** | |
17 | * $Header$ | |
18 | * | |
19 | * types.cxx | |
20 | * | |
21 | * This file contains functions for dealing with datatypes. This | |
22 | * is a combination of the file typedef.cc (now obsolete) and functions | |
23 | * that used to be in the swig.h header. | |
24 | * | |
25 | ***********************************************************************/ | |
26 | ||
27 | #include "internal.h" | |
28 | ||
29 | // ------------------------------------------------------------------- | |
30 | // class DataType member functions. | |
31 | // ------------------------------------------------------------------- | |
32 | ||
33 | DataType::DataType() { | |
34 | type = 1; | |
35 | name[0] = 0; | |
36 | is_pointer = 0; | |
37 | implicit_ptr = 0; | |
38 | qualifier = 0; | |
39 | is_reference = 0; | |
40 | status = 0; | |
41 | arraystr = 0; | |
42 | id = type_id++; | |
43 | } | |
44 | ||
45 | // Create a data type only from the type code (used to form constants) | |
46 | ||
47 | DataType::DataType(int t) { | |
48 | switch(t) { | |
49 | case T_BOOL: | |
50 | strcpy(name,"bool"); | |
51 | break; | |
52 | case T_INT: case T_SINT: | |
53 | strcpy(name,"int"); | |
54 | break; | |
55 | case T_UINT: | |
56 | strcpy(name,"unsigned int"); | |
57 | break; | |
58 | case T_SHORT: case T_SSHORT: | |
59 | strcpy(name,"short"); | |
60 | break; | |
61 | case T_USHORT: | |
62 | strcpy(name,"unsigned short"); | |
63 | break; | |
64 | case T_LONG: case T_SLONG: | |
65 | strcpy(name,"long"); | |
66 | break; | |
67 | case T_ULONG: | |
68 | strcpy(name,"unsigned long"); | |
69 | break; | |
70 | case T_FLOAT: | |
71 | strcpy(name, "float"); | |
72 | break; | |
73 | case T_DOUBLE: | |
74 | strcpy(name, "double"); | |
75 | break; | |
76 | case T_CHAR: case T_SCHAR: | |
77 | strcpy(name, "char"); | |
78 | break; | |
79 | case T_UCHAR: | |
80 | strcpy(name,"unsigned char"); | |
81 | break; | |
82 | case T_VOID: | |
83 | strcpy(name,"void"); | |
84 | break; | |
85 | case T_USER: | |
86 | strcpy(name,"USER"); | |
87 | break; | |
88 | default : | |
89 | strcpy(name,"UNKNOWN"); | |
90 | break; | |
91 | } | |
92 | type = t; | |
93 | is_pointer = 0; | |
94 | implicit_ptr = 0; | |
95 | qualifier = 0; | |
96 | is_reference = 0; | |
97 | status = 0; | |
98 | arraystr = 0; | |
99 | id = type_id++; | |
100 | } | |
101 | ||
102 | DataType::DataType(DataType *t) { | |
103 | type = t->type; | |
104 | strcpy(name,t->name); | |
105 | is_pointer = t->is_pointer; | |
106 | implicit_ptr = t->implicit_ptr; | |
107 | qualifier = copy_string(t->qualifier); | |
108 | is_reference = t->is_reference; | |
109 | status = t->status; | |
110 | arraystr = copy_string(t->arraystr); | |
111 | id = t->id; | |
112 | } | |
113 | ||
114 | DataType::~DataType() { | |
115 | if (qualifier) delete qualifier; | |
116 | if (arraystr) delete arraystr; | |
117 | } | |
118 | ||
119 | // -------------------------------------------------------------------- | |
120 | // DataType::primitive() | |
121 | // | |
122 | // Turns a datatype into its bare-bones primitive type. Rarely used, | |
123 | // but sometimes used for typemaps. Permanently alters the datatype! | |
124 | // -------------------------------------------------------------------- | |
125 | ||
126 | void DataType::primitive() { | |
127 | switch(type) { | |
128 | case T_BOOL: | |
129 | strcpy(name,"bool"); | |
130 | break; | |
131 | case T_INT: case T_SINT: | |
132 | strcpy(name,"int"); | |
133 | break; | |
134 | case T_SHORT: case T_SSHORT: | |
135 | strcpy(name,"short"); | |
136 | break; | |
137 | case T_LONG: case T_SLONG: | |
138 | strcpy(name,"long"); | |
139 | break; | |
140 | case T_CHAR: | |
141 | strcpy(name,"char"); | |
142 | break; | |
143 | case T_SCHAR: | |
144 | strcpy(name,"signed char"); | |
145 | break; | |
146 | case T_UINT: | |
147 | strcpy(name,"unsigned int"); | |
148 | break; | |
149 | case T_USHORT: | |
150 | strcpy(name,"unsigned short"); | |
151 | break; | |
152 | case T_ULONG: | |
153 | strcpy(name,"unsigned long"); | |
154 | break; | |
155 | case T_UCHAR: | |
156 | strcpy(name,"unsigned char"); | |
157 | break; | |
158 | case T_FLOAT: | |
159 | strcpy(name,"float"); | |
160 | break; | |
161 | case T_DOUBLE: | |
162 | strcpy(name,"double"); | |
163 | break; | |
164 | case T_VOID: | |
165 | strcpy(name,"void"); | |
166 | break; | |
167 | case T_USER: | |
168 | strcpy(name,"USER"); | |
169 | break; | |
170 | default: | |
171 | strcpy(name,"UNKNOWN"); | |
172 | break; | |
173 | } | |
174 | // if (is_pointer) { | |
175 | // if (!((is_pointer == 1) && (type == T_CHAR))) { | |
176 | // is_pointer = 1; | |
177 | // strcpy(name,"POINTER"); | |
178 | // } | |
179 | // } | |
180 | ||
181 | implicit_ptr = 0; // Gets rid of typedef'd pointers | |
182 | ||
183 | // Ditch qualifiers (const, volatile, etc...) | |
184 | ||
185 | if (qualifier) { | |
186 | delete qualifier; | |
187 | qualifier = 0; | |
188 | } | |
189 | qualifier = 0; | |
190 | status = 0; | |
191 | } | |
192 | ||
193 | // -------------------------------------------------------------------- | |
194 | // char *print_type() | |
195 | // | |
196 | // Print the datatype, but without qualifiers (ie. const, volatile) | |
197 | // Returns a string containing the result. | |
198 | // | |
199 | // If a datatype is marked as an implicit ptr it means that is_pointer | |
200 | // is at least one, but we don't print '*'. | |
201 | // | |
202 | // If the type status is STAT_REPLACETYPE, it means that we can't | |
203 | // use this type as a valid type. We'll substitute it's old name in. | |
204 | // -------------------------------------------------------------------- | |
205 | ||
206 | char *DataType::print_type() { | |
207 | static String result[8]; | |
208 | static int ri = 0; | |
209 | ||
210 | DataType *t = this; | |
211 | ||
212 | if (status & STAT_REPLACETYPE) { | |
213 | t = new DataType(this); | |
214 | t->typedef_replace(); // Upgrade type | |
215 | } | |
216 | ||
217 | ri = ri % 8; | |
218 | result[ri] = ""; | |
219 | result[ri] << t->name << " "; | |
220 | for (int i = 0; i < (t->is_pointer-t->implicit_ptr); i++) | |
221 | result[ri] << '*'; | |
222 | ||
223 | if (status & STAT_REPLACETYPE) { | |
224 | delete t; | |
225 | }; | |
226 | ||
227 | return result[ri++].get(); | |
228 | ||
229 | } | |
230 | ||
231 | // -------------------------------------------------------------------- | |
232 | // char *print_full() | |
233 | // | |
234 | // Prints full type, with qualifiers. | |
235 | // -------------------------------------------------------------------- | |
236 | ||
237 | char *DataType::print_full() { | |
238 | static String result[8]; | |
239 | static int ri = 0; | |
240 | ||
241 | ri = ri % 8; | |
242 | result[ri] = ""; | |
243 | if (qualifier) | |
244 | result[ri] << qualifier << " " << print_type(); | |
245 | else | |
246 | result[ri] << print_type(); | |
247 | ||
248 | return result[ri++].get(); | |
249 | ||
250 | } | |
251 | ||
252 | // -------------------------------------------------------------------- | |
253 | // char *print_real() | |
254 | // | |
255 | // Prints real type, with qualifiers and arrays if necessary. | |
256 | // -------------------------------------------------------------------- | |
257 | ||
258 | char *DataType::print_real(char *local) { | |
259 | static String result[8]; | |
260 | static int ri = 0; | |
261 | int oldstatus; | |
262 | ||
263 | oldstatus = status; | |
264 | status = status & (~STAT_REPLACETYPE); | |
265 | ri = ri % 8; | |
266 | result[ri] = ""; | |
267 | if (arraystr) is_pointer--; | |
268 | result[ri] << print_full(); | |
269 | if (local) result[ri] << local; | |
270 | if (arraystr) { | |
271 | result[ri] << arraystr; | |
272 | is_pointer++; | |
273 | } | |
274 | status = oldstatus; | |
275 | return result[ri++].get(); | |
276 | } | |
277 | ||
278 | // -------------------------------------------------------------------- | |
279 | // char *print_cast() | |
280 | // | |
281 | // Prints a cast. (Basically just a type but with parens added). | |
282 | // -------------------------------------------------------------------- | |
283 | ||
284 | char *DataType::print_cast() { | |
285 | static String result[8]; | |
286 | static int ri = 0; | |
287 | ||
288 | ri = ri % 8; | |
289 | result[ri] = ""; | |
290 | result[ri] << "(" << print_type() << ")"; | |
291 | return result[ri++].get(); | |
292 | ||
293 | } | |
294 | ||
295 | // -------------------------------------------------------------------- | |
296 | // char *print_arraycast() | |
297 | // | |
298 | // Prints a cast, but for array datatypes. Super ugly, but necessary | |
299 | // for multidimensional arrays. | |
300 | // -------------------------------------------------------------------- | |
301 | ||
302 | char *DataType::print_arraycast() { | |
303 | static String result[8]; | |
304 | static int ri = 0; | |
305 | int ndim; | |
306 | char *c; | |
307 | DataType *t; | |
308 | ||
309 | t = this; | |
310 | if (status & STAT_REPLACETYPE) { | |
311 | t = new DataType(this); | |
312 | t->typedef_replace(); // Upgrade type | |
313 | } | |
314 | ||
315 | ri = ri % 8; | |
316 | result[ri] = ""; | |
317 | ||
318 | if (t->arraystr) { | |
319 | ndim = 0; | |
320 | c = t->arraystr; | |
321 | while (*c) { | |
322 | if (*c == '[') ndim++; | |
323 | c++; | |
324 | } | |
325 | if (ndim > 1) { | |
326 | // a Multidimensional array. Provide a special cast for it | |
327 | int oldstatus = status; | |
328 | t->status = t->status & (~STAT_REPLACETYPE); | |
329 | t->is_pointer--; | |
330 | result[ri] << "(" << t->print_type(); | |
331 | t->is_pointer++; | |
332 | t->status = oldstatus; | |
333 | result[ri] << " (*)"; | |
334 | c = t->arraystr; | |
335 | while (*c) { | |
336 | if (*c == ']') break; | |
337 | c++; | |
338 | } | |
339 | if (*c) c++; | |
340 | result[ri] << c << ")"; | |
341 | } | |
342 | } | |
343 | if (status & STAT_REPLACETYPE) { | |
344 | delete t; | |
345 | } | |
346 | return result[ri++].get(); | |
347 | } | |
348 | ||
349 | // -------------------------------------------------------------------- | |
350 | // char *print_mangle_default() | |
351 | // | |
352 | // Prints a mangled version of this datatype. Used for run-time type | |
353 | // checking in order to print out a "language friendly" version (ie. no | |
354 | // spaces and no weird characters). | |
355 | // -------------------------------------------------------------------- | |
356 | ||
357 | char *DataType::print_mangle_default() { | |
358 | static String result[8]; | |
359 | static int ri = 0; | |
360 | int i; | |
361 | char *c; | |
362 | ||
363 | ri = ri % 8; | |
364 | result[ri] = ""; | |
365 | c = name; | |
366 | ||
367 | result[ri] << '_'; | |
368 | for (; *c; c++) { | |
369 | if (*c == ' ') result[ri] << '_'; | |
370 | else result[ri] << *c; | |
371 | } | |
372 | if ((is_pointer-implicit_ptr)) result[ri] << '_'; | |
373 | for (i = 0; i < (is_pointer-implicit_ptr); i++) | |
374 | result[ri] << 'p'; | |
375 | ||
376 | return result[ri++].get(); | |
377 | } | |
378 | ||
379 | // This is kind of ugly but needed for each language to support a | |
380 | // custom name mangling mechanism. (ie. Perl5). | |
381 | ||
382 | char *DataType::print_mangle() { | |
383 | ||
384 | // Call into target language for name mangling. | |
385 | return lang->type_mangle(this); | |
386 | } | |
387 | ||
388 | // -------------------------------------------------------------------- | |
389 | // int DataType::array_dimensions() | |
390 | // | |
391 | // Returns the number of dimensions in an array or 0 if not an array. | |
392 | // -------------------------------------------------------------------- | |
393 | int DataType::array_dimensions() { | |
394 | char *c; | |
395 | int ndim = 0; | |
396 | ||
397 | if (!arraystr) return 0; | |
398 | c = arraystr; | |
399 | while (*c) { | |
400 | if (*c == '[') { | |
401 | ndim++; | |
402 | } | |
403 | c++; | |
404 | } | |
405 | return ndim; | |
406 | } | |
407 | ||
408 | // -------------------------------------------------------------------- | |
409 | // char *DataType::get_dimension(int n) | |
410 | // | |
411 | // Returns a string containing the value specified for dimension n. | |
412 | // -------------------------------------------------------------------- | |
413 | ||
414 | char *DataType::get_dimension(int n) { | |
415 | static String dim; | |
416 | char *c; | |
417 | ||
418 | dim = ""; | |
419 | if (n >= array_dimensions()) return dim; | |
420 | ||
421 | // Attemp to locate the right dimension | |
422 | ||
423 | c = arraystr; | |
424 | while ((*c) && (n >= 0)) { | |
425 | if (*c == '[') n--; | |
426 | c++; | |
427 | } | |
428 | ||
429 | // c is now at start of array dimension | |
430 | if (*c) { | |
431 | while ((*c) && (*c != ']')) { | |
432 | dim << *c; | |
433 | c++; | |
434 | } | |
435 | } | |
436 | return dim; | |
437 | } | |
438 | ||
439 | // -------------------------------------------------------------------- | |
440 | // char *DataType::get_array() | |
441 | // | |
442 | // Returns the array string for a datatype. | |
443 | // -------------------------------------------------------------------- | |
444 | ||
445 | char *DataType::get_array() { | |
446 | return arraystr; | |
447 | } | |
448 | ||
449 | // -------------------------------------------------------------------- | |
450 | // typedef support. This needs to be scoped. | |
451 | // -------------------------------------------------------------------- | |
452 | ||
453 | Hash *DataType::typedef_hash[MAXSCOPE]; | |
454 | int DataType::scope = 0; // Current scope | |
455 | ||
456 | static Hash undefined_types; // Hash table containing undefined datatypes. | |
457 | ||
458 | // ----------------------------------------------------------------------------- | |
459 | // int DataType::check_defined() | |
460 | // | |
461 | // Checks to see if a datatype is defined. If not, returns -1 and puts an entry | |
462 | // into an internal hash table | |
463 | // ----------------------------------------------------------------------------- | |
464 | ||
465 | int DataType::check_defined() { | |
466 | if (type == T_USER) { | |
467 | ||
468 | // Type might be in typedef hash. Check for that | |
469 | int s = scope; | |
470 | while (s >= 0) { | |
471 | if (typedef_hash[s]->lookup(name)) return 0; | |
472 | s--; | |
473 | } | |
474 | ||
475 | // Nope. Add as an undefined type and continue. | |
476 | ||
477 | char *st; | |
478 | st = copy_string(name); | |
479 | undefined_types.add(st,st); | |
480 | return -1; | |
481 | } | |
482 | return 0; | |
483 | } | |
484 | ||
485 | // ----------------------------------------------------------------------------- | |
486 | // void DataType::init_typedef() | |
487 | // | |
488 | // Inputs : None | |
489 | // | |
490 | // Output : None | |
491 | // | |
492 | // Side Effects : Initializes the typedef hash tables | |
493 | // ----------------------------------------------------------------------------- | |
494 | ||
495 | void DataType::init_typedef() { | |
496 | int i; | |
497 | for (i = 0; i < MAXSCOPE; i++) | |
498 | typedef_hash[i] = 0; | |
499 | scope = 0; | |
500 | // Create a new hash | |
501 | typedef_hash[scope] = new Hash; | |
502 | } | |
503 | ||
504 | // -------------------------------------------------------------------- | |
505 | // void DataType::typedef_add(char *typename, int mode = 0) | |
506 | // | |
507 | // Adds this datatype to the typedef hash table. mode is an optional | |
508 | // flag that can be used to only add the symbol as a typedef, but not | |
509 | // generate any support code for the SWIG typechecker. This is used | |
510 | // for some of the more obscure datatypes like function pointers, | |
511 | // arrays, and enums. | |
512 | // -------------------------------------------------------------------- | |
513 | ||
514 | void DataType::typedef_add(char *tname, int mode) { | |
515 | String name1,name2; | |
516 | DataType *nt, t1; | |
517 | void typeeq_addtypedef(char *name, char *eqname); | |
518 | ||
519 | // Check to see if this typedef already defined | |
520 | // We only check in the local scope. C++ classes may make typedefs | |
521 | // that shadow global ones. | |
522 | ||
523 | if (typedef_hash[scope]->lookup(tname)) { | |
524 | fprintf(stderr,"%s : Line %d. Warning. Datatype %s already defined (2nd definition ignored).\n", | |
525 | input_file, line_number, tname); | |
526 | return; | |
527 | } | |
528 | ||
529 | // Make a new datatype that we will place in our hash table | |
530 | ||
531 | nt = new DataType(this); | |
532 | nt->implicit_ptr = (is_pointer-implicit_ptr); // Record if mapped type is a pointer | |
533 | nt->is_pointer = (is_pointer-implicit_ptr); // Adjust pointer value to be correct | |
534 | nt->typedef_resolve(); // Resolve any other mappings of this type | |
535 | // strcpy(nt->name,tname); // Copy over the new name | |
536 | ||
537 | // Add this type to our hash table | |
538 | typedef_hash[scope]->add(tname,(void *) nt); | |
539 | ||
540 | // Now add this type mapping to our type-equivalence table | |
541 | ||
542 | if (mode == 0) { | |
543 | if ((type != T_VOID) && (strcmp(name,tname) != 0)) { | |
544 | strcpy(t1.name,tname); | |
545 | name2 << t1.print_mangle(); | |
546 | name1 << print_mangle(); | |
547 | typeeq_addtypedef(name1,name2); | |
548 | typeeq_addtypedef(name2,name1); | |
549 | } | |
550 | } | |
551 | // Call into the target language with this typedef | |
552 | lang->add_typedef(this,tname); | |
553 | } | |
554 | ||
555 | ||
556 | // -------------------------------------------------------------------- | |
557 | // void DataType::typedef_resolve(int level = 0) | |
558 | // | |
559 | // Checks to see if this datatype is in the typedef hash and | |
560 | // resolves it if necessary. This will check all of the typedef | |
561 | // hash tables we know about. | |
562 | // | |
563 | // level is an optional parameter that determines which scope to use. | |
564 | // Usually this is only used with a bare :: operator in a datatype. | |
565 | // | |
566 | // The const headache : | |
567 | // | |
568 | // Normally SWIG will fail if a const variable is used in a typedef | |
569 | // like this : | |
570 | // | |
571 | // typedef const char *String; | |
572 | // | |
573 | // This is because future occurrences of "String" will be treated like | |
574 | // a char *, but without regard to the "constness". To work around | |
575 | // this problem. The resolve() method checks to see if these original | |
576 | // data type is const. If so, we'll substitute the name of the original | |
577 | // datatype instead. Got it? Whew. In a nutshell, this means that | |
578 | // all future occurrences of "String" will really be "const char *". | |
579 | // -------------------------------------------------------------------- | |
580 | ||
581 | void DataType::typedef_resolve(int level) { | |
582 | ||
583 | DataType *td; | |
584 | int s = scope - level; | |
585 | ||
586 | while (s >= 0) { | |
587 | if ((td = (DataType *) typedef_hash[s]->lookup(name))) { | |
588 | type = td->type; | |
589 | is_pointer += td->is_pointer; | |
590 | implicit_ptr += td->implicit_ptr; | |
591 | status = status | td->status; | |
592 | ||
593 | // Check for constness, and replace type name if necessary | |
594 | ||
595 | if (td->qualifier) { | |
596 | if (strcmp(td->qualifier,"const") == 0) { | |
597 | strcpy(name,td->name); | |
598 | qualifier = copy_string(td->qualifier); | |
599 | implicit_ptr -= td->implicit_ptr; | |
600 | } | |
601 | } | |
602 | return; | |
603 | } | |
604 | s--; | |
605 | } | |
606 | // Not found, do nothing | |
607 | return; | |
608 | } | |
609 | ||
610 | // -------------------------------------------------------------------- | |
611 | // void DataType::typedef_replace() | |
612 | // | |
613 | // Checks to see if this datatype is in the typedef hash and | |
614 | // replaces it with the hash entry. Only applies to current scope. | |
615 | // -------------------------------------------------------------------- | |
616 | ||
617 | void DataType::typedef_replace () { | |
618 | DataType *td; | |
619 | String temp; | |
620 | ||
621 | if ((td = (DataType *) typedef_hash[scope]->lookup(name))) { | |
622 | type = td->type; | |
623 | is_pointer = td->is_pointer; | |
624 | implicit_ptr -= td->implicit_ptr; | |
625 | strcpy(name, td->name); | |
626 | if (td->arraystr) { | |
627 | if (arraystr) { | |
628 | temp << arraystr; | |
629 | delete arraystr; | |
630 | } | |
631 | temp << td->arraystr; | |
632 | arraystr = copy_string(temp); | |
633 | } | |
634 | } | |
635 | // Not found, do nothing | |
636 | return; | |
637 | } | |
638 | ||
639 | // --------------------------------------------------------------- | |
640 | // int DataType::is_typedef(char *t) | |
641 | // | |
642 | // Checks to see whether t is the name of a datatype we know | |
643 | // about. Returns 1 if there's a match, 0 otherwise | |
644 | // --------------------------------------------------------------- | |
645 | ||
646 | int DataType::is_typedef(char *t) { | |
647 | int s = scope; | |
648 | while (s >= 0) { | |
649 | if (typedef_hash[s]->lookup(t)) return 1; | |
650 | s--; | |
651 | } | |
652 | return 0; | |
653 | } | |
654 | ||
655 | // --------------------------------------------------------------- | |
656 | // void DataType::typedef_updatestatus(int newstatus) | |
657 | // | |
658 | // Checks to see if this datatype is in the hash table. If | |
659 | // so, we'll update its status. This is sometimes used with | |
660 | // typemap handling. Only applies to current scope. | |
661 | // --------------------------------------------------------------- | |
662 | ||
663 | void DataType::typedef_updatestatus(int newstatus) { | |
664 | ||
665 | DataType *t; | |
666 | if ((t = (DataType *) typedef_hash[scope]->lookup(name))) { | |
667 | t->status = newstatus; | |
668 | } | |
669 | } | |
670 | ||
671 | ||
672 | // ----------------------------------------------------------------------------- | |
673 | // void DataType::merge_scope(Hash *h) | |
674 | // | |
675 | // Copies all of the entries in scope h into the current scope. This is | |
676 | // primarily done with C++ inheritance. | |
677 | // | |
678 | // Inputs : Hash table h. | |
679 | // | |
680 | // Output : None | |
681 | // | |
682 | // Side Effects : Copies all of the entries in h to current scope. | |
683 | // ----------------------------------------------------------------------------- | |
684 | ||
685 | void DataType::merge_scope(Hash *h) { | |
686 | char *key; | |
687 | DataType *t, *nt; | |
688 | ||
689 | if (h) { | |
690 | // Copy all of the entries in the given hash table to this new one | |
691 | key = h->firstkey(); | |
692 | while (key) { | |
693 | // printf("%s\n", key); | |
694 | t = (DataType *) h->lookup(key); | |
695 | nt = new DataType(t); | |
696 | typedef_hash[scope]->add(key,(void *) nt); | |
697 | key = h->nextkey(); | |
698 | } | |
699 | } | |
700 | } | |
701 | ||
702 | // ----------------------------------------------------------------------------- | |
703 | // void DataType::new_scope(Hash *h = 0) | |
704 | // | |
705 | // Creates a new scope for handling typedefs. This is used in C++ handling | |
706 | // to create typedef local to a class definition. | |
707 | // | |
708 | // Inputs : h = Optional hash table scope (Used for C++ inheritance). | |
709 | // | |
710 | // Output : None | |
711 | // | |
712 | // Side Effects : Creates a new hash table and increments the scope counter | |
713 | // ----------------------------------------------------------------------------- | |
714 | ||
715 | void DataType::new_scope(Hash *h) { | |
716 | scope++; | |
717 | typedef_hash[scope] = new Hash; | |
718 | ||
719 | if (h) { | |
720 | merge_scope(h); | |
721 | } | |
722 | } | |
723 | ||
724 | // ----------------------------------------------------------------------------- | |
725 | // Hash *DataType::collapse_scope(char *prefix) | |
726 | // | |
727 | // Collapses the current scope into the previous one, but applies a prefix to | |
728 | // all of the datatypes. This is done in order to properly handle C++ stuff. | |
729 | // For example : | |
730 | // | |
731 | // class Foo { | |
732 | // ... | |
733 | // typedef double Real; | |
734 | // } | |
735 | // | |
736 | // will have a type mapping of "double --> Real" within the class itself. | |
737 | // When we collapse the scope, this mapping will become "double --> Foo::Real" | |
738 | // | |
739 | // Inputs : None | |
740 | // | |
741 | // Output : None | |
742 | // | |
743 | // Side Effects : Returns the hash table corresponding to the current scope | |
744 | // ----------------------------------------------------------------------------- | |
745 | ||
746 | Hash *DataType::collapse_scope(char *prefix) { | |
747 | DataType *t,*nt; | |
748 | char *key; | |
749 | char *temp; | |
750 | Hash *h; | |
751 | ||
752 | if (scope > 0) { | |
753 | if (prefix) { | |
754 | key = typedef_hash[scope]->firstkey(); | |
755 | while (key) { | |
756 | t = (DataType *) typedef_hash[scope]->lookup(key); | |
757 | nt = new DataType(t); | |
758 | temp = new char[strlen(prefix)+strlen(key)+3]; | |
759 | sprintf(temp,"%s::%s",prefix,key); | |
760 | // printf("creating %s\n", temp); | |
761 | typedef_hash[scope-1]->add(temp,(void *) nt); | |
762 | delete temp; | |
763 | key = typedef_hash[scope]->nextkey(); | |
764 | } | |
765 | } | |
766 | h = typedef_hash[scope]; | |
767 | typedef_hash[scope] = 0; | |
768 | scope--; | |
769 | return h; | |
770 | } | |
771 | return (Hash *) 0; | |
772 | } | |
773 | ||
774 | // ------------------------------------------------------------- | |
775 | // Class equivalency lists | |
776 | // | |
777 | // These are used to keep track of which datatypes are equivalent. | |
778 | // This information can be dumped in tabular form upon completion | |
779 | // for use in the pointer type checker. | |
780 | // | |
781 | // cast is an extension needed to properly handle multiple inheritance | |
782 | // -------------------------------------------------------------- | |
783 | ||
784 | struct EqEntry { | |
785 | char *name; | |
786 | char *cast; | |
787 | EqEntry *next; | |
788 | char *sz; | |
789 | }; | |
790 | ||
791 | static Hash typeeq_hash; | |
792 | static int te_init = 0; | |
793 | ||
794 | void typeeq_init() { | |
795 | void typeeq_standard(); | |
796 | te_init = 1; | |
797 | typeeq_standard(); | |
798 | } | |
799 | ||
800 | ||
801 | // -------------------------------------------------------------- | |
802 | // typeeq_add(char *name, char *eqname, char *cast) | |
803 | // | |
804 | // Adds a new name to the type-equivalence tables. | |
805 | // Creates a new entry if it doesn't exit. | |
806 | // | |
807 | // Cast is an optional name for a pointer casting function. | |
808 | // -------------------------------------------------------------- | |
809 | ||
810 | void typeeq_add(char *name, char *eqname, char *cast = 0) { | |
811 | EqEntry *e1,*e2; | |
812 | ||
813 | if (!te_init) typeeq_init(); | |
814 | ||
815 | if (strcmp(name,eqname) == 0) return; // If they're the same, forget it. | |
816 | ||
817 | // Search for "name" entry in the hash table | |
818 | ||
819 | e1 = (EqEntry *) typeeq_hash.lookup(name); | |
820 | ||
821 | if (!e1) { | |
822 | // Create a new entry | |
823 | e1 = new EqEntry; | |
824 | e1->name = copy_string(name); | |
825 | e1->next = 0; | |
826 | e1->cast = 0; | |
827 | // Add it to the hash table | |
828 | typeeq_hash.add(name,(void *) e1); | |
829 | } | |
830 | ||
831 | ||
832 | ||
833 | // Add new type to the list | |
834 | // We'll first check to see if it's already been added | |
835 | ||
836 | e2 = e1->next; | |
837 | while (e2) { | |
838 | if (strcmp(e2->name, eqname) == 0) { | |
839 | if (cast) | |
840 | e2->cast = copy_string(cast); | |
841 | return; | |
842 | } | |
843 | e2 = e2->next; | |
844 | } | |
845 | ||
846 | e2 = new EqEntry; | |
847 | e2->name = copy_string(eqname); | |
848 | e2->cast = copy_string(cast); | |
849 | e2->next = e1->next; // Add onto the linked list for name | |
850 | e1->next = e2; | |
851 | ||
852 | } | |
853 | ||
854 | // -------------------------------------------------------------- | |
855 | // typeeq_addtypedef(char *name, char *eqname) | |
856 | // | |
857 | // Adds a new typedef declaration to the equivelency list. | |
858 | // -------------------------------------------------------------- | |
859 | ||
860 | void typeeq_addtypedef(char *name, char *eqname) { | |
861 | EqEntry *e1,*e2; | |
862 | ||
863 | if (!te_init) typeeq_init(); | |
864 | ||
865 | // First we're going to add the equivalence, no matter what | |
866 | ||
867 | typeeq_add(name,eqname); | |
868 | ||
869 | // Now find the hash entry | |
870 | ||
871 | e1 = (EqEntry *) typeeq_hash.lookup(name); | |
872 | if (!e1) return; | |
873 | ||
874 | // Walk down the list and make other equivalences | |
875 | ||
876 | e2 = e1->next; | |
877 | while (e2) { | |
878 | if (strcmp(e2->name, eqname) != 0) { | |
879 | typeeq_add(e2->name, eqname,e2->cast); | |
880 | typeeq_add(eqname, e2->name,e2->cast); | |
881 | } | |
882 | e2 = e2->next; | |
883 | } | |
884 | } | |
885 | ||
886 | // ---------------------------------------------------------------- | |
887 | // void emit_ptr_equivalence(FILE *f) | |
888 | // | |
889 | // Dump out the pointer equivalence table to file. | |
890 | // | |
891 | // Changed to register datatypes with the type checker in order | |
892 | // to support proper type-casting (needed for multiple inheritance) | |
893 | // ---------------------------------------------------------------- | |
894 | ||
895 | void emit_ptr_equivalence(FILE *f) { | |
896 | ||
897 | EqEntry *e1,*e2; | |
898 | void typeeq_standard(); | |
899 | String ttable; | |
900 | ||
901 | if (!te_init) typeeq_init(); | |
902 | ||
903 | ttable << "\ | |
904 | /*\n\ | |
905 | * This table is used by the pointer type-checker\n\ | |
906 | */\n\ | |
907 | static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {\n"; | |
908 | ||
909 | e1 = (EqEntry *) typeeq_hash.first(); | |
910 | while (e1) { | |
911 | e2 = e1->next; | |
912 | // Walk through the equivalency list | |
913 | while (e2) { | |
914 | if (e2->cast) | |
915 | ttable << tab4 << "{ \"" << e1->name << "\",\"" << e2->name << "\"," << e2->cast << "},\n"; | |
916 | else | |
917 | ttable << tab4 << "{ \"" << e1->name << "\",\"" << e2->name << "\",0},\n"; | |
918 | e2 = e2->next; | |
919 | } | |
920 | e1 = (EqEntry *) typeeq_hash.next(); | |
921 | } | |
922 | ttable << "{0,0,0}};\n"; | |
923 | fprintf(f_wrappers,"%s\n", ttable.get()); | |
924 | fprintf(f,"{\n"); | |
925 | fprintf(f," int i;\n"); | |
926 | fprintf(f," for (i = 0; _swig_mapping[i].n1; i++)\n"); | |
927 | fprintf(f," SWIG_RegisterMapping(_swig_mapping[i].n1,_swig_mapping[i].n2,_swig_mapping[i].pcnv);\n"); | |
928 | fprintf(f,"}\n"); | |
929 | } | |
930 | ||
931 | // ------------------------------------------------------------------------------ | |
932 | // typeeq_derived(char *n1, char *n2, char *cast=) | |
933 | // | |
934 | // Adds a one-way mapping between datatypes. | |
935 | // ------------------------------------------------------------------------------ | |
936 | ||
937 | void typeeq_derived(char *n1, char *n2, char *cast=0) { | |
938 | DataType t,t1; | |
939 | String name,name2; | |
940 | EqEntry *e1; | |
941 | ||
942 | if (!te_init) typeeq_init(); | |
943 | ||
944 | strcpy(t.name,n1); | |
945 | strcpy(t1.name,n2); | |
946 | name << t.print_mangle(); | |
947 | name2 << t1.print_mangle(); | |
948 | typeeq_add(name,name2,cast); | |
949 | ||
950 | // Now find the hash entry | |
951 | ||
952 | e1 = (EqEntry *) typeeq_hash.lookup(name); | |
953 | ||
954 | // Walk down the list and make other equivalences | |
955 | ||
956 | /* I don't think this is necessary, but we'll keep this code in case | |
957 | ||
958 | e2 = e1->next; | |
959 | while (e2) { | |
960 | if (strcmp(e2->name, name2) != 0) { | |
961 | typeeq_add(e2->name, name2,e2->cast); | |
962 | } | |
963 | e2 = e2->next; | |
964 | } | |
965 | */ | |
966 | ||
967 | } | |
968 | ||
969 | // ------------------------------------------------------------------------------ | |
970 | // typeeq_mangle(char *n1, char *n2, char *cast=) | |
971 | // | |
972 | // Adds a single type equivalence | |
973 | // ------------------------------------------------------------------------------ | |
974 | ||
975 | void typeeq_mangle(char *n1, char *n2, char *cast=0) { | |
976 | DataType t,t1; | |
977 | String name,name2; | |
978 | ||
979 | if (!te_init) typeeq_init(); | |
980 | ||
981 | strcpy(t.name,n1); | |
982 | strcpy(t1.name,n2); | |
983 | name << t.print_mangle(); | |
984 | name2 << t1.print_mangle(); | |
985 | typeeq_add(name,name2,cast); | |
986 | } | |
987 | ||
988 | // ------------------------------------------------------------------------------ | |
989 | // typeeq_standard(void) | |
990 | // | |
991 | // Generate standard type equivalences (well, pointers that can map into | |
992 | // other pointers naturally). | |
993 | // | |
994 | // ------------------------------------------------------------------------------- | |
995 | ||
996 | void typeeq_standard(void) { | |
997 | ||
998 | typeeq_mangle("int", "signed int"); | |
999 | typeeq_mangle("int", "unsigned int"); | |
1000 | typeeq_mangle("signed int", "int"); | |
1001 | typeeq_mangle("unsigned int", "int"); | |
1002 | typeeq_mangle("short","signed short"); | |
1003 | typeeq_mangle("signed short","short"); | |
1004 | typeeq_mangle("short","unsigned short"); | |
1005 | typeeq_mangle("unsigned short","short"); | |
1006 | typeeq_mangle("long","signed long"); | |
1007 | typeeq_mangle("signed long","long"); | |
1008 | typeeq_mangle("long","unsigned long"); | |
1009 | typeeq_mangle("unsigned long","long"); | |
1010 | ||
1011 | } | |
1012 | ||
1013 | // ------------------------------------------------------------------------------ | |
1014 | // type_undefined_check(void) | |
1015 | // | |
1016 | // Checks the hash table for undefined datatypes and prints a warning message. | |
1017 | // ------------------------------------------------------------------------------- | |
1018 | ||
1019 | void type_undefined_check(void) { | |
1020 | char *s; | |
1021 | ||
1022 | s = (char *) undefined_types.first(); | |
1023 | if (s) { | |
1024 | fprintf(stderr,"The following datatypes were used, but undefined.\n"); | |
1025 | while (s) { | |
1026 | fprintf(stderr," %s\n",s); | |
1027 | s = (char *) undefined_types.next(); | |
1028 | } | |
1029 | } | |
1030 | } | |
1031 |