]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/SWIG/typemap.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
4 * Author : David Beazley
6 * Department of Computer Science
7 * University of Chicago
10 * beazley@cs.uchicago.edu
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
20 // ------------------------------------------------------------------------
25 // This file provides universal support for typemaps. Typemaps are created
26 // using the following SWIG command in an interface file:
28 // %typemap(lang,operation) type { code } Make a new typemap
29 // %typemap(lang,operation) type; Clears any previous typemap
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
36 // %typemap(tcl,get) double {
37 // $target = atof($source);
39 // %typemap(tcl,set) double {
40 // sprintf($target,"%0.17f",$source);
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.
47 // The C++ API to the type-mapper is as follows :
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);
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.
57 // (2/19/97) This module has been extended somewhat to provide generic mappings
58 // of other parts of the code--most notably exceptions.
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);
64 // ------------------------------------------------------------------------
66 // Structure for holding a typemap
75 TypeMap
*previous
; // Previously defined typemap (if any)
76 ParmList
*args
; // Local variables (if any)
78 TypeMap(char *l
, DataType
*t
, String
&c
, ParmList
*p
= 0) {
79 lang
= copy_string(l
);
80 type
= new DataType(t
);
87 args
= new ParmList(p
);
92 TypeMap(char *l
, DataType
*t
, char *c
, ParmList
*p
= 0) {
93 lang
= copy_string(l
);
94 type
= new DataType(t
);
101 args
= new ParmList(p
);
106 TypeMap(char *l
, char *c
) {
107 lang
= copy_string(l
);
116 TypeMap(TypeMap
*t
) {
117 lang
= copy_string(t
->lang
);
118 type
= new DataType(t
->type
);
123 previous
= t
->previous
;
125 args
= new ParmList(args
);
132 // Hash tables for storing type-mappings
134 static Hash typemap_hash
;
136 // Structure for holding "applications of a typemap"
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
);
146 type
= new DataType(t
);
154 // Hash table for storing applications of a datatype
156 static Hash application_hash
;
158 // ------------------------------------------------------------------------
159 // void typemap_apply(DataType *tm_type, char *tm_name, DataType *type, char *pname)
161 // Attempts to apply a typemap given by (tm_type,tm_name) to (type,pname)
162 // Called by the %apply directive.
163 // ------------------------------------------------------------------------
165 void typemap_apply(DataType
*tm_type
, char *tm_name
, DataType
*type
, char *pname
) {
169 // Form the application name
170 if (!pname
) pname
= "";
171 sprintf(temp
,"%s$%s",type
->print_type(),pname
);
173 // See if there is a method already defined
175 m
= (TmMethod
*) application_hash
.lookup(temp
);
178 m
= new TmMethod(temp
,type
,0);
179 application_hash
.add(temp
,m
);
182 // Check to see if an array typemap has been applied to a non-array type
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
);
189 // If both are arrays, make sure they have the same dimension
191 if ((tm_type
->arraystr
) && (type
->arraystr
)) {
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
);
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) {
202 fprintf(stderr
,"%s:%d: Warning. Array typemap applied to an array of different size.\n",
203 input_file
, line_number
);
209 // Add a new mapping corresponding to the typemap
211 m1
= new TmMethod(tm_name
,tm_type
,m
->next
);
215 // ------------------------------------------------------------------------
216 // void typemap_clear_apply(DataType *type, char *pname)
218 // Clears the application of a typemap.
219 // Called by the %clear directive.
220 // ------------------------------------------------------------------------
222 void typemap_clear_apply(DataType
*type
, char *pname
) {
224 if (!pname
) pname
= "";
225 sprintf(temp
,"%s$%s", type
->print_type(), pname
);
226 application_hash
.remove(temp
);
229 // ------------------------------------------------------------------------
230 // char *typemap_string(char *lang, DataType *type, char *pname, char *ary, char *suffix)
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 // ------------------------------------------------------------------------
236 static char *typemap_string(char *lang
, DataType
*type
, char *pname
, char *ary
, char *suffix
) {
240 old_status
= type
->status
;
245 str
<< lang
<< type
->print_type() << pname
<< ary
<< suffix
;
247 str
<< lang
<< type
->print_type() << pname
<< suffix
;
249 type
->status
= old_status
;
253 // ------------------------------------------------------------------------
254 // void typemap_register(char *op, char *lang, DataType *type, char *pname,
255 // char *getcode, ParmList *args)
257 // Register a new mapping with the type-mapper.
258 // ------------------------------------------------------------------------
260 void typemap_register(char *op
, char *lang
, DataType
*type
, char *pname
,
261 char *getcode
, ParmList
*args
) {
268 // printf("Registering : %s %s %s %s\n%s\n", op, lang, type->print_type(), pname, getcode);
271 tm
= new TypeMap(lang
,type
,getcode
,args
);
272 // If this is a default typemap, downgrade the type!
274 if (strcmp(pname
,"SWIG_DEFAULT_TYPE") == 0) {
275 tm
->type
->primitive();
279 key
= typemap_string(lang
,tm
->type
,pname
,tm
->type
->arraystr
, op
);
281 // Get any previous setting of the typemap
283 tm_old
= (TypeMap
*) typemap_hash
.lookup(key
);
287 // Perform a chaining operation, but only if the last typemap is
290 if (type_id
< tm_old
->last
) {
291 sprintf(temp
,"$%s",op
);
292 tm
->code
.replace(temp
,tm_old
->code
);
295 // If found, we need to attach the old version to the new one
297 tm
->previous
= tm_old
;
299 tm_old
->last
= type_id
;
301 // Remove the old one from the hash
303 typemap_hash
.remove(key
);
306 // Add new typemap to the hash table
307 typemap_hash
.add(key
,(void *) tm
);
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));
317 // Just a sanity check to make sure args look okay.
321 p
= tm
->args
->get_first();
324 // printf(" %s %s\n", p->t->print_type(),p->name);
326 fprintf(stderr
,"%s:%d: Typemap error. Local variables must have a name\n",
327 input_file
, line_number
);
329 // If a call by reference thingy, fix that
330 if (p
->call_type
& CALL_REFERENCE
) {
334 p
= tm
->args
->get_next();
339 // ------------------------------------------------------------------------
340 // void typemap_register(char *op, char *lang, char *type, char *pname,
341 // char *getcode, ParmList *args)
343 // Register a new mapping with the type-mapper. Special version that uses a
344 // string instead of a datatype.
345 // ------------------------------------------------------------------------
347 void typemap_register(char *op
, char *lang
, char *type
, char *pname
,
348 char *getcode
, ParmList
*args
) {
350 strcpy(temp
.name
,type
);
353 typemap_register(op
,lang
,&temp
,pname
,getcode
,args
);
357 // ------------------------------------------------------------------------
358 // void typemap_register_default(char *op, char *lang, int type, int ptr, char *arraystr,
359 // char *code, ParmList *args)
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 // ------------------------------------------------------------------------
365 void typemap_register_default(char *op
, char *lang
, int type
, int ptr
, char *arraystr
,
366 char *code
, ParmList
*args
) {
368 DataType
*t
= new DataType(type
);
370 // Create a raw datatype from the arguments
373 t
->arraystr
= copy_string(arraystr
);
375 // Now, go register this as a default type
377 typemap_register(op
,lang
,t
,"SWIG_DEFAULT_TYPE",code
,args
);
382 // ------------------------------------------------------------------------
383 // static TypeMap *typemap_search(char *key, int id)
385 // An internal function for searching for a particular typemap given
386 // a key value and datatype id.
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 // ------------------------------------------------------------------------
393 TypeMap
*typemap_search(char *key
, int id
) {
397 tm
= (TypeMap
*) typemap_hash
.lookup(key
);
399 if ((id
>= tm
->first
) && (id
< tm
->last
)) return tm
;
405 // ------------------------------------------------------------------------
406 // TypeMap *typemap_search_array(char *op, char *lang, DataType *type, char *pname, String &str)
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
412 // ------------------------------------------------------------------------
414 TypeMap
*typemap_search_array(char *op
, char *lang
, DataType
*type
, char *pname
, String
&str
) {
415 char *origarr
= type
->arraystr
;
421 if (!type
->arraystr
) return 0;
423 // First check to see if exactly this array has been mapped
425 key
= typemap_string(lang
,type
,pname
,type
->arraystr
,op
);
426 tm
= typemap_search(key
,type
->id
);
428 // Check for unnamed array of specific dimensions
430 key
= typemap_string(lang
,type
,"",type
->arraystr
,op
);
431 tm
= typemap_search(key
,type
->id
);
435 // We're going to go search for matches with the ANY tag
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
443 for (n
= 0; n
< ndim
; n
++) {
445 tempastr
<< "[" << type
->get_dimension(n
) << "]";
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
);
456 key
= typemap_string(lang
,type
,"",type
->arraystr
,op
);
457 tm
= typemap_search(key
,type
->id
);
459 type
->arraystr
= origarr
;
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
));
476 // ------------------------------------------------------------------------
477 // static typemap_locals(Datatype *t, char *pname, String &s, ParmList *l, WrapperFunction &f)
479 // Takes a string, a parameter list and a wrapper function argument and
480 // starts creating local variables.
482 // Substitutes locals in the string with actual values used.
483 // ------------------------------------------------------------------------
485 static void typemap_locals(DataType
*t
, char *pname
, String
&s
, ParmList
*l
, WrapperFunction
&f
) {
492 if (strlen(p
->name
) > 0) {
496 // If the user gave us $type as the name of the local variable, we'll use
497 // the passed datatype instead
499 if (strcmp(p
->t
->name
,"$type")==0 || strcmp(p
->t
->name
,"$basetype")==0) {
505 // Have a real parameter here
508 str
<< p
->name
<< tt
->arraystr
;
514 // Substitute parameter names
515 str
.replace("$arg",pname
);
516 if (strcmp(p
->t
->name
,"$basetype")==0) {
518 char temp_ip
= tt
->is_pointer
;
519 char temp_ip1
= tt
->implicit_ptr
;
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
;
527 new_name
= f
.new_local(tt
->print_full(),str
);
529 if (tt
->arraystr
) tt
->is_pointer
++;
531 s
.replaceid(p
->name
,new_name
);
536 // If the original datatype was an array. We're going to go through and substitute
537 // it's array dimensions
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
));
549 // ------------------------------------------------------------------------
550 // char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source,
551 // char *target, WrapperFunction *f)
553 // Looks up a "get" function in the type-map and returns a character string
554 // containing the appropriate translation code.
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)
564 // Returns NULL if no mapping is found.
566 // Typemaps follow a few rules regarding naming and C pointers by checking
567 // declarations in this order.
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
574 // Array checking is only made if the datatype actally has an array specifier
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.
580 // Array dimensions are substituted into the variables $dim1, $dim2,...,$dim9
581 // ------------------------------------------------------------------------
583 static DataType
*realtype
; // This is a gross hack
584 static char *realname
= 0; // Real parameter name
586 char *typemap_lookup_internal(char *op
, char *lang
, DataType
*type
, char *pname
, char *source
,
587 char *target
, WrapperFunction
*f
) {
596 // First check for named array
598 tm
= typemap_search_array(op
,lang
,type
,pname
,str
);
600 // Check for named argument
602 key
= typemap_string(lang
,type
,pname
,0,op
);
603 tm
= typemap_search(key
,type
->id
);
608 // Check for unnamed type
610 key
= typemap_string(lang
,type
,"",0,op
);
611 tm
= typemap_search(key
,type
->id
);
617 // Now perform character replacements
619 str
.replace("$source",source
);
620 str
.replace("$target",target
);
621 str
.replace("$type", realtype
->print_type());
623 str
.replace("$parmname", realname
);
625 str
.replace("$parmname","");
627 // Print base type (without any pointers)
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
;
642 str
.replace("$mangle",realtype
->print_mangle());
644 // If there were locals and a wrapper function, replace
645 if ((tm
->args
) && f
) {
646 typemap_locals(realtype
, pname
, str
,tm
->args
,*f
);
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
);
656 // Return character string
661 // ----------------------------------------------------------
662 // Real function call that takes care of application mappings
663 // ----------------------------------------------------------
665 char *typemap_lookup(char *op
, char *lang
, DataType
*type
, char *pname
, char *source
,
666 char *target
, WrapperFunction
*f
) {
673 realtype
= type
; // The other half of the gross hack
676 // Try to apply typemap right away
678 result
= typemap_lookup_internal(op
,lang
,type
,pname
,source
,target
,f
);
680 // If not found, try to pick up anything that might have been
681 // specified with %apply
683 if ((!result
) && (pname
)) {
684 int drop_pointer
= 0;
686 if (!ppname
) ppname
= "";
688 // The idea : We're going to cycle through applications and
689 // drop pointers off until we get a match.
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
);
698 sprintf(temp
,"%s$",tstr
);
699 m
= (TmMethod
*) application_hash
.lookup(temp
);
705 static String newarray
;
706 if (*(m
->name
)) ppname
= m
->name
;
708 m
->type
->is_pointer
+= drop_pointer
;
710 // Copy old array string (just in case)
712 oldary
= m
->type
->arraystr
;
714 // If the mapping type is an array and has the 'ANY' keyword, we
715 // have to play some magic
717 if ((m
->type
->arraystr
) && (type
->arraystr
)) {
718 // Build up the new array string
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
) << "]";
725 newarray
<< "[" << d
<< "]";
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
;
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
;
738 type
->is_pointer
+= drop_pointer
;
744 type
->is_pointer
+= drop_pointer
;
748 // Still no idea, try to find a default typemap
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
);
758 if ((t
->type
== T_USER
) || (t
->is_pointer
)) {
759 if ((t
->type
== T_CHAR
) && (t
->is_pointer
== 1)) return 0;
761 // Still no result, go even more primitive
764 if (t
->arraystr
) delete [] t
->arraystr
;
767 result
= typemap_lookup_internal(op
,lang
,t
,"SWIG_DEFAULT_TYPE",source
,target
,f
);
774 // ----------------------------------------------------------------------------
775 // char *typemap_check(char *op, char *lang, DataType *type, char *pname)
777 // Checks to see if there is a typemap. Returns typemap string if found, NULL
779 // ----------------------------------------------------------------------------
781 char *typemap_check_internal(char *op
, char *lang
, DataType
*type
, char *pname
) {
789 // First check for named array
791 tm
= typemap_search_array(op
,lang
,type
,pname
,str
);
793 // First check for named array
795 // if (type->arraystr) {
796 // key = typemap_string(lang,type,pname,type->arraystr,op);
797 // tm = typemap_search(key,type->id);
800 // Check for named argument
802 key
= typemap_string(lang
,type
,pname
,0,op
);
803 tm
= typemap_search(key
,type
->id
);
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
);
812 // Check for unname type
814 key
= typemap_string(lang
,type
,"",0,op
);
815 tm
= typemap_search(key
,type
->id
);
822 // Return character string
827 // Function for checking with applications
829 char *typemap_check(char *op
, char *lang
, DataType
*type
, char *pname
) {
835 // Try to apply typemap right away
837 result
= typemap_check_internal(op
,lang
,type
,pname
);
840 int drop_pointer
= 0;
842 if (!ppname
) ppname
= "";
844 // The idea : We're going to cycle through applications and
845 // drop pointers off until we get a match.
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
);
854 sprintf(temp
,"%s$",tstr
);
855 m
= (TmMethod
*) application_hash
.lookup(temp
);
861 static String newarray
;
862 if (*(m
->name
)) ppname
= m
->name
;
864 m
->type
->is_pointer
+= drop_pointer
;
865 oldary
= m
->type
->arraystr
;
867 // If the mapping type is an array and has the 'ANY' keyword, we
868 // have to play some magic
870 if ((m
->type
->arraystr
) && (type
->arraystr
)) {
871 // Build up the new array string
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
) << "]";
878 newarray
<< "[" << d
<< "]";
881 oldary
= m
->type
->arraystr
;
882 m
->type
->arraystr
= newarray
.get();
883 } else if (type
->arraystr
) {
884 m
->type
->arraystr
= type
->arraystr
;
886 result
= typemap_check_internal(op
,lang
,m
->type
,ppname
);
887 m
->type
->arraystr
= oldary
;
888 m
->type
->is_pointer
-= drop_pointer
;
890 type
->is_pointer
+= drop_pointer
;
896 type
->is_pointer
+= drop_pointer
;
901 // If still no result, might have a default typemap
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");
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
915 if (t
->arraystr
) delete [] t
->arraystr
;
918 result
= typemap_check_internal(op
,lang
,t
,"SWIG_DEFAULT_TYPE");
925 // ------------------------------------------------------------------------
926 // void typemap_clear(char *op, char *lang, DataType *type, char *pname)
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 // ------------------------------------------------------------------------
933 void typemap_clear(char *op
, char *lang
, DataType
*type
, char *pname
) {
938 key
= typemap_string(lang
,type
,pname
,type
->arraystr
,op
);
940 // Look for any previous version, simply set the last id if
943 tm
= (TypeMap
*) typemap_hash
.lookup(key
);
945 if (tm
->last
> type_id
) tm
->last
= type_id
;
949 // ------------------------------------------------------------------------
950 // void typemap_copy(char *op, char *lang, DataType *stype, char *sname,
951 // DataType *ttype, char *tname)
953 // Copies the code associate with a typemap
954 // ------------------------------------------------------------------------
956 void typemap_copy(char *op
, char *lang
, DataType
*stype
, char *sname
,
957 DataType
*ttype
, char *tname
) {
960 TypeMap
*tm
, *tk
, *tn
;
962 // Try to locate a previous typemap
964 key
= typemap_string(lang
,stype
,sname
,stype
->arraystr
,op
);
965 tm
= typemap_search(key
,stype
->id
);
967 if (strcmp(ttype
->name
,"PREVIOUS") == 0) {
968 // Pop back up to the previous typemap (if any)
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
);
977 typemap_register(op
,lang
,ttype
,tname
,tm
->code
,tm
->args
);
981 // ------------------------------------------------------------------------
982 // char *fragment_string(char *op, char *lang)
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 // ------------------------------------------------------------------------
988 static char *fragment_string(char *op
, char *lang
) {
993 str
<< "fragment:" << lang
<< op
;
997 // ------------------------------------------------------------------------
998 // void fragment_register(char *op, char *lang, char *code)
1000 // Register a code fragment with the type-mapper.
1001 // ------------------------------------------------------------------------
1003 void fragment_register(char *op
, char *lang
, char *code
) {
1006 TypeMap
*tm
,*tm_old
;
1009 tm
= new TypeMap(lang
,code
);
1010 key
= fragment_string(op
,lang
);
1012 // Get any previous setting of the typemap
1014 tm_old
= (TypeMap
*) typemap_hash
.lookup(key
);
1016 // If found, we need to attach the old version to the new one
1018 // Perform a chaining operation
1020 sprintf(temp
,"$%s",op
);
1021 if (type_id
< tm_old
->last
)
1022 tm
->code
.replace(temp
,tm_old
->code
);
1025 tm_old
->last
= type_id
;
1027 // Remove the old one from the hash
1029 typemap_hash
.remove(key
);
1032 // Perform a default chaining operation if needed (defaults to nothing)
1033 sprintf(temp
,"$%s",op
);
1034 tm
->code
.replace(temp
,"");
1036 // Add new typemap to the hash table
1037 typemap_hash
.add(key
,(void *) tm
);
1042 // ------------------------------------------------------------------------
1043 // char *fragment_lookup(char *op, char *lang, int age)
1045 // op is string code for type of mapping
1046 // lang is the target language string
1047 // age is age of fragment.
1049 // Returns NULL if no mapping is found.
1051 // ------------------------------------------------------------------------
1053 char *fragment_lookup(char *op
, char *lang
, int age
) {
1063 key
= fragment_string(op
,lang
);
1064 tm
= typemap_search(key
,age
);
1072 // ------------------------------------------------------------------------
1073 // void fragment_clear(char *op, char *lang)
1075 // Clears any previous fragment definition. Is a stack operation--will
1076 // restore any previously declared typemap.
1077 // ------------------------------------------------------------------------
1079 void fragment_clear(char *op
, char *lang
) {
1084 key
= fragment_string(op
,lang
);
1086 // Look for any previous version, simply set the last id if
1089 tm
= (TypeMap
*) typemap_hash
.lookup(key
);
1091 if (tm
->last
> type_id
) tm
->last
= type_id
;