/tags/rel-1.3.35/Source/Swig/typemap.c
C | 1900 lines | 1387 code | 206 blank | 307 comment | 351 complexity | 9d280ab9c0f442829cd831a7eecfd7b1 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
1/* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4 *
5 * typemap.c
6 *
7 * A somewhat generalized implementation of SWIG1.1 typemaps.
8 * ----------------------------------------------------------------------------- */
9
10char cvsroot_typemap_c[] = "$Id: typemap.c 9889 2007-08-10 02:55:27Z wuzzeb $";
11
12#include "swig.h"
13#include "cparse.h"
14#include <ctype.h>
15
16#if 0
17#define SWIG_DEBUG
18#endif
19
20static void replace_embedded_typemap(String *s);
21
22/* -----------------------------------------------------------------------------
23 * Typemaps are stored in a collection of nested hash tables. Something like
24 * this:
25 *
26 * [ type ]
27 * +-------- [ name ]
28 * +-------- [ name ]
29 *
30 * Each hash table [ type ] or [ name ] then contains references to the
31 * different typemap methods. These are referenced by names such as
32 * "tmap:in", "tmap:out", "tmap:argout", and so forth.
33 *
34 * The object corresponding to a specific method has the following
35 * attributes:
36 *
37 * "type" - Typemap type
38 * "pname" - Parameter name
39 * "code" - Typemap code
40 * "typemap" - Descriptive text describing the actual map
41 * "locals" - Local variables (if any)
42 *
43 * ----------------------------------------------------------------------------- */
44
45#define MAX_SCOPE 32
46
47
48static Hash *typemaps[MAX_SCOPE];
49static int tm_scope = 0;
50
51static Hash *get_typemap(int tm_scope, SwigType *type) {
52 Hash *tm = 0;
53 SwigType *dtype = 0;
54 if (SwigType_istemplate(type)) {
55 String *ty = Swig_symbol_template_deftype(type, 0);
56 dtype = Swig_symbol_type_qualify(ty, 0);
57 /* Printf(stderr,"gettm %s %s\n", type, dtype); */
58 type = dtype;
59 Delete(ty);
60 }
61 tm = Getattr(typemaps[tm_scope], type);
62
63
64 if (dtype) {
65 if (!tm) {
66 String *t_name = SwigType_templateprefix(type);
67 if (!Equal(t_name, type)) {
68 tm = Getattr(typemaps[tm_scope], t_name);
69 }
70 Delete(t_name);
71 }
72 Delete(dtype);
73 }
74
75 return tm;
76}
77
78static void set_typemap(int tm_scope, SwigType *type, Hash *tm) {
79 SwigType *dtype = 0;
80 if (SwigType_istemplate(type)) {
81 String *ty = Swig_symbol_template_deftype(type, 0);
82 dtype = Swig_symbol_type_qualify(ty, 0);
83 /* Printf(stderr,"settm %s %s\n", type, dtype); */
84 type = dtype;
85 Delete(ty);
86 } else {
87 dtype = Copy(type);
88 type = dtype;
89 }
90 Setattr(typemaps[tm_scope], type, tm);
91 Delete(dtype);
92}
93
94
95/* -----------------------------------------------------------------------------
96 * Swig_typemap_init()
97 *
98 * Initialize the typemap system
99 * ----------------------------------------------------------------------------- */
100
101void Swig_typemap_init() {
102 int i;
103 for (i = 0; i < MAX_SCOPE; i++) {
104 typemaps[i] = 0;
105 }
106 typemaps[0] = NewHash();
107 tm_scope = 0;
108}
109
110static String *tmop_name(const String_or_char *op) {
111 static Hash *names = 0;
112 String *s;
113 /* Due to "interesting" object-identity semantics of DOH,
114 we have to make sure that we only intern strings without object
115 identity into the hash table.
116
117 (Swig_typemap_attach_kwargs calls tmop_name several times with
118 the "same" String *op (i.e., same object identity) but differing
119 string values.)
120
121 Most other callers work around this by using char* rather than
122 String *.
123 -- mkoeppe, Jun 17, 2003
124 */
125 const char *op_without_object_identity = Char(op);
126 if (!names)
127 names = NewHash();
128 s = Getattr(names, op_without_object_identity);
129 if (s)
130 return s;
131 s = NewStringf("tmap:%s", op);
132 Setattr(names, op_without_object_identity, s);
133 Delete(s);
134 return s;
135}
136
137/* -----------------------------------------------------------------------------
138 * Swig_typemap_new_scope()
139 *
140 * Create a new typemap scope
141 * ----------------------------------------------------------------------------- */
142
143void Swig_typemap_new_scope() {
144 tm_scope++;
145 typemaps[tm_scope] = NewHash();
146}
147
148/* -----------------------------------------------------------------------------
149 * Swig_typemap_pop_scope()
150 *
151 * Pop the last typemap scope off
152 * ----------------------------------------------------------------------------- */
153
154Hash *Swig_typemap_pop_scope() {
155 if (tm_scope > 0) {
156 return typemaps[tm_scope--];
157 }
158 return 0;
159}
160
161/* -----------------------------------------------------------------------------
162 * Swig_typemap_register()
163 *
164 * Add a new multi-valued typemap
165 * ----------------------------------------------------------------------------- */
166
167void Swig_typemap_register(const String_or_char *op, ParmList *parms, String_or_char *code, ParmList *locals, ParmList *kwargs) {
168 Hash *tm;
169 Hash *tm1;
170 Hash *tm2;
171 Parm *np;
172 String *tmop;
173 SwigType *type;
174 String *pname;
175
176 if (!parms)
177 return;
178 tmop = tmop_name(op);
179
180 /* Register the first type in the parameter list */
181
182 type = Getattr(parms, "type");
183 pname = Getattr(parms, "name");
184
185 /* See if this type has been seen before */
186 tm = get_typemap(tm_scope, type);
187 if (!tm) {
188 tm = NewHash();
189 set_typemap(tm_scope, type, tm);
190 Delete(tm);
191 }
192 if (pname) {
193 /* See if parameter has been seen before */
194 tm1 = Getattr(tm, pname);
195 if (!tm1) {
196 tm1 = NewHash();
197 Setattr(tm, pname, tm1);
198 Delete(tm1);
199 }
200 tm = tm1;
201 }
202
203 /* Now see if this typemap op has been seen before */
204 tm2 = Getattr(tm, tmop);
205 if (!tm2) {
206 tm2 = NewHash();
207 Setattr(tm, tmop, tm2);
208 Delete(tm2);
209 }
210
211 /* For a multi-valued typemap, the typemap code and information
212 is really only stored in the last argument. However, to
213 make this work, we perform a really neat trick using
214 the typemap operator name.
215
216 For example, consider this typemap
217
218 %typemap(in) (int foo, int *bar, char *blah[]) {
219 ...
220 }
221
222 To store it, we look at typemaps for the following:
223
224 operator type-name
225 ----------------------------------------------
226 "in" int foo
227 "in-int+foo:" int *bar
228 "in-int+foo:-p.int+bar: char *blah[]
229
230 Notice how the operator expands to encode information about
231 previous arguments.
232
233 */
234
235 np = nextSibling(parms);
236 if (np) {
237 /* Make an entirely new operator key */
238 String *newop = NewStringf("%s-%s+%s:", op, type, pname);
239 /* Now reregister on the remaining arguments */
240 Swig_typemap_register(newop, np, code, locals, kwargs);
241
242 /* Setattr(tm2,newop,newop); */
243 Delete(newop);
244 } else {
245 String *str = SwigType_str(type, pname);
246 String *typemap = NewStringf("typemap(%s) %s", op, str);
247 ParmList *clocals = CopyParmList(locals);
248 ParmList *ckwargs = CopyParmList(kwargs);
249
250 Setattr(tm2, "code", code);
251 Setattr(tm2, "type", type);
252 Setattr(tm2, "typemap", typemap);
253 if (pname) {
254 Setattr(tm2, "pname", pname);
255 }
256 Setattr(tm2, "locals", clocals);
257 Setattr(tm2, "kwargs", ckwargs);
258
259 Delete(clocals);
260 Delete(ckwargs);
261
262 Delete(str);
263 Delete(typemap);
264 }
265}
266
267/* -----------------------------------------------------------------------------
268 * Swig_typemap_get()
269 *
270 * Retrieve typemap information from current scope.
271 * ----------------------------------------------------------------------------- */
272
273static Hash *Swig_typemap_get(SwigType *type, String_or_char *name, int scope) {
274 Hash *tm, *tm1;
275 /* See if this type has been seen before */
276 if ((scope < 0) || (scope > tm_scope))
277 return 0;
278 tm = get_typemap(scope, type);
279 if (!tm) {
280 return 0;
281 }
282 if ((name) && Len(name)) {
283 tm1 = Getattr(tm, name);
284 return tm1;
285 }
286 return tm;
287}
288
289/* -----------------------------------------------------------------------------
290 * Swig_typemap_copy()
291 *
292 * Copy a typemap
293 * ----------------------------------------------------------------------------- */
294
295int Swig_typemap_copy(const String_or_char *op, ParmList *srcparms, ParmList *parms) {
296 Hash *tm = 0;
297 String *tmop;
298 Parm *p;
299 String *pname;
300 SwigType *ptype;
301 int ts = tm_scope;
302 String *tmops, *newop;
303 if (ParmList_len(parms) != ParmList_len(srcparms))
304 return -1;
305
306 tmop = tmop_name(op);
307 while (ts >= 0) {
308 p = srcparms;
309 tmops = NewString(tmop);
310 while (p) {
311 ptype = Getattr(p, "type");
312 pname = Getattr(p, "name");
313
314 /* Lookup the type */
315 tm = Swig_typemap_get(ptype, pname, ts);
316 if (!tm)
317 break;
318
319 tm = Getattr(tm, tmops);
320 if (!tm)
321 break;
322
323 /* Got a match. Look for next typemap */
324 newop = NewStringf("%s-%s+%s:", tmops, ptype, pname);
325 Delete(tmops);
326 tmops = newop;
327 p = nextSibling(p);
328 }
329 Delete(tmops);
330
331 if (!p && tm) {
332
333 /* Got some kind of match */
334 Swig_typemap_register(op, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"));
335 return 0;
336 }
337 ts--;
338 }
339 /* Not found */
340 return -1;
341
342}
343
344/* -----------------------------------------------------------------------------
345 * Swig_typemap_clear()
346 *
347 * Delete a multi-valued typemap
348 * ----------------------------------------------------------------------------- */
349
350void Swig_typemap_clear(const String_or_char *op, ParmList *parms) {
351 SwigType *type;
352 String *name;
353 Parm *p;
354 String *newop;
355 Hash *tm = 0;
356
357 /* This might not work */
358 newop = NewString(op);
359 p = parms;
360 while (p) {
361 type = Getattr(p, "type");
362 name = Getattr(p, "name");
363 tm = Swig_typemap_get(type, name, tm_scope);
364 if (!tm)
365 return;
366 p = nextSibling(p);
367 if (p)
368 Printf(newop, "-%s+%s:", type, name);
369 }
370 if (tm) {
371 tm = Getattr(tm, tmop_name(newop));
372 if (tm) {
373 Delattr(tm, "code");
374 Delattr(tm, "locals");
375 Delattr(tm, "kwargs");
376 }
377 }
378 Delete(newop);
379}
380
381/* -----------------------------------------------------------------------------
382 * Swig_typemap_apply()
383 *
384 * Multi-argument %apply directive. This is pretty horrible so I sure hope
385 * it works.
386 * ----------------------------------------------------------------------------- */
387
388static
389int count_args(String *s) {
390 /* Count up number of arguments */
391 int na = 0;
392 char *c = Char(s);
393 while (*c) {
394 if (*c == '+')
395 na++;
396 c++;
397 }
398 return na;
399}
400
401int Swig_typemap_apply(ParmList *src, ParmList *dest) {
402 String *ssig, *dsig;
403 Parm *p, *np, *lastp, *dp, *lastdp = 0;
404 int narg = 0;
405 int ts = tm_scope;
406 SwigType *type = 0, *name;
407 Hash *tm, *sm;
408 int match = 0;
409
410 /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */
411
412 /* Create type signature of source */
413 ssig = NewStringEmpty();
414 dsig = NewStringEmpty();
415 p = src;
416 dp = dest;
417 lastp = 0;
418 while (p) {
419 lastp = p;
420 lastdp = dp;
421 np = nextSibling(p);
422 if (np) {
423 Printf(ssig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
424 Printf(dsig, "-%s+%s:", Getattr(dp, "type"), Getattr(dp, "name"));
425 narg++;
426 }
427 p = np;
428 dp = nextSibling(dp);
429 }
430
431 /* make sure a typemap node exists for the last destination node */
432 type = Getattr(lastdp, "type");
433 tm = get_typemap(tm_scope, type);
434 if (!tm) {
435 tm = NewHash();
436 set_typemap(tm_scope, type, tm);
437 Delete(tm);
438 }
439 name = Getattr(lastdp, "name");
440 if (name) {
441 Hash *tm1 = Getattr(tm, name);
442 if (!tm1) {
443 tm1 = NewHash();
444 Setattr(tm, NewString(name), tm1);
445 Delete(tm1);
446 }
447 tm = tm1;
448 }
449
450 /* This is a little nasty. We need to go searching for all possible typemaps in the
451 source and apply them to the target */
452
453 type = Getattr(lastp, "type");
454 name = Getattr(lastp, "name");
455
456 while (ts >= 0) {
457
458 /* See if there is a matching typemap in this scope */
459 sm = Swig_typemap_get(type, name, ts);
460
461 /* if there is not matching, look for a typemap in the
462 original typedef, if any, like in:
463
464 typedef unsigned long size_t;
465 ...
466 %apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size};
467 */
468 if (!sm) {
469 SwigType *ntype = SwigType_typedef_resolve(type);
470 if (ntype && (Cmp(ntype, type) != 0)) {
471 sm = Swig_typemap_get(ntype, name, ts);
472 }
473 Delete(ntype);
474 }
475
476 if (sm) {
477 /* Got a typemap. Need to only merge attributes for methods that match our signature */
478 Iterator ki;
479 match = 1;
480 for (ki = First(sm); ki.key; ki = Next(ki)) {
481 /* Check for a signature match with the source signature */
482 if ((count_args(ki.key) == narg) && (Strstr(ki.key, ssig))) {
483 String *oldm;
484 /* A typemap we have to copy */
485 String *nkey = Copy(ki.key);
486 Replace(nkey, ssig, dsig, DOH_REPLACE_ANY);
487
488 /* Make sure the typemap doesn't already exist in the target map */
489
490 oldm = Getattr(tm, nkey);
491 if (!oldm || (!Getattr(tm, "code"))) {
492 String *code;
493 ParmList *locals;
494 ParmList *kwargs;
495 Hash *sm1 = ki.item;
496
497 code = Getattr(sm1, "code");
498 locals = Getattr(sm1, "locals");
499 kwargs = Getattr(sm1, "kwargs");
500 if (code) {
501 Replace(nkey, dsig, "", DOH_REPLACE_ANY);
502 Replace(nkey, "tmap:", "", DOH_REPLACE_ANY);
503 Swig_typemap_register(nkey, dest, code, locals, kwargs);
504 }
505 }
506 Delete(nkey);
507 }
508 }
509 }
510 ts--;
511 }
512 Delete(ssig);
513 Delete(dsig);
514 return match;
515}
516
517/* -----------------------------------------------------------------------------
518 * Swig_typemap_clear_apply()
519 *
520 * %clear directive. Clears all typemaps for a type (in the current scope only).
521 * ----------------------------------------------------------------------------- */
522
523/* Multi-argument %clear directive */
524void Swig_typemap_clear_apply(Parm *parms) {
525 String *tsig;
526 Parm *p, *np, *lastp;
527 int narg = 0;
528 Hash *tm;
529 String *name;
530
531 /* Create a type signature of the parameters */
532 tsig = NewStringEmpty();
533 p = parms;
534 lastp = 0;
535 while (p) {
536 lastp = p;
537 np = nextSibling(p);
538 if (np) {
539 Printf(tsig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
540 narg++;
541 }
542 p = np;
543 }
544 tm = get_typemap(tm_scope, Getattr(lastp, "type"));
545 if (!tm) {
546 Delete(tsig);
547 return;
548 }
549 name = Getattr(lastp, "name");
550 if (name) {
551 tm = Getattr(tm, name);
552 }
553 if (tm) {
554 /* Clear typemaps that match our signature */
555 Iterator ki, ki2;
556 char *ctsig = Char(tsig);
557 for (ki = First(tm); ki.key; ki = Next(ki)) {
558 char *ckey = Char(ki.key);
559 if (strncmp(ckey, "tmap:", 5) == 0) {
560 int na = count_args(ki.key);
561 if ((na == narg) && strstr(ckey, ctsig)) {
562 Hash *h = ki.item;
563 for (ki2 = First(h); ki2.key; ki2 = Next(ki2)) {
564 Delattr(h, ki2.key);
565 }
566 }
567 }
568 }
569 }
570 Delete(tsig);
571}
572
573/* Internal function to strip array dimensions. */
574static SwigType *strip_arrays(SwigType *type) {
575 SwigType *t;
576 int ndim;
577 int i;
578 t = Copy(type);
579 ndim = SwigType_array_ndim(t);
580 for (i = 0; i < ndim; i++) {
581 SwigType_array_setdim(t, i, "ANY");
582 }
583 return t;
584}
585
586/* -----------------------------------------------------------------------------
587 * Swig_typemap_search()
588 *
589 * Search for a typemap match. Tries to find the most specific typemap
590 * that includes a 'code' attribute.
591 * ----------------------------------------------------------------------------- */
592
593Hash *Swig_typemap_search(const String_or_char *op, SwigType *type, const String_or_char *name, SwigType **matchtype) {
594 Hash *result = 0, *tm, *tm1, *tma;
595 Hash *backup = 0;
596 SwigType *noarrays = 0;
597 SwigType *primitive = 0;
598 SwigType *ctype = 0;
599 int ts;
600 int isarray;
601 const String *cname = 0;
602 SwigType *unstripped = 0;
603 String *tmop = tmop_name(op);
604
605 if ((name) && Len(name))
606 cname = name;
607 ts = tm_scope;
608
609 while (ts >= 0) {
610 ctype = type;
611 while (ctype) {
612 /* Try to get an exact type-match */
613 tm = get_typemap(ts, ctype);
614 if (tm && cname) {
615 tm1 = Getattr(tm, cname);
616 if (tm1) {
617 result = Getattr(tm1, tmop); /* See if there is a type-name match */
618 if (result && Getattr(result, "code"))
619 goto ret_result;
620 if (result)
621 backup = result;
622 }
623 }
624 if (tm) {
625 result = Getattr(tm, tmop); /* See if there is simply a type match */
626 if (result && Getattr(result, "code"))
627 goto ret_result;
628 if (result)
629 backup = result;
630 }
631 isarray = SwigType_isarray(ctype);
632 if (isarray) {
633 /* If working with arrays, strip away all of the dimensions and replace with "ANY".
634 See if that generates a match */
635 if (!noarrays) {
636 noarrays = strip_arrays(ctype);
637 }
638 tma = get_typemap(ts, noarrays);
639 if (tma && cname) {
640 tm1 = Getattr(tma, cname);
641 if (tm1) {
642 result = Getattr(tm1, tmop); /* type-name match */
643 if (result && Getattr(result, "code"))
644 goto ret_result;
645 if (result)
646 backup = result;
647 }
648 }
649 if (tma) {
650 result = Getattr(tma, tmop); /* type match */
651 if (result && Getattr(result, "code"))
652 goto ret_result;
653 if (result)
654 backup = result;
655 }
656 Delete(noarrays);
657 noarrays = 0;
658 }
659
660 /* No match so far. If the type is unstripped, we'll strip its
661 qualifiers and check. Otherwise, we'll try to resolve a typedef */
662
663 if (!unstripped) {
664 unstripped = ctype;
665 ctype = SwigType_strip_qualifiers(ctype);
666 if (!Equal(ctype, unstripped))
667 continue; /* Types are different */
668 Delete(ctype);
669 ctype = unstripped;
670 unstripped = 0;
671 }
672 {
673 String *octype;
674 if (unstripped) {
675 Delete(ctype);
676 ctype = unstripped;
677 unstripped = 0;
678 }
679 octype = ctype;
680 ctype = SwigType_typedef_resolve(ctype);
681 if (octype != type)
682 Delete(octype);
683 }
684 }
685
686 /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */
687
688 primitive = SwigType_default(type);
689 while (primitive) {
690 tm = get_typemap(ts, primitive);
691 if (tm && cname) {
692 tm1 = Getattr(tm, cname);
693 if (tm1) {
694 result = Getattr(tm1, tmop); /* See if there is a type-name match */
695 if (result)
696 goto ret_result;
697 }
698 }
699 if (tm) { /* See if there is simply a type match */
700 result = Getattr(tm, tmop);
701 if (result)
702 goto ret_result;
703 }
704 {
705 SwigType *nprim = SwigType_default(primitive);
706 Delete(primitive);
707 primitive = nprim;
708 }
709 }
710 if (ctype != type) {
711 Delete(ctype);
712 ctype = 0;
713 }
714 ts--; /* Hmmm. Nothing found in this scope. Guess we'll go try another scope */
715 }
716 result = backup;
717
718ret_result:
719 if (noarrays)
720 Delete(noarrays);
721 if (primitive)
722 Delete(primitive);
723 if ((unstripped) && (unstripped != type))
724 Delete(unstripped);
725 if (matchtype) {
726 *matchtype = Copy(ctype);
727 }
728 if (type != ctype)
729 Delete(ctype);
730 return result;
731}
732
733
734/* -----------------------------------------------------------------------------
735 * Swig_typemap_search_multi()
736 *
737 * Search for a multi-valued typemap.
738 * ----------------------------------------------------------------------------- */
739
740Hash *Swig_typemap_search_multi(const String_or_char *op, ParmList *parms, int *nmatch) {
741 SwigType *type;
742 SwigType *mtype = 0;
743 String *name;
744 String *newop;
745 Hash *tm, *tm1;
746
747 if (!parms) {
748 *nmatch = 0;
749 return 0;
750 }
751 type = Getattr(parms, "type");
752 name = Getattr(parms, "name");
753
754 /* Try to find a match on the first type */
755 tm = Swig_typemap_search(op, type, name, &mtype);
756 if (tm) {
757 if (mtype && SwigType_isarray(mtype)) {
758 Setattr(parms, "tmap:match", mtype);
759 }
760 Delete(mtype);
761 newop = NewStringf("%s-%s+%s:", op, type, name);
762 tm1 = Swig_typemap_search_multi(newop, nextSibling(parms), nmatch);
763 if (tm1)
764 tm = tm1;
765 if (Getattr(tm, "code")) {
766 *(nmatch) = *nmatch + 1;
767 } else {
768 tm = 0;
769 }
770 Delete(newop);
771 }
772 return tm;
773}
774
775
776/* -----------------------------------------------------------------------------
777 * typemap_replace_vars()
778 *
779 * Replaces typemap variables on a string. index is the $n variable.
780 * type and pname are the type and parameter name.
781 * ----------------------------------------------------------------------------- */
782
783static
784void replace_local_types(ParmList *p, const String *name, const String *rep) {
785 SwigType *t;
786 while (p) {
787 t = Getattr(p, "type");
788 Replace(t, name, rep, DOH_REPLACE_ANY);
789 p = nextSibling(p);
790 }
791}
792
793static
794int check_locals(ParmList *p, const char *s) {
795 while (p) {
796 char *c = GetChar(p, "type");
797 if (strstr(c, s))
798 return 1;
799 p = nextSibling(p);
800 }
801 return 0;
802}
803
804static
805void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) {
806 char var[512];
807 char *varname;
808 SwigType *ftype;
809
810 Replaceall(s, "$typemap", "$TYPEMAP");
811
812 ftype = SwigType_typedef_resolve_all(type);
813
814 if (!pname)
815 pname = lname;
816 {
817 Parm *p;
818 int rep = 0;
819 p = locals;
820 while (p) {
821 if (Strchr(Getattr(p, "type"), '$'))
822 rep = 1;
823 p = nextSibling(p);
824 }
825 if (!rep)
826 locals = 0;
827 }
828
829 sprintf(var, "$%d_", index);
830 varname = &var[strlen(var)];
831
832 /* If the original datatype was an array. We're going to go through and substitute
833 its array dimensions */
834
835 if (SwigType_isarray(type) || SwigType_isarray(ftype)) {
836 String *size;
837 int ndim;
838 int i;
839 if (SwigType_array_ndim(type) != SwigType_array_ndim(ftype))
840 type = ftype;
841 ndim = SwigType_array_ndim(type);
842 size = NewStringEmpty();
843 for (i = 0; i < ndim; i++) {
844 String *dim = SwigType_array_getdim(type, i);
845 if (index == 1) {
846 char t[32];
847 sprintf(t, "$dim%d", i);
848 Replace(s, t, dim, DOH_REPLACE_ANY);
849 replace_local_types(locals, t, dim);
850 }
851 sprintf(varname, "dim%d", i);
852 Replace(s, var, dim, DOH_REPLACE_ANY);
853 replace_local_types(locals, var, dim);
854 if (Len(size))
855 Putc('*', size);
856 Append(size, dim);
857 Delete(dim);
858 }
859 sprintf(varname, "size");
860 Replace(s, var, size, DOH_REPLACE_ANY);
861 replace_local_types(locals, var, size);
862 Delete(size);
863 }
864
865 /* Parameter name substitution */
866 if (index == 1) {
867 Replace(s, "$parmname", pname, DOH_REPLACE_ANY);
868 }
869 strcpy(varname, "name");
870 Replace(s, var, pname, DOH_REPLACE_ANY);
871
872 /* Type-related stuff */
873 {
874 SwigType *star_type, *amp_type, *base_type, *lex_type;
875 SwigType *ltype, *star_ltype, *amp_ltype;
876 String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name;
877 String *descriptor, *star_descriptor, *amp_descriptor;
878 String *ts;
879 char *sc;
880
881 sc = Char(s);
882
883 if (strstr(sc, "type") || check_locals(locals, "type")) {
884 /* Given type : $type */
885 ts = SwigType_str(type, 0);
886 if (index == 1) {
887 Replace(s, "$type", ts, DOH_REPLACE_ANY);
888 replace_local_types(locals, "$type", type);
889 }
890 strcpy(varname, "type");
891 Replace(s, var, ts, DOH_REPLACE_ANY);
892 replace_local_types(locals, var, type);
893 Delete(ts);
894 sc = Char(s);
895 }
896 if (strstr(sc, "ltype") || check_locals(locals, "ltype")) {
897 /* Local type: $ltype */
898 ltype = SwigType_ltype(type);
899 ts = SwigType_str(ltype, 0);
900 if (index == 1) {
901 Replace(s, "$ltype", ts, DOH_REPLACE_ANY);
902 replace_local_types(locals, "$ltype", ltype);
903 }
904 strcpy(varname, "ltype");
905 Replace(s, var, ts, DOH_REPLACE_ANY);
906 replace_local_types(locals, var, ltype);
907 Delete(ts);
908 Delete(ltype);
909 sc = Char(s);
910 }
911 if (strstr(sc, "mangle") || strstr(sc, "descriptor")) {
912 /* Mangled type */
913
914 mangle = SwigType_manglestr(type);
915 if (index == 1)
916 Replace(s, "$mangle", mangle, DOH_REPLACE_ANY);
917 strcpy(varname, "mangle");
918 Replace(s, var, mangle, DOH_REPLACE_ANY);
919
920 descriptor = NewStringf("SWIGTYPE%s", mangle);
921
922 if (index == 1)
923 if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY))
924 SwigType_remember(type);
925
926 strcpy(varname, "descriptor");
927 if (Replace(s, var, descriptor, DOH_REPLACE_ANY))
928 SwigType_remember(type);
929
930 Delete(descriptor);
931 Delete(mangle);
932 }
933
934 /* One pointer level removed */
935 /* This creates variables of the form
936 $*n_type
937 $*n_ltype
938 */
939
940 if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype))) {
941 if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type))) {
942 star_type = Copy(ftype);
943 } else {
944 star_type = Copy(type);
945 }
946 if (!SwigType_isreference(star_type)) {
947 if (SwigType_isarray(star_type)) {
948 SwigType_del_element(star_type);
949 } else {
950 SwigType_del_pointer(star_type);
951 }
952 ts = SwigType_str(star_type, 0);
953 if (index == 1) {
954 Replace(s, "$*type", ts, DOH_REPLACE_ANY);
955 replace_local_types(locals, "$*type", star_type);
956 }
957 sprintf(varname, "$*%d_type", index);
958 Replace(s, varname, ts, DOH_REPLACE_ANY);
959 replace_local_types(locals, varname, star_type);
960 Delete(ts);
961 } else {
962 SwigType_del_element(star_type);
963 }
964 star_ltype = SwigType_ltype(star_type);
965 ts = SwigType_str(star_ltype, 0);
966 if (index == 1) {
967 Replace(s, "$*ltype", ts, DOH_REPLACE_ANY);
968 replace_local_types(locals, "$*ltype", star_ltype);
969 }
970 sprintf(varname, "$*%d_ltype", index);
971 Replace(s, varname, ts, DOH_REPLACE_ANY);
972 replace_local_types(locals, varname, star_ltype);
973 Delete(ts);
974 Delete(star_ltype);
975
976 star_mangle = SwigType_manglestr(star_type);
977 if (index == 1)
978 Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY);
979
980 sprintf(varname, "$*%d_mangle", index);
981 Replace(s, varname, star_mangle, DOH_REPLACE_ANY);
982
983 star_descriptor = NewStringf("SWIGTYPE%s", star_mangle);
984 if (index == 1)
985 if (Replace(s, "$*descriptor", star_descriptor, DOH_REPLACE_ANY))
986 SwigType_remember(star_type);
987 sprintf(varname, "$*%d_descriptor", index);
988 if (Replace(s, varname, star_descriptor, DOH_REPLACE_ANY))
989 SwigType_remember(star_type);
990
991 Delete(star_descriptor);
992 Delete(star_mangle);
993 Delete(star_type);
994 } else {
995 /* TODO: Signal error if one of the $* substitutions is
996 requested */
997 }
998 /* One pointer level added */
999 amp_type = Copy(type);
1000 SwigType_add_pointer(amp_type);
1001 ts = SwigType_str(amp_type, 0);
1002 if (index == 1) {
1003 Replace(s, "$&type", ts, DOH_REPLACE_ANY);
1004 replace_local_types(locals, "$&type", amp_type);
1005 }
1006 sprintf(varname, "$&%d_type", index);
1007 Replace(s, varname, ts, DOH_REPLACE_ANY);
1008 replace_local_types(locals, varname, amp_type);
1009 Delete(ts);
1010
1011 amp_ltype = SwigType_ltype(type);
1012 SwigType_add_pointer(amp_ltype);
1013 ts = SwigType_str(amp_ltype, 0);
1014
1015 if (index == 1) {
1016 Replace(s, "$<ype", ts, DOH_REPLACE_ANY);
1017 replace_local_types(locals, "$<ype", amp_ltype);
1018 }
1019 sprintf(varname, "$&%d_ltype", index);
1020 Replace(s, varname, ts, DOH_REPLACE_ANY);
1021 replace_local_types(locals, varname, amp_ltype);
1022 Delete(ts);
1023 Delete(amp_ltype);
1024
1025 amp_mangle = SwigType_manglestr(amp_type);
1026 if (index == 1)
1027 Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY);
1028 sprintf(varname, "$&%d_mangle", index);
1029 Replace(s, varname, amp_mangle, DOH_REPLACE_ANY);
1030
1031 amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle);
1032 if (index == 1)
1033 if (Replace(s, "$&descriptor", amp_descriptor, DOH_REPLACE_ANY))
1034 SwigType_remember(amp_type);
1035 sprintf(varname, "$&%d_descriptor", index);
1036 if (Replace(s, varname, amp_descriptor, DOH_REPLACE_ANY))
1037 SwigType_remember(amp_type);
1038
1039 Delete(amp_descriptor);
1040 Delete(amp_mangle);
1041 Delete(amp_type);
1042
1043 /* Base type */
1044 if (SwigType_isarray(type)) {
1045 SwigType *bt = Copy(type);
1046 Delete(SwigType_pop_arrays(bt));
1047 base_type = SwigType_str(bt, 0);
1048 Delete(bt);
1049 } else {
1050 base_type = SwigType_base(type);
1051 }
1052
1053 base_name = SwigType_namestr(base_type);
1054 if (index == 1) {
1055 Replace(s, "$basetype", base_name, DOH_REPLACE_ANY);
1056 replace_local_types(locals, "$basetype", base_name);
1057 }
1058 strcpy(varname, "basetype");
1059 Replace(s, var, base_type, DOH_REPLACE_ANY);
1060 replace_local_types(locals, var, base_name);
1061
1062 base_mangle = SwigType_manglestr(base_type);
1063 if (index == 1)
1064 Replace(s, "$basemangle", base_mangle, DOH_REPLACE_ANY);
1065 strcpy(varname, "basemangle");
1066 Replace(s, var, base_mangle, DOH_REPLACE_ANY);
1067 Delete(base_mangle);
1068 Delete(base_type);
1069 Delete(base_name);
1070
1071 lex_type = SwigType_base(rtype);
1072 if (index == 1)
1073 Replace(s, "$lextype", lex_type, DOH_REPLACE_ANY);
1074 strcpy(varname, "lextype");
1075 Replace(s, var, lex_type, DOH_REPLACE_ANY);
1076 Delete(lex_type);
1077 }
1078
1079 /* Replace any $n. with (&n)-> */
1080 {
1081 char temp[64];
1082 sprintf(var, "$%d.", index);
1083 sprintf(temp, "(&$%d)->", index);
1084 Replace(s, var, temp, DOH_REPLACE_ANY);
1085 }
1086
1087 /* Replace the bare $n variable */
1088 sprintf(var, "$%d", index);
1089 Replace(s, var, lname, DOH_REPLACE_ANY);
1090 Delete(ftype);
1091}
1092
1093/* ------------------------------------------------------------------------
1094 * static typemap_locals()
1095 *
1096 * Takes a string, a parameter list and a wrapper function argument and
1097 * creates the local variables.
1098 * ------------------------------------------------------------------------ */
1099
1100static void typemap_locals(DOHString * s, ParmList *l, Wrapper *f, int argnum) {
1101 Parm *p;
1102 char *new_name;
1103
1104 p = l;
1105 while (p) {
1106 SwigType *pt = Getattr(p, "type");
1107 SwigType *at = SwigType_alttype(pt, 1);
1108 String *pn = Getattr(p, "name");
1109 String *value = Getattr(p, "value");
1110 if (at)
1111 pt = at;
1112 if (pn) {
1113 if (Len(pn) > 0) {
1114 String *str;
1115 int isglobal = 0;
1116
1117 str = NewStringEmpty();
1118
1119 if (strncmp(Char(pn), "_global_", 8) == 0) {
1120 isglobal = 1;
1121 }
1122
1123 /* If the user gave us $type as the name of the local variable, we'll use
1124 the passed datatype instead */
1125
1126 if ((argnum >= 0) && (!isglobal)) {
1127 Printf(str, "%s%d", pn, argnum);
1128 } else {
1129 Append(str, pn);
1130 }
1131 if (isglobal && Wrapper_check_local(f, str)) {
1132 p = nextSibling(p);
1133 Delete(str);
1134 if (at)
1135 Delete(at);
1136 continue;
1137 }
1138 if (value) {
1139 String *pstr = SwigType_str(pt, str);
1140 new_name = Wrapper_new_localv(f, str, pstr, "=", value, NIL);
1141 Delete(pstr);
1142 } else {
1143 String *pstr = SwigType_str(pt, str);
1144 new_name = Wrapper_new_localv(f, str, pstr, NIL);
1145 Delete(pstr);
1146 }
1147 if (!isglobal) {
1148 /* Substitute */
1149 Replace(s, pn, new_name, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
1150 }
1151 Delete(str);
1152 }
1153 }
1154 p = nextSibling(p);
1155 if (at)
1156 Delete(at);
1157 }
1158}
1159
1160/* -----------------------------------------------------------------------------
1161 * Swig_typemap_lookup()
1162 *
1163 * Perform a typemap lookup (ala SWIG1.1)
1164 * ----------------------------------------------------------------------------- */
1165
1166String *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname,
1167 String_or_char *lname, String_or_char *source, String_or_char *target, Wrapper *f) {
1168 Hash *tm;
1169 String *s = 0;
1170 SwigType *mtype = 0;
1171 ParmList *locals;
1172 tm = Swig_typemap_search(op, type, pname, &mtype);
1173 if (!tm)
1174 return 0;
1175
1176 s = Getattr(tm, "code");
1177 if (!s) {
1178 if (mtype)
1179 Delete(mtype);
1180 return 0;
1181 }
1182
1183
1184 /* Blocked */
1185 if (Cmp(s, "pass") == 0) {
1186 Delete(mtype);
1187 return 0;
1188 }
1189
1190 s = Copy(s); /* Make a local copy of the typemap code */
1191
1192 locals = Getattr(tm, "locals");
1193 if (locals)
1194 locals = CopyParmList(locals);
1195
1196 /* This is wrong. It replaces locals in place. Need to fix this */
1197 if (mtype && SwigType_isarray(mtype)) {
1198 typemap_replace_vars(s, locals, mtype, type, pname, lname, 1);
1199 } else {
1200 typemap_replace_vars(s, locals, type, type, pname, lname, 1);
1201 }
1202
1203 if (locals && f) {
1204 typemap_locals(s, locals, f, -1);
1205 }
1206
1207 replace_embedded_typemap(s);
1208
1209 /* Now perform character replacements */
1210 Replace(s, "$source", source, DOH_REPLACE_ANY);
1211 Replace(s, "$target", target, DOH_REPLACE_ANY);
1212
1213 /* {
1214 String *tmname = Getattr(tm,"typemap");
1215 if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY);
1216 }
1217 */
1218
1219 Replace(s, "$parmname", pname, DOH_REPLACE_ANY);
1220 /* Replace(s,"$name",pname,DOH_REPLACE_ANY); */
1221
1222 Delete(locals);
1223 Delete(mtype);
1224 return s;
1225}
1226
1227/* -----------------------------------------------------------------------------
1228 * Swig_typemap_lookup_new()
1229 *
1230 * Attach one or more typemaps to a node
1231 * op - typemap name, eg "out", "newfree"
1232 * node - the node to attach the typemaps to
1233 * lname -
1234 * f -
1235 * ----------------------------------------------------------------------------- */
1236
1237String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f) {
1238 SwigType *type;
1239 SwigType *mtype = 0;
1240 String *pname;
1241 Hash *tm = 0;
1242 String *s = 0;
1243 String *sdef = 0;
1244 ParmList *locals;
1245 ParmList *kw;
1246 char temp[256];
1247 String *symname;
1248 String *cname = 0;
1249 String *clname = 0;
1250 char *cop = Char(op);
1251 /* special case, we need to check for 'ref' call
1252 and set the default code 'sdef' */
1253 if (node && Cmp(op, "newfree") == 0) {
1254 sdef = Swig_ref_call(node, lname);
1255 }
1256
1257 type = Getattr(node, "type");
1258 if (!type)
1259 return sdef;
1260
1261 pname = Getattr(node, "name");
1262
1263#if 1
1264 if (pname && node && checkAttribute(node, "kind", "function")) {
1265 /*
1266 For functions, look qualified names first, such as
1267
1268 struct Foo {
1269 int *foo(int bar) -> Foo::foo
1270 };
1271 */
1272 Symtab *st = Getattr(node, "sym:symtab");
1273 String *qsn = st ? Swig_symbol_string_qualify(pname, st) : 0;
1274 if (qsn) {
1275 if (Len(qsn) && !Equal(qsn, pname)) {
1276 tm = Swig_typemap_search(op, type, qsn, &mtype);
1277 if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) {
1278 tm = 0;
1279 }
1280 }
1281 Delete(qsn);
1282 }
1283 }
1284 if (!tm)
1285#endif
1286 tm = Swig_typemap_search(op, type, pname, &mtype);
1287 if (!tm)
1288 return sdef;
1289
1290 s = Getattr(tm, "code");
1291 if (!s)
1292 return sdef;
1293
1294 /* Empty typemap. No match */
1295 if (Cmp(s, "pass") == 0)
1296 return sdef;
1297
1298 s = Copy(s); /* Make a local copy of the typemap code */
1299
1300 locals = Getattr(tm, "locals");
1301 if (locals)
1302 locals = CopyParmList(locals);
1303
1304 if (pname) {
1305 if (SwigType_istemplate(pname)) {
1306 cname = SwigType_namestr(pname);
1307 pname = cname;
1308 }
1309 }
1310 if (SwigType_istemplate((char *) lname)) {
1311 clname = SwigType_namestr((char *) lname);
1312 lname = clname;
1313 }
1314
1315 if (mtype && SwigType_isarray(mtype)) {
1316 typemap_replace_vars(s, locals, mtype, type, pname, (char *) lname, 1);
1317 } else {
1318 typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1);
1319 }
1320
1321 if (locals && f) {
1322 typemap_locals(s, locals, f, -1);
1323 }
1324 replace_embedded_typemap(s);
1325 /* {
1326 String *tmname = Getattr(tm,"typemap");
1327 if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY);
1328 } */
1329
1330 Replace(s, "$name", pname, DOH_REPLACE_ANY);
1331
1332 symname = Getattr(node, "sym:name");
1333 if (symname) {
1334 Replace(s, "$symname", symname, DOH_REPLACE_ANY);
1335 }
1336
1337 Setattr(node, tmop_name(op), s);
1338 if (locals) {
1339 sprintf(temp, "%s:locals", cop);
1340 Setattr(node, tmop_name(temp), locals);
1341 Delete(locals);
1342 }
1343
1344 if (Checkattr(tm, "type", "SWIGTYPE")) {
1345 sprintf(temp, "%s:SWIGTYPE", cop);
1346 Setattr(node, tmop_name(temp), "1");
1347 }
1348
1349 /* Attach kwargs */
1350 kw = Getattr(tm, "kwargs");
1351 while (kw) {
1352 String *value = Copy(Getattr(kw, "value"));
1353 String *type = Getattr(kw, "type");
1354 char *ckwname = Char(Getattr(kw, "name"));
1355 if (type) {
1356 String *mangle = Swig_string_mangle(type);
1357 Append(value, mangle);
1358 Delete(mangle);
1359 }
1360 sprintf(temp, "%s:%s", cop, ckwname);
1361 Setattr(node, tmop_name(temp), value);
1362 Delete(value);
1363 kw = nextSibling(kw);
1364 }
1365
1366 /* Look for warnings */
1367 {
1368 String *w;
1369 sprintf(temp, "%s:warning", cop);
1370 w = Getattr(node, tmop_name(temp));
1371 if (w) {
1372 Swig_warning(0, Getfile(node), Getline(node), "%s\n", w);
1373 }
1374 }
1375
1376 /* Look for code fragments */
1377 {
1378 String *f;
1379 sprintf(temp, "%s:fragment", cop);
1380 f = Getattr(node, tmop_name(temp));
1381 if (f) {
1382 String *fname = Copy(f);
1383 Setfile(fname, Getfile(node));
1384 Setline(fname, Getline(node));
1385 Swig_fragment_emit(fname);
1386 Delete(fname);
1387 }
1388 }
1389
1390 if (cname)
1391 Delete(cname);
1392 if (clname)
1393 Delete(clname);
1394 if (mtype)
1395 Delete(mtype);
1396 if (sdef) { /* put 'ref' and 'newfree' codes together */
1397 String *p = NewStringf("%s\n%s", sdef, s);
1398 Delete(s);
1399 Delete(sdef);
1400 s = p;
1401 }
1402 return s;
1403}
1404
1405/* -----------------------------------------------------------------------------
1406 * Swig_typemap_attach_kwargs()
1407 *
1408 * If this hash (tm) contains a linked list of parameters under its "kwargs"
1409 * attribute, add keys for each of those named keyword arguments to this
1410 * parameter for later use.
1411 * For example, attach the typemap attributes to p:
1412 * %typemap(in, foo="xyz") ...
1413 * A new attribute called "tmap:in:foo" with value "xyz" is attached to p.
1414 * ----------------------------------------------------------------------------- */
1415
1416void Swig_typemap_attach_kwargs(Hash *tm, const String_or_char *op, Parm *p) {
1417 String *temp = NewStringEmpty();
1418 Parm *kw = Getattr(tm, "kwargs");
1419 while (kw) {
1420 String *value = Copy(Getattr(kw, "value"));
1421 String *type = Getattr(kw, "type");
1422 if (type) {
1423 Hash *v = NewHash();
1424 Setattr(v, "type", type);
1425 Setattr(v, "value", value);
1426 Delete(value);
1427 value = v;
1428 }
1429 Clear(temp);
1430 Printf(temp, "%s:%s", op, Getattr(kw, "name"));
1431 Setattr(p, tmop_name(temp), value);
1432 Delete(value);
1433 kw = nextSibling(kw);
1434 }
1435 Clear(temp);
1436 Printf(temp, "%s:match_type", op);
1437 Setattr(p, tmop_name(temp), Getattr(tm, "type"));
1438 Delete(temp);
1439}
1440
1441/* -----------------------------------------------------------------------------
1442 * Swig_typemap_warn()
1443 *
1444 * If any warning message is attached to this parameter's "tmap:op:warning"
1445 * attribute, print that warning message.
1446 * ----------------------------------------------------------------------------- */
1447
1448static void Swig_typemap_warn(const String_or_char *op, Parm *p) {
1449 String *temp = NewStringf("%s:warning", op);
1450 String *w = Getattr(p, tmop_name(temp));
1451 Delete(temp);
1452 if (w) {
1453 Swig_warning(0, Getfile(p), Getline(p), "%s\n", w);
1454 }
1455}
1456
1457static void Swig_typemap_emit_code_fragments(const String_or_char *op, Parm *p) {
1458 String *temp = NewStringf("%s:fragment", op);
1459 String *f = Getattr(p, tmop_name(temp));
1460 if (f) {
1461 String *fname = Copy(f);
1462 Setfile(fname, Getfile(p));
1463 Setline(fname, Getline(p));
1464 Swig_fragment_emit(fname);
1465 Delete(fname);
1466 }
1467 Delete(temp);
1468}
1469
1470/* -----------------------------------------------------------------------------
1471 * Swig_typemap_attach_parms()
1472 *
1473 * Given a parameter list, this function attaches all of the typemaps for a
1474 * given typemap type
1475 * ----------------------------------------------------------------------------- */
1476
1477String *Swig_typemap_get_option(Hash *tm, String *name) {
1478 Parm *kw = Getattr(tm, "kwargs");
1479 while (kw) {
1480 String *kname = Getattr(kw, "name");
1481 if (Equal(kname, name)) {
1482 return Getattr(kw, "value");
1483 }
1484 kw = nextSibling(kw);
1485 }
1486 return 0;
1487}
1488
1489void Swig_typemap_attach_parms(const String_or_char *op, ParmList *parms, Wrapper *f) {
1490 Parm *p, *firstp;
1491 Hash *tm;
1492 int nmatch = 0;
1493 int i;
1494 String *s;
1495 ParmList *locals;
1496 int argnum = 0;
1497 char temp[256];
1498 char *cop = Char(op);
1499 String *kwmatch = 0;
1500 p = parms;
1501
1502#ifdef SWIG_DEBUG
1503 Printf(stdout, "Swig_typemap_attach_parms: %s\n", op);
1504#endif
1505
1506 while (p) {
1507 argnum++;
1508 nmatch = 0;
1509#ifdef SWIG_DEBUG
1510 Printf(stdout, "parms: %s %s %s\n", op, Getattr(p, "name"), Getattr(p, "type"));
1511#endif
1512 tm = Swig_typemap_search_multi(op, p, &nmatch);
1513#ifdef SWIG_DEBUG
1514 if (tm)
1515 Printf(stdout, "found: %s\n", tm);
1516#endif
1517 if (!tm) {
1518 p = nextSibling(p);
1519 continue;
1520 }
1521 /*
1522 Check if the typemap requires to match the type of another
1523 typemap, for example:
1524
1525 %typemap(in) SWIGTYPE * (int var) {...}
1526 %typemap(freearg,match="in") SWIGTYPE * {if (var$argnum) ...}
1527
1528 here, the freearg typemap requires the "in" typemap to match,
1529 or the 'var$argnum' variable will not exist.
1530 */
1531 kwmatch = Swig_typemap_get_option(tm, "match");
1532 if (kwmatch) {
1533 String *tmname = NewStringf("tmap:%s", kwmatch);
1534 String *tmin = Getattr(p, tmname);
1535 Delete(tmname);
1536#ifdef SWIG_DEBUG
1537 if (tm)
1538 Printf(stdout, "matching: %s\n", kwmatch);
1539#endif
1540 if (tmin) {
1541 String *tmninp = NewStringf("tmap:%s:numinputs", kwmatch);
1542 String *ninp = Getattr(p, tmninp);
1543 Delete(tmninp);
1544 if (ninp && Equal(ninp, "0")) {
1545 p = nextSibling(p);
1546 continue;
1547 } else {
1548 SwigType *typetm = Getattr(tm, "type");
1549 String *temp = NewStringf("tmap:%s:match_type", kwmatch);
1550 SwigType *typein = Getattr(p, temp);
1551 Delete(temp);
1552 if (!Equal(typein, typetm)) {
1553 p = nextSibling(p);
1554 continue;
1555 } else {
1556 int nnmatch;
1557 Hash *tmapin = Swig_typemap_search_multi(kwmatch, p, &nnmatch);
1558 String *tmname = Getattr(tm, "pname");
1559 String *tnname = Getattr(tmapin, "pname");
1560 if (!(tmname && tnname && Equal(tmname, tnname)) && !(!tmname && !tnname)) {
1561 p = nextSibling(p);
1562 continue;
1563 }
1564 }
1565
1566 }
1567 } else {
1568 p = nextSibling(p);
1569 continue;
1570 }
1571 }
1572
1573 s = Getattr(tm, "code");
1574 if (!s) {
1575 p = nextSibling(p);
1576 continue;
1577 }
1578#ifdef SWIG_DEBUG
1579 if (s)
1580 Printf(stdout, "code: %s\n", s);
1581#endif
1582
1583 /* Empty typemap. No match */
1584 if (Cmp(s, "pass") == 0) {
1585 p = nextSibling(p);
1586 continue;
1587 }
1588
1589 s = Copy(s);
1590 locals = Getattr(tm, "locals");
1591 if (locals)
1592 locals = CopyParmList(locals);
1593 firstp = p;
1594#ifdef SWIG_DEBUG
1595 Printf(stdout, "nmatch: %d\n", nmatch);
1596#endif
1597 for (i = 0; i < nmatch; i++) {
1598 SwigType *type;
1599 String *pname;
1600 String *lname;
1601 SwigType *mtype;
1602
1603
1604 type = Getattr(p, "type");
1605 pname = Getattr(p, "name");
1606 lname = Getattr(p, "lname");
1607 mtype = Getattr(p, "tmap:match");
1608
1609 if (mtype) {
1610 typemap_replace_vars(s, locals, mtype, type, pname, lname, i + 1);
1611 Delattr(p, "tmap:match");
1612 } else {
1613 typemap_replace_vars(s, locals, type, type, pname, lname, i + 1);
1614 }
1615
1616 if (Checkattr(tm, "type", "SWIGTYPE")) {
1617 sprintf(temp, "%s:SWIGTYPE", cop);
1618 Setattr(p, tmop_name(temp), "1");
1619 }
1620 p = nextSibling(p);
1621 }
1622
1623 if (locals && f) {
1624 typemap_locals(s, locals, f, argnum);
1625 }
1626
1627 replace_embedded_typemap(s);
1628
1629 /* Replace the argument number */
1630 sprintf(temp, "%d", argnum);
1631 Replace(s, "$argnum", temp, DOH_REPLACE_ANY);
1632
1633 /* Attach attributes to object */
1634#ifdef SWIG_DEBUG
1635 Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), s);
1636#endif
1637 Setattr(firstp, tmop_name(op), s); /* Code object */
1638
1639 if (locals) {
1640 sprintf(temp, "%s:locals", cop);
1641 Setattr(firstp, tmop_name(temp), locals);
1642 Delete(locals);
1643 }
1644
1645 /* Attach a link to the next parameter. Needed for multimaps */
1646 sprintf(temp, "%s:next", cop);
1647 Setattr(firstp, tmop_name(temp), p);
1648
1649 /* Attach kwargs */
1650 Swig_typemap_attach_kwargs(tm, op, firstp);
1651
1652 /* Print warnings, if any */
1653 Swig_typemap_warn(op, firstp);
1654
1655 /* Look for code fragments */
1656 Swig_typemap_emit_code_fragments(op, firstp);
1657
1658 /* increase argnum to consider numinputs */
1659 argnum += nmatch - 1;
1660 Delete(s);
1661#ifdef SWIG_DEBUG
1662 Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), Getattr(firstp, tmop_name(op)));
1663#endif
1664
1665 }
1666#ifdef SWIG_DEBUG
1667 Printf(stdout, "Swig_typemap_attach_parms: end\n");
1668#endif
1669
1670}
1671
1672/* -----------------------------------------------------------------------------
1673 * split_embedded()
1674 *
1675 * This function replaces the special variable $typemap(....) with typemap
1676 * code. The general form of $typemap is as follows:
1677 *
1678 * $TYPEMAP(method, $var1=value, $var2=value, $var3=value,...)
1679 *
1680 * For example:
1681 *
1682 * $TYPEMAP(in, $1=int x, $input=y, ...)
1683 *
1684 * Note: this was added as an experiment and could be removed
1685 * ----------------------------------------------------------------------------- */
1686
1687/* Splits the arguments of an embedded typemap */
1688static List *split_embedded(String *s) {
1689 List *args = 0;
1690 char *c, *start;
1691 int level = 0;
1692 int leading = 1;
1693 args = NewList();
1694
1695 c = strchr(Char(s), '(');
1696 c++;
1697
1698 start = c;
1699 while (*c) {
1700 if (*c == '\"') {
1701 c++;
1702 while (*c) {
1703 if (*c == '\\') {
1704 c++;
1705 } else {
1706 if (*c == '\"')
1707 break;
1708 }
1709 c++;
1710 }
1711 }
1712 if ((level == 0) && ((*c == ',') || (*c == ')'))) {
1713 String *tmp = NewStringWithSize(start, c - start);
1714 Append(args, tmp);
1715 Delete(tmp);
1716 start = c + 1;
1717 leading = 1;
1718 if (*c == ')')
1719 break;
1720 c++;
1721 continue;
1722 }
1723 if (*c == '(')
1724 level++;
1725 if (*c == ')')
1726 level--;
1727 if (isspace((int) *c) && leading)
1728 start++;
1729 if (!isspace((int) *c))
1730 leading = 0;
1731 c++;
1732 }
1733 return args;
1734}
1735
1736static void split_var(String *s, String **name, String **value) {
1737 char *eq;
1738 char *c;
1739
1740 eq = strchr(Char(s), '=');
1741 if (!eq) {
1742 *name = 0;
1743 *value = 0;
1744 return;
1745 }
1746 c = Char(s);
1747 *name = NewStringWithSize(c, eq - c);
1748
1749 /* Look for $n variables */
1750 if (isdigit((int) *(c))) {
1751 /* Parse the value as a type */
1752 String *v;
1753 Parm *p;
1754 v = NewString(eq + 1);
1755 p = Swig_cparse_parm(v);
1756 Delete(v);
1757 *value = p;
1758 } else {
1759 *value = NewString(eq + 1);
1760 }
1761}
1762
1763static void replace_embedded_typemap(String *s) {
1764 char *start = 0;
1765 while ((start = strstr(Char(s), "$TYPEMAP("))) {
1766
1767 /* Gather the argument */
1768 char *end = 0, *c;
1769 int level = 0;
1770 String *tmp;
1771 c = start;
1772 while (*c) {
1773 if (*c == '(')
1774 level++;
1775 if (*c == ')') {
1776 level--;
1777 if (level == 0) {
1778 end = c + 1;
1779 break;
1780 }
1781 }
1782 c++;
1783 }
1784 if (end) {
1785 tmp = NewStringWithSize(start, (end - start));
1786 } else {
1787 tmp = 0;
1788 }
1789
1790 /* Got a substitution. Split it apart into pieces */
1791 if (tmp) {
1792 List *l;
1793 Hash *vars;
1794 String *method;
1795 int i, ilen;
1796
1797 l = split_embedded(tmp);
1798 vars = NewHash();
1799 ilen = Len(l);
1800 for (i = 1; i < ilen; i++) {
1801 String *n, *v;
1802 split_var(Getitem(l, i), &n, &v);
1803 if (n && v) {
1804 Insert(n, 0, "$");
1805 Setattr(vars, n, v);
1806 }
1807 Delete(n);
1808 Delete(v);
1809 }
1810
1811 method = Getitem(l, 0);
1812 /* Generate the parameter list for matching typemaps */
1813
1814 {
1815 Parm *p = 0;
1816 Parm *first = 0;
1817 char temp[32];
1818 int n = 1;
1819 while (1) {
1820 Hash *v;
1821 sprintf(temp, "$%d", n);
1822 v = Getattr(vars, temp);
1823 if (v) {
1824 if (p) {
1825 set_nextSibling(p, v);
1826 set_previousSibling(v, p);
1827 }
1828 p = v;
1829 Setattr(p, "lname", Getattr(p, "name"));
1830 if (Getattr(p, "value")) {
1831 Setattr(p, "name", Getattr(p, "value"));
1832 }
1833 if (!first)
1834 first = p;
1835 DohIncref(p);
1836 Delattr(vars, temp);
1837 } else {
1838 break;
1839 }
1840 n++;
1841 }
1842 /* Perform a typemap search */
1843 if (first) {
1844#ifdef SWIG_DEBUG
1845 Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
1846#endif
1847 Swig_typemap_attach_parms(method, first, 0);
1848 {
1849 String *tm;
1850 int match = 0;
1851 char attr[64];
1852 sprintf(attr, "tmap:%s", Char(method));
1853
1854 /* Look for the typemap code */
1855 tm = Getattr(first, attr);
1856 if (tm) {
1857 sprintf(attr, "tmap:%s:next", Char(method));
1858 if (!Getattr(first, attr)) {
1859 /* Should be no more matches. Hack??? */
1860 /* Replace all of the remaining variables */
1861 Iterator ki;
1862 for (ki = First(vars); ki.key; ki = Next(ki)) {
1863 Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY);
1864 }
1865 /* Do the replacement */
1866 Replace(s, tmp, tm, DOH_REPLACE_ANY);
1867 Delete(tm);
1868 match = 1;
1869 }
1870 }
1871 if (!match) {
1872 Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", tmp);
1873 }
1874 }
1875 }
1876 }
1877 Replace(s, tmp, "<embedded typemap>", DOH_REPLACE_ANY);
1878 Delete(vars);
1879 Delete(tmp);
1880 Delete(l);
1881 }
1882 }
1883}
1884
1885/* -----------------------------------------------------------------------------
1886 * Swig_typemap_debug()
1887 * ----------------------------------------------------------------------------- */
1888
1889void Swig_typemap_debug() {
1890 int ts;
1891 Printf(stdout, "---[ typemaps ]--------------------------------------------------------------\n");
1892
1893 ts = tm_scope;
1894 while (ts >= 0) {
1895 Printf(stdout, "::: scope %d\n\n", ts);
1896 Printf(stdout, "%s\n", typemaps[ts]);
1897 ts--;
1898 }
1899 Printf(stdout, "-----------------------------------------------------------------------------\n");
1900}