]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wxSWIG/SWIG/types.cxx
reSWIGged
[wxWidgets.git] / wxPython / wxSWIG / SWIG / types.cxx
CommitLineData
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
33DataType::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
47DataType::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
102DataType::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
114DataType::~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
126void 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
206char *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
237char *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
258char *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
284char *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
302char *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
357char *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
382char *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// --------------------------------------------------------------------
393int 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
414char *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
445char *DataType::get_array() {
446 return arraystr;
447}
448
449// --------------------------------------------------------------------
450// typedef support. This needs to be scoped.
451// --------------------------------------------------------------------
452
453Hash *DataType::typedef_hash[MAXSCOPE];
454int DataType::scope = 0; // Current scope
455
456static 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
465int 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
495void 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
514void 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
581void 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
617void 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
646int 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
663void 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
685void 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
715void 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
746Hash *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
784struct EqEntry {
785 char *name;
786 char *cast;
787 EqEntry *next;
788 char *sz;
789};
790
791static Hash typeeq_hash;
792static int te_init = 0;
793
794void 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
810void 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
860void 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
895void 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\
907static 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
937void 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
975void 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
996void 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
1019void 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