PageRenderTime 86ms CodeModel.GetById 55ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Source/Swig/wrapfunc.c

#
C | 522 lines | 407 code | 38 blank | 77 comment | 194 complexity | f6fe51a560dd762dc0515990589f2711 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 * wrapfunc.c
 10 *
 11 * This file defines a object for creating wrapper functions.  Primarily
 12 * this is used for convenience since it allows pieces of a wrapper function
 13 * to be created in a piecemeal manner.
 14 * ----------------------------------------------------------------------------- */
 15
 16char cvsroot_wrapfunc_c[] = "$Id: wrapfunc.c 11876 2010-02-27 23:53:33Z wsfulton $";
 17
 18#include "swig.h"
 19#include <ctype.h>
 20
 21static int Compact_mode = 0;	/* set to 0 on default */
 22static int Max_line_size = 128;
 23
 24/* -----------------------------------------------------------------------------
 25 * NewWrapper()
 26 *
 27 * Create a new wrapper function object.
 28 * ----------------------------------------------------------------------------- */
 29
 30Wrapper *NewWrapper(void) {
 31  Wrapper *w;
 32  w = (Wrapper *) malloc(sizeof(Wrapper));
 33  w->localh = NewHash();
 34  w->locals = NewStringEmpty();
 35  w->code = NewStringEmpty();
 36  w->def = NewStringEmpty();
 37  return w;
 38}
 39
 40/* -----------------------------------------------------------------------------
 41 * DelWrapper()
 42 *
 43 * Delete a wrapper function object.
 44 * ----------------------------------------------------------------------------- */
 45
 46void DelWrapper(Wrapper *w) {
 47  Delete(w->localh);
 48  Delete(w->locals);
 49  Delete(w->code);
 50  Delete(w->def);
 51  free(w);
 52}
 53
 54/* -----------------------------------------------------------------------------
 55 * Wrapper_compact_print_mode_set()
 56 *
 57 * Set compact_mode.
 58 * ----------------------------------------------------------------------------- */
 59
 60void Wrapper_compact_print_mode_set(int flag) {
 61  Compact_mode = flag;
 62}
 63
 64/* -----------------------------------------------------------------------------
 65 * Wrapper_pretty_print()
 66 *
 67 * Formats a wrapper function and fixes up the indentation.
 68 * ----------------------------------------------------------------------------- */
 69
 70void Wrapper_pretty_print(String *str, File *f) {
 71  String *ts;
 72  int level = 0;
 73  int c, i;
 74  int empty = 1;
 75  int indent = 2;
 76  int plevel = 0;
 77  int label = 0;
 78
 79  ts = NewStringEmpty();
 80  Seek(str, 0, SEEK_SET);
 81  while ((c = Getc(str)) != EOF) {
 82    if (c == '\"') {
 83      Putc(c, ts);
 84      while ((c = Getc(str)) != EOF) {
 85	if (c == '\\') {
 86	  Putc(c, ts);
 87	  c = Getc(str);
 88	}
 89	Putc(c, ts);
 90	if (c == '\"')
 91	  break;
 92      }
 93      empty = 0;
 94    } else if (c == '\'') {
 95      Putc(c, ts);
 96      while ((c = Getc(str)) != EOF) {
 97	if (c == '\\') {
 98	  Putc(c, ts);
 99	  c = Getc(str);
100	}
101	Putc(c, ts);
102	if (c == '\'')
103	  break;
104      }
105      empty = 0;
106    } else if (c == ':') {
107      Putc(c, ts);
108      if ((c = Getc(str)) == '\n') {
109	if (!empty && !strchr(Char(ts), '?'))
110	  label = 1;
111      }
112      Ungetc(c, str);
113    } else if (c == '(') {
114      Putc(c, ts);
115      plevel += indent;
116      empty = 0;
117    } else if (c == ')') {
118      Putc(c, ts);
119      plevel -= indent;
120      empty = 0;
121    } else if (c == '{') {
122      Putc(c, ts);
123      Putc('\n', ts);
124      for (i = 0; i < level; i++)
125	Putc(' ', f);
126      Printf(f, "%s", ts);
127      Clear(ts);
128      level += indent;
129      while ((c = Getc(str)) != EOF) {
130	if (!isspace(c)) {
131	  Ungetc(c, str);
132	  break;
133	}
134      }
135      empty = 0;
136    } else if (c == '}') {
137      if (!empty) {
138	Putc('\n', ts);
139	for (i = 0; i < level; i++)
140	  Putc(' ', f);
141	Printf(f, "%s", ts);
142	Clear(ts);
143      }
144      level -= indent;
145      Putc(c, ts);
146      empty = 0;
147    } else if (c == '\n') {
148      Putc(c, ts);
149      empty = 0;
150      if (!empty) {
151	int slevel = level;
152	if (label && (slevel >= indent))
153	  slevel -= indent;
154	if ((Char(ts))[0] != '#') {
155	  for (i = 0; i < slevel; i++)
156	    Putc(' ', f);
157	}
158	Printf(f, "%s", ts);
159	for (i = 0; i < plevel; i++)
160	  Putc(' ', f);
161      }
162      Clear(ts);
163      label = 0;
164      empty = 1;
165    } else if (c == '/') {
166      empty = 0;
167      Putc(c, ts);
168      c = Getc(str);
169      if (c != EOF) {
170	Putc(c, ts);
171	if (c == '/') {		/* C++ comment */
172	  while ((c = Getc(str)) != EOF) {
173	    if (c == '\n') {
174	      Ungetc(c, str);
175	      break;
176	    }
177	    Putc(c, ts);
178	  }
179	} else if (c == '*') {	/* C comment */
180	  int endstar = 0;
181	  while ((c = Getc(str)) != EOF) {
182	    if (endstar && c == '/') {	/* end of C comment */
183	      Putc(c, ts);
184	      break;
185	    }
186	    endstar = (c == '*');
187	    Putc(c, ts);
188	    if (c == '\n') {	/* multi-line C comment. Could be improved slightly. */
189	      for (i = 0; i < level; i++)
190		Putc(' ', ts);
191	    }
192	  }
193	}
194      }
195    } else {
196      if (!empty || !isspace(c)) {
197	Putc(c, ts);
198	empty = 0;
199      }
200    }
201  }
202  if (!empty)
203    Printf(f, "%s", ts);
204  Delete(ts);
205  Printf(f, "\n");
206}
207
208/* -----------------------------------------------------------------------------
209 * Wrapper_compact_print()
210 *
211 * Formats a wrapper function and fixes up the indentation.
212 * Print out in compact format, with Compact enabled.
213 * ----------------------------------------------------------------------------- */
214
215void Wrapper_compact_print(String *str, File *f) {
216  String *ts, *tf;		/*temp string & temp file */
217  int level = 0;
218  int c, i;
219  int empty = 1;
220  int indent = 2;
221
222  ts = NewStringEmpty();
223  tf = NewStringEmpty();
224  Seek(str, 0, SEEK_SET);
225
226  while ((c = Getc(str)) != EOF) {
227    if (c == '\"') {		/* string 1 */
228      empty = 0;
229      Putc(c, ts);
230      while ((c = Getc(str)) != EOF) {
231	if (c == '\\') {
232	  Putc(c, ts);
233	  c = Getc(str);
234	}
235	Putc(c, ts);
236	if (c == '\"')
237	  break;
238      }
239    } else if (c == '\'') {	/* string 2 */
240      empty = 0;
241      Putc(c, ts);
242      while ((c = Getc(str)) != EOF) {
243	if (c == '\\') {
244	  Putc(c, ts);
245	  c = Getc(str);
246	}
247	Putc(c, ts);
248	if (c == '\'')
249	  break;
250      }
251    } else if (c == '{') {	/* start of {...} */
252      empty = 0;
253      Putc(c, ts);
254      if (Len(tf) == 0) {
255	for (i = 0; i < level; i++)
256	  Putc(' ', tf);
257      } else if ((Len(tf) + Len(ts)) < Max_line_size) {
258	Putc(' ', tf);
259      } else {
260	Putc('\n', tf);
261	Printf(f, "%s", tf);
262	Clear(tf);
263	for (i = 0; i < level; i++)
264	  Putc(' ', tf);
265      }
266      Append(tf, ts);
267      Clear(ts);
268      level += indent;
269      while ((c = Getc(str)) != EOF) {
270	if (!isspace(c)) {
271	  Ungetc(c, str);
272	  break;
273	}
274      }
275    } else if (c == '}') {	/* end of {...} */
276      empty = 0;
277      if (Len(tf) == 0) {
278	for (i = 0; i < level; i++)
279	  Putc(' ', tf);
280      } else if ((Len(tf) + Len(ts)) < Max_line_size) {
281	Putc(' ', tf);
282      } else {
283	Putc('\n', tf);
284	Printf(f, "%s", tf);
285	Clear(tf);
286	for (i = 0; i < level; i++)
287	  Putc(' ', tf);
288      }
289      Append(tf, ts);
290      Putc(c, tf);
291      Clear(ts);
292      level -= indent;
293    } else if (c == '\n') {	/* line end */
294      while ((c = Getc(str)) != EOF) {
295	if (!isspace(c))
296	  break;
297      }
298      if (c == '#') {
299	Putc('\n', ts);
300      } else if (c == '}') {
301	Putc(' ', ts);
302      } else if ((c != EOF) || (Len(ts) != 0)) {
303	if (Len(tf) == 0) {
304	  for (i = 0; i < level; i++)
305	    Putc(' ', tf);
306	} else if ((Len(tf) + Len(ts)) < Max_line_size) {
307	  Putc(' ', tf);
308	} else {
309	  Putc('\n', tf);
310	  Printf(f, "%s", tf);
311	  Clear(tf);
312	  for (i = 0; i < level; i++)
313	    Putc(' ', tf);
314	}
315	Append(tf, ts);
316	Clear(ts);
317      }
318      Ungetc(c, str);
319
320      empty = 1;
321    } else if (c == '/') {	/* comment */
322      empty = 0;
323      c = Getc(str);
324      if (c != EOF) {
325	if (c == '/') {		/* C++ comment */
326	  while ((c = Getc(str)) != EOF) {
327	    if (c == '\n') {
328	      Ungetc(c, str);
329	      break;
330	    }
331	  }
332	} else if (c == '*') {	/* C comment */
333	  int endstar = 0;
334	  while ((c = Getc(str)) != EOF) {
335	    if (endstar && c == '/') {	/* end of C comment */
336	      break;
337	    }
338	    endstar = (c == '*');
339	  }
340	} else {
341	  Putc('/', ts);
342	  Putc(c, ts);
343	}
344      }
345    } else if (c == '#') {	/* Preprocessor line */
346      Putc('#', ts);
347      while ((c = Getc(str)) != EOF) {
348	Putc(c, ts);
349	if (c == '\\') {	/* Continued line of the same PP */
350	  c = Getc(str);
351	  if (c == '\n')
352	    Putc(c, ts);
353	  else
354	    Ungetc(c, str);
355	} else if (c == '\n')
356	  break;
357      }
358      if (!empty) {
359	Append(tf, "\n");
360      }
361      Append(tf, ts);
362      Printf(f, "%s", tf);
363      Clear(tf);
364      Clear(ts);
365      for (i = 0; i < level; i++)
366	Putc(' ', tf);
367      empty = 1;
368    } else {
369      if (!empty || !isspace(c)) {
370	Putc(c, ts);
371	empty = 0;
372      }
373    }
374  }
375  if (!empty) {
376    Append(tf, ts);
377  }
378  if (Len(tf) != 0)
379    Printf(f, "%s", tf);
380  Delete(ts);
381  Delete(tf);
382  Printf(f, "\n");
383}
384
385/* -----------------------------------------------------------------------------
386 * Wrapper_print()
387 *
388 * Print out a wrapper function.  Does pretty or compact printing as well.
389 * ----------------------------------------------------------------------------- */
390
391void Wrapper_print(Wrapper *w, File *f) {
392  String *str;
393
394  str = NewStringEmpty();
395  Printf(str, "%s\n", w->def);
396  Printf(str, "%s\n", w->locals);
397  Printf(str, "%s\n", w->code);
398  if (Compact_mode == 1)
399    Wrapper_compact_print(str, f);
400  else
401    Wrapper_pretty_print(str, f);
402
403  Delete(str);
404}
405
406/* -----------------------------------------------------------------------------
407 * Wrapper_add_local()
408 *
409 * Adds a new local variable declaration to a function. Returns -1 if already
410 * present (which may or may not be okay to the caller).
411 * ----------------------------------------------------------------------------- */
412
413int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
414  /* See if the local has already been declared */
415  if (Getattr(w->localh, name)) {
416    return -1;
417  }
418  Setattr(w->localh, name, decl);
419  Printf(w->locals, "%s;\n", decl);
420  return 0;
421}
422
423/* -----------------------------------------------------------------------------
424 * Wrapper_add_localv()
425 *
426 * Same as add_local(), but allows a NULL terminated list of strings to be
427 * used as a replacement for decl.   This saves the caller the trouble of having
428 * to manually construct the 'decl' string before calling.
429 * ----------------------------------------------------------------------------- */
430
431int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
432  va_list ap;
433  int ret;
434  String *decl;
435  DOH *obj;
436  decl = NewStringEmpty();
437  va_start(ap, name);
438
439  obj = va_arg(ap, void *);
440  while (obj) {
441    Append(decl, obj);
442    Putc(' ', decl);
443    obj = va_arg(ap, void *);
444  }
445  va_end(ap);
446
447  ret = Wrapper_add_local(w, name, decl);
448  Delete(decl);
449  return ret;
450}
451
452/* -----------------------------------------------------------------------------
453 * Wrapper_check_local()
454 *
455 * Check to see if a local name has already been declared
456 * ----------------------------------------------------------------------------- */
457
458int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name) {
459  if (Getattr(w->localh, name)) {
460    return 1;
461  }
462  return 0;
463}
464
465/* ----------------------------------------------------------------------------- 
466 * Wrapper_new_local()
467 *
468 * Adds a new local variable with a guarantee that a unique local name will be
469 * used.  Returns the name that was actually selected.
470 * ----------------------------------------------------------------------------- */
471
472char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
473  int i;
474  String *nname = NewString(name);
475  String *ndecl = NewString(decl);
476  char *ret;
477
478  i = 0;
479
480  while (Wrapper_check_local(w, nname)) {
481    Clear(nname);
482    Printf(nname, "%s%d", name, i);
483    i++;
484  }
485  Replace(ndecl, name, nname, DOH_REPLACE_ID);
486  Setattr(w->localh, nname, ndecl);
487  Printf(w->locals, "%s;\n", ndecl);
488  ret = Char(nname);
489  Delete(nname);
490  Delete(ndecl);
491  return ret;			/* Note: nname should still exists in the w->localh hash */
492}
493
494
495/* -----------------------------------------------------------------------------
496 * Wrapper_new_localv()
497 *
498 * Same as add_local(), but allows a NULL terminated list of strings to be
499 * used as a replacement for decl.   This saves the caller the trouble of having
500 * to manually construct the 'decl' string before calling.
501 * ----------------------------------------------------------------------------- */
502
503char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
504  va_list ap;
505  char *ret;
506  String *decl;
507  DOH *obj;
508  decl = NewStringEmpty();
509  va_start(ap, name);
510
511  obj = va_arg(ap, void *);
512  while (obj) {
513    Append(decl, obj);
514    Putc(' ', decl);
515    obj = va_arg(ap, void *);
516  }
517  va_end(ap);
518
519  ret = Wrapper_new_local(w, name, decl);
520  Delete(decl);
521  return ret;
522}