import source from 1.3.40
[external/swig.git] / Source / Swig / fragment.c
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  * fragment.c
6  *
7  * This file manages named code fragments.  Code fragments are typically
8  * used to hold helper-code that may or may not be included in the wrapper
9  * file (depending on what features are actually used in the interface).
10  *
11  * By using fragments, it's possible to greatly reduce the amount of
12  * wrapper code and to generate cleaner wrapper files. 
13  * ----------------------------------------------------------------------------- */
14
15 char cvsroot_fragment_c[] = "$Id: fragment.c 9632 2007-01-03 20:58:19Z beazley $";
16
17 #include "swig.h"
18 #include "swigwarn.h"
19
20 static Hash *fragments = 0;
21 static Hash *looking_fragments = 0;
22 static int debug = 0;
23
24
25 /* -----------------------------------------------------------------------------
26  * Swig_fragment_register()
27  *
28  * Add a fragment. Use the original Node*, so, if something needs to be
29  * changed, lang.cxx doesn't nedd to be touched again.
30  * ----------------------------------------------------------------------------- */
31
32 void Swig_fragment_register(Node *fragment) {
33   if (Getattr(fragment, "emitonly")) {
34     Swig_fragment_emit(fragment);
35     return;
36   } else {
37     String *name = Copy(Getattr(fragment, "value"));
38     String *type = Getattr(fragment, "type");
39     if (type) {
40       SwigType *rtype = SwigType_typedef_resolve_all(type);
41       String *mangle = Swig_string_mangle(type);
42       Append(name, mangle);
43       Delete(mangle);
44       Delete(rtype);
45       if (debug)
46         Printf(stdout, "register fragment %s %s\n", name, type);
47     }
48     if (!fragments) {
49       fragments = NewHash();
50     }
51     if (!Getattr(fragments, name)) {
52       String *section = Copy(Getattr(fragment, "section"));
53       String *ccode = Copy(Getattr(fragment, "code"));
54       Hash *kwargs = Getattr(fragment, "kwargs");
55       Setmeta(ccode, "section", section);
56       if (kwargs) {
57         Setmeta(ccode, "kwargs", kwargs);
58       }
59       Setattr(fragments, name, ccode);
60       if (debug)
61         Printf(stdout, "registering fragment %s %s\n", name, section);
62       Delete(section);
63       Delete(ccode);
64     }
65     Delete(name);
66   }
67 }
68
69 /* -----------------------------------------------------------------------------
70  * Swig_fragment_emit()
71  *
72  * Emit a fragment
73  * ----------------------------------------------------------------------------- */
74
75 static
76 char *char_index(char *str, char c) {
77   while (*str && (c != *str))
78     ++str;
79   return (c == *str) ? str : 0;
80 }
81
82 void Swig_fragment_emit(Node *n) {
83   String *code;
84   char *pc, *tok;
85   String *t;
86   String *mangle = 0;
87   String *name = 0;
88   String *type = 0;
89
90   if (!fragments) {
91     Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name);
92     return;
93   }
94
95
96   name = Getattr(n, "value");
97   if (!name) {
98     name = n;
99   }
100   type = Getattr(n, "type");
101   if (type) {
102     mangle = Swig_string_mangle(type);
103   }
104
105   if (debug)
106     Printf(stdout, "looking fragment %s %s\n", name, type);
107   t = Copy(name);
108   tok = Char(t);
109   pc = char_index(tok, ',');
110   if (pc)
111     *pc = 0;
112   while (tok) {
113     String *name = NewString(tok);
114     if (mangle)
115       Append(name, mangle);
116     if (looking_fragments && Getattr(looking_fragments, name)) {
117       return;
118     }
119     code = Getattr(fragments, name);
120     if (debug)
121       Printf(stdout, "looking subfragment %s\n", name);
122     if (code && (Strcmp(code, "ignore") != 0)) {
123       String *section = Getmeta(code, "section");
124       Hash *nn = Getmeta(code, "kwargs");
125       if (!looking_fragments)
126         looking_fragments = NewHash();
127       Setattr(looking_fragments, name, "1");
128       while (nn) {
129         if (Equal(Getattr(nn, "name"), "fragment")) {
130           if (debug)
131             Printf(stdout, "emitting fragment %s %s\n", nn, type);
132           Setfile(nn, Getfile(n));
133           Setline(nn, Getline(n));
134           Swig_fragment_emit(nn);
135         }
136         nn = nextSibling(nn);
137       }
138       if (section) {
139         File *f = Swig_filebyname(section);
140         if (!f) {
141           Swig_error(Getfile(code), Getline(code), "Bad section '%s' for code fragment '%s'\n", section, name);
142         } else {
143           if (debug)
144             Printf(stdout, "emitting subfragment %s %s\n", name, section);
145           if (debug)
146             Printf(f, "/* begin fragment %s */\n", name);
147           Printf(f, "%s\n", code);
148           if (debug)
149             Printf(f, "/* end fragment %s */\n\n", name);
150           Setattr(fragments, name, "ignore");
151           Delattr(looking_fragments, name);
152         }
153       }
154     } else if (!code && type) {
155       SwigType *rtype = SwigType_typedef_resolve_all(type);
156       if (!Equal(type, rtype)) {
157         String *name = Copy(Getattr(n, "value"));
158         String *mangle = Swig_string_mangle(type);
159         Append(name, mangle);
160         Setfile(name, Getfile(n));
161         Setline(name, Getline(n));
162         Swig_fragment_emit(name);
163         Delete(mangle);
164         Delete(name);
165       }
166       Delete(rtype);
167     }
168
169     if (!code) {
170       Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name);
171     }
172     tok = pc ? pc + 1 : 0;
173     if (tok) {
174       pc = char_index(tok, ',');
175       if (pc)
176         *pc = 0;
177     }
178     Delete(name);
179   }
180   Delete(t);
181 }