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 * misc.c
6 *
7 * Miscellaneous functions that don't really fit anywhere else.
8 * ----------------------------------------------------------------------------- */
9
10char cvsroot_misc_c[] = "$Id: misc.c 11133 2009-02-20 07:52:24Z wsfulton $";
11
12#include "swig.h"
13#include <errno.h>
14#include <ctype.h>
15#include <limits.h>
16
17static char *fake_version = 0;
18
19/* -----------------------------------------------------------------------------
20 * Swig_copy_string()
21 *
22 * Duplicate a NULL-terminate string given as a char *.
23 * ----------------------------------------------------------------------------- */
24
25char *Swig_copy_string(const char *s) {
26  char *c = 0;
27  if (s) {
28    c = (char *) malloc(strlen(s) + 1);
29    strcpy(c, s);
30  }
31  return c;
32}
33
34/* -----------------------------------------------------------------------------
35 * Swig_set_fakeversion()
36 *
37 * Version string override
38 * ----------------------------------------------------------------------------- */
39
40void Swig_set_fakeversion(const char *version) {
41  fake_version = Swig_copy_string(version);
42}
43
44/* -----------------------------------------------------------------------------
45 * Swig_package_version()
46 *
47 * Return the package string containing the version number
48 * ----------------------------------------------------------------------------- */
49
50const char *Swig_package_version(void) {
51  return fake_version ? fake_version : PACKAGE_VERSION;
52}
53
54/* -----------------------------------------------------------------------------
55 * Swig_banner()
56 *
57 * Emits the SWIG identifying banner for the C/C++ wrapper file.
58 * ----------------------------------------------------------------------------- */
59
60void Swig_banner(File *f) {
61  Printf(f, "/* ----------------------------------------------------------------------------\n\
62 * This file was automatically generated by SWIG (http://www.swig.org).\n\
63 * Version %s\n\
64 * \n\
65 * This file is not intended to be easily readable and contains a number of \n\
66 * coding conventions designed to improve portability and efficiency. Do not make\n\
67 * changes to this file unless you know what you are doing--modify the SWIG \n\
68 * interface file instead. \n", Swig_package_version());
69  /* String too long for ISO compliance */
70  Printf(f, " * ----------------------------------------------------------------------------- */\n");
71
72}
73
74/* -----------------------------------------------------------------------------
75 * Swig_banner_target_lang()
76 *
77 * Emits a SWIG identifying banner in the target language
78 * ----------------------------------------------------------------------------- */
79
80void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar) {
81  Printf(f, "%s This file was automatically generated by SWIG (http://www.swig.org).\n", commentchar);
82  Printf(f, "%s Version %s\n", commentchar, Swig_package_version());
83  Printf(f, "%s\n", commentchar);
84  Printf(f, "%s Do not make changes to this file unless you know what you are doing--modify\n", commentchar);
85  Printf(f, "%s the SWIG interface file instead.\n", commentchar);
86}
87
88/* -----------------------------------------------------------------------------
89 * Swig_strip_c_comments()
90 *
91 * Return a new string with C comments stripped from the input string. Null is
92 * returned if there aren't any.
93 * ----------------------------------------------------------------------------- */
94
95String *Swig_strip_c_comments(const String *s) {
96  const char *c = Char(s);
97  const char *comment_begin = 0;
98  const char *comment_end = 0;
99  String *stripped = 0;
100
101  while (*c) {
102    if (!comment_begin && *c == '/') {
103      ++c;
104      if (!*c)
105        break;
106      if (*c == '*')
107        comment_begin = c-1;
108    } else if (comment_begin && !comment_end && *c == '*') {
109      ++c;
110      if (*c == '/')
111        comment_end = c;
112      break;
113    }
114    ++c;
115  }
116
117  if (comment_begin && comment_end) {
118    int size = comment_begin - Char(s);
119    String *stripmore = 0;
120    stripped = NewStringWithSize(s, size);
121    Printv(stripped, comment_end + 1, NIL);
122    do {
123      stripmore = Swig_strip_c_comments(stripped);
124      if (stripmore) {
125        Delete(stripped);
126        stripped = stripmore;
127      }
128    } while (stripmore);
129  }
130  return stripped;
131}
132
133
134/* -----------------------------------------------------------------------------
135 * Swig_filename_correct()
136 *
137 * Corrects filenames on non-unix systems
138 * ----------------------------------------------------------------------------- */
139
140void Swig_filename_correct(String *filename) {
141  (void)filename;
142#if defined(_WIN32) || defined(MACSWIG)
143  /* accept Unix path separator on non-Unix systems */
144  Replaceall(filename, "/", SWIG_FILE_DELIMITER);
145#endif
146#if defined(__CYGWIN__)
147  /* accept Windows path separator in addition to Unix path separator */
148  Replaceall(filename, "\\", SWIG_FILE_DELIMITER);
149#endif
150}
151
152/* -----------------------------------------------------------------------------
153 * Swig_filename_escape()
154 *
155 * Escapes backslashes in filename - for Windows
156 * ----------------------------------------------------------------------------- */
157
158String *Swig_filename_escape(String *filename) {
159  String *adjusted_filename = Copy(filename);
160#if defined(_WIN32)		/* Note not on Cygwin else filename is displayed with double '/' */
161    Replaceall(adjusted_filename, "\\\\", "\\");	/* remove double '\' in case any already present */
162    Replaceall(adjusted_filename, "\\", "\\\\");
163#endif
164    return adjusted_filename;
165}
166
167/* -----------------------------------------------------------------------------
168 * Swig_string_escape()
169 *
170 * Takes a string object and produces a string with escape codes added to it.
171 * ----------------------------------------------------------------------------- */
172
173String *Swig_string_escape(String *s) {
174  String *ns;
175  int c;
176  ns = NewStringEmpty();
177
178  while ((c = Getc(s)) != EOF) {
179    if (c == '\n') {
180      Printf(ns, "\\n");
181    } else if (c == '\r') {
182      Printf(ns, "\\r");
183    } else if (c == '\t') {
184      Printf(ns, "\\t");
185    } else if (c == '\\') {
186      Printf(ns, "\\\\");
187    } else if (c == '\'') {
188      Printf(ns, "\\'");
189    } else if (c == '\"') {
190      Printf(ns, "\\\"");
191    } else if (c == ' ') {
192      Putc(c, ns);
193    } else if (!isgraph(c)) {
194      if (c < 0)
195	c += UCHAR_MAX + 1;
196      Printf(ns, "\\%o", c);
197    } else {
198      Putc(c, ns);
199    }
200  }
201  return ns;
202}
203
204
205/* -----------------------------------------------------------------------------
206 * Swig_string_upper()
207 *
208 * Takes a string object and returns a copy that is uppercase
209 * ----------------------------------------------------------------------------- */
210
211String *Swig_string_upper(String *s) {
212  String *ns;
213  int c;
214  ns = NewStringEmpty();
215
216  Seek(s, 0, SEEK_SET);
217  while ((c = Getc(s)) != EOF) {
218    Putc(toupper(c), ns);
219  }
220  return ns;
221}
222
223/* -----------------------------------------------------------------------------
224 * Swig_string_lower()
225 *
226 * Takes a string object and returns a copy that is lowercase
227 * ----------------------------------------------------------------------------- */
228
229String *Swig_string_lower(String *s) {
230  String *ns;
231  int c;
232  ns = NewStringEmpty();
233
234  Seek(s, 0, SEEK_SET);
235  while ((c = Getc(s)) != EOF) {
236    Putc(tolower(c), ns);
237  }
238  return ns;
239}
240
241
242/* -----------------------------------------------------------------------------
243 * Swig_string_title()
244 *
245 * Takes a string object and returns a copy that is lowercase with first letter
246 * capitalized
247 * ----------------------------------------------------------------------------- */
248
249String *Swig_string_title(String *s) {
250  String *ns;
251  int first = 1;
252  int c;
253  ns = NewStringEmpty();
254
255  Seek(s, 0, SEEK_SET);
256  while ((c = Getc(s)) != EOF) {
257    Putc(first ? toupper(c) : tolower(c), ns);
258    first = 0;
259  }
260  return ns;
261}
262
263/* -----------------------------------------------------------------------------
264 * Swig_string_ccase()
265 *
266 * Takes a string object and returns a copy that is lowercase with the first
267 * letter capitalized and the one following '_', which are removed.
268 *
269 *      camel_case -> CamelCase
270 *      camelCase  -> CamelCase
271 * ----------------------------------------------------------------------------- */
272
273String *Swig_string_ccase(String *s) {
274  String *ns;
275  int first = 1;
276  int c;
277  ns = NewStringEmpty();
278
279  Seek(s, 0, SEEK_SET);
280  while ((c = Getc(s)) != EOF) {
281    if (c == '_') {
282      first = 1;
283      continue;
284    }
285    Putc(first ? toupper(c) : c, ns);
286    first = 0;
287  }
288  return ns;
289}
290
291/* -----------------------------------------------------------------------------
292 * Swig_string_lccase()
293 *
294 * Takes a string object and returns a copy with the character after
295 * each '_' capitalised, and the '_' removed.  The first character is
296 * also forced to lowercase.
297 *
298 *      camel_case -> camelCase
299 *      CamelCase  -> camelCase
300 * ----------------------------------------------------------------------------- */
301
302String *Swig_string_lccase(String *s) {
303  String *ns;
304  int first = 1;
305  int after_underscore = 0;
306  int c;
307  ns = NewStringEmpty();
308
309  Seek(s, 0, SEEK_SET);
310  while ((c = Getc(s)) != EOF) {
311    if (c == '_') {
312      after_underscore = 1;
313      continue;
314    }
315    if (first) {
316      Putc(tolower(c), ns);
317      first = 0;
318    } else {
319      Putc(after_underscore ? toupper(c) : c, ns);
320    }
321    after_underscore = 0;
322  }
323  return ns;
324}
325
326/* -----------------------------------------------------------------------------
327 * Swig_string_ucase()
328 *
329 * This is the reverse case of ccase, ie
330 *
331 *      CamelCase -> camel_case
332 *      get2D     -> get_2d
333 *      asFloat2  -> as_float2
334 * ----------------------------------------------------------------------------- */
335
336String *Swig_string_ucase(String *s) {
337  String *ns;
338  int c;
339  int lastC = 0;
340  int nextC = 0;
341  int underscore = 0;
342  ns = NewStringEmpty();
343
344  /* We insert a underscore when:
345     1. Lower case char followed by upper case char
346     getFoo > get_foo; getFOo > get_foo; GETFOO > getfoo
347     2. Number proceded by char and not end of string
348     get2D > get_2d; get22D > get_22d; GET2D > get_2d
349     but:
350     asFloat2 > as_float2
351  */
352
353  Seek(s, 0, SEEK_SET);
354
355  while ((c = Getc(s)) != EOF) {
356    nextC = Getc(s); Ungetc(nextC, s);
357    if (isdigit(c) && isalpha(lastC) && nextC != EOF)
358      underscore = 1;
359    else if (isupper(c) && isalpha(lastC) && !isupper(lastC))
360      underscore = 1;
361
362    lastC = c;
363
364    if (underscore) {
365      Putc('_', ns);
366      underscore = 0;
367    }
368
369    Putc(tolower(c), ns);
370  }
371  return ns;
372}
373
374/* -----------------------------------------------------------------------------
375 * Swig_string_first_upper()
376 *
377 * Make the first character in the string uppercase, leave all the
378 * rest the same.  This is used by the Ruby module to provide backwards
379 * compatibility with the old way of naming classes and constants.  For
380 * more info see the Ruby documentation.
381 *
382 *      firstUpper -> FirstUpper
383 * ----------------------------------------------------------------------------- */
384
385String *Swig_string_first_upper(String *s) {
386  String *ns = NewStringEmpty();
387  char *cs = Char(s);
388  if (cs && cs[0] != 0) {
389    Putc(toupper((int)cs[0]), ns);
390    Append(ns, cs + 1);
391  }
392  return ns;
393}
394
395/* -----------------------------------------------------------------------------
396 * Swig_string_first_lower()
397 *
398 * Make the first character in the string lowercase, leave all the
399 * rest the same.  This is used by the Ruby module to provide backwards
400 * compatibility with the old way of naming classes and constants.  For
401 * more info see the Ruby documentation.
402 *
403 *      firstLower -> FirstLower
404 * ----------------------------------------------------------------------------- */
405
406String *Swig_string_first_lower(String *s) {
407  String *ns = NewStringEmpty();
408  char *cs = Char(s);
409  if (cs && cs[0] != 0) {
410    Putc(tolower((int)cs[0]), ns);
411    Append(ns, cs + 1);
412  }
413  return ns;
414}
415
416/* -----------------------------------------------------------------------------
417 * Swig_string_schemify()
418 *
419 * Replace underscores with dashes, to make identifiers look nice to Schemers.
420 *
421 *      under_scores -> under-scores
422 * ----------------------------------------------------------------------------- */
423
424String *Swig_string_schemify(String *s) {
425  String *ns = NewString(s);
426  Replaceall(ns, "_", "-");
427  return ns;
428}
429
430
431/* -----------------------------------------------------------------------------
432 * Swig_string_typecode()
433 *
434 * Takes a string with possible type-escapes in it and replaces them with
435 * real C datatypes.
436 * ----------------------------------------------------------------------------- */
437
438String *Swig_string_typecode(String *s) {
439  String *ns;
440  int c;
441  String *tc;
442  ns = NewStringEmpty();
443  while ((c = Getc(s)) != EOF) {
444    if (c == '`') {
445      String *str = 0;
446      tc = NewStringEmpty();
447      while ((c = Getc(s)) != EOF) {
448	if (c == '`')
449	  break;
450	Putc(c, tc);
451      }
452      str = SwigType_str(tc, 0);
453      Append(ns, str);
454      Delete(str);
455    } else {
456      Putc(c, ns);
457      if (c == '\'') {
458	while ((c = Getc(s)) != EOF) {
459	  Putc(c, ns);
460	  if (c == '\'')
461	    break;
462	  if (c == '\\') {
463	    c = Getc(s);
464	    Putc(c, ns);
465	  }
466	}
467      } else if (c == '\"') {
468	while ((c = Getc(s)) != EOF) {
469	  Putc(c, ns);
470	  if (c == '\"')
471	    break;
472	  if (c == '\\') {
473	    c = Getc(s);
474	    Putc(c, ns);
475	  }
476	}
477      }
478    }
479  }
480  return ns;
481}
482
483/* -----------------------------------------------------------------------------
484 * Swig_string_mangle()
485 *
486 * Take a string and mangle it by stripping all non-valid C identifier
487 * characters.
488 *
489 * This routine skips unnecessary blank spaces, therefore mangling
490 * 'char *' and 'char*', 'std::pair<int, int >' and
491 * 'std::pair<int,int>', produce the same result.
492 *
493 * However, note that 'long long' and 'long_long' produce different
494 * mangled strings.
495 *
496 * The mangling method still is not 'perfect', for example std::pair and
497 * std_pair return the same mangling. This is just a little better
498 * than before, but it seems to be enough for most of the purposes.
499 *
500 * Having a perfect mangling will break some examples and code which
501 * assume, for example, that A::get_value will be mangled as
502 * A_get_value.
503 * ----------------------------------------------------------------------------- */
504
505String *Swig_string_mangle(const String *s) {
506#if 0
507  /* old mangling, not suitable for using in macros */
508  String *t = Copy(s);
509  char *c = Char(t);
510  while (*c) {
511    if (!isalnum(*c))
512      *c = '_';
513    c++;
514  }
515  return t;
516#else
517  String *result = NewStringEmpty();
518  int space = 0;
519  int state = 0;
520  char *pc, *cb;
521  String *b = Copy(s);
522  if (SwigType_istemplate(b)) {
523    String *st = Swig_symbol_template_deftype(b, 0);
524    String *sq = Swig_symbol_type_qualify(st, 0);
525    String *t = SwigType_namestr(sq);
526    Delete(st);
527    Delete(sq);
528    Delete(b);
529    b = t;
530  }
531  pc = cb = Char(b);
532  while (*pc) {
533    char c = *pc;
534    if (isalnum((int) c) || (c == '_')) {
535      state = 1;
536      if (space && (space == state)) {
537	Append(result, "_SS_");
538      }
539      space = 0;
540      Printf(result, "%c", (int) c);
541
542    } else {
543      if (isspace((int) c)) {
544	space = state;
545	++pc;
546	continue;
547      } else {
548	state = 3;
549	space = 0;
550      }
551      switch (c) {
552      case '.':
553	if ((cb != pc) && (*(pc - 1) == 'p')) {
554	  Append(result, "_");
555	  ++pc;
556	  continue;
557	} else {
558	  c = 'f';
559	}
560	break;
561      case ':':
562	if (*(pc + 1) == ':') {
563	  Append(result, "_");
564	  ++pc;
565	  ++pc;
566	  continue;
567	}
568	break;
569      case '*':
570	c = 'm';
571	break;
572      case '&':
573	c = 'A';
574	break;
575      case '<':
576	c = 'l';
577	break;
578      case '>':
579	c = 'g';
580	break;
581      case '=':
582	c = 'e';
583	break;
584      case ',':
585	c = 'c';
586	break;
587      case '(':
588	c = 'p';
589	break;
590      case ')':
591	c = 'P';
592	break;
593      case '[':
594	c = 'b';
595	break;
596      case ']':
597	c = 'B';
598	break;
599      case '^':
600	c = 'x';
601	break;
602      case '|':
603	c = 'o';
604	break;
605      case '~':
606	c = 'n';
607	break;
608      case '!':
609	c = 'N';
610	break;
611      case '%':
612	c = 'M';
613	break;
614      case '?':
615	c = 'q';
616	break;
617      case '+':
618	c = 'a';
619	break;
620      case '-':
621	c = 's';
622	break;
623      case '/':
624	c = 'd';
625	break;
626      default:
627	break;
628      }
629      if (isalpha((int) c)) {
630	Printf(result, "_S%c_", (int) c);
631      } else {
632	Printf(result, "_S%02X_", (int) c);
633      }
634    }
635    ++pc;
636  }
637  Delete(b);
638  return result;
639#endif
640}
641
642String *Swig_string_emangle(String *s) {
643  return Swig_string_mangle(s);
644}
645
646
647/* -----------------------------------------------------------------------------
648 * Swig_scopename_prefix()
649 *
650 * Take a qualified name like "A::B::C" and return the scope name.
651 * In this case, "A::B".   Returns NULL if there is no base.
652 * ----------------------------------------------------------------------------- */
653
654void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
655  char *tmp = Char(s);
656  char *c = tmp;
657  char *cc = c;
658  char *co = 0;
659  if (!strstr(c, "::")) {
660    *rprefix = 0;
661    *rlast = Copy(s);
662  }
663
664  co = strstr(cc, "operator ");
665  if (co) {
666    if (co == cc) {
667      *rprefix = 0;
668      *rlast = Copy(s);
669      return;
670    } else {
671      *rprefix = NewStringWithSize(cc, co - cc - 2);
672      *rlast = NewString(co);
673      return;
674    }
675  }
676  while (*c) {
677    if ((*c == ':') && (*(c + 1) == ':')) {
678      cc = c;
679      c += 2;
680    } else {
681      if (*c == '<') {
682	int level = 1;
683	c++;
684	while (*c && level) {
685	  if (*c == '<')
686	    level++;
687	  if (*c == '>')
688	    level--;
689	  c++;
690	}
691      } else {
692	c++;
693      }
694    }
695  }
696
697  if (cc != tmp) {
698    *rprefix = NewStringWithSize(tmp, cc - tmp);
699    *rlast = NewString(cc + 2);
700    return;
701  } else {
702    *rprefix = 0;
703    *rlast = Copy(s);
704  }
705}
706
707
708String *Swig_scopename_prefix(const String *s) {
709  char *tmp = Char(s);
710  char *c = tmp;
711  char *cc = c;
712  char *co = 0;
713  if (!strstr(c, "::"))
714    return 0;
715  co = strstr(cc, "operator ");
716
717  if (co) {
718    if (co == cc) {
719      return 0;
720    } else {
721      String *prefix = NewStringWithSize(cc, co - cc - 2);
722      return prefix;
723    }
724  }
725  while (*c) {
726    if ((*c == ':') && (*(c + 1) == ':')) {
727      cc = c;
728      c += 2;
729    } else {
730      if (*c == '<') {
731	int level = 1;
732	c++;
733	while (*c && level) {
734	  if (*c == '<')
735	    level++;
736	  if (*c == '>')
737	    level--;
738	  c++;
739	}
740      } else {
741	c++;
742      }
743    }
744  }
745
746  if (cc != tmp) {
747    return NewStringWithSize(tmp, cc - tmp);
748  } else {
749    return 0;
750  }
751}
752
753/* -----------------------------------------------------------------------------
754 * Swig_scopename_last()
755 *
756 * Take a qualified name like "A::B::C" and returns the last.  In this
757 * case, "C".
758 * ----------------------------------------------------------------------------- */
759
760String *Swig_scopename_last(const String *s) {
761  char *tmp = Char(s);
762  char *c = tmp;
763  char *cc = c;
764  char *co = 0;
765  if (!strstr(c, "::"))
766    return NewString(s);
767
768  co = strstr(cc, "operator ");
769  if (co) {
770    return NewString(co);
771  }
772
773
774  while (*c) {
775    if ((*c == ':') && (*(c + 1) == ':')) {
776      cc = c;
777      c += 2;
778    } else {
779      if (*c == '<') {
780	int level = 1;
781	c++;
782	while (*c && level) {
783	  if (*c == '<')
784	    level++;
785	  if (*c == '>')
786	    level--;
787	  c++;
788	}
789      } else {
790	c++;
791      }
792    }
793  }
794  return NewString(cc + 2);
795}
796
797/* -----------------------------------------------------------------------------
798 * Swig_scopename_first()
799 *
800 * Take a qualified name like "A::B::C" and returns the first scope name.
801 * In this case, "A".   Returns NULL if there is no base.
802 * ----------------------------------------------------------------------------- */
803
804String *Swig_scopename_first(const String *s) {
805  char *tmp = Char(s);
806  char *c = tmp;
807  char *co = 0;
808  if (!strstr(c, "::"))
809    return 0;
810
811  co = strstr(c, "operator ");
812  if (co) {
813    if (co == c) {
814      return 0;
815    }
816  } else {
817    co = c + Len(s);
818  }
819
820  while (*c && (c != co)) {
821    if ((*c == ':') && (*(c + 1) == ':')) {
822      break;
823    } else {
824      if (*c == '<') {
825	int level = 1;
826	c++;
827	while (*c && level) {
828	  if (*c == '<')
829	    level++;
830	  if (*c == '>')
831	    level--;
832	  c++;
833	}
834      } else {
835	c++;
836      }
837    }
838  }
839  if (*c && (c != tmp)) {
840    return NewStringWithSize(tmp, c - tmp);
841  } else {
842    return 0;
843  }
844}
845
846
847/* -----------------------------------------------------------------------------
848 * Swig_scopename_suffix()
849 *
850 * Take a qualified name like "A::B::C" and returns the suffix.
851 * In this case, "B::C".   Returns NULL if there is no suffix.
852 * ----------------------------------------------------------------------------- */
853
854String *Swig_scopename_suffix(const String *s) {
855  char *tmp = Char(s);
856  char *c = tmp;
857  char *co = 0;
858  if (!strstr(c, "::"))
859    return 0;
860
861  co = strstr(c, "operator ");
862  if (co) {
863    if (co == c)
864      return 0;
865  }
866  while (*c) {
867    if ((*c == ':') && (*(c + 1) == ':')) {
868      break;
869    } else {
870      if (*c == '<') {
871	int level = 1;
872	c++;
873	while (*c && level) {
874	  if (*c == '<')
875	    level++;
876	  if (*c == '>')
877	    level--;
878	  c++;
879	}
880      } else {
881	c++;
882      }
883    }
884  }
885  if (*c && (c != tmp)) {
886    return NewString(c + 2);
887  } else {
888    return 0;
889  }
890}
891
892/* -----------------------------------------------------------------------------
893 * Swig_scopename_check()
894 *
895 * Checks to see if a name is qualified with a scope name
896 * ----------------------------------------------------------------------------- */
897
898int Swig_scopename_check(const String *s) {
899  char *c = Char(s);
900  char *co = strstr(c, "operator ");
901
902  if (co) {
903    if (co == c)
904      return 0;
905  }
906  if (!strstr(c, "::"))
907    return 0;
908  while (*c) {
909    if ((*c == ':') && (*(c + 1) == ':')) {
910      return 1;
911    } else {
912      if (*c == '<') {
913	int level = 1;
914	c++;
915	while (*c && level) {
916	  if (*c == '<')
917	    level++;
918	  if (*c == '>')
919	    level--;
920	  c++;
921	}
922      } else {
923	c++;
924      }
925    }
926  }
927  return 0;
928}
929
930/* -----------------------------------------------------------------------------
931 * Swig_string_command()
932 *
933 * Executes a external command via popen with the string as a command
934 * line parameter. For example:
935 *
936 *  Printf(stderr,"%(command:sed 's/[a-z]/\U\\1/' <<<)s","hello") -> Hello
937 * ----------------------------------------------------------------------------- */
938#if defined(HAVE_POPEN)
939#  if defined(_MSC_VER)
940#    define popen _popen
941#    define pclose _pclose
942#  else
943extern FILE *popen(const char *command, const char *type);
944extern int pclose(FILE *stream);
945#  endif
946#else
947#  if defined(_MSC_VER)
948#    define HAVE_POPEN 1
949#    define popen _popen
950#    define pclose _pclose
951#  endif
952#endif
953
954String *Swig_string_command(String *s) {
955  String *res = NewStringEmpty();
956#if defined(HAVE_POPEN)
957  if (Len(s)) {
958    char *command = Char(s);
959    FILE *fp = popen(command, "r");
960    if (fp) {
961      char buffer[1025];
962      while (fscanf(fp, "%1024s", buffer) != EOF) {
963	Append(res, buffer);
964      }
965      pclose(fp);
966    } else {
967      Swig_error("SWIG", Getline(s), "Command encoder fails attempting '%s'.\n", s);
968      exit(1);
969    }
970  }
971#endif
972  return res;
973}
974
975
976/* -----------------------------------------------------------------------------
977 * Swig_string_strip()
978 *
979 * Strip given prefix from identifiers
980 *
981 *  Printf(stderr,"%(strip:[wx])s","wxHello") -> Hello
982 * ----------------------------------------------------------------------------- */
983
984String *Swig_string_strip(String *s) {
985  String *ns;
986  if (!Len(s)) {
987    ns = NewString(s);
988  } else {
989    const char *cs = Char(s);
990    const char *ce = Strchr(cs, ']');
991    if (*cs != '[' || ce == NULL) {
992      ns = NewString(s);
993    } else {
994      String *fmt = NewStringf("%%.%ds", ce-cs-1);
995      String *prefix = NewStringf(fmt, cs+1);
996      if (0 == Strncmp(ce+1, prefix, Len(prefix))) {
997        ns = NewString(ce+1+Len(prefix));
998      } else {
999        ns = NewString(ce+1);
1000      }
1001    }
1002  }
1003  return ns;
1004}
1005
1006
1007/* -----------------------------------------------------------------------------
1008 * Swig_string_rxspencer()
1009 *
1010 * Executes a regexp substitution via the RxSpencer library. For example:
1011 *
1012 *   Printf(stderr,"gsl%(rxspencer:[GSL_.*_][@1])s","GSL_Hello_") -> gslHello
1013 * ----------------------------------------------------------------------------- */
1014#if defined(HAVE_RXSPENCER)
1015#include <sys/types.h>
1016#include <rxspencer/regex.h>
1017#define USE_RXSPENCER
1018#endif
1019
1020const char *skip_delim(char pb, char pe, const char *ce) {
1021  int end = 0;
1022  int lb = 0;
1023  while (!end && *ce != '\0') {
1024    if (*ce == pb) {
1025      ++lb;
1026    }
1027    if (*ce == pe) {
1028      if (!lb) {
1029	end = 1;
1030	--ce;
1031      } else {
1032	--lb;
1033      }
1034    }
1035    ++ce;
1036  }
1037  return end ? ce : 0;
1038}
1039
1040
1041#if defined(USE_RXSPENCER)
1042String *Swig_string_rxspencer(String *s) {
1043  String *res = 0;
1044  if (Len(s)) {
1045    const char *cs = Char(s);
1046    const char *cb;
1047    const char *ce;
1048    if (*cs == '[') {
1049      int retval;
1050      regex_t compiled;
1051      cb = ++cs;
1052      ce = skip_delim('[', ']', cb);
1053      if (ce) {
1054	char bregexp[512];
1055	strncpy(bregexp, cb, ce - cb);
1056	bregexp[ce - cb] = '\0';
1057	++ce;
1058	retval = regcomp(&compiled, bregexp, REG_EXTENDED);
1059	if (retval == 0) {
1060	  cs = ce;
1061	  if (*cs == '[') {
1062	    cb = ++cs;
1063	    ce = skip_delim('[', ']', cb);
1064	    if (ce) {
1065	      const char *cvalue = ce + 1;
1066	      int nsub = (int) compiled.re_nsub + 1;
1067	      regmatch_t *pmatch = (regmatch_t *) malloc(sizeof(regmatch_t) * (nsub));
1068	      retval = regexec(&compiled, cvalue, nsub, pmatch, 0);
1069	      if (retval != REG_NOMATCH) {
1070		char *spos = 0;
1071		res = NewStringWithSize(cb, ce - cb);
1072		spos = Strchr(res, '@');
1073		while (spos) {
1074		  char cd = *(++spos);
1075		  if (isdigit(cd)) {
1076		    char arg[8];
1077		    size_t len;
1078		    int i = cd - '0';
1079		    sprintf(arg, "@%d", i);
1080		    if (i < nsub && (len = pmatch[i].rm_eo - pmatch[i].rm_so)) {
1081		      char value[256];
1082		      strncpy(value, cvalue + pmatch[i].rm_so, len);
1083		      value[len] = 0;
1084		      Replaceall(res, arg, value);
1085		    } else {
1086		      Replaceall(res, arg, "");
1087		    }
1088		    spos = Strchr(res, '@');
1089		  } else if (cd == '@') {
1090		    spos = strchr(spos + 1, '@');
1091		  }
1092		}
1093	      }
1094	      free(pmatch);
1095	    }
1096	  }
1097	}
1098	regfree(&compiled);
1099      }
1100    }
1101  }
1102  if (!res)
1103    res = NewStringEmpty();
1104  return res;
1105}
1106#else
1107String *Swig_string_rxspencer(String *s) {
1108  (void) s;
1109  return NewStringEmpty();
1110}
1111#endif
1112
1113
1114/* -----------------------------------------------------------------------------
1115 * Swig_init()
1116 *
1117 * Initialize the SWIG core
1118 * ----------------------------------------------------------------------------- */
1119
1120void Swig_init() {
1121  /* Set some useful string encoding methods */
1122  DohEncoding("escape", Swig_string_escape);
1123  DohEncoding("upper", Swig_string_upper);
1124  DohEncoding("lower", Swig_string_lower);
1125  DohEncoding("title", Swig_string_title);
1126  DohEncoding("ctitle", Swig_string_ccase);
1127  DohEncoding("lctitle", Swig_string_lccase);
1128  DohEncoding("utitle", Swig_string_ucase);
1129  DohEncoding("typecode", Swig_string_typecode);
1130  DohEncoding("mangle", Swig_string_emangle);
1131  DohEncoding("command", Swig_string_command);
1132  DohEncoding("rxspencer", Swig_string_rxspencer);
1133  DohEncoding("schemify", Swig_string_schemify);
1134  DohEncoding("strip", Swig_string_strip);
1135
1136  /* aliases for the case encoders */
1137  DohEncoding("uppercase", Swig_string_upper);
1138  DohEncoding("lowercase", Swig_string_lower);
1139  DohEncoding("camelcase", Swig_string_ccase);
1140  DohEncoding("lowercamelcase", Swig_string_lccase);
1141  DohEncoding("undercase", Swig_string_ucase);
1142  DohEncoding("firstuppercase", Swig_string_first_upper);
1143  DohEncoding("firstlowercase", Swig_string_first_lower);
1144
1145  /* Initialize typemaps */
1146  Swig_typemap_init();
1147
1148  /* Initialize symbol table */
1149  Swig_symbol_init();
1150
1151  /* Initialize type system */
1152  SwigType_typesystem_init();
1153
1154  /* Initialize template system */
1155  SwigType_template_init();
1156}
1157