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 15char cvsroot_fragment_c[] = "$Id: fragment.c 9632 2007-01-03 20:58:19Z beazley $"; 16 17#include "swig.h" 18#include "swigwarn.h" 19 20static Hash *fragments = 0; 21static Hash *looking_fragments = 0; 22static 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 32void 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 75static 76char *char_index(char *str, char c) { 77 while (*str && (c != *str)) 78 ++str; 79 return (c == *str) ? str : 0; 80} 81 82void 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} 182