PageRenderTime 28ms CodeModel.GetById 16ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/Source/Swig/fragment.c

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