summaryrefslogtreecommitdiff
path: root/trunk/Source/Swig/wrapfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/Source/Swig/wrapfunc.c')
-rw-r--r--trunk/Source/Swig/wrapfunc.c522
1 files changed, 522 insertions, 0 deletions
diff --git a/trunk/Source/Swig/wrapfunc.c b/trunk/Source/Swig/wrapfunc.c
new file mode 100644
index 000000000..2c9f7c86a
--- /dev/null
+++ b/trunk/Source/Swig/wrapfunc.c
@@ -0,0 +1,522 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * wrapfunc.c
+ *
+ * This file defines a object for creating wrapper functions. Primarily
+ * this is used for convenience since it allows pieces of a wrapper function
+ * to be created in a piecemeal manner.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_wrapfunc_c[] = "$Id$";
+
+#include "swig.h"
+#include <ctype.h>
+
+static int Compact_mode = 0; /* set to 0 on default */
+static int Max_line_size = 128;
+
+/* -----------------------------------------------------------------------------
+ * NewWrapper()
+ *
+ * Create a new wrapper function object.
+ * ----------------------------------------------------------------------------- */
+
+Wrapper *NewWrapper(void) {
+ Wrapper *w;
+ w = (Wrapper *) malloc(sizeof(Wrapper));
+ w->localh = NewHash();
+ w->locals = NewStringEmpty();
+ w->code = NewStringEmpty();
+ w->def = NewStringEmpty();
+ return w;
+}
+
+/* -----------------------------------------------------------------------------
+ * DelWrapper()
+ *
+ * Delete a wrapper function object.
+ * ----------------------------------------------------------------------------- */
+
+void DelWrapper(Wrapper *w) {
+ Delete(w->localh);
+ Delete(w->locals);
+ Delete(w->code);
+ Delete(w->def);
+ free(w);
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_compact_print_mode_set()
+ *
+ * Set compact_mode.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_compact_print_mode_set(int flag) {
+ Compact_mode = flag;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_pretty_print()
+ *
+ * Formats a wrapper function and fixes up the indentation.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_pretty_print(String *str, File *f) {
+ String *ts;
+ int level = 0;
+ int c, i;
+ int empty = 1;
+ int indent = 2;
+ int plevel = 0;
+ int label = 0;
+
+ ts = NewStringEmpty();
+ Seek(str, 0, SEEK_SET);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\"') {
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\"')
+ break;
+ }
+ empty = 0;
+ } else if (c == '\'') {
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\'')
+ break;
+ }
+ empty = 0;
+ } else if (c == ':') {
+ Putc(c, ts);
+ if ((c = Getc(str)) == '\n') {
+ if (!empty && !strchr(Char(ts), '?'))
+ label = 1;
+ }
+ Ungetc(c, str);
+ } else if (c == '(') {
+ Putc(c, ts);
+ plevel += indent;
+ empty = 0;
+ } else if (c == ')') {
+ Putc(c, ts);
+ plevel -= indent;
+ empty = 0;
+ } else if (c == '{') {
+ Putc(c, ts);
+ Putc('\n', ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', f);
+ Printf(f, "%s", ts);
+ Clear(ts);
+ level += indent;
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ empty = 0;
+ } else if (c == '}') {
+ if (!empty) {
+ Putc('\n', ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', f);
+ Printf(f, "%s", ts);
+ Clear(ts);
+ }
+ level -= indent;
+ Putc(c, ts);
+ empty = 0;
+ } else if (c == '\n') {
+ Putc(c, ts);
+ empty = 0;
+ if (!empty) {
+ int slevel = level;
+ if (label && (slevel >= indent))
+ slevel -= indent;
+ if ((Char(ts))[0] != '#') {
+ for (i = 0; i < slevel; i++)
+ Putc(' ', f);
+ }
+ Printf(f, "%s", ts);
+ for (i = 0; i < plevel; i++)
+ Putc(' ', f);
+ }
+ Clear(ts);
+ label = 0;
+ empty = 1;
+ } else if (c == '/') {
+ empty = 0;
+ Putc(c, ts);
+ c = Getc(str);
+ if (c != EOF) {
+ Putc(c, ts);
+ if (c == '/') { /* C++ comment */
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, str);
+ break;
+ }
+ Putc(c, ts);
+ }
+ } else if (c == '*') { /* C comment */
+ int endstar = 0;
+ while ((c = Getc(str)) != EOF) {
+ if (endstar && c == '/') { /* end of C comment */
+ Putc(c, ts);
+ break;
+ }
+ endstar = (c == '*');
+ Putc(c, ts);
+ if (c == '\n') { /* multi-line C comment. Could be improved slightly. */
+ for (i = 0; i < level; i++)
+ Putc(' ', ts);
+ }
+ }
+ }
+ }
+ } else {
+ if (!empty || !isspace(c)) {
+ Putc(c, ts);
+ empty = 0;
+ }
+ }
+ }
+ if (!empty)
+ Printf(f, "%s", ts);
+ Delete(ts);
+ Printf(f, "\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_compact_print()
+ *
+ * Formats a wrapper function and fixes up the indentation.
+ * Print out in compact format, with Compact enabled.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_compact_print(String *str, File *f) {
+ String *ts, *tf; /*temp string & temp file */
+ int level = 0;
+ int c, i;
+ int empty = 1;
+ int indent = 2;
+
+ ts = NewStringEmpty();
+ tf = NewStringEmpty();
+ Seek(str, 0, SEEK_SET);
+
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\"') { /* string 1 */
+ empty = 0;
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\"')
+ break;
+ }
+ } else if (c == '\'') { /* string 2 */
+ empty = 0;
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\'')
+ break;
+ }
+ } else if (c == '{') { /* start of {...} */
+ empty = 0;
+ Putc(c, ts);
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Clear(ts);
+ level += indent;
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ } else if (c == '}') { /* end of {...} */
+ empty = 0;
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Putc(c, tf);
+ Clear(ts);
+ level -= indent;
+ } else if (c == '\n') { /* line end */
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c))
+ break;
+ }
+ if (c == '#') {
+ Putc('\n', ts);
+ } else if (c == '}') {
+ Putc(' ', ts);
+ } else if ((c != EOF) || (Len(ts) != 0)) {
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Clear(ts);
+ }
+ Ungetc(c, str);
+
+ empty = 1;
+ } else if (c == '/') { /* comment */
+ empty = 0;
+ c = Getc(str);
+ if (c != EOF) {
+ if (c == '/') { /* C++ comment */
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ } else if (c == '*') { /* C comment */
+ int endstar = 0;
+ while ((c = Getc(str)) != EOF) {
+ if (endstar && c == '/') { /* end of C comment */
+ break;
+ }
+ endstar = (c == '*');
+ }
+ } else {
+ Putc('/', ts);
+ Putc(c, ts);
+ }
+ }
+ } else if (c == '#') { /* Preprocessor line */
+ Putc('#', ts);
+ while ((c = Getc(str)) != EOF) {
+ Putc(c, ts);
+ if (c == '\\') { /* Continued line of the same PP */
+ c = Getc(str);
+ if (c == '\n')
+ Putc(c, ts);
+ else
+ Ungetc(c, str);
+ } else if (c == '\n')
+ break;
+ }
+ if (!empty) {
+ Append(tf, "\n");
+ }
+ Append(tf, ts);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ Clear(ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ empty = 1;
+ } else {
+ if (!empty || !isspace(c)) {
+ Putc(c, ts);
+ empty = 0;
+ }
+ }
+ }
+ if (!empty) {
+ Append(tf, ts);
+ }
+ if (Len(tf) != 0)
+ Printf(f, "%s", tf);
+ Delete(ts);
+ Delete(tf);
+ Printf(f, "\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_print()
+ *
+ * Print out a wrapper function. Does pretty or compact printing as well.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_print(Wrapper *w, File *f) {
+ String *str;
+
+ str = NewStringEmpty();
+ Printf(str, "%s\n", w->def);
+ Printf(str, "%s\n", w->locals);
+ Printf(str, "%s\n", w->code);
+ if (Compact_mode == 1)
+ Wrapper_compact_print(str, f);
+ else
+ Wrapper_pretty_print(str, f);
+
+ Delete(str);
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_add_local()
+ *
+ * Adds a new local variable declaration to a function. Returns -1 if already
+ * present (which may or may not be okay to the caller).
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ /* See if the local has already been declared */
+ if (Getattr(w->localh, name)) {
+ return -1;
+ }
+ Setattr(w->localh, name, decl);
+ Printf(w->locals, "%s;\n", decl);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_add_localv()
+ *
+ * Same as add_local(), but allows a NULL terminated list of strings to be
+ * used as a replacement for decl. This saves the caller the trouble of having
+ * to manually construct the 'decl' string before calling.
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
+ va_list ap;
+ int ret;
+ String *decl;
+ DOH *obj;
+ decl = NewStringEmpty();
+ va_start(ap, name);
+
+ obj = va_arg(ap, void *);
+ while (obj) {
+ Append(decl, obj);
+ Putc(' ', decl);
+ obj = va_arg(ap, void *);
+ }
+ va_end(ap);
+
+ ret = Wrapper_add_local(w, name, decl);
+ Delete(decl);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_check_local()
+ *
+ * Check to see if a local name has already been declared
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name) {
+ if (Getattr(w->localh, name)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_new_local()
+ *
+ * Adds a new local variable with a guarantee that a unique local name will be
+ * used. Returns the name that was actually selected.
+ * ----------------------------------------------------------------------------- */
+
+char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ int i;
+ String *nname = NewString(name);
+ String *ndecl = NewString(decl);
+ char *ret;
+
+ i = 0;
+
+ while (Wrapper_check_local(w, nname)) {
+ Clear(nname);
+ Printf(nname, "%s%d", name, i);
+ i++;
+ }
+ Replace(ndecl, name, nname, DOH_REPLACE_ID);
+ Setattr(w->localh, nname, ndecl);
+ Printf(w->locals, "%s;\n", ndecl);
+ ret = Char(nname);
+ Delete(nname);
+ Delete(ndecl);
+ return ret; /* Note: nname should still exists in the w->localh hash */
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_new_localv()
+ *
+ * Same as add_local(), but allows a NULL terminated list of strings to be
+ * used as a replacement for decl. This saves the caller the trouble of having
+ * to manually construct the 'decl' string before calling.
+ * ----------------------------------------------------------------------------- */
+
+char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
+ va_list ap;
+ char *ret;
+ String *decl;
+ DOH *obj;
+ decl = NewStringEmpty();
+ va_start(ap, name);
+
+ obj = va_arg(ap, void *);
+ while (obj) {
+ Append(decl, obj);
+ Putc(' ', decl);
+ obj = va_arg(ap, void *);
+ }
+ va_end(ap);
+
+ ret = Wrapper_new_local(w, name, decl);
+ Delete(decl);
+ return ret;
+}