]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wxSWIG/SWIG/typemap.cxx
compilation error fix (trailing comma in an enum)
[wxWidgets.git] / wxPython / wxSWIG / SWIG / typemap.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#include "internal.h"
17
18#include <limits.h>
19
20// ------------------------------------------------------------------------
21// $Header$
22//
23// typemap.cxx
24//
25// This file provides universal support for typemaps. Typemaps are created
26// using the following SWIG command in an interface file:
27//
28// %typemap(lang,operation) type { code } Make a new typemap
29// %typemap(lang,operation) type; Clears any previous typemap
30//
31// lang is an identifier indicating the target language. The typemap will
32// simply be ignored if its for a different language. The code is the
33// corresponding C code for the mapping. An example typemap might look
34// like this :
35//
36// %typemap(tcl,get) double {
37// $target = atof($source);
38// }
39// %typemap(tcl,set) double {
40// sprintf($target,"%0.17f",$source);
41// }
42//
43// The variables $target and $source should be used in any type-mappings.
44// Additional local variables can be created, but this should be done
45// by enclosing the entire code fragment in an extra set of braces.
46//
47// The C++ API to the type-mapper is as follows :
48//
49// void typemap_register(char *op, char *lang, DataType *type, char *pname, String &getcode, ParmList *args)
50// char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source, char *target);
51// void typemap_clear(char *op, char *lang, DataType *type, char *pname);
52//
53// The lookup functions return a character string corresponding to the type-mapping
54// code or NULL if none exists. The string return will have the source and target
55// strings substituted for the strings "$source" and "$target" in the type-mapping code.
56//
57// (2/19/97) This module has been extended somewhat to provide generic mappings
58// of other parts of the code--most notably exceptions.
59//
60// void fragment_register(char *op, char *lang, String &code)
61// char fragment_lookup(char *op, char *lang, int age);
62// char fragment_clear(char *op, char *lang);
63//
64// ------------------------------------------------------------------------
65
66// Structure for holding a typemap
67
68struct TypeMap {
69 char *lang;
70 DataType *type;
71 String code;
72 int first;
73 int last;
74 TypeMap *next;
75 TypeMap *previous; // Previously defined typemap (if any)
76 ParmList *args; // Local variables (if any)
77
78 TypeMap(char *l, DataType *t, String &c, ParmList *p = 0) {
79 lang = copy_string(l);
80 type = new DataType(t);
81 code << c;
82 first = type_id;
83 last = INT_MAX;
84 next = 0;
85 previous = 0;
86 if (p) {
87 args = new ParmList(p);
88 } else {
89 args = 0;
90 }
91 }
92 TypeMap(char *l, DataType *t, char *c, ParmList *p = 0) {
93 lang = copy_string(l);
94 type = new DataType(t);
95 code << c;
96 first = type_id;
97 last = INT_MAX;
98 next = 0;
99 previous = 0;
100 if (p) {
101 args = new ParmList(p);
102 } else {
103 args = 0;
104 }
105 }
106 TypeMap(char *l, char *c) {
107 lang = copy_string(l);
108 type = 0;
109 code << c;
110 first = type_id;
111 last = INT_MAX;
112 next = 0;
113 previous = 0;
114 args = 0;
115 }
116 TypeMap(TypeMap *t) {
117 lang = copy_string(t->lang);
118 type = new DataType(t->type);
119 code << t->code;
120 first = type_id;
121 last = INT_MAX;
122 next = 0;
123 previous = t->previous;
124 if (args) {
125 args = new ParmList(args);
126 } else {
127 args = 0;
128 }
129 }
130};
131
132// Hash tables for storing type-mappings
133
134static Hash typemap_hash;
135
136// Structure for holding "applications of a typemap"
137
138struct TmMethod {
139 char *name; // Typemap name;
140 DataType *type; // Typemap type
141 TmMethod *next; // Next method
142 TmMethod(char *n, DataType *t, TmMethod *m = 0) {
143 if (n) name = copy_string(n);
144 else name = 0;
145 if (t) {
146 type = new DataType(t);
147 } else {
148 type = 0;
149 }
150 next = m;
151 }
152};
153
154// Hash table for storing applications of a datatype
155
156static Hash application_hash;
157
158// ------------------------------------------------------------------------
159// void typemap_apply(DataType *tm_type, char *tm_name, DataType *type, char *pname)
160//
161// Attempts to apply a typemap given by (tm_type,tm_name) to (type,pname)
162// Called by the %apply directive.
163// ------------------------------------------------------------------------
164
165void typemap_apply(DataType *tm_type, char *tm_name, DataType *type, char *pname) {
166 TmMethod *m,*m1;
167 char temp[512];
168
169 // Form the application name
170 if (!pname) pname = "";
171 sprintf(temp,"%s$%s",type->print_type(),pname);
172
173 // See if there is a method already defined
174
175 m = (TmMethod *) application_hash.lookup(temp);
176
177 if (!m) {
178 m = new TmMethod(temp,type,0);
179 application_hash.add(temp,m);
180 }
181
182 // Check to see if an array typemap has been applied to a non-array type
183
184 if ((tm_type->arraystr) && (!type->arraystr)) {
185 fprintf(stderr,"%s:%d: Warning. Array typemap has been applied to a non-array type.\n",
186 input_file,line_number);
187 }
188
189 // If both are arrays, make sure they have the same dimension
190
191 if ((tm_type->arraystr) && (type->arraystr)) {
192 char s[128],*t;
193 if (tm_type->array_dimensions() != type->array_dimensions()) {
194 fprintf(stderr,"%s:%d: Warning. Array types have different number of dimensions.\n",
195 input_file,line_number);
196 } else {
197 for (int i = 0; i < tm_type->array_dimensions(); i++) {
198 strcpy(s,tm_type->get_dimension(i));
199 t = type->get_dimension(i);
200 if (strcmp(s,"ANY") != 0) {
201 if (strcmp(s,t))
202 fprintf(stderr,"%s:%d: Warning. Array typemap applied to an array of different size.\n",
203 input_file, line_number);
204 }
205 }
206 }
207 }
208
209 // Add a new mapping corresponding to the typemap
210
211 m1 = new TmMethod(tm_name,tm_type,m->next);
212 m->next = m1;
213
214}
215// ------------------------------------------------------------------------
216// void typemap_clear_apply(DataType *type, char *pname)
217//
218// Clears the application of a typemap.
219// Called by the %clear directive.
220// ------------------------------------------------------------------------
221
222void typemap_clear_apply(DataType *type, char *pname) {
223 char temp[512];
224 if (!pname) pname = "";
225 sprintf(temp,"%s$%s", type->print_type(), pname);
226 application_hash.remove(temp);
227}
228
229// ------------------------------------------------------------------------
230// char *typemap_string(char *lang, DataType *type, char *pname, char *ary, char *suffix)
231//
232// Produces a character string corresponding to a lang, datatype, and
233// method. This string is used as the key for our typemap hash table.
234// ------------------------------------------------------------------------
235
236static char *typemap_string(char *lang, DataType *type, char *pname, char *ary, char *suffix) {
237 static String str;
238
239 int old_status;
240 old_status = type->status;
241 type->status = 0;
242 str = "";
243
244 if (ary)
245 str << lang << type->print_type() << pname << ary << suffix;
246 else
247 str << lang << type->print_type() << pname << suffix;
248
249 type->status = old_status;
250 return str;
251}
252
253// ------------------------------------------------------------------------
254// void typemap_register(char *op, char *lang, DataType *type, char *pname,
255// char *getcode, ParmList *args)
256//
257// Register a new mapping with the type-mapper.
258// ------------------------------------------------------------------------
259
260void typemap_register(char *op, char *lang, DataType *type, char *pname,
261 char *getcode, ParmList *args) {
262
263 char *key;
264 TypeMap *tm,*tm_old;
265 char temp[256];
266 int is_default = 0;
267
268 // printf("Registering : %s %s %s %s\n%s\n", op, lang, type->print_type(), pname, getcode);
269
270
271 tm = new TypeMap(lang,type,getcode,args);
272 // If this is a default typemap, downgrade the type!
273
274 if (strcmp(pname,"SWIG_DEFAULT_TYPE") == 0) {
275 tm->type->primitive();
276 is_default = 1;
277 }
278
279 key = typemap_string(lang,tm->type,pname,tm->type->arraystr, op);
280
281 // Get any previous setting of the typemap
282
283 tm_old = (TypeMap *) typemap_hash.lookup(key);
284
285 if (tm_old) {
286
287 // Perform a chaining operation, but only if the last typemap is
288 // active.
289
290 if (type_id < tm_old->last) {
291 sprintf(temp,"$%s",op);
292 tm->code.replace(temp,tm_old->code);
293 }
294
295 // If found, we need to attach the old version to the new one
296
297 tm->previous = tm_old;
298 tm->next = tm_old;
299 tm_old->last = type_id;
300
301 // Remove the old one from the hash
302
303 typemap_hash.remove(key);
304 }
305
306 // Add new typemap to the hash table
307 typemap_hash.add(key,(void *) tm);
308
309 // Now try to perform default chaining operation (if available)
310 // if (!is_default) {
311 // sprintf(temp,"$%s",op);
312 // if (strstr(tm->code,temp)) {
313 // tm->code.replace(temp,typemap_resolve_default(op,lang,type));
314 // }
315 // }
316
317 // Just a sanity check to make sure args look okay.
318
319 if (args) {
320 Parm *p;
321 p = tm->args->get_first();
322 while (p) {
323 if (p->name) {
324 // printf(" %s %s\n", p->t->print_type(),p->name);
325 } else {
326 fprintf(stderr,"%s:%d: Typemap error. Local variables must have a name\n",
327 input_file, line_number);
328 }
329 // If a call by reference thingy, fix that
330 if (p->call_type & CALL_REFERENCE) {
331 p->t->is_pointer--;
332 p->call_type = 0;
333 }
334 p = tm->args->get_next();
335 }
336 }
337}
338
339// ------------------------------------------------------------------------
340// void typemap_register(char *op, char *lang, char *type, char *pname,
341// char *getcode, ParmList *args)
342//
343// Register a new mapping with the type-mapper. Special version that uses a
344// string instead of a datatype.
345// ------------------------------------------------------------------------
346
347void typemap_register(char *op, char *lang, char *type, char *pname,
348 char *getcode, ParmList *args) {
349 DataType temp;
350 strcpy(temp.name,type);
351 temp.is_pointer = 0;
352 temp.type = T_USER;
353 typemap_register(op,lang,&temp,pname,getcode,args);
354}
355
356
357// ------------------------------------------------------------------------
358// void typemap_register_default(char *op, char *lang, int type, int ptr, char *arraystr,
359// char *code, ParmList *args)
360//
361// Registers a default typemap with the system using numerical type codes.
362// type is the numerical code, ptr is the level of indirection.
363// ------------------------------------------------------------------------
364
365void typemap_register_default(char *op, char *lang, int type, int ptr, char *arraystr,
366 char *code, ParmList *args) {
367
368 DataType *t = new DataType(type);
369
370 // Create a raw datatype from the arguments
371
372 t->is_pointer = ptr;
373 t->arraystr = copy_string(arraystr);
374
375 // Now, go register this as a default type
376
377 typemap_register(op,lang,t,"SWIG_DEFAULT_TYPE",code,args);
378 delete t;
379}
380
381
382// ------------------------------------------------------------------------
383// static TypeMap *typemap_search(char *key, int id)
384//
385// An internal function for searching for a particular typemap given
386// a key value and datatype id.
387//
388// Basically this checks the hash table and then checks the id against
389// first and last values, looking for a match. This is to properly
390// handle scoping problems.
391// ------------------------------------------------------------------------
392
393TypeMap *typemap_search(char *key, int id) {
394
395 TypeMap *tm;
396
397 tm = (TypeMap *) typemap_hash.lookup(key);
398 while (tm) {
399 if ((id >= tm->first) && (id < tm->last)) return tm;
400 else tm = tm->next;
401 }
402 return tm;
403}
404
405// ------------------------------------------------------------------------
406// TypeMap *typemap_search_array(char *op, char *lang, DataType *type, char *pname, String &str)
407//
408// Performs a typemap lookup on an array type. This is abit complicated
409// because we need to look for ANY tags specifying that any array dimension
410// is valid. The resulting code will be placed in str with dimension variables
411// substituted.
412// ------------------------------------------------------------------------
413
414TypeMap *typemap_search_array(char *op, char *lang, DataType *type, char *pname, String &str) {
415 char *origarr = type->arraystr;
416 char *key;
417 int ndim,i,j,k,n;
418 TypeMap *tm;
419 char temp[10];
420
421 if (!type->arraystr) return 0;
422
423 // First check to see if exactly this array has been mapped
424
425 key = typemap_string(lang,type,pname,type->arraystr,op);
426 tm = typemap_search(key,type->id);
427
428 // Check for unnamed array of specific dimensions
429 if (!tm) {
430 key = typemap_string(lang,type,"",type->arraystr,op);
431 tm = typemap_search(key,type->id);
432 }
433
434 if (!tm) {
435 // We're going to go search for matches with the ANY tag
436 String tempastr;
437 ndim = type->array_dimensions(); // Get number of dimensions
438 j = (1 << ndim) - 1; // Status bits
439 for (i = 0; i < (1 << ndim); i++) {
440 // Form an array string
441 tempastr = "";
442 k = j;
443 for (n = 0; n < ndim; n++) {
444 if (k & 1) {
445 tempastr << "[" << type->get_dimension(n) << "]";
446 } else {
447 tempastr << "[ANY]";
448 }
449 k = k >> 1;
450 }
451 // printf("checking (%s) : %s\n",origarr,tempastr.get());
452 type->arraystr = tempastr.get();
453 key = typemap_string(lang,type,pname,type->arraystr,op);
454 tm = typemap_search(key,type->id);
455 if (!tm) {
456 key = typemap_string(lang,type,"",type->arraystr,op);
457 tm = typemap_search(key,type->id);
458 }
459 type->arraystr = origarr;
460 if (tm) break;
461 j--;
462 }
463 }
464
465 if (tm) {
466 str << tm->code;
467 ndim = type->array_dimensions();
468 for (i = 0; i < ndim; i++) {
469 sprintf(temp,"$dim%d",i);
470 str.replace(temp,type->get_dimension(i));
471 }
472 }
473 return tm;
474}
475
476// ------------------------------------------------------------------------
477// static typemap_locals(Datatype *t, char *pname, String &s, ParmList *l, WrapperFunction &f)
478//
479// Takes a string, a parameter list and a wrapper function argument and
480// starts creating local variables.
481//
482// Substitutes locals in the string with actual values used.
483// ------------------------------------------------------------------------
484
485static void typemap_locals(DataType *t, char *pname, String &s, ParmList *l, WrapperFunction &f) {
486 Parm *p;
487 char *new_name;
488
489 p = l->get_first();
490 while (p) {
491 if (p->name) {
492 if (strlen(p->name) > 0) {
493 String str;
494 DataType *tt;
495
496 // If the user gave us $type as the name of the local variable, we'll use
497 // the passed datatype instead
498
499 if (strcmp(p->t->name,"$type")==0 || strcmp(p->t->name,"$basetype")==0) {
500 tt = t;
501 } else {
502 tt = p->t;
503 }
504
505 // Have a real parameter here
506 if (tt->arraystr) {
507 tt->is_pointer--;
508 str << p->name << tt->arraystr;
509 }
510 else {
511 str << p->name;
512 }
513
514 // Substitute parameter names
515 str.replace("$arg",pname);
516 if (strcmp(p->t->name,"$basetype")==0) {
517 // use $basetype
518 char temp_ip = tt->is_pointer;
519 char temp_ip1 = tt->implicit_ptr;
520 tt->is_pointer = 0;
521 tt->implicit_ptr = 0;
522 new_name = f.new_local(tt->print_type(),str);
523 tt->is_pointer = temp_ip;
524 tt->implicit_ptr = temp_ip1;
525 }
526 else
527 new_name = f.new_local(tt->print_full(),str);
528
529 if (tt->arraystr) tt->is_pointer++;
530 // Substitute
531 s.replaceid(p->name,new_name);
532 }
533 }
534 p = l->get_next();
535 }
536 // If the original datatype was an array. We're going to go through and substitute
537 // it's array dimensions
538
539 if (t->arraystr) {
540 char temp[10];
541 for (int i = 0; i < t->array_dimensions(); i++) {
542 sprintf(temp,"$dim%d",i);
543 f.locals.replace(temp,t->get_dimension(i));
544 }
545 }
546
547}
548
549// ------------------------------------------------------------------------
550// char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source,
551// char *target, WrapperFunction *f)
552//
553// Looks up a "get" function in the type-map and returns a character string
554// containing the appropriate translation code.
555//
556// op is string code for type of mapping
557// lang is the target language string
558// type is the datatype
559// pname is an optional parameter name
560// source is a string with the source variable
561// target is a string containing the target value
562// f is a wrapper function object (optional)
563//
564// Returns NULL if no mapping is found.
565//
566// Typemaps follow a few rules regarding naming and C pointers by checking
567// declarations in this order.
568//
569// 1. type name [] - A named array (most specific)
570// 2. type name - Named argument
571// 3. type [] - Type with array
572// 4. type - Ordinary type
573//
574// Array checking is only made if the datatype actally has an array specifier
575//
576// Array checking uses a special token "ANY" that indicates that any
577// dimension will match. Since we are passed a real datatype here, we
578// need to hack this a special case.
579//
580// Array dimensions are substituted into the variables $dim1, $dim2,...,$dim9
581// ------------------------------------------------------------------------
582
583static DataType *realtype; // This is a gross hack
584static char *realname = 0; // Real parameter name
585
586char *typemap_lookup_internal(char *op, char *lang, DataType *type, char *pname, char *source,
587 char *target, WrapperFunction *f) {
588 static String str;
589 char *key = 0;
590 TypeMap *tm = 0;
591
592 if (!lang) {
593 return 0;
594 }
595
596 // First check for named array
597 str = "";
598 tm = typemap_search_array(op,lang,type,pname,str);
599
600 // Check for named argument
601 if (!tm) {
602 key = typemap_string(lang,type,pname,0,op);
603 tm = typemap_search(key,type->id);
604 if (tm)
605 str << tm->code;
606 }
607
608 // Check for unnamed type
609 if (!tm) {
610 key = typemap_string(lang,type,"",0,op);
611 tm = typemap_search(key,type->id);
612 if (tm)
613 str << tm->code;
614 }
615 if (!tm) return 0;
616
617 // Now perform character replacements
618
619 str.replace("$source",source);
620 str.replace("$target",target);
621 str.replace("$type", realtype->print_type());
622 if (realname) {
623 str.replace("$parmname", realname);
624 } else {
625 str.replace("$parmname","");
626 }
627 // Print base type (without any pointers)
628 {
629 char temp_ip = realtype->is_pointer;
630 char temp_ip1 = realtype->implicit_ptr;
631 realtype->is_pointer = 0;
632 realtype->implicit_ptr = 0;
633 char *bt = realtype->print_type();
634 if (bt[strlen(bt)-1] == ' ')
635 bt[strlen(bt)-1] = 0;
636 str.replace("$basetype",bt);
637 str.replace("$basemangle",realtype->print_mangle());
638 realtype->is_pointer = temp_ip;
639 realtype->implicit_ptr = temp_ip1;
640 }
641
642 str.replace("$mangle",realtype->print_mangle());
643
644 // If there were locals and a wrapper function, replace
645 if ((tm->args) && f) {
646 typemap_locals(realtype, pname, str,tm->args,*f);
647 }
648
649 // If there were locals and no wrapper function, print a warning
650 if ((tm->args) && !f) {
651 if (!pname) pname = "";
652 fprintf(stderr,"%s:%d: Warning. '%%typemap(%s,%s) %s %s' being applied with ignored locals.\n",
653 input_file, line_number, lang,op, type->print_type(), pname);
654 }
655
656 // Return character string
657
658 return str;
659}
660
661// ----------------------------------------------------------
662// Real function call that takes care of application mappings
663// ----------------------------------------------------------
664
665char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source,
666 char *target, WrapperFunction *f) {
667 TmMethod *m;
668 char temp[512];
669 char *result;
670 char *ppname;
671 char *tstr;
672
673 realtype = type; // The other half of the gross hack
674 realname = pname;
675
676 // Try to apply typemap right away
677
678 result = typemap_lookup_internal(op,lang,type,pname,source,target,f);
679
680 // If not found, try to pick up anything that might have been
681 // specified with %apply
682
683 if ((!result) && (pname)) {
684 int drop_pointer = 0;
685 ppname = pname;
686 if (!ppname) ppname = "";
687
688 // The idea : We're going to cycle through applications and
689 // drop pointers off until we get a match.
690
691 while (drop_pointer <= (type->is_pointer - type->implicit_ptr)) {
692 type->is_pointer -= drop_pointer;
693 tstr = type->print_type();
694 sprintf(temp,"%s$%s",tstr,ppname);
695 // No mapping was found. See if the name has been mapped with %apply
696 m = (TmMethod *) application_hash.lookup(temp);
697 if (!m) {
698 sprintf(temp,"%s$",tstr);
699 m = (TmMethod *) application_hash.lookup(temp);
700 }
701 if (m) {
702 m = m->next;
703 while (m) {
704 char *oldary = 0;
705 static String newarray;
706 if (*(m->name)) ppname = m->name;
707 else ppname = pname;
708 m->type->is_pointer += drop_pointer;
709
710 // Copy old array string (just in case)
711
712 oldary = m->type->arraystr;
713
714 // If the mapping type is an array and has the 'ANY' keyword, we
715 // have to play some magic
716
717 if ((m->type->arraystr) && (type->arraystr)) {
718 // Build up the new array string
719 newarray = "";
720 for (int n = 0; n < m->type->array_dimensions(); n++) {
721 char *d = m->type->get_dimension(n);
722 if (strcmp(d,"ANY") == 0) {
723 newarray << "[" << type->get_dimension(n) << "]";
724 } else {
725 newarray << "[" << d << "]";
726 }
727 }
728 m->type->arraystr = newarray.get();
729 } else if (type->arraystr) {
730 // If an array string is available for the current datatype,
731 // make it available.
732 m->type->arraystr = type->arraystr;
733 }
734 result = typemap_lookup_internal(op,lang,m->type,ppname,source,target,f);
735 m->type->arraystr = oldary;
736 m->type->is_pointer -= drop_pointer;
737 if (result) {
738 type->is_pointer += drop_pointer;
739 return result;
740 }
741 m = m->next;
742 }
743 }
744 type->is_pointer += drop_pointer;
745 drop_pointer++;
746 }
747 }
748 // Still no idea, try to find a default typemap
749
750 if (!result) {
751 DataType *t = new DataType(type);
752 t->primitive(); // Knock it down to its basic type
753 result = typemap_lookup_internal(op,lang,t,"SWIG_DEFAULT_TYPE",source,target,f);
754 if (result) {
755 delete t;
756 return result;
757 }
758 if ((t->type == T_USER) || (t->is_pointer)) {
759 if ((t->type == T_CHAR) && (t->is_pointer == 1)) return 0;
760
761 // Still no result, go even more primitive
762 t->type = T_USER;
763 t->is_pointer = 1;
764 if (t->arraystr) delete [] t->arraystr;
765 t->arraystr = 0;
766 t->primitive();
767 result = typemap_lookup_internal(op,lang,t,"SWIG_DEFAULT_TYPE",source,target,f);
768 }
769 delete t;
770 }
771 return result;
772}
773
774// ----------------------------------------------------------------------------
775// char *typemap_check(char *op, char *lang, DataType *type, char *pname)
776//
777// Checks to see if there is a typemap. Returns typemap string if found, NULL
778// if not.
779// ----------------------------------------------------------------------------
780
781char *typemap_check_internal(char *op, char *lang, DataType *type, char *pname) {
782 static String str;
783 char *key = 0;
784 TypeMap *tm = 0;
785
786 if (!lang) {
787 return 0;
788 }
789 // First check for named array
790 str = "";
791 tm = typemap_search_array(op,lang,type,pname,str);
792
793 // First check for named array
794 //
795 // if (type->arraystr) {
796 // key = typemap_string(lang,type,pname,type->arraystr,op);
797 // tm = typemap_search(key,type->id);
798 // }
799
800 // Check for named argument
801 if (!tm) {
802 key = typemap_string(lang,type,pname,0,op);
803 tm = typemap_search(key,type->id);
804 }
805
806 // Check for unnamed array
807 if ((!tm) && (type->arraystr)) {
808 key = typemap_string(lang,type,"",type->arraystr,op);
809 tm = typemap_search(key,type->id);
810 }
811
812 // Check for unname type
813 if (!tm) {
814 key = typemap_string(lang,type,"",0,op);
815 tm = typemap_search(key,type->id);
816 }
817 if (!tm) return 0;
818
819 str = "";
820 str << tm->code;
821
822 // Return character string
823
824 return str;
825}
826
827// Function for checking with applications
828
829char *typemap_check(char *op, char *lang, DataType *type, char *pname) {
830 TmMethod *m;
831 char temp[512];
832 char *result;
833 char *ppname;
834 char *tstr;
835 // Try to apply typemap right away
836
837 result = typemap_check_internal(op,lang,type,pname);
838
839 if (!result) {
840 int drop_pointer = 0;
841 ppname = pname;
842 if (!ppname) ppname = "";
843
844 // The idea : We're going to cycle through applications and
845 // drop pointers off until we get a match.
846
847 while (drop_pointer <= (type->is_pointer - type->implicit_ptr)) {
848 type->is_pointer -= drop_pointer;
849 tstr = type->print_type();
850 sprintf(temp,"%s$%s",tstr,ppname);
851 // No mapping was found. See if the name has been mapped with %apply
852 m = (TmMethod *) application_hash.lookup(temp);
853 if (!m) {
854 sprintf(temp,"%s$",tstr);
855 m = (TmMethod *) application_hash.lookup(temp);
856 }
857 if (m) {
858 m = m->next;
859 while (m) {
860 char *oldary = 0;
861 static String newarray;
862 if (*(m->name)) ppname = m->name;
863 else ppname = pname;
864 m->type->is_pointer += drop_pointer;
865 oldary = m->type->arraystr;
866
867 // If the mapping type is an array and has the 'ANY' keyword, we
868 // have to play some magic
869
870 if ((m->type->arraystr) && (type->arraystr)) {
871 // Build up the new array string
872 newarray = "";
873 for (int n = 0; n < m->type->array_dimensions(); n++) {
874 char *d = m->type->get_dimension(n);
875 if (strcmp(d,"ANY") == 0) {
876 newarray << "[" << type->get_dimension(n) << "]";
877 } else {
878 newarray << "[" << d << "]";
879 }
880 }
881 oldary = m->type->arraystr;
882 m->type->arraystr = newarray.get();
883 } else if (type->arraystr) {
884 m->type->arraystr = type->arraystr;
885 }
886 result = typemap_check_internal(op,lang,m->type,ppname);
887 m->type->arraystr = oldary;
888 m->type->is_pointer -= drop_pointer;
889 if (result) {
890 type->is_pointer += drop_pointer;
891 return result;
892 }
893 m = m->next;
894 }
895 }
896 type->is_pointer += drop_pointer;
897 drop_pointer++;
898 }
899 }
900
901 // If still no result, might have a default typemap
902 if (!result) {
903 DataType *t = new DataType(type);
904 t->primitive(); // Knock it down to its basic type
905 result = typemap_check_internal(op,lang,t,"SWIG_DEFAULT_TYPE");
906 if (result) {
907 delete t;
908 return result;
909 }
910 if ((t->type == T_USER) || (t->is_pointer)) {
911 if ((t->type == T_CHAR) && (t->is_pointer == 1)) return 0;
912 // Still no result, go even more primitive
913 t->type = T_USER;
914 t->is_pointer = 1;
915 if (t->arraystr) delete [] t->arraystr;
916 t->arraystr = 0;
917 t->primitive();
918 result = typemap_check_internal(op,lang,t,"SWIG_DEFAULT_TYPE");
919 }
920 delete t;
921 }
922 return result;
923}
924
925// ------------------------------------------------------------------------
926// void typemap_clear(char *op, char *lang, DataType *type, char *pname)
927//
928// Clears any previous typemap. This works like a stack. Clearing a
929// typemap returns to any previous typemap in force. If there is no
930// previous map, then don't worry about it.
931// ------------------------------------------------------------------------
932
933void typemap_clear(char *op, char *lang, DataType *type, char *pname) {
934
935 char *key;
936 TypeMap *tm;
937
938 key = typemap_string(lang,type,pname,type->arraystr,op);
939
940 // Look for any previous version, simply set the last id if
941 // applicable.
942
943 tm = (TypeMap *) typemap_hash.lookup(key);
944 if (tm) {
945 if (tm->last > type_id) tm->last = type_id;
946 }
947}
948
949// ------------------------------------------------------------------------
950// void typemap_copy(char *op, char *lang, DataType *stype, char *sname,
951// DataType *ttype, char *tname)
952//
953// Copies the code associate with a typemap
954// ------------------------------------------------------------------------
955
956void typemap_copy(char *op, char *lang, DataType *stype, char *sname,
957 DataType *ttype, char *tname) {
958
959 char *key;
960 TypeMap *tm, *tk, *tn;
961
962 // Try to locate a previous typemap
963
964 key = typemap_string(lang,stype,sname,stype->arraystr,op);
965 tm = typemap_search(key,stype->id);
966 if (!tm) return;
967 if (strcmp(ttype->name,"PREVIOUS") == 0) {
968 // Pop back up to the previous typemap (if any)
969 tk = tm->next;
970 if (tk) {
971 tn = new TypeMap(tk); // Make a copy of the previous typemap
972 tn->next = tm; // Set up symlinks
973 typemap_hash.remove(key); // Remove old hash entry
974 typemap_hash.add(key,(void *) tn);
975 }
976 } else {
977 typemap_register(op,lang,ttype,tname,tm->code,tm->args);
978 }
979}
980
981// ------------------------------------------------------------------------
982// char *fragment_string(char *op, char *lang)
983//
984// Produces a character string corresponding to a language and method
985// This string is used as the key for our typemap hash table.
986// ------------------------------------------------------------------------
987
988static char *fragment_string(char *op, char *lang) {
989 static String str;
990
991 str = "";
992
993 str << "fragment:" << lang << op;
994 return str;
995}
996
997// ------------------------------------------------------------------------
998// void fragment_register(char *op, char *lang, char *code)
999//
1000// Register a code fragment with the type-mapper.
1001// ------------------------------------------------------------------------
1002
1003void fragment_register(char *op, char *lang, char *code) {
1004
1005 char *key;
1006 TypeMap *tm,*tm_old;
1007 char temp[256];
1008
1009 tm = new TypeMap(lang,code);
1010 key = fragment_string(op,lang);
1011
1012 // Get any previous setting of the typemap
1013
1014 tm_old = (TypeMap *) typemap_hash.lookup(key);
1015 if (tm_old) {
1016 // If found, we need to attach the old version to the new one
1017
1018 // Perform a chaining operation
1019
1020 sprintf(temp,"$%s",op);
1021 if (type_id < tm_old->last)
1022 tm->code.replace(temp,tm_old->code);
1023
1024 tm->next = tm_old;
1025 tm_old->last = type_id;
1026
1027 // Remove the old one from the hash
1028
1029 typemap_hash.remove(key);
1030 }
1031
1032 // Perform a default chaining operation if needed (defaults to nothing)
1033 sprintf(temp,"$%s",op);
1034 tm->code.replace(temp,"");
1035
1036 // Add new typemap to the hash table
1037 typemap_hash.add(key,(void *) tm);
1038
1039}
1040
1041
1042// ------------------------------------------------------------------------
1043// char *fragment_lookup(char *op, char *lang, int age)
1044//
1045// op is string code for type of mapping
1046// lang is the target language string
1047// age is age of fragment.
1048//
1049// Returns NULL if no mapping is found.
1050//
1051// ------------------------------------------------------------------------
1052
1053char *fragment_lookup(char *op, char *lang, int age) {
1054 static String str;
1055 char *key = 0;
1056 TypeMap *tm = 0;
1057
1058 if (!lang) {
1059 return 0;
1060 }
1061
1062 str = "";
1063 key = fragment_string(op,lang);
1064 tm = typemap_search(key,age);
1065
1066 if (!tm) return 0;
1067
1068 str << tm->code;
1069 return str;
1070}
1071
1072// ------------------------------------------------------------------------
1073// void fragment_clear(char *op, char *lang)
1074//
1075// Clears any previous fragment definition. Is a stack operation--will
1076// restore any previously declared typemap.
1077// ------------------------------------------------------------------------
1078
1079void fragment_clear(char *op, char *lang) {
1080
1081 char *key;
1082 TypeMap *tm;
1083
1084 key = fragment_string(op,lang);
1085
1086 // Look for any previous version, simply set the last id if
1087 // applicable.
1088
1089 tm = (TypeMap *) typemap_hash.lookup(key);
1090 if (tm) {
1091 if (tm->last > type_id) tm->last = type_id;
1092 }
1093}