diff options
author | Dave Beazley <dave-swig@dabeaz.com> | 2002-11-30 22:01:28 +0000 |
---|---|---|
committer | Dave Beazley <dave-swig@dabeaz.com> | 2002-11-30 22:01:28 +0000 |
commit | 12a43edc2df8853e8e0315f742e57be88f0c4269 (patch) | |
tree | e3237f5f8c0a67c9bfa9bb5d6d095a739a49e4b2 /Source | |
parent | 5fcae5eb66d377e1c3f81da7465c44a62295a72b (diff) | |
download | swig-12a43edc2df8853e8e0315f742e57be88f0c4269.tar.gz |
The great merge
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4141 626c5289-ae23-0410-ae9c-e8d60b6d4f22
Diffstat (limited to 'Source')
89 files changed, 32438 insertions, 14632 deletions
diff --git a/Source/CParse/.cvsignore b/Source/CParse/.cvsignore new file mode 100644 index 000000000..82e5e2e10 --- /dev/null +++ b/Source/CParse/.cvsignore @@ -0,0 +1,9 @@ +Makefile +.deps +parser.c +parser.h +libcparse.a +cscanner.o +parser.o +y.tab.c +y.tab.h diff --git a/Source/CParse/Makefile.in b/Source/CParse/Makefile.in new file mode 100644 index 000000000..648d1b9f9 --- /dev/null +++ b/Source/CParse/Makefile.in @@ -0,0 +1,69 @@ +####################################################################### +# $Header$ +####################################################################### + +srcdir = @srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh +CC = @CC@ +CFLAGS = @CFLAGS@ +YACC = @YACC@ +AR = @AR@ +RANLIB = @RANLIB@ + +TARGET = libcparse.a + +OBJS = parser.@OBJEXT@ cscanner.@OBJEXT@ templ.@OBJEXT@ util.@OBJEXT@ + +SRCS = cscanner.c templ.c util.c + +PARSER = $(srcdir)/parser.y +INCLUDES = -I$(srcdir)/../Include \ + -I$(srcdir)/. \ + -I$(srcdir)/../Swig \ + -I$(srcdir)/../Preprocessor \ + -I$(srcdir)/../DOH/Include \ + -I../Include \ + -I. + +.c.@OBJEXT@: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $*.@OBJEXT@ $< + +cparse: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) cr $(TARGET) $(OBJS) + $(RANLIB) $(TARGET) + +parser.@OBJEXT@: parser.c + $(CC) $(INCLUDES) $(CFLAGS) $< -c -o parser.@OBJEXT@ + +parser.c parser.h: $(PARSER) + $(YACC) @YFLAGS@ $(PARSER) + @cp y.tab.h parser.h + @cp y.tab.c parser.c + +scanner.@OBJEXT@: parser.h + +parser:: + @cp y.tab.c.bison parser.c + @cp y.tab.h.bison parser.h + @cp y.tab.h.bison y.tab.h + $(CC) $(CFLAGS) parser.c -c -o parser.@OBJEXT@ + +clean:: + rm -f *.@OBJEXT@ $(TARGET) y.tab.c y.tab.h + +nuke:: + rm -f Makefile *~ + + + + + + + + + + diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h new file mode 100644 index 000000000..fa323768e --- /dev/null +++ b/Source/CParse/cparse.h @@ -0,0 +1,12 @@ +#include "swig.h" +#include "swigwarn.h" +#include "swigver.h" + +extern char *cparse_file; +extern int cparse_line; +extern int cparse_cplusplus; +extern int cparse_start_line; +extern void Swig_cparse_replace_descriptor(String *s); +extern void Swig_cparse_cplusplus(int); +extern void Swig_cparse_debug_templates(int); + diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c new file mode 100644 index 000000000..1d185f597 --- /dev/null +++ b/Source/CParse/cscanner.c @@ -0,0 +1,1290 @@ +/* ----------------------------------------------------------------------------- + * scanner.cxx + * + * SWIG1.1 tokenizer. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2000. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_cscanner_c[] = "$Header$"; + +#include "cparse.h" +#include "parser.h" +#include <string.h> +#include <ctype.h> + +#define YYBSIZE 8192 + +typedef struct InFile { + DOHFile *f; + int line_number; + char *in_file; + struct InFile *prev; +} InFile; + +InFile *in_head; + +DOHFile *LEX_in = 0; +static DOHString *header = 0; +static DOHString *comment = 0; +DOHString *scanner_ccode = 0; /* String containing C code */ +static char *yybuffer = 0; + +static char yytext[YYBSIZE]; +static int yylen = 0; +int cparse_line = 1; +char *cparse_file; +int cparse_start_line = 0; +static int comment_start; +static int scan_init = 0; +static int num_brace = 0; +static int last_brace = 0; +static int last_id = 0; +static int rename_active = 0; + int cparse_cplusplus; + +/* ----------------------------------------------------------------------------- + * Swig_cparse_cplusplus() + * ----------------------------------------------------------------------------- */ + +void +Swig_cparse_cplusplus(int v) { + cparse_cplusplus = v; +} + +/* ---------------------------------------------------------------------- + * locator() + * + * Support for locator strings. These are strings of the form + * @filename,line,id@ emitted by the SWIG preprocessor. They + * are primarily used for macro line number reporting + * ---------------------------------------------------------------------- */ + +typedef struct Locator { + char *filename; + int line_number; + struct Locator *next; +} Locator; + +static Locator *locs = 0; + +static void +scanner_locator(String *loc) { + int c; + Locator *l; + Seek(loc,1,SEEK_SET); + c = Getc(loc); + if (c == '@') { + /* Empty locator. We pop the last location off */ + if (locs) { + cparse_file = locs->filename; + cparse_line = locs->line_number; + l = locs->next; + free(locs); + locs = l; + } + /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line);*/ + return; + } + + /* We're going to push a new location */ + l = (Locator *) malloc(sizeof(Locator)); + l->filename = cparse_file; + l->line_number = cparse_line; + l->next = locs; + locs = l; + + /* Now, parse the new location out of the locator string */ + { + String *fn = NewString(""); + Putc(c,fn); + + while ((c = Getc(loc)) != EOF) { + if ((c == '@') || (c == ',')) break; + Putc(c,fn); + } + + cparse_file = Swig_copy_string(Char(fn)); + Clear(fn); + + cparse_line = 1; + /* Get the line number */ + while ((c = Getc(loc)) != EOF) { + if ((c == '@') || (c == ',')) break; + Putc(c,fn); + } + + cparse_line = atoi(Char(fn)); + Clear(fn); + + /* Get the rest of it */ + while (( c= Getc(loc)) != EOF) { + if (c == '@') break; + Putc(c,fn); + } + /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */ + Delete(fn); + } +} + +/************************************************************** + * scanner_init() + * + * Initialize buffers + **************************************************************/ + +void scanner_init() { + yybuffer = (char *) malloc(YYBSIZE); + scan_init = 1; + header = NewString(""); + comment = NewString(""); + scanner_ccode = NewString(""); +} + +/************************************************************** + * scanner_file(FILE *f) + * + * Start reading from new file + **************************************************************/ +void scanner_file(DOHFile *f) { + InFile *in; + + in = (InFile *) malloc(sizeof(InFile)); + in->f = f; + in->in_file = cparse_file; + in->line_number = 1; + if (!in_head) in->prev = 0; + else in->prev = in_head; + in_head = in; + LEX_in = f; + cparse_line = 1; +} + +/************************************************************** + * scanner_close() + * + * Close current input file and go to next + **************************************************************/ + +void scanner_close() { + InFile *p; + if (!in_head) return; + Delete(LEX_in); + p = in_head->prev; + if (p != 0) { + LEX_in = p->f; + cparse_line = p->line_number; + cparse_file = p->in_file; + } else { + LEX_in = 0; + } + free(in_head); + in_head = p; +} + +/************************************************************** + * char nextchar() + * + * gets next character from input. + * If we're in inlining mode, we actually retrieve a character + * from inline_yybuffer instead. + **************************************************************/ + +char nextchar() { + int c = 0; + + while (LEX_in) { + c = Getc(LEX_in); + if (c == EOF) { + scanner_close(); + } else { + break; + } + } + if (!LEX_in) return 0; + if (yylen >= YYBSIZE) { + Printf(stderr,"** FATAL ERROR. Buffer overflow in scanner.cxx.\nReport this to swig-dev@cs.uchicago.edu.\n"); + exit (EXIT_FAILURE); + } + yytext[yylen] = c; + yylen++; + if (c == '\n') { + cparse_line++; + } + return(c); +} + +void retract(int n) { + int i; + for (i = 0; i < n; i++) { + yylen--; + if (yylen >= 0) { + Ungetc(yytext[yylen],LEX_in); + if (yytext[yylen] == '\n') { + cparse_line--; + } + } + } + if (yylen < 0) yylen = 0; +} + +/************************************************************** + * start_inline(char *text, int line) + * + * This grabs a chunk of text and tries to inline it into + * the current file. (This is kind of wild, but cool when + * it works). + * + * If we're already in inlining mode, we will save the code + * as a new fragment. + **************************************************************/ + +void start_inline(char *text, int line) { + InFile *in; + + /* Save current state */ + in_head->line_number = cparse_line; + in_head->in_file = cparse_file; + + in = (InFile *) malloc(sizeof(InFile)); + in->f = NewString(text); + Seek(in->f,0,SEEK_SET); + in->in_file = Swig_copy_string(cparse_file); + in->line_number = line; + in->prev = in_head; + in_head = in; + LEX_in = in->f; + cparse_line = line; +} + +/************************************************************** + * yycomment(char *, int line) + * + * Inserts a comment into a documentation entry. + **************************************************************/ + +void yycomment(char *a, int b, int c) { +} + + +/* ----------------------------------------------------------------------------- + * skip_balanced() + * + * Skips a piece of code enclosed in begin/end symbols such as '{...}' or + * (...). Ignores symbols inside comments or strings. + * ----------------------------------------------------------------------------- */ + +void +skip_balanced(int startchar, int endchar) { + char c; + int num_levels = 1; + int state = 0; + char temp[2] = {0,0}; + int start_line = cparse_line; + + Clear(scanner_ccode); + Putc(startchar,scanner_ccode); + temp[0] = (char) startchar; + while (num_levels > 0) { + c = nextchar(); + if (c == 0) { + Swig_error(cparse_file, start_line, "Missing '%c'. Reached end of input.\n", endchar); + return; + } + Putc(c,scanner_ccode); + switch(state) { + case 0: + if (c == startchar) num_levels++; + else if (c == endchar) num_levels--; + else if (c == '/') state = 10; + else if (c == '\"') state = 20; + else if (c == '\'') state = 30; + break; + case 10: + if (c == '/') state = 11; + else if (c == '*') state = 12; + else state = 0; + break; + case 11: + if (c == '\n') state = 0; + else state = 11; + break; + case 12: + if (c == '*') state = 13; + break; + case 13: + if (c == '*') state = 13; + else if (c == '/') state = 0; + else state = 12; + break; + case 20: + if (c == '\"') state = 0; + else if (c == '\\') state = 21; + break; + case 21: + state = 20; + break; + case 30: + if (c == '\'') state = 0; + else if (c == '\\') state = 31; + break; + case 31: + state = 30; + break; + default: + break; + } + yylen = 0; + } + if (endchar == '}') num_brace--; + return; +} + +/************************************************************** + * void skip_decl(void) + * + * This tries to skip over an entire declaration. For example + * + * friend ostream& operator<<(ostream&, const char *s); + * + * or + * friend ostream& operator<<(ostream&, const char *s) { }; + * + **************************************************************/ + +void skip_decl(void) { + char c; + int done = 0; + while (!done) { + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,cparse_line,"Missing semicolon. Reached end of input.\n"); + return; + } + if (c == '{') { + last_brace = num_brace; + num_brace++; + break; + } + yylen = 0; + if (c == ';') done = 1; + } + if (!done) { + while (num_brace > last_brace) { + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,cparse_line,"Missing '}'. Reached end of input.\n"); + return; + } + if (c == '{') num_brace++; + if (c == '}') num_brace--; + yylen = 0; + } + } +} + +/* This function is called when a backslash is found in a string */ +static void get_escape() { + int result = 0; + int state = 0; + char c; + + while(1) { + c = nextchar(); + if (c == 0) break; + switch(state) { + case 0: + if (c == 'n') { + yytext[yylen-1] = '\n'; + return; + } + if (c == 'r') { + yytext[yylen-1] = '\r'; + return; + } + if (c == 't') { + yytext[yylen-1] = '\t'; + return; + } + if (c == 'a') { + yytext[yylen-1] = '\a'; + return; + } + if (c == 'b') { + yytext[yylen-1] = '\b'; + return; + } + if (c == 'f') { + yytext[yylen-1] = '\f'; + return; + } + if (c == '\\') { + yytext[yylen-1] = '\\'; + return; + } + if (c == 'v') { + yytext[yylen-1] = '\v'; + return; + } + if (c == 'e') { + yytext[yylen-1] = '\033'; + return; + } + if (c == '\'') { + yytext[yylen-1] = '\''; + return; + } + if (c == '\"') { + yytext[yylen-1] = '\"'; + return; + } + if (c == '\n') { + yylen--; + return; + } + if (c == '0') { + state = 10; + } + else if (c == 'x') { + state = 20; + } else { + yytext[yylen-1] = '\\'; + yytext[yylen] = c; + yylen++; + return; + } + break; + case 10: + if (!isdigit(c)) { + retract(1); + yytext[yylen-1] = (char) result; + return; + } + result = (result << 3) + (c - '0'); + yylen--; + break; + case 20: + if (!isxdigit(c)) { + retract(1); + yytext[yylen-1] = (char) result; + return; + } + if (isdigit(c)) + result = (result << 4) + (c - '0'); + else + result = (result << 4) + (10 + tolower(c) - 'a'); + yylen--; + break; + } + } + return; +} + +/************************************************************** + * int yylook() + * + * Lexical scanner. + * See Aho,Sethi, and Ullman, pg. 106 + **************************************************************/ + +int yylook(void) { + + int state; + char c = 0; + + state = 0; + yylen = 0; + while(1) { + +/* printf("State = %d\n", state); */ + switch(state) { + + case 0 : + if((c = nextchar()) == 0) return (0); + + /* Process delimeters */ + + if (c == '\n') { + state = 0; + yylen = 0; + last_id = 0; + } else if (isspace(c) || (c=='\\')) { + state = 0; + yylen = 0; + last_id = 0; + } + + else if ((isalpha(c)) || (c == '_')) state = 7; + else if (c == '$') state = 75; + + /* Look for single character symbols */ + + else if (c == '(') return (LPAREN); + else if (c == ')') return (RPAREN); + else if (c == ';') return (SEMI); + else if (c == ',') return (COMMA); + else if (c == '*') return (STAR); + else if (c == '}') { + num_brace--; + if (num_brace < 0) { + Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '}'\n"); + state = 0; + num_brace = 0; + } else { + return (RBRACE); + } + } + else if (c == '{') { + last_brace = num_brace; + num_brace++; + return (LBRACE); + } + else if (c == '=') return (EQUAL); + else if (c == '+') return (PLUS); + else if (c == '-') return (MINUS); + else if (c == '&') { + state = 300; + } + else if (c == '|') { + state = 301; + } + else if (c == '^') return (XOR); + else if (c == '<') state = 60; + else if (c == '>') state = 61; + else if (c == '~') { + return (NOT); + } + else if (c == '!') return (LNOT); + else if (c == '\\') { + state = 99; + } + else if (c == '[') return (LBRACKET); + else if (c == ']') return (RBRACKET); + + /* Look for multi-character sequences */ + + else if (c == '/') state = 1; /* Comment (maybe) */ + else if (c == '\"') state = 2; /* Possibly a string */ + else if (c == '#') state = 3; /* CPP */ + else if (c == '%') state = 4; /* Directive */ + else if (c == '@') state = 4; /* Objective C keyword */ + else if (c == ':') state = 5; /* maybe double colon */ + else if (c == '0') state = 83; /* An octal or hex value */ + else if (c == '\'') state = 9; /* A character constant */ + else if (c == '.') state = 100; /* Maybe a number, maybe just a period */ + else if (c == '`') { + state = 200; /* Back-tick type */ + yylen = 0; + } + else if (isdigit(c)) state = 8; /* A numerical value */ + + else state = 99; + break; + case 1: /* Comment block */ + if ((c = nextchar()) == 0) return(0); + if (c == '/') { + comment_start = cparse_line; + Clear(comment); + state = 10; /* C++ style comment */ + } else if (c == '*') { + comment_start = cparse_line; + Clear(comment); + state = 12; /* C style comment */ + } else { + retract(1); + return(SLASH); + } + break; + case 300: /* & or && */ + if ((c = nextchar()) == 0) return(AND); + if (c == '&') return(LAND); + else { + retract(1); + return(AND); + } + + case 301: /* | or || */ + if ((c = nextchar()) == 0) return(OR); + if (c == '|') return(LOR); + else { + retract(1); + return(OR); + } + case 10: /* C++ style comment */ + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,-1, "Unterminated comment detected.\n"); + return 0; + } + if (c == '\n') { + Putc(c,comment); + /* Add the comment to documentation */ + /* yycomment(Char(comment),comment_start, column_start);*/ + yylen = 0; + state = 0; + } else { + state = 10; + Putc(c,comment); + yylen = 0; + } + break; + + case 12: /* C style comment block */ + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,-1,"Unterminated comment detected.\n"); + return 0; + } + if (c == '*') { + state = 13; + } else { + Putc(c,comment); + yylen = 0; + state = 12; + } + break; + case 13: /* Still in C style comment */ + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,-1,"Unterminated comment detected.\n"); + return 0; + } + if (c == '*') { + Putc(c,comment); + state = 13; + } else if (c == '/') { + + /* Look for locator markers */ + { + char *loc = Char(comment); + if (Len(comment)) { + if ((*loc == '@') && (*(loc+Len(comment)-1) == '@')) { + /* Locator */ + scanner_locator(comment); + } + } + } + /* yycomment(Char(comment),comment_start,column_start); */ + yylen = 0; + state = 0; + } else { + Putc('*',comment); + Putc(c,comment); + yylen = 0; + state = 12; + } + break; + + case 2: /* Processing a string */ + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,-1, "Unterminated string detected.\n"); + return 0; + } + if (c == '\"') { + yytext[yylen-1] = 0; + yylval.id = Swig_copy_string(yytext+1); + return(STRING); + } else if (c == '\\') { + yylen--; + get_escape(); + break; + } else state = 2; + break; + + case 3: /* a CPP directive */ + if (( c= nextchar()) == 0) return 0; + if (c == '\n') { + retract(1); + yytext[yylen] = 0; + yylval.id = yytext; + return(POUND); + } + break; + + case 4: /* A wrapper generator directive (maybe) */ + if (( c= nextchar()) == 0) return 0; + if (c == '{') { + state = 40; /* Include block */ + Clear(header); + cparse_start_line = cparse_line; + } else if ((isalpha(c)) || (c == '_')) state = 7; + else if (c == '}') { + Swig_error(cparse_file,cparse_line, "Misplaced %%}.\n"); + return 0; + } else { + retract(1); + return(MODULO); + } + break; + + case 40: /* Process an include block */ + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,-1, "Unterminated include block detected.\n"); + return 0; + } + yylen = 0; + if (c == '%') state = 41; + else { + Putc(c,header); + yylen = 0; + state = 40; + } + break; + case 41: /* Still processing include block */ + if ((c = nextchar()) == 0) { + Swig_error(cparse_file,-1, "Unterminated include block detected.\n"); + return 0; + } + if (c == '}') { + yylval.str = NewString(header); + return(HBLOCK); + } else { + Putc('%',header); + Putc(c,header); + yylen = 0; + state = 40; + } + break; + + case 5: /* Maybe a double colon */ + + if (( c= nextchar()) == 0) return 0; + if ( c == ':') { + state = 51; + } else { + retract(1); + return COLON; + } + break; + case 51: /* Maybe a ::*, ::~, or :: */ + if (( c = nextchar()) == 0) return 0; + if (c == '*') { + return DSTAR; + } if (c == '~') { + return DCNOT; + } else { + retract(1); + if (!last_id) { + retract(2); + return NONID; + } else { + return DCOLON; + } + } + + case 60: /* shift operators */ + if ((c = nextchar()) == 0) return (0); + if (c == '<') return LSHIFT; + else { + retract(1); + return LESSTHAN; + } + break; + case 61: + if ((c = nextchar()) == 0) return (0); + if (c == '>') return RSHIFT; + else { + retract(1); + return GREATERTHAN; + } + break; + case 7: /* Identifier */ + if ((c = nextchar()) == 0) return(0); + if (isalnum(c) || (c == '_') || (c == '.') || (c == '$')) { + state = 7; + } else { + retract(1); + return(ID); + } + break; + case 75: /* Special identifier $*/ + if ((c = nextchar()) == 0) return(0); + if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) { + state = 7; + } else { + retract(1); + return(ID); + } + break; + + case 8: /* A numerical digit */ + if ((c = nextchar()) == 0) return(0); + if (c == '.') {state = 81;} + else if ((c == 'e') || (c == 'E')) {state = 86;} + else if ((c == 'f') || (c == 'F')) { + return(NUM_FLOAT); + } + else if (isdigit(c)) { state = 8;} + else if ((c == 'l') || (c == 'L')) { + state = 87; + } else if ((c == 'u') || (c == 'U')) { + state = 88; + } else { + retract(1); + return(NUM_INT); + } + break; + case 81: /* A floating pointer number of some sort */ + if ((c = nextchar()) == 0) return(0); + if (isdigit(c)) state = 81; + else if ((c == 'e') || (c == 'E')) state = 82; + else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) { + return(NUM_FLOAT); + } else { + retract(1); + return(NUM_FLOAT); + } + break; + case 82: + if ((c = nextchar()) == 0) return(0); + if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86; + else { + retract(2); + yytext[yylen-1] = 0; + return(NUM_INT); + } + break; + case 83: + /* Might be a hexidecimal or octal number */ + if ((c = nextchar()) == 0) return(0); + if (isdigit(c)) state = 84; + else if ((c == 'x') || (c == 'X')) state = 85; + else if (c == '.') state = 81; + else if ((c == 'l') || (c == 'L')) { + state = 87; + } else if ((c == 'u') || (c == 'U')) { + state = 88; + } else { + retract(1); + return(NUM_INT); + } + break; + case 84: + /* This is an octal number */ + if ((c = nextchar()) == 0) return (0); + if (isdigit(c)) state = 84; + else if ((c == 'l') || (c == 'L')) { + state = 87; + } else if ((c == 'u') || (c == 'U')) { + state = 88; + } else { + retract(1); + return(NUM_INT); + } + break; + case 85: + /* This is an hex number */ + if ((c = nextchar()) == 0) return (0); + if ((isdigit(c)) || (c=='a') || (c=='b') || (c=='c') || + (c=='d') || (c=='e') || (c=='f') || (c=='A') || + (c=='B') || (c=='C') || (c=='D') || (c=='E') || + (c=='F')) + state = 85; + else if ((c == 'l') || (c == 'L')) { + state = 87; + } else if ((c == 'u') || (c == 'U')) { + state = 88; + } else { + retract(1); + return(NUM_INT); + } + break; + + case 86: + /* Rest of floating point number */ + + if ((c = nextchar()) == 0) return (0); + if (isdigit(c)) state = 86; + else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) { + return(NUM_FLOAT); + } else { + retract(1); + return(NUM_FLOAT); + } + /* Parse a character constant. ie. 'a' */ + break; + + case 87 : + /* A long integer of some sort */ + if ((c = nextchar()) == 0) return (NUM_LONG); + if ((c == 'u') || (c == 'U')) { + return(NUM_ULONG); + } else if ((c == 'l') || (c == 'L')) { + state = 870; + } else { + retract(1); + return(NUM_LONG); + } + break; + + case 870: + if ((c = nextchar()) == 0) return (NUM_LONGLONG); + if ((c == 'u') || (c == 'U')) { + return (NUM_ULONGLONG); + } else { + retract(1); + return(NUM_LONGLONG); + } + + case 88: + /* An unsigned integer of some sort */ + if ((c = nextchar()) == 0) return (NUM_UNSIGNED); + if ((c == 'l') || (c == 'L')) { + state = 880; + } else { + retract(1); + return(NUM_UNSIGNED); + } + break; + + case 880: + if ((c = nextchar()) == 0) return (NUM_ULONG); + if ((c == 'l') || (c == 'L')) return (NUM_ULONGLONG); + else { + retract(1); + return(NUM_ULONG); + } + + case 9: + if ((c = nextchar()) == 0) return (0); + if (c == '\\') { + yylen--; + get_escape(); + } else if (c == '\'') { + yytext[yylen-1] = 0; + yylval.str = NewString(yytext+1); + if (yylen == 2) { + Swig_error(cparse_file, cparse_line, "Empty character constant\n"); + } + return(CHARCONST); + } + break; + + case 100: + if ((c = nextchar()) == 0) return (0); + if (isdigit(c)) state = 81; + else { + retract(1); + return(PERIOD); + } + break; + case 200: + if ((c = nextchar()) == 0) return (0); + if (c == '`') { + yytext[yylen-1] = 0; + yylval.type = NewString(yytext); + return(TYPE_RAW); + } + break; + + default: + Swig_error(cparse_file, cparse_line, "Illegal character '%c'=%d.\n",c,c); + state = 0; + return(ILLEGAL); + } + } +} + +static int check_typedef = 0; + +void scanner_check_typedef() { + check_typedef = 1; +} + +void scanner_ignore_typedef() { + check_typedef = 0; +} + +void scanner_last_id(int x) { + last_id = x; +} + +void scanner_clear_rename() { + rename_active = 0; +} + +static int next_token = 0; +void scanner_next_token(int tok) { + next_token = tok; +} + +/************************************************************** + * int yylex() + * + * Gets the lexene and returns tokens. + *************************************************************/ + +int yylex(void) { + + int l; + + if (!scan_init) { + scanner_init(); + } + + if (next_token) { + l = next_token; + next_token = 0; + return l; + } + l = yylook(); + + + if (l == NONID) { + last_id = 1; + } else { + last_id = 0; + } + + /* We got some sort of non-white space object. We set the start_line + variable unless it has already been set */ + + if (!cparse_start_line) { + cparse_start_line = cparse_line; + } + + /* Copy the lexene */ + + yytext[yylen] = 0; + switch(l) { + + case NUM_INT: + case NUM_FLOAT: + case NUM_ULONG: + case NUM_LONG: + case NUM_UNSIGNED: + case NUM_LONGLONG: + case NUM_ULONGLONG: + if (l == NUM_INT) yylval.dtype.type = T_INT; + if (l == NUM_FLOAT) yylval.dtype.type = T_DOUBLE; + if (l == NUM_ULONG) yylval.dtype.type = T_ULONG; + if (l == NUM_LONG) yylval.dtype.type = T_LONG; + if (l == NUM_UNSIGNED) yylval.dtype.type = T_UINT; + if (l == NUM_LONGLONG) yylval.dtype.type = T_LONGLONG; + if (l == NUM_ULONGLONG) yylval.dtype.type = T_ULONGLONG; + yylval.dtype.val = NewString(yytext); + yylval.dtype.bitfield = 0; + yylval.dtype.throws = 0; + return(l); + break; + + case ID: + + if (yytext[0] != '%') { + /* Look for keywords now */ + + if (strcmp(yytext,"int") == 0) { + yylval.type = NewSwigType(T_INT); + return(TYPE_INT); + } + if (strcmp(yytext,"double") == 0) { + yylval.type = NewSwigType(T_DOUBLE); + return(TYPE_DOUBLE); + } + if (strcmp(yytext,"void") == 0) { + yylval.type = NewSwigType(T_VOID); + return(TYPE_VOID); + } + if (strcmp(yytext,"char") == 0) { + yylval.type = NewSwigType(T_CHAR); + return(TYPE_CHAR); + } + if (strcmp(yytext,"short") == 0) { + yylval.type = NewSwigType(T_SHORT); + return(TYPE_SHORT); + } + if (strcmp(yytext,"long") == 0) { + yylval.type = NewSwigType(T_LONG); + return(TYPE_LONG); + } + if (strcmp(yytext,"float") == 0) { + yylval.type = NewSwigType(T_FLOAT); + return(TYPE_FLOAT); + } + if (strcmp(yytext,"signed") == 0) { + yylval.type = NewSwigType(T_INT); + return(TYPE_SIGNED); + } + if (strcmp(yytext,"unsigned") == 0) { + yylval.type = NewSwigType(T_UINT); + return(TYPE_UNSIGNED); + } + if (strcmp(yytext,"bool") == 0) { + yylval.type = NewSwigType(T_BOOL); + return(TYPE_BOOL); + } + /* C++ keywords */ + + if (cparse_cplusplus) { + if (strcmp(yytext,"class") == 0) return(CLASS); + if (strcmp(yytext,"private") == 0) return(PRIVATE); + if (strcmp(yytext,"public") == 0) return(PUBLIC); + if (strcmp(yytext,"protected") == 0) return(PROTECTED); + if (strcmp(yytext,"friend") == 0) return(FRIEND); + if (strcmp(yytext,"virtual") == 0) return(VIRTUAL); + if (strcmp(yytext,"operator") == 0) { + String *s = NewString("operator"); + int c; + int state = 0; + int sticky = 0; + int isconversion = 0; + int count = 0; + while ((c = nextchar())) { + if (((c == '(') || (c == ';')) && state) { + retract(1); + break; + } + count++; + if (!isspace(c)) { + if ((!state) && (isalpha(c))) isconversion = 1; + if (!state && !sticky) Putc(' ',s); + Putc(c,s); + sticky = 0; + state = 1; + } else { + if (!sticky) Putc(' ',s); + sticky = 1; + } + } + Chop(s); + yylval.str = s; + while(Replaceall(s,"[ ", "[")); + if (isconversion) { + String *ns = Swig_symbol_string_qualify(s,0); + yylval.str = ns; + } + if (isconversion && !rename_active) { + char *t = Char(s) + 9; + if (!((strcmp(t,"new") == 0) || (strcmp(t,"delete") == 0) + || (strcmp(t,"new[]") == 0) || (strcmp(t,"delete[]") == 0))) { + /* retract(strlen(t));*/ + retract(count); + return COPERATOR; + } + } + return(OPERATOR); + } + if (strcmp(yytext,"throw") == 0) return(THROW); + if (strcmp(yytext,"try") == 0) return (yylex()); + if (strcmp(yytext,"catch") == 0) return (CATCH); + if (strcmp(yytext,"inline") == 0) return(yylex()); + if (strcmp(yytext,"mutable") == 0) return(yylex()); + if (strcmp(yytext,"explicit") == 0) return(yylex()); + if (strcmp(yytext,"export") == 0) return(yylex()); + if (strcmp(yytext,"typename") == 0) return (TYPENAME); + if (strcmp(yytext,"template") == 0) { + yylval.ivalue = cparse_line; + return(TEMPLATE); + } + if (strcmp(yytext,"delete") == 0) { + return(DELETE); + } + if (strcmp(yytext,"using") == 0) { + return(USING); + } + if (strcmp(yytext,"namespace") == 0) { + return(NAMESPACE); + } + } else { + if (strcmp(yytext,"class") == 0) { + Swig_warning(WARN_PARSE_CLASS_KEYWORD,cparse_file,cparse_line, "class keyword used, but not in C++ mode.\n"); + } + } + + /* Objective-C keywords */ +#ifdef OBJECTIVEC + if ((ObjC) && (yytext[0] == '@')) { + if (strcmp(yytext,"@interface") == 0) return (OC_INTERFACE); + if (strcmp(yytext,"@end") == 0) return (OC_END); + if (strcmp(yytext,"@public") == 0) return (OC_PUBLIC); + if (strcmp(yytext,"@private") == 0) return (OC_PRIVATE); + if (strcmp(yytext,"@protected") == 0) return (OC_PROTECTED); + if (strcmp(yytext,"@class") == 0) return(OC_CLASS); + if (strcmp(yytext,"@implementation") == 0) return(OC_IMPLEMENT); + if (strcmp(yytext,"@protocol") == 0) return(OC_PROTOCOL); + } +#endif + + /* Misc keywords */ + + if (strcmp(yytext,"extern") == 0) return(EXTERN); + if (strcmp(yytext,"const") == 0) return(CONST); + if (strcmp(yytext,"static") == 0) return(STATIC); + if (strcmp(yytext,"struct") == 0) return(STRUCT); + if (strcmp(yytext,"union") == 0) return(UNION); + if (strcmp(yytext,"enum") == 0) return(ENUM); + if (strcmp(yytext,"sizeof") == 0) return(SIZEOF); + + if (strcmp(yytext,"typedef") == 0) { + yylval.ivalue = 0; + return(TYPEDEF); + } + + /* Ignored keywords */ + + if (strcmp(yytext,"volatile") == 0) return(VOLATILE); + + /* SWIG directives */ + } else { + if (strcmp(yytext,"%module") == 0) return(MODULE); + if (strcmp(yytext,"%insert") == 0) return(INSERT); + if (strcmp(yytext,"%name") == 0) return(NAME); + if (strcmp(yytext,"%rename") == 0) { + rename_active = 1; + return(RENAME); + } + if (strcmp(yytext,"%namewarn") == 0) { + rename_active = 1; + return (NAMEWARN); + } + if (strcmp(yytext,"%includefile") == 0) return(INCLUDE); + if (strcmp(yytext,"%val") == 0) { + Swig_warning(WARN_DEPRECATED_VAL, cparse_file, cparse_line, "%%val directive deprecated (ignored).\n"); + return (yylex()); + } + if (strcmp(yytext,"%out") == 0) { + Swig_warning(WARN_DEPRECATED_OUT, cparse_file, cparse_line, "%%out directive deprecated (ignored).\n"); + return(yylex()); + } + if (strcmp(yytext,"%constant") == 0) return(CONSTANT); + if (strcmp(yytext,"%typedef") == 0) { + yylval.ivalue = 1; + return(TYPEDEF); + } + if (strcmp(yytext,"%native") == 0) return(NATIVE); + if (strcmp(yytext,"%pragma") == 0) return(PRAGMA); + if (strcmp(yytext,"%extend") == 0) return(EXTEND); + if (strcmp(yytext,"%fragment") == 0) return(FRAGMENT); + if (strcmp(yytext,"%inline") == 0) return(INLINE); + if (strcmp(yytext,"%typemap") == 0) return(TYPEMAP); + if (strcmp(yytext,"%feature") == 0) return(FEATURE); + if (strcmp(yytext,"%except") == 0) return(EXCEPT); + if (strcmp(yytext,"%importfile") == 0) return(IMPORT); + if (strcmp(yytext,"%echo") == 0) return(ECHO); + if (strcmp(yytext,"%apply") == 0) return(APPLY); + if (strcmp(yytext,"%clear") == 0) return(CLEAR); + if (strcmp(yytext,"%types") == 0) return(TYPES); + if (strcmp(yytext,"%parms") == 0) return(PARMS); + if (strcmp(yytext,"%varargs") == 0) return(VARARGS); + if (strcmp(yytext,"%template") == 0) return (SWIGTEMPLATE); + if (strcmp(yytext,"%warn") == 0) return(WARN); + } + /* Have an unknown identifier, as a last step, we'll do a typedef lookup on it. */ + + /* Need to fix this */ + if (check_typedef) { + if (SwigType_istypedef(yytext)) { + yylval.type = NewString(yytext); + return(TYPE_TYPEDEF); + } + } + yylval.id = Swig_copy_string(yytext); + last_id = 1; + return(ID); + case POUND: + return yylex(); + default: + return(l); + } +} diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y new file mode 100644 index 000000000..350e4cdc4 --- /dev/null +++ b/Source/CParse/parser.y @@ -0,0 +1,4568 @@ +%{ +/* ----------------------------------------------------------------------------- + * parser.y + * + * YACC parser for SWIG. The grammar is a somewhat broken subset of C/C++. + * This file is a bit of a mess and probably needs to be rewritten at + * some point. Beware. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2001. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +#define yylex yylex + +char cvsroot_parser_y[] = "$Header$"; + +#include "cparse.h" +#include "preprocessor.h" +#include <ctype.h> + +/* We do this for portability */ +#undef alloca +#define alloca malloc + +/* ----------------------------------------------------------------------------- + * Externals + * ----------------------------------------------------------------------------- */ + +extern int yylex(); +extern void yyerror (const char *s); + +/* scanner.cxx */ + +extern int cparse_line; +extern int cparse_start_line; +extern void skip_balanced(int startchar, int endchar); +extern void skip_decl(void); +extern void scanner_check_typedef(void); +extern void scanner_ignore_typedef(void); +extern void scanner_last_id(int); +extern void scanner_clear_rename(void); +extern void start_inline(char *, int); +extern String *scanner_ccode; +extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms); +extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms); + +/* NEW Variables */ + +extern void generate_all(Node *); + +static Node *top = 0; /* Top of the generated parse tree */ +static int unnamed = 0; /* Unnamed datatype counter */ +static Hash *extendhash = 0; /* Hash table of added methods */ +static Hash *classes = 0; /* Hash table of classes */ +static Symtab *prev_symtab = 0; +static Node *current_class = 0; + String *ModuleName = 0; +static Node *module_node = 0; +static String *Classprefix = 0; +static String *Namespaceprefix = 0; +static int inclass = 0; +static char *last_cpptype = 0; +static int inherit_list = 0; +static Parm *template_parameters = 0; + +/* ----------------------------------------------------------------------------- + * Assist Functions + * ----------------------------------------------------------------------------- */ + +static Node *new_node(const String_or_char *tag) { + Node *n = NewHash(); + set_nodeType(n,tag); + Setfile(n,cparse_file); + Setline(n,cparse_line); + return n; +} + +/* Copies a node. Does not copy tree links or symbol table data (except for + sym:name) */ + +static Node *copy_node(Node *n) { + Node *nn; + String *key; + nn = NewHash(); + Setfile(nn,Getfile(n)); + Setline(nn,Getline(n)); + for (key = Firstkey(n); key; key = Nextkey(n)) { + if ((Strcmp(key,"nextSibling") == 0) || + (Strcmp(key,"previousSibling") == 0) || + (Strcmp(key,"parentNode") == 0) || + (Strcmp(key,"lastChild") == 0)) { + continue; + } + if (Strncmp(key,"csym:",5) == 0) continue; + /* We do copy sym:name. For templates */ + if ((Strcmp(key,"sym:name") == 0) || + (Strcmp(key,"sym:weak") == 0) || + (Strcmp(key,"sym:typename") == 0)) { + Setattr(nn,key, Copy(Getattr(n,key))); + continue; + } + if (Strcmp(key,"sym:symtab") == 0) { + Setattr(nn,"sym:needs_symtab", "1"); + } + /* We don't copy any other symbol table attributes */ + if (Strncmp(key,"sym:",4) == 0) { + continue; + } + /* If children. We copy them recursively using this function */ + if (Strcmp(key,"firstChild") == 0) { + /* Copy children */ + Node *cn = Getattr(n,key); + while (cn) { + appendChild(nn,copy_node(cn)); + cn = nextSibling(cn); + } + continue; + } + /* We don't copy the symbol table. But we drop an attribute + requires_symtab so that functions know it needs to be built */ + + if (Strcmp(key,"symtab") == 0) { + /* Node defined a symbol table. */ + Setattr(nn,"requires_symtab","1"); + continue; + } + /* Can't copy nodes */ + if (Strcmp(key,"node") == 0) { + continue; + } + if ((Strcmp(key,"parms") == 0) || (Strcmp(key,"pattern") == 0) || (Strcmp(key,"throws") == 0)) { + Setattr(nn,key,CopyParmList(Getattr(n,key))); + continue; + } + /* Looks okay. Just copy the data using Copy */ + Setattr(nn, key, Copy(Getattr(n,key))); + } + return nn; +} + +/* ----------------------------------------------------------------------------- + * Variables + * ----------------------------------------------------------------------------- */ + + char *typemap_lang = 0; /* Current language setting */ + +static int cplus_mode = 0; +static String *class_rename = 0; + +/* C++ modes */ + +#define CPLUS_PUBLIC 1 +#define CPLUS_PRIVATE 2 +#define CPLUS_PROTECTED 3 + +void SWIG_typemap_lang(const char *tm_lang) { + typemap_lang = Swig_copy_string(tm_lang); +} + +/* ----------------------------------------------------------------------------- + * Assist functions + * ----------------------------------------------------------------------------- */ + +/* Perform type-promotion for binary operators */ +static int promote(int t1, int t2) { + return t1 > t2 ? t1 : t2; +} + +static String *yyrename = 0; + +/* Forward renaming operator */ +static Hash *rename_hash = 0; +static Hash *namewarn_hash = 0; +static Hash *features_hash = 0; + +static String *feature_identifier_fix(String *s) { + if (SwigType_istemplate(s)) { + String *tp, *ts, *ta, *tq; + tp = SwigType_templateprefix(s); + ts = SwigType_templatesuffix(s); + ta = SwigType_templateargs(s); + tq = Swig_symbol_type_qualify(ta,0); + Append(tp,tq); + Append(tp,ts); + Delete(ts); + Delete(ta); + Delete(tq); + return tp; + } else { + return NewString(s); + } +} + +static void +rename_add(char *name, SwigType *decl, char *newname) { + String *nname; + if (!rename_hash) rename_hash = NewHash(); + if (Namespaceprefix) { + nname = NewStringf("%s::%s",Namespaceprefix, name); + } else { + nname = NewString(name); + } + Swig_name_object_set(rename_hash,nname,decl,NewString(newname)); + Delete(nname); +} + +static void +namewarn_add(char *name, SwigType *decl, char *warning) { + String *nname; + if (!namewarn_hash) namewarn_hash = NewHash(); + if (Namespaceprefix) { + nname = NewStringf("%s::%s",Namespaceprefix, name); + } else { + nname = NewString(name); + } + + Swig_name_object_set(namewarn_hash,nname,decl,NewString(warning)); + Delete(nname); +} + +static void +rename_inherit(String *base, String *derived) { + /* Printf(stdout,"base = '%s', derived = '%s'\n", base, derived); */ + Swig_name_object_inherit(rename_hash,base,derived); + Swig_name_object_inherit(namewarn_hash,base,derived); + Swig_name_object_inherit(features_hash,base,derived); +} + +/* Generate the symbol table name for an object */ +/* This is a bit of a mess. Need to clean up */ +static String *add_oldname = 0; + +static String *make_name(String *name,SwigType *decl) { + String *rn = 0; + String *origname = name; + int destructor = 0; + + if (name && (*(Char(name)) == '~')) { + destructor = 1; + } + if (yyrename) { + String *s = yyrename; + yyrename = 0; + if (destructor) { + Insert(s,0,"~"); + } + return s; + } + if (!name) return 0; + /* Check to see if the name is in the hash */ + if (!rename_hash) { + if (add_oldname) return Copy(add_oldname); + return origname; + } + rn = Swig_name_object_get(rename_hash, Namespaceprefix, name, decl); + if (!rn) { + if (add_oldname) return Copy(add_oldname); + return name; + } + if (destructor) { + if (Strcmp(rn,"$ignore") != 0) { + String *s = NewStringf("~%s", rn); + return s; + } + } + return Copy(rn); +} + +/* Generate an unnamed identifier */ +static String *make_unnamed() { + unnamed++; + return NewStringf("$unnamed%d$",unnamed); +} + +/* Generate the symbol table name for an object */ +static String *name_warning(String *name,SwigType *decl) { + String *rn = 0; + if (!name) return 0; + + /* Check to see if the name is in the hash */ + if (!namewarn_hash) return 0; + rn = Swig_name_object_get(namewarn_hash, Namespaceprefix,name,decl); + if (!rn) return 0; + return rn; +} + +/* Add declaration list to symbol table */ +static int add_only_one = 0; + + +static void add_symbols(Node *n) { + String *decl; + String *wrn = 0; + + /* Don't add symbols for private/protected members */ + if (inclass && (cplus_mode != CPLUS_PUBLIC)) { + while (n) { + Swig_symbol_add(0, n); /* Add to C symbol table */ + if (cplus_mode == CPLUS_PRIVATE) { + Setattr(n,"access", "private"); + } else { + Setattr(n,"access", "protected"); + } + if (add_only_one) break; + n = nextSibling(n); + } + return; + } + while (n) { + String *symname; + if (Getattr(n,"sym:name")) { + n = nextSibling(n); + continue; + } + decl = Getattr(n,"decl"); + if (!SwigType_isfunction(decl)) { + symname = make_name(Getattr(n,"name"),0); + if (!symname) { + symname = Getattr(n,"unnamed"); + } + if (symname) { + wrn = name_warning(symname,0); + Swig_features_get(features_hash, Namespaceprefix, Getattr(n,"name"), 0, n); + } + } else { + SwigType *fdecl = Copy(decl); + SwigType *fun = SwigType_pop_function(fdecl); + symname = make_name(Getattr(n,"name"),fun); + wrn = name_warning(symname,fun); + + Swig_features_get(features_hash,Namespaceprefix,Getattr(n,"name"),fun,n); + Delete(fdecl); + Delete(fun); + } + if (!symname) { + n = nextSibling(n); + continue; + } + if (strncmp(Char(symname),"$ignore",7) == 0) { + char *c = Char(symname)+7; + Setattr(n,"feature:ignore","1"); + if (strlen(c)) { + Swig_warning(0,Getfile(n), Getline(n), "%s\n",c+1); + } + Swig_symbol_add(0, n); + } else { + Node *c; + if ((wrn) && (Len(wrn))) { + Swig_warning(0,Getfile(n),Getline(n), "%s\n", wrn); + } + if (Strcmp(nodeType(n),"enum") != 0) { + c = Swig_symbol_add(symname,n); + if (c != n) { + if (Getattr(n,"sym:weak")) { + Setattr(n,"sym:name",symname); + } else if ((Strcmp(nodeType(n),"template") == 0) && (Strcmp(Getattr(n,"templatetype"),"cdecl") == 0)) { + Setattr(n,"sym:name",symname); + } else { + String *e = NewString(""); + Printf(e,"Identifier '%s' redeclared (ignored).", symname); + if (Cmp(symname,Getattr(n,"name"))) { + Printf(e," (Renamed from '%s')", SwigType_namestr(Getattr(n,"name"))); + } + Printf(e,"\n%s:%d: Previous declaration of '%s'", Getfile(c),Getline(c),symname); + if (Cmp(symname,Getattr(c,"name"))) { + Printf(e," (Renamed from '%s')", SwigType_namestr(Getattr(c,"name"))); + } + Swig_warning(WARN_PARSE_REDEFINED,Getfile(n), Getline(n),"%s\n", e); + Setattr(n,"error",e); + } + } + } else { + Setattr(n,"sym:name", symname); + } + } + if (add_only_one) return; + n = nextSibling(n); + } +} + + +/* add symbols a parse tree node copy */ + +void add_symbols_copy(Node *n) { + String *name; + int emode = 0; + + while (n) { + + if (Strcmp(nodeType(n),"access") == 0) { + String *kind = Getattr(n,"kind"); + if (Strcmp(kind,"public") == 0) { + cplus_mode = CPLUS_PUBLIC; + } else if (Strcmp(kind,"private") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else if (Strcmp(kind,"protected") == 0) { + cplus_mode = CPLUS_PROTECTED; + } + n = nextSibling(n); + continue; + } + + add_oldname = Getattr(n,"sym:name"); + if ((add_oldname) || (Getattr(n,"sym:needs_symtab"))) { + if (add_oldname) { + DohIncref(add_oldname); + /* If already renamed, we used that name */ + if (Strcmp(add_oldname, Getattr(n,"name")) != 0) { + yyrename = add_oldname; + } + } + Delattr(n,"sym:needs_symtab"); + Delattr(n,"sym:name"); + + add_only_one = 1; + add_symbols(n); + + if (Getattr(n,"partialargs")) { + Swig_symbol_cadd(Getattr(n,"partialargs"),n); + } + add_only_one = 0; + name = Getattr(n,"name"); + if (Getattr(n,"requires_symtab")) { + Swig_symbol_newscope(); + Swig_symbol_setscopename(name); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + } + if (Strcmp(nodeType(n),"class") == 0) { + inclass = 1; + if (Strcmp(Getattr(n,"kind"),"class") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else { + cplus_mode = CPLUS_PUBLIC; + } + } + if (Strcmp(nodeType(n),"extend") == 0) { + emode = cplus_mode; + cplus_mode = CPLUS_PUBLIC; + } + add_symbols_copy(firstChild(n)); + if (Strcmp(nodeType(n),"extend") == 0) { + cplus_mode = emode; + } + if (Getattr(n,"requires_symtab")) { + Setattr(n,"symtab", Swig_symbol_popscope()); + Delattr(n,"requires_symtab"); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + } + if (add_oldname) { + Delete(add_oldname); + } + if (Strcmp(nodeType(n),"class") == 0) { + inclass = 0; + } + add_oldname = 0; + } else { + if (Strcmp(nodeType(n),"extend") == 0) { + emode = cplus_mode; + cplus_mode = CPLUS_PUBLIC; + } + add_symbols_copy(firstChild(n)); + if (Strcmp(nodeType(n),"extend") == 0) { + cplus_mode = emode; + } + } + n = nextSibling(n); + } +} + +/* Extension merge. This function is used to handle the %extend directive + when it appears before a class definition. To handle this, the %extend + actually needs to take precedence. Therefore, we will selectively nuke symbols + from the current symbol table, replacing them with the added methods */ + +static void merge_extensions(Node *am) { + Node *n; + Node *csym; + + n = firstChild(am); + while (n) { + String *symname; + symname = Getattr(n,"sym:name"); + DohIncref(symname); + if ((symname) && (!Getattr(n,"error"))) { + /* Remove node from its symbol table */ + Swig_symbol_remove(n); + csym = Swig_symbol_add(symname,n); + if (csym != n) { + /* Conflict with previous definition. Nuke previous definition */ + String *e = NewString(""); + Printf(e,"Identifier '%s' redeclared (ignored).\n", symname); + Printf(e,"%s:%d: Previous definition of tag '%s'", Getfile(n),Getline(n), symname); + Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym), Getline(csym), "%s\n", e); + Setattr(csym,"error",e); + Swig_symbol_remove(csym); /* Remove class definition */ + Swig_symbol_add(symname,n); /* Insert extend definition */ + } + } + n = nextSibling(n); + } +} + +/* Check for unused %extend. Special case, don't report unused + extensions for templates */ + + static void check_extensions() { + String *key; + if (!extendhash) return; + for (key = Firstkey(extendhash); key; key = Nextkey(extendhash)) { + Node *n = Getattr(extendhash,key); + if (!Strstr(key,"<")) { + Swig_warning(WARN_PARSE_EXTEND_UNDEF,Getfile(n), Getline(n), "%%extend defined for an undeclared class %s.\n", key); + } + } + } + +/* Check a set of declarations to see if any are pure-abstract */ + + static List *pure_abstract(Node *n) { + List *abs = 0; + while (n) { + if (Cmp(nodeType(n),"cdecl") == 0) { + String *decl = Getattr(n,"decl"); + if (SwigType_isfunction(decl)) { + String *init = Getattr(n,"value"); + if (Cmp(init,"0") == 0) { + if (!abs) { + abs = NewList(); + } + Append(abs,n); + Setattr(n,"abstract","1"); + } + } + } else if (Cmp(nodeType(n),"destructor") == 0) { + if (Cmp(Getattr(n,"value"),"0") == 0) { + if (!abs) { + abs = NewList(); + } + Append(abs,n); + Setattr(n,"abstract","1"); + } + } + n = nextSibling(n); + } + return abs; + } + + /* Make a classname */ + + static String *make_class_name(String *name) { + String *nname = 0; + if (Namespaceprefix) { + nname= NewStringf("%s::%s", Namespaceprefix, name); + } else { + nname = NewString(name); + } + if (SwigType_istemplate(nname)) { + String *prefix, *args, *qargs; + prefix = SwigType_templateprefix(nname); + args = SwigType_templateargs(nname); + qargs = Swig_symbol_type_qualify(args,0); + Append(prefix,qargs); + Delete(nname); + nname = prefix; + } + return nname; + } + + static List *make_inherit_list(String *clsname, List *names) { + int i; + String *derived; + List *bases = NewList(); + + if (Namespaceprefix) derived = NewStringf("%s::%s", Namespaceprefix,clsname); + else derived = NewString(clsname); + + for (i = 0; i < Len(names); i++) { + Node *s; + String *base; + String *n = Getitem(names,i); + /* Try to figure out where this symbol is */ + s = Swig_symbol_clookup(n,0); + if (s) { + while (s && (Strcmp(nodeType(s),"class") != 0)) { + /* Not a class. Could be a typedef though. */ + String *storage = Getattr(s,"storage"); + if (storage && (Strcmp(storage,"typedef") == 0)) { + String *nn = Getattr(s,"type"); + s = Swig_symbol_clookup(nn,Getattr(s,"sym:symtab")); + } else { + break; + } + } + if (s && ((Strcmp(nodeType(s),"class") == 0) || (Strcmp(nodeType(s),"template") == 0))) { + String *q = Swig_symbol_qualified(s); + Append(bases,s); + if (q) { + base = NewStringf("%s::%s", q, Getattr(s,"name")); + } else { + base = NewString(Getattr(s,"name")); + } + } else { + base = NewString(n); + } + } else { + base = NewString(n); + } + if (base) { + rename_inherit(base,derived); + Delete(base); + } + } + return bases; + } + +/* Structures for handling code fragments built for nested classes */ + +typedef struct Nested { + String *code; /* Associated code fragment */ + int line; /* line number where it starts */ + char *name; /* Name associated with this nested class */ + char *kind; /* Kind of class */ + SwigType *type; /* Datatype associated with the name */ + struct Nested *next; /* Next code fragment in list */ +} Nested; + +/* Some internal variables for saving nested class information */ + +static Nested *nested_list = 0; + +/* Add a function to the nested list */ + +static void add_nested(Nested *n) { + Nested *n1; + if (!nested_list) nested_list = n; + else { + n1 = nested_list; + while (n1->next) n1 = n1->next; + n1->next = n; + } +} + +/* Dump all of the nested class declarations to the inline processor + * However. We need to do a few name replacements and other munging + * first. This function must be called before closing a class! */ + +static Node *dump_nested(char *parent) { + Nested *n,*n1; + Node *ret = 0; + n = nested_list; + if (!parent) { + nested_list = 0; + return 0; + } + while (n) { + char temp[256]; + Node *retx; + /* Token replace the name of the parent class */ + Replace(n->code, "$classname", parent, DOH_REPLACE_ANY); + /* Fix up the name of the datatype (for building typedefs and other stuff) */ + sprintf(temp,"%s_%s", parent,n->name); + + Append(n->type,parent); + Append(n->type,"_"); + Append(n->type,n->name); + + /* Add the appropriate declaration to the C++ processor */ + retx = new_node("cdecl"); + Setattr(retx,"name",n->name); + Setattr(retx,"type",Copy(n->type)); + Setattr(retx,"nested",parent); + add_symbols(retx); + if (ret) { + set_nextSibling(retx,ret); + } + ret = retx; + + /* Insert a forward class declaration */ + /* Disabled: [ 597599 ] union in class: incorrect scope + retx = new_node("classforward"); + Setattr(retx,"kind",n->kind); + Setattr(retx,"name",Copy(n->type)); + Setattr(retx,"sym:name", make_name(n->type,0)); + set_nextSibling(retx,ret); + ret = retx; + */ + + /* Make all SWIG created typedef structs/unions/classes unnamed else + redefinition errors occur - nasty hack alert.*/ + + { + const char* types_array[3] = {"struct", "union", "class"}; + int i; + for (i=0; i<3; i++) { + char* code_ptr = Char(n->code); + while (code_ptr) { + /* Replace struct name (as in 'struct name {' ) with whitespace + name will be between struct and { */ + + code_ptr = strstr(code_ptr, types_array[i]); + if (code_ptr) { + char *open_bracket_pos; + code_ptr += strlen(types_array[i]); + open_bracket_pos = strstr(code_ptr, "{"); + if (open_bracket_pos) { + /* Make sure we don't have something like struct A a; */ + char* semi_colon_pos = strstr(code_ptr, ";"); + if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos))) + while (code_ptr < open_bracket_pos) + *code_ptr++ = ' '; + } + } + } + } + } + + { + /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */ + char* code_ptr = Char(n->code); + while (code_ptr) { + code_ptr = strstr(code_ptr, "%constant"); + if (code_ptr) { + char* directive_end_pos = strstr(code_ptr, ";"); + if (directive_end_pos) { + while (code_ptr <= directive_end_pos) + *code_ptr++ = ' '; + } + } + } + } + { + Node *head; + head = new_node("insert"); + Setattr(head,"code",NewStringf("\n%s\n",n->code)); + set_nextSibling(head,ret); + ret = head; + } + + /* Dump the code to the scanner */ + start_inline(Char(n->code),n->line); + + n1 = n->next; + Delete(n->code); + free(n); + n = n1; + } + nested_list = 0; + return ret; +} + +Node *Swig_cparse(File *f) { + extern void scanner_file(File *); + extern int yyparse(); + scanner_file(f); + top = 0; + yyparse(); + return top; +} + +%} + +%union { + char *id; + List *bases; + struct Define { + String *val; + String *rawval; + int type; + String *qualifier; + String *bitfield; + Parm *throws; + } dtype; + struct { + char *type; + char *filename; + int line; + } loc; + struct { + char *id; + SwigType *type; + String *defarg; + ParmList *parms; + short have_parms; + ParmList *throws; + } decl; + Parm *tparms; + struct { + String *op; + Hash *kwargs; + } tmap; + struct { + String *type; + String *us; + } ptype; + SwigType *type; + String *str; + Parm *p; + ParmList *pl; + int ivalue; + Node *node; +}; + +%token <id> ID +%token <str> HBLOCK +%token <id> POUND +%token <id> STRING +%token <loc> INCLUDE IMPORT INSERT +%token <str> CHARCONST +%token <dtype> NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG +%token <ivalue> TYPEDEF +%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_TYPEDEF TYPE_RAW +%token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD +%token CONST VOLATILE STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET +%token ILLEGAL CONSTANT +%token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS +%token ENUM +%token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH +%token USING +%token <node> NAMESPACE +%token NATIVE INLINE +%token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT +%token WARN +%token LESSTHAN GREATERTHAN MODULO DELETE +%token TYPES PARMS +%token NONID DSTAR DCNOT +%token <ivalue> TEMPLATE +%token <str> OPERATOR +%token <str> COPERATOR +%token PARSETYPE + +%left CAST +%left LOR +%left LAND +%left OR +%left XOR +%left AND +%left LSHIFT RSHIFT +%left PLUS MINUS +%left STAR SLASH +%left UMINUS NOT LNOT +%left DCOLON + +%type <node> program interface declaration swig_directive ; + +/* SWIG directives */ +%type <node> extend_directive apply_directive clear_directive constant_directive ; +%type <node> echo_directive except_directive fragment_directive include_directive inline_directive ; +%type <node> insert_directive module_directive name_directive native_directive ; +%type <node> pragma_directive rename_directive feature_directive varargs_directive typemap_directive ; +%type <node> types_directive template_directive warn_directive ; + +/* C declarations */ +%type <node> c_declaration c_decl c_decl_tail c_enum_decl c_constructor_decl ; +%type <node> enumlist edecl; + +/* C++ declarations */ +%type <node> cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl; +%type <node> cpp_members cpp_member; +%type <node> cpp_constructor_decl cpp_destructor_decl cpp_protection_decl cpp_conversion_operator; +%type <node> cpp_swig_directive cpp_temp_possible cpp_nested cpp_opt_declarators ; +%type <node> cpp_using_decl cpp_namespace_decl cpp_catch_decl ; +%type <node> kwargs options; + +/* Misc */ +%type <dtype> initializer cpp_const ; +%type <id> storage_class; +%type <pl> parms ptail rawparms varargs_parms ; +%type <p> parm valparm rawvalparms valparms valptail ; +%type <p> typemap_parm tm_list tm_tail ; +%type <id> cpptype access_specifier; +%type <node> base_specifier +%type <type> type rawtype type_right ; +%type <bases> base_list inherit raw_inherit; +%type <dtype> definetype def_args etype; +%type <dtype> expr exprnum exprcompound ; +%type <id> ename ; +%type <id> template_decl; +%type <str> type_qualifier ; +%type <id> type_qualifier_raw; +%type <id> idstring idstringopt; +%type <id> pragma_lang; +%type <str> pragma_arg; +%type <loc> includetype; +%type <type> pointer primitive_type; +%type <decl> declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator nested_decl; +%type <decl> abstract_declarator direct_abstract_declarator ctor_end; +%type <tmap> typemap_type; +%type <str> idcolon idcolontail idcolonnt idcolontailnt idtemplate stringbrace stringbracesemi; +%type <id> string stringnum ; +%type <tparms> template_parms; +%type <dtype> cpp_vend; +%type <ivalue> rename_namewarn; +%type <ptype> type_specifier primitive_type_list ; + +%% + +/* ====================================================================== + * High-level Interface file + * + * An interface is just a sequence of declarations which may be SWIG directives + * or normal C declarations. + * ====================================================================== */ + +program : interface { + Setattr($1,"classes",classes); + Setattr($1,"name",ModuleName); + + if ((!module_node) && ModuleName) { + module_node = new_node("module"); + Setattr(module_node,"name",ModuleName); + } + Setattr($1,"module",module_node); + check_extensions(); + top = $1; + } + | PARSETYPE parm SEMI { + top = Getattr($2,"type"); + } + | PARSETYPE error { + top = 0; + } + ; + +interface : interface declaration { + appendChild($1,$2); + $$ = $1; + } + | empty { + $$ = new_node("top"); + } + ; + +declaration : swig_directive { $$ = $1; } + | c_declaration { $$ = $1; } + | cpp_declaration { $$ = $1; } + | SEMI { $$ = 0; } + | error { + $$ = 0; + if (!Swig_error_count()) { + static int last_error_line = -1; + if (last_error_line != cparse_line) { + Swig_error(cparse_file, cparse_line,"Syntax error in input.\n"); + last_error_line = cparse_line; + skip_decl(); + } + } + } +/* Out of class constructor/destructor declarations */ + | c_constructor_decl { + if ($$) { + add_symbols($$); + } + $$ = $1; + } + ; + + +/* ====================================================================== + * SWIG DIRECTIVES + * ====================================================================== */ + +swig_directive : extend_directive { $$ = $1; } + | apply_directive { $$ = $1; } + | clear_directive { $$ = $1; } + | constant_directive { $$ = $1; } + | echo_directive { $$ = $1; } + | except_directive { $$ = $1; } + | fragment_directive { $$ = $1; } + | include_directive { $$ = $1; } + | inline_directive { $$ = $1; } + | insert_directive { $$ = $1; } + | module_directive { $$ = $1; } + | name_directive { $$ = $1; } + | native_directive { $$ = $1; } + | pragma_directive { $$ = $1; } + | rename_directive { $$ = $1; } + | feature_directive { $$ = $1; } + | varargs_directive { $$ = $1; } + | typemap_directive { $$ = $1; } + | types_directive { $$ = $1; } + | template_directive { $$ = $1; } + | warn_directive { $$ = $1; } + ; + +/* ------------------------------------------------------------ + %extend classname { ... } + ------------------------------------------------------------ */ + +extend_directive : EXTEND options idcolon LBRACE { + Node *cls; + String *clsname; + cplus_mode = CPLUS_PUBLIC; + if (!classes) classes = NewHash(); + if (!extendhash) extendhash = NewHash(); + clsname = make_class_name($3); + /* Printf(stdout,"clsname = '%s'\n",clsname);*/ + cls = Getattr(classes,clsname); + if (!cls) { + /* No previous definition. Create a new scope */ + Node *am = Getattr(extendhash,clsname); + if (!am) { + Swig_symbol_newscope(); + Swig_symbol_setscopename($3); + prev_symtab = 0; + } else { + prev_symtab = Swig_symbol_setscope(Getattr(am,"symtab")); + } + current_class = 0; + } else { + /* Previous class definition. Use its symbol table */ + prev_symtab = Swig_symbol_setscope(Getattr(cls,"symtab")); + current_class = cls; + } + Classprefix = NewString($3); + Namespaceprefix= Swig_symbol_qualifiedscopename(0); + Delete(clsname); + } cpp_members RBRACE { + String *clsname; + $$ = new_node("extend"); + Setattr($$,"symtab",Swig_symbol_popscope()); + if (prev_symtab) { + Swig_symbol_setscope(prev_symtab); + } + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + clsname = make_class_name($3); + Setattr($$,"name",clsname); + + /* Mark members as extend */ + + Swig_tag_nodes($6,"feature:extend",(char*) "1"); + if (current_class) { + /* We add the extension to the previously defined class */ + appendChild($$,$6); + appendChild(current_class,$$); + } else { + /* We store the extensions in the extensions hash */ + Node *am = Getattr(extendhash,clsname); + if (am) { + /* Append the members to the previous extend methods */ + appendChild(am,$6); + } else { + appendChild($$,$6); + Setattr(extendhash,clsname,$$); + } + } + current_class = 0; + Delete(Classprefix); + Delete(clsname); + Classprefix = 0; + prev_symtab = 0; + $$ = 0; + } + ; + +/* ------------------------------------------------------------ + %apply + ------------------------------------------------------------ */ + +apply_directive : APPLY typemap_parm LBRACE tm_list RBRACE { + $$ = new_node("apply"); + Setattr($$,"pattern",Getattr($2,"pattern")); + appendChild($$,$4); + }; + +/* ------------------------------------------------------------ + %clear + ------------------------------------------------------------ */ + +clear_directive : CLEAR tm_list SEMI { + $$ = new_node("clear"); + appendChild($$,$2); + } + ; + +/* ------------------------------------------------------------ + %constant name = value; + %constant type name = value; + ------------------------------------------------------------ */ + +constant_directive : CONSTANT ID EQUAL definetype SEMI { + if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) { + $$ = new_node("constant"); + Setattr($$,"name",$2); + Setattr($$,"type",NewSwigType($4.type)); + Setattr($$,"value",$4.val); + Setattr($$,"storage","%constant"); + Setattr($$,"feature:immutable","1"); + add_symbols($$); + } else { + if ($4.type == T_ERROR) { + Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line,"Unsupported constant value (ignored)\n"); + } + $$ = 0; + } + + } + + | CONSTANT type declarator def_args SEMI { + if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) { + SwigType_push($2,$3.type); + /* Sneaky callback function trick */ + if (SwigType_isfunction($2)) { + SwigType_add_pointer($2); + } + $$ = new_node("constant"); + Setattr($$,"name",$3.id); + Setattr($$,"type",$2); + Setattr($$,"value",$4.val); + Setattr($$,"storage","%constant"); + Setattr($$,"feature:immutable","1"); + add_symbols($$); + } else { + if ($4.type == T_ERROR) { + Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line,"Unsupported constant value\n"); + } + $$ = 0; + } + } + | CONSTANT error SEMI { + Swig_warning(WARN_PARSE_BAD_VALUE,cparse_file,cparse_line,"Bad constant value (ignored).\n"); + $$ = 0; + } + ; + +/* ------------------------------------------------------------ + %echo "text" + %echo %{ ... %} + ------------------------------------------------------------ */ + +echo_directive : ECHO HBLOCK { + char temp[64]; + Replace($2,"$file",cparse_file, DOH_REPLACE_ANY); + sprintf(temp,"%d", cparse_line); + Replace($2,"$line",temp,DOH_REPLACE_ANY); + Printf(stderr,"%s\n", $2); + Delete($2); + $$ = 0; + } + | ECHO string { + char temp[64]; + String *s = NewString($2); + Replace(s,"$file",cparse_file, DOH_REPLACE_ANY); + sprintf(temp,"%d", cparse_line); + Replace(s,"$line",temp,DOH_REPLACE_ANY); + Printf(stderr,"%s\n", s); + Delete(s); + $$ = 0; + } + ; + +/* ------------------------------------------------------------ + %except(lang) { ... } + %except { ... } + %except(lang); + %except; + ------------------------------------------------------------ */ + +except_directive : EXCEPT LPAREN ID RPAREN LBRACE { + skip_balanced('{','}'); + $$ = 0; + Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead."); + } + + | EXCEPT LBRACE { + skip_balanced('{','}'); + $$ = 0; + Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead."); + } + + | EXCEPT LPAREN ID RPAREN SEMI { + $$ = 0; + Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead."); + } + + | EXCEPT SEMI { + $$ = 0; + Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead."); + } + ; + +/* ------------------------------------------------------------ + %fragment(name,location) { ... } + ------------------------------------------------------------ */ + +fragment_directive: FRAGMENT LPAREN idstring COMMA idstring RPAREN HBLOCK { + $$ = new_node("fragment"); + Setattr($$,"section", $5); + Setattr($$,"name",$3); + Setattr($$,"code",$7); + } + | FRAGMENT LPAREN idstring COMMA idstring RPAREN LBRACE { + skip_balanced('{','}'); + $$ = new_node("fragment"); + Setattr($$,"section",$5); + Setattr($$,"name",$3); + Delitem(scanner_ccode,0); + Delitem(scanner_ccode,DOH_END); + Setattr($$,"code",Copy(scanner_ccode)); + } + ; + +/* ------------------------------------------------------------ + %includefile "filename" [ declarations ] + %importfile "filename" [ declarations ] + ------------------------------------------------------------ */ + +include_directive: includetype options string LBRACKET { + $1.filename = Swig_copy_string(cparse_file); + $1.line = cparse_line; + cparse_file = Swig_copy_string($3); + cparse_line = 0; + } interface RBRACKET { + $$ = $6; + cparse_file = $1.filename; + cparse_line = $1.line; + if (strcmp($1.type,"include") == 0) set_nodeType($$,"include"); + if (strcmp($1.type,"import") == 0) set_nodeType($$,"import"); + Setattr($$,"name",$3); + /* Search for the module (if any) */ + { + Node *n = firstChild($$); + while (n) { + if (Strcmp(nodeType(n),"module") == 0) { + Setattr($$,"module",Getattr(n,"name")); + break; + } + n = nextSibling(n); + } + } + Setattr($$,"options",$2); + } + ; + +includetype : INCLUDE { $$.type = (char *) "include"; } + | IMPORT { $$.type = (char *) "import"; } + ; + +/* ------------------------------------------------------------ + %inline %{ ... %} + ------------------------------------------------------------ */ + +inline_directive : INLINE HBLOCK { + String *cpps; + if (Namespaceprefix) { + Swig_error(cparse_file, cparse_start_line, "Error. %%inline directive inside a namespace is disallowed.\n"); + + $$ = 0; + } else { + $$ = new_node("insert"); + Setattr($$,"code",$2); + /* Need to run through the preprocessor */ + Setline($2,cparse_start_line); + Setfile($2,cparse_file); + Seek($2,0,SEEK_SET); + cpps = Preprocessor_parse($2); + start_inline(Char(cpps), cparse_start_line); + Delete($2); + Delete(cpps); + } + } + ; + +/* ------------------------------------------------------------ + %{ ... %} + %insert(section) "filename" + %insert("section") "filename" + %insert(section) %{ ... %} + %insert("section") %{ ... %} + ------------------------------------------------------------ */ + +insert_directive : HBLOCK { + $$ = new_node("insert"); + Setattr($$,"code",$1); + } + | INSERT LPAREN idstring RPAREN string { + String *code = NewString(""); + $$ = new_node("insert"); + Setattr($$,"section",$3); + Setattr($$,"code",code); + if (Swig_insert_file($5,code) < 0) { + Swig_error(cparse_file, cparse_line, "Couldn't find '%s'.\n", $5); + $$ = 0; + } + } + | INSERT LPAREN idstring RPAREN HBLOCK { + $$ = new_node("insert"); + Setattr($$,"section",$3); + Setattr($$,"code",$5); + } + | INSERT LPAREN idstring RPAREN LBRACE { + skip_balanced('{','}'); + $$ = new_node("insert"); + Setattr($$,"section",$3); + Delitem(scanner_ccode,0); + Delitem(scanner_ccode,DOH_END); + Setattr($$,"code", Copy(scanner_ccode)); + } + ; + +/* ------------------------------------------------------------ + %module modname + %module "modname" + ------------------------------------------------------------ */ + +module_directive: MODULE options idstring { + $$ = new_node("module"); + Setattr($$,"name",$3); + if ($2) Setattr($$,"options",$2); + if (!ModuleName) ModuleName = NewString($3); + if (!module_node) module_node = $$; + } + ; + +/* ------------------------------------------------------------ + %name(newname) declaration + %name("newname") declaration + ------------------------------------------------------------ */ + +name_directive : NAME LPAREN idstring RPAREN { + yyrename = NewString($3); + $$ = 0; + } + | NAME LPAREN RPAREN { + $$ = 0; + Swig_error(cparse_file,cparse_line,"Missing argument to %%name directive.\n"); + } + ; + + +/* ------------------------------------------------------------ + %native(scriptname) name; + %native(scriptname) type name (parms); + ------------------------------------------------------------ */ + +native_directive : NATIVE LPAREN ID RPAREN storage_class ID SEMI { + $$ = new_node("native"); + Setattr($$,"name",$3); + Setattr($$,"wrap:name",$6); + add_symbols($$); + } + | NATIVE LPAREN ID RPAREN storage_class type declarator SEMI { + if (!SwigType_isfunction($7.type)) { + Swig_error(cparse_file,cparse_line,"%%native declaration '%s' is not a function.\n", $7.id); + $$ = 0; + } else { + Delete(SwigType_pop_function($7.type)); + /* Need check for function here */ + SwigType_push($6,$7.type); + $$ = new_node("native"); + Setattr($$,"name",$3); + Setattr($$,"wrap:name",$7.id); + Setattr($$,"type",$6); + Setattr($$,"parms",$7.parms); + Setattr($$,"decl",$7.type); + } + add_symbols($$); + } + ; + +/* ------------------------------------------------------------ + %pragma(lang) name=value + %pragma(lang) name + %pragma name = value + %pragma name + ------------------------------------------------------------ */ + +pragma_directive : PRAGMA pragma_lang ID EQUAL pragma_arg { + $$ = new_node("pragma"); + Setattr($$,"lang",$2); + Setattr($$,"name",$3); + Setattr($$,"value",$5); + } + | PRAGMA pragma_lang ID { + $$ = new_node("pragma"); + Setattr($$,"lang",$2); + Setattr($$,"name",$3); + } + ; + +pragma_arg : string { $$ = NewString($1); } + | HBLOCK { $$ = $1; } + ; + +pragma_lang : LPAREN ID RPAREN { $$ = $2; } + | empty { $$ = (char *) "swig"; } + ; + +/* ------------------------------------------------------------ + %rename identifier newname; + %rename identifier "newname"; + ------------------------------------------------------------ */ + +rename_directive : rename_namewarn declarator idstring SEMI { + SwigType *t = $2.type; + if (!Len(t)) t = 0; + if ($1) { + rename_add($2.id,t,$3); + } else { + namewarn_add($2.id,t,$3); + } + $$ = 0; + scanner_clear_rename(); + } + | rename_namewarn LPAREN idstring RPAREN declarator cpp_const SEMI { + String *fixname; + SwigType *t = $5.type; + fixname = feature_identifier_fix($5.id); + if (!Len(t)) t = 0; + /* Special declarator check */ + if (t) { + if ($6.qualifier) SwigType_push(t,$6.qualifier); + if (SwigType_isfunction(t)) { + SwigType *decl = SwigType_pop_function(t); + if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",fixname); + if ($1) { + rename_add(Char(nname),decl,$3); + } else { + namewarn_add(Char(nname),decl,$3); + } + Delete(nname); + } else { + if ($1) { + rename_add(Char(fixname),decl,$3); + } else { + namewarn_add(Char(fixname),decl,$3); + } + } + } else if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",fixname); + if ($1) { + rename_add(Char(nname),0,$3); + } else { + namewarn_add(Char(nname),0,$3); + } + Delete(nname); + } + } else { + if ($1) { + rename_add(Char(fixname),0,$3); + } else { + namewarn_add(Char(fixname),0,$3); + } + } + $$ = 0; + scanner_clear_rename(); + } + | rename_namewarn LPAREN idstring RPAREN string SEMI { + if ($1) { + rename_add($5,0,$3); + } else { + namewarn_add($5,0,$3); + } + $$ = 0; + scanner_clear_rename(); + } + ; + +rename_namewarn : RENAME { + $$ = 1; + } + | NAMEWARN { + $$ = 0; + }; + + +/* ------------------------------------------------------------ + %feature(featurename) name { val } + %feature(featurename) name "val"; + %feature(featurename) name %{ val % } + %feature(featurename,val) name; + ------------------------------------------------------------ */ + + +feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbracesemi { + String *fname; + String *val; + String *name; + String *fixname; + SwigType *t; + if (!features_hash) features_hash = NewHash(); + fname = NewStringf("feature:%s",$3); + fixname = feature_identifier_fix($5.id); + if (Namespaceprefix) { + name = NewStringf("%s::%s",Namespaceprefix, fixname); + } else { + name = fixname; + } + val = $7 ? NewString($7) : NewString("1"); + if ($5.parms) { + Setmeta(val,"parms",$5.parms); + } + t = $5.type; + if ($5.parms) Setmeta(val,"parms",$5.parms); + if (!Len(t)) t = 0; + if (t) { + if ($6.qualifier) SwigType_push(t,$6.qualifier); + if (SwigType_isfunction(t)) { + SwigType *decl = SwigType_pop_function(t); + if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",name); + Swig_feature_set(features_hash, nname, decl, fname, val); + Delete(nname); + } else { + Swig_feature_set(features_hash, name, decl, fname, val); + } + } else if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",name); + Swig_feature_set(features_hash,nname,0,fname,val); + Delete(nname); + } + } else { + Swig_feature_set(features_hash,name,0,fname,val); + } + Delete(fname); + Delete(name); + $$ = 0; + } + + /* Special form where value is included in (...) part */ + + | FEATURE LPAREN idstring COMMA idstring RPAREN declarator cpp_const SEMI { + String *fname; + String *val; + String *name; + String *fixname; + SwigType *t; + + if (!features_hash) features_hash = NewHash(); + fname = NewStringf("feature:%s",$3); + fixname = feature_identifier_fix($7.id); + if (Namespaceprefix) { + name = NewStringf("%s::%s",Namespaceprefix, fixname); + } else { + name = fixname; + } + if (Len($5)) { + val = NewString($5); + } else { + val = 0; + } + if ($7.parms) { + Setmeta(val,"parms",$7.parms); + } + t = $7.type; + if ($7.parms) Setmeta(val,"parms",$7.parms); + if (!Len(t)) t = 0; + if (t) { + if ($8.qualifier) SwigType_push(t,$8.qualifier); + if (SwigType_isfunction(t)) { + SwigType *decl = SwigType_pop_function(t); + if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",name); + Swig_feature_set(features_hash, nname, decl, fname, val); + Delete(nname); + } else { + Swig_feature_set(features_hash, name, decl, fname, val); + } + } else if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",name); + Swig_feature_set(features_hash,nname,0,fname,val); + Delete(nname); + } + } else { + Swig_feature_set(features_hash,name,0,fname,val); + } + Delete(fname); + Delete(name); + $$ = 0; + } + + /* Global feature */ + + | FEATURE LPAREN idstring RPAREN stringbracesemi { + String *name; + String *fname = NewStringf("feature:%s",$3); + if (!features_hash) features_hash = NewHash(); + if (Namespaceprefix) name = NewStringf("%s::", Namespaceprefix); + else name = NewString(""); + Swig_feature_set(features_hash,name,0,fname,($5 ? NewString($5) : NewString("1"))); + Delete(name); + Delete(fname); + $$ = 0; + } + | FEATURE LPAREN idstring COMMA idstring RPAREN SEMI { + String *name; + String *fname = NewStringf("feature:%s",$3); + if (!features_hash) features_hash = NewHash(); + if (Namespaceprefix) name = NewStringf("%s::", Namespaceprefix); + else name = NewString(""); + Swig_feature_set(features_hash,name,0,fname,(Len($5) ? NewString($5) : 0)); + Delete(name); + Delete(fname); + $$ = 0; + } + ; + +stringbracesemi : stringbrace { $$ = $1; } + | SEMI { $$ = 0; } + | PARMS LPAREN parms RPAREN SEMI { $$ = $3; } + ; + +/* %varargs() directive. */ + +varargs_directive : VARARGS LPAREN varargs_parms RPAREN declarator cpp_const SEMI { + Parm *val; + String *name; + SwigType *t; + if (!features_hash) features_hash = NewHash(); + if (Namespaceprefix) name = NewStringf("%s::%s", Namespaceprefix, $5.id); + else name = NewString($5.id); + val = $3; + if ($5.parms) { + Setmeta(val,"parms",$5.parms); + } + t = $5.type; + if (!Len(t)) t = 0; + if (t) { + if ($6.qualifier) SwigType_push(t,$6.qualifier); + if (SwigType_isfunction(t)) { + SwigType *decl = SwigType_pop_function(t); + if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",name); + Swig_feature_set(features_hash, nname, decl, "feature:varargs", val); + Delete(nname); + } else { + Swig_feature_set(features_hash, name, decl, "feature:varargs", val); + } + } else if (SwigType_ispointer(t)) { + String *nname = NewStringf("*%s",name); + Swig_feature_set(features_hash,nname,0,"feature:varargs",val); + Delete(nname); + } + } else { + Swig_feature_set(features_hash,name,0,"feature:varargs",val); + } + Delete(name); + $$ = 0; + }; + +varargs_parms : parms { $$ = $1; } + | NUM_INT COMMA parm { + int i; + int n; + Parm *p; + n = atoi(Char($1.val)); + if (n <= 0) { + Swig_error(cparse_file, cparse_line,"Argument count in %%varargs must be positive.\n"); + $$ = 0; + } else { + $$ = Copy($3); + Setattr($$,"name","VARARGS_SENTINEL"); + for (i = 0; i < n; i++) { + p = Copy($3); + set_nextSibling(p,$$); + $$ = p; + } + } + } + ; + + +/* ------------------------------------------------------------ + %typemap(method) type { ... } + %typemap(method) type "..." + %typemap(method) type; - typemap deletion + %typemap(method) type1,type2,... = type; - typemap copy + %typemap type1,type2,... = type; - typemap copy + ------------------------------------------------------------ */ + +typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace { + $$ = 0; + if ($3.op) { + $$ = new_node("typemap"); + Setattr($$,"method",$3.op); + Setattr($$,"code",NewString($6)); + if ($3.kwargs) { + Setattr($$,"kwargs", $3.kwargs); + } + appendChild($$,$5); + } + } + | TYPEMAP LPAREN typemap_type RPAREN tm_list SEMI { + $$ = 0; + if ($3.op) { + $$ = new_node("typemap"); + Setattr($$,"method",$3.op); + appendChild($$,$5); + } + } + | TYPEMAP LPAREN typemap_type RPAREN tm_list EQUAL typemap_parm SEMI { + $$ = 0; + if ($3.op) { + $$ = new_node("typemapcopy"); + Setattr($$,"method",$3.op); + Setattr($$,"pattern", Getattr($7,"pattern")); + appendChild($$,$5); + } + } + ; + +/* typemap method type (lang,method) or (method) */ + +typemap_type : kwargs { + Hash *p; + String *name; + p = nextSibling($1); + if (p && (!Getattr(p,"value"))) { + /* two argument typemap form */ + name = Getattr($1,"name"); + if (!name || (Strcmp(name,typemap_lang))) { + $$.op = 0; + $$.kwargs = 0; + } else { + $$.op = Getattr(p,"name"); + $$.kwargs = nextSibling(p); + } + } else { + /* one-argument typemap-form */ + $$.op = Getattr($1,"name"); + $$.kwargs = p; + } + } + ; + +tm_list : typemap_parm tm_tail { + $$ = $1; + set_nextSibling($$,$2); + } + ; + +tm_tail : COMMA typemap_parm tm_tail { + $$ = $2; + set_nextSibling($$,$3); + } + | empty { $$ = 0;} + ; + +typemap_parm : type typemap_parameter_declarator { + SwigType_push($1,$2.type); + $$ = new_node("typemapitem"); + Setattr($$,"pattern",NewParm($1,$2.id)); + Setattr($$,"parms", $2.parms); + /* $$ = NewParm($1,$2.id); + Setattr($$,"parms",$2.parms); */ + } + | LPAREN parms RPAREN { + $$ = new_node("typemapitem"); + Setattr($$,"pattern",$2); + /* Setattr($$,"multitype",$2); */ + } + | LPAREN parms RPAREN LPAREN parms RPAREN { + $$ = new_node("typemapitem"); + Setattr($$,"pattern", $2); + /* Setattr($$,"multitype",$2); */ + Setattr($$,"parms",$5); + } + ; + +/* ------------------------------------------------------------ + %types(parmlist); + ------------------------------------------------------------ */ + +types_directive : TYPES LPAREN parms RPAREN SEMI { + $$ = new_node("types"); + Setattr($$,"parms",$3); + } + ; + +/* ------------------------------------------------------------ + %template(name) tname<args>; + ------------------------------------------------------------ */ + +template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI { + Parm *p, *tp; + Node *n; + Node *nspace = 0, *nspace_inner = 0; + Node *tnode = 0; + Symtab *tscope = 0; + int specialized = 0; + $$ = 0; + + tscope = Swig_symbol_current(); /* Get the current scope */ + + /* If the template name is qualified. We need to create or lookup namespace entries */ + if (Swig_scopename_check($5)) { + String *prefix, *base; + Node *ns; + prefix = Swig_scopename_prefix($5); + base = Swig_scopename_last($5); + + /* Try to locate the scope */ + ns = Swig_symbol_clookup(prefix,0); + if (!ns) { + Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix); + } else { + if (Strcmp(nodeType(ns),"namespace") != 0) { + Swig_error(cparse_file,cparse_line,"'%s' is not defined as namespace.\n", prefix); + ns = 0; + } else { + /* Swig_symbol_setscope(Getattr(ns,"symtab")); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); */ + } + } + + /* Create namespace nodes to enclose the template declaration */ + if (ns) { + List *scopes; + String *sname; + String *name = NewString(prefix); + scopes = NewList(); + while (name) { + String *tprefix; + String *base = Swig_scopename_last(name); + Insert(scopes,0,base); + tprefix = Swig_scopename_prefix(name); + Delete(name); + name = tprefix; + } + for (sname = Firstitem(scopes); sname; sname = Nextitem(scopes)) { + Node *ns1,*ns2; + + ns1 = Swig_symbol_clookup(sname,0); + assert(ns1); + if (Strcmp(nodeType(ns1),"namespace") == 0) { + if (Getattr(ns1,"alias")) { + ns1 = Getattr(ns1,"namespace"); + } + } else { + assert(0); + } + ns2 = new_node("namespace"); + Setattr(ns2,"name",sname); + Setattr(ns2,"symtab", Getattr(ns1,"symtab")); + add_symbols(ns2); + Swig_symbol_setscope(Getattr(ns1,"symtab")); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + if (nspace_inner) { + appendChild(nspace_inner,ns2); + } + nspace_inner = ns2; + if (!nspace) nspace = ns2; + } + $5 = base; + } + } + + n = Swig_cparse_template_locate($5,$7); + + /* Patch the argument types to respect namespaces */ + p = $7; + while (p) { + if (!Getattr(p,"value")) { + SwigType *ty = Getattr(p,"type"); + if (ty) { + ty = Swig_symbol_type_qualify(ty,0); + /* ty = Swig_symbol_typedef_reduce(ty,0); */ + Setattr(p,"type",ty); + } + } + p = nextSibling(p); + } + /* Look for the template */ + + if (n && (Strcmp(nodeType(n),"template") == 0)) { + Parm *tparms = Getattr(n,"templateparms"); + if (!tparms) specialized = 1; + if (!specialized && ((ParmList_len($7) > ParmList_len(tparms)))) { + Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparms)); + } else if (!specialized && ((ParmList_len($7) < ParmList_numrequired(tparms)))) { + Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", ParmList_numrequired(tparms)); + } else { + int def_supplied = 0; + /* Expand the template */ + ParmList *temparms; + if (specialized) temparms = CopyParmList($7); + else temparms = CopyParmList(tparms); + /* Create typedef's and arguments */ + p = $7; + tp = temparms; + while (p) { + String *value = Getattr(p,"value"); + if (def_supplied) { + Setattr(p,"default","1"); + } + if (value) { + Setattr(tp,"value",value); + } else { + SwigType *ty = Getattr(p,"type"); + if (ty) { + Setattr(tp,"type",ty); + } + Delattr(tp,"value"); + } + p = nextSibling(p); + tp = nextSibling(tp); + if (!p && tp) { + p = tp; + def_supplied = 1; + } + } + + $$ = copy_node(n); + /* We need to set the node name based on name used to instantiate */ + Setattr($$,"name",Copy($5)); + if (!specialized) { + Delattr($$,"sym:typename"); + } else { + Setattr($$,"sym:typename","1"); + } + if ($3) { + Swig_cparse_template_expand($$,$3,temparms); + Setattr($$,"sym:name",$3); + } else { + static int cnt = 0; + String *nname = NewStringf("__dummy_%d__", cnt++); + Swig_cparse_template_expand($$,nname,temparms); + Setattr($$,"sym:name",nname); + Setattr($$,"feature:ignore","1"); + } + Delattr($$,"templatetype"); + Setattr($$,"template",n); + tnode = $$; + Setfile($$,cparse_file); + Setline($$,cparse_line); + Delete(temparms); + + add_symbols_copy($$); + if (Strcmp(nodeType($$),"class") == 0) { + + /* Identify pure abstract methods */ + Setattr($$,"abstract", pure_abstract(firstChild($$))); + + /* Set up inheritance in symbol table */ + { + Symtab *csyms; + List *baselist = Getattr($$,"baselist"); + csyms = Swig_symbol_current(); + Swig_symbol_setscope(Getattr($$,"symtab")); + if (baselist) { + List *bases = make_inherit_list(Getattr($$,"name"),baselist); + if (bases) { + Node *s; + for (s = Firstitem(bases); s; s = Nextitem(bases)) { + Symtab *st = Getattr(s,"symtab"); + if (st) { + Swig_symbol_inherit(st); + } + } + } + } + Swig_symbol_setscope(csyms); + } + + /* Merge in addmethods for this class */ + + /* !!! This may be broken. We may have to + add the addmethods at the beginning of + the class */ + + if (extendhash) { + String *clsname; + Node *am; + if (Namespaceprefix) { + clsname = NewStringf("%s::%s", Namespaceprefix, Getattr($$,"name")); + } else { + clsname = Getattr($$,"name"); + } + am = Getattr(extendhash,clsname); + if (am) { + merge_extensions(am); + appendChild($$,am); + Delattr(extendhash,clsname); + } + } + /* Add to classes hash */ + if (!classes) classes = NewHash(); + Setattr(classes,Swig_symbol_qualifiedscopename($$),$$); + } + } + if ($$ && nspace) { + appendChild(nspace_inner,$$); + $$ = nspace; + } + } + Swig_symbol_setscope(tscope); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + + } + ; + +/* ------------------------------------------------------------ + %warn "text" + %warn(no) + ------------------------------------------------------------ */ + +warn_directive : WARN string { + Swig_warning(0,cparse_file, cparse_line,"%s\n", $2); + $$ = 0; + } + ; + +/* ====================================================================== + * C Parsing + * ====================================================================== */ + +c_declaration : c_decl { + $$ = $1; + if ($$) { + add_symbols($$); + } + } + | c_enum_decl { $$ = $1; } + +/* A an extern C type declaration. Does nothing, but is ignored */ + + | EXTERN string LBRACE interface RBRACE { + if (Strcmp($2,"C") == 0) { + $$ = new_node("extern"); + Setattr($$,"name",$2); + appendChild($$,firstChild($4)); + } else { + Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\" (ignored).\n", $2); + $$ = 0; + } + } + ; + +/* ------------------------------------------------------------ + A C global declaration of some kind (may be variable, function, typedef, etc.) + ------------------------------------------------------------ */ + +c_decl : storage_class type declarator initializer c_decl_tail { + $$ = new_node("cdecl"); + if ($4.qualifier) SwigType_push($3.type,$4.qualifier); + Setattr($$,"type",$2); + Setattr($$,"storage",$1); + Setattr($$,"name",$3.id); + Setattr($$,"decl",$3.type); + Setattr($$,"parms",$3.parms); + Setattr($$,"value",$4.val); + Setattr($$,"throws",$4.throws); + if (!$5) { + if (Len(scanner_ccode)) { + Setattr($$,"code",Copy(scanner_ccode)); + } + } else { + Node *n = $5; + /* Inherit attributes */ + while (n) { + Setattr(n,"type",Copy($2)); + Setattr(n,"storage",$1); + n = nextSibling(n); + } + } + if ($4.bitfield) { + Setattr($$,"bitfield", $4.bitfield); + } + + /* Look for "::" declarations (ignored) */ + if (Strstr($3.id,"::")) { + Delete($$); + $$ = $5; + } else { + set_nextSibling($$,$5); + } + } + ; + +/* Allow lists of variables and functions to be built up */ + +c_decl_tail : SEMI { + $$ = 0; + Clear(scanner_ccode); + } + | COMMA declarator initializer c_decl_tail { + $$ = new_node("cdecl"); + if ($3.qualifier) SwigType_push($2.type,$3.qualifier); + Setattr($$,"name",$2.id); + Setattr($$,"decl",$2.type); + Setattr($$,"parms",$2.parms); + Setattr($$,"value",$3.val); + Setattr($$,"throws",$3.throws); + if ($3.bitfield) { + Setattr($$,"bitfield", $3.bitfield); + } + if (!$4) { + if (Len(scanner_ccode)) { + Setattr($$,"code",Copy(scanner_ccode)); + } + } else { + set_nextSibling($$,$4); + } + } + | LBRACE { + skip_balanced('{','}'); + $$ = 0; + } + ; + +initializer : def_args { + $$ = $1; + $$.qualifier = 0; + $$.throws = 0; + } + | type_qualifier def_args { + $$ = $2; + $$.qualifier = $1; + $$.throws = 0; + } + | THROW LPAREN parms RPAREN def_args { + $$ = $5; + $$.qualifier = 0; + $$.throws = $3; + } + | type_qualifier THROW LPAREN parms RPAREN def_args { + $$ = $6; + $$.qualifier = $1; + $$.throws = $4; + } + ; + + +/* ------------------------------------------------------------ + enum { ... } + * ------------------------------------------------------------ */ + +c_enum_decl : storage_class ENUM ename LBRACE enumlist RBRACE SEMI { + $$ = new_node("enum"); + Setattr($$,"name",$3); + appendChild($$,$5); + add_symbols($$); /* Add to tag space */ + add_symbols($5); /* Add enum values to id space */ + } + + | storage_class ENUM ename LBRACE enumlist RBRACE declarator c_decl_tail { + Node *n; + SwigType *ty = 0; + String *unnamed = 0; + + $$ = new_node("enum"); + if ($3) { + Setattr($$,"name",$3); + ty = NewStringf("enum %s", $3); + } else if ($7.id){ + unnamed = make_unnamed(); + ty = NewStringf("enum %s", unnamed); + Setattr($$,"unnamed",unnamed); + /* WF 20/12/2001: Cannot get sym:name and symtab set without setting name - fix! + // I don't think sym:name should be set. */ + Setattr($$,"name",$7.id); + Setattr($$,"tdname",$7.id); + Setattr($$,"storage",$1); + } + appendChild($$,$5); + n = new_node("cdecl"); + Setattr(n,"type",ty); + Setattr(n,"name",$7.id); + Setattr(n,"storage",$1); + Setattr(n,"decl",$7.type); + Setattr(n,"parms",$7.parms); + Setattr(n,"unnamed",unnamed); + if ($8) { + Node *p = $8; + set_nextSibling(n,p); + while (p) { + Setattr(p,"type",Copy(ty)); + Setattr(p,"unnamed",unnamed); + Setattr(p,"storage",$1); + p = nextSibling(p); + } + } else { + if (Len(scanner_ccode)) { + Setattr(n,"code",Copy(scanner_ccode)); + } + } + add_symbols($$); /* Add enum to tag space */ + set_nextSibling($$,n); + add_symbols($5); /* Add to id space */ + add_symbols(n); + } + ; + +c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { + /* This is a sick hack. If the ctor_end has parameters, + and the parms paremeter only has 1 parameter, this + could be a declaration of the form: + + type (id)(parms) + + Otherwise it's an error. */ + int err = 0; + $$ = 0; + + if ((ParmList_len($4) == 1) && (!Swig_scopename_check($2))) { + SwigType *ty = Getattr($4,"type"); + String *name = Getattr($4,"name"); + err = 1; + if (!name) { + $$ = new_node("cdecl"); + Setattr($$,"type",$2); + Setattr($$,"storage",$1); + Setattr($$,"name",ty); + + if ($6.have_parms) { + SwigType *decl = NewString(""); + SwigType_add_function(decl,$6.parms); + Setattr($$,"decl",decl); + Setattr($$,"parms",$6.parms); + if (Len(scanner_ccode)) { + Setattr($$,"code",Copy(scanner_ccode)); + } + } + if ($6.defarg) { + Setattr($$,"value",$6.defarg); + } + Setattr($$,"throws",$6.throws); + err = 0; + } + } + if (err) { + Swig_error(cparse_file,cparse_line,"Syntax error in input.\n"); + } + } + ; + +/* ====================================================================== + * C++ Support + * ====================================================================== */ + +cpp_declaration : cpp_class_decl { $$ = $1; } + | cpp_forward_class_decl { $$ = $1; } + | cpp_template_decl { $$ = $1; } + | cpp_using_decl { $$ = $1; } + | cpp_namespace_decl { $$ = $1; } + | cpp_catch_decl { $$ = 0; } + ; + +cpp_class_decl : + +/* A simple class/struct/union definition */ + storage_class cpptype idcolon inherit LBRACE { + List *bases = 0; + class_rename = make_name($3,0); + Classprefix = NewString($3); + /* Deal with inheritance */ + if ($4) { + bases = make_inherit_list($3,$4); + } + if (SwigType_istemplate($3)) { + String *fbase, *tbase, *prefix; + prefix = SwigType_templateprefix($3); + if (Namespaceprefix) { + fbase = NewStringf("%s::%s", Namespaceprefix,$3); + tbase = NewStringf("%s::%s", Namespaceprefix, prefix); + } else { + fbase = Copy($3); + tbase = Copy(prefix); + } + rename_inherit(tbase,fbase); + Delete(fbase); + Delete(tbase); + Delete(prefix); + } + if (strcmp($2,"class") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else { + cplus_mode = CPLUS_PUBLIC; + } + Swig_symbol_newscope(); + Swig_symbol_setscopename($3); + if (bases) { + Node *s; + for (s = Firstitem(bases); s; s = Nextitem(bases)) { + Symtab *st = Getattr(s,"symtab"); + if (st) { + Swig_symbol_inherit(st); + } + } + } + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + cparse_start_line = cparse_line; + + /* If there are active template parameters, we need to make sure they are + placed in the class symbol table so we can catch shadows */ + + if (template_parameters) { + Parm *tp = template_parameters; + while(tp) { + Node *tn = new_node("templateparm"); + Setattr(tn,"name",Getattr(tp,"name")); + Swig_symbol_cadd(Copy(Getattr(tp,"name")),tn); + tp = nextSibling(tp); + } + } + inclass = 1; + } cpp_members RBRACE cpp_opt_declarators { + Node *p; + SwigType *ty; + inclass = 0; + $$ = new_node("class"); + Setline($$,cparse_start_line); + Setattr($$,"name",$3); + Setattr($$,"kind",$2); + Setattr($$,"baselist",$4); + Setattr($$,"allows_typedef","1"); + /* Check for pure-abstract class */ + Setattr($$,"abstract", pure_abstract($7)); + + /* This bit of code merges in a previously defined %extend directive (if any) */ + if (extendhash) { + String *clsname = Swig_symbol_qualifiedscopename(0); + Node *am = Getattr(extendhash,clsname); + if (am) { + merge_extensions(am); + appendChild($$,am); + Delattr(extendhash,clsname); + } + Delete(clsname); + } + if (!classes) classes = NewHash(); + Setattr(classes,Swig_symbol_qualifiedscopename(0),$$); + + + appendChild($$,$7); + p = $9; + if (p) { + set_nextSibling($$,p); + } + + if (cparse_cplusplus) { + ty = NewString($3); + } else { + ty = NewStringf("%s %s", $2,$3); + } + while (p) { + Setattr(p,"storage",$1); + Setattr(p,"type",ty); + p = nextSibling(p); + } + /* Dump nested classes */ + { + String *name = $3; + if ($9) { + SwigType *decltype = Getattr($9,"decl"); + if (Cmp($1,"typedef") == 0) { + if (!decltype || !Len(decltype)) { + name = Getattr($9,"name"); + Setattr($$,"tdname",Copy(name)); + + /* Use typedef name as class name */ + if (class_rename && (Strcmp(class_rename,$3) == 0)) { + class_rename = NewString(name); + } + if (!Getattr(classes,name)) { + Setattr(classes,name,$$); + } + Setattr($$,"decl",decltype); + } + } + } + appendChild($$,dump_nested(Char(name))); + } + Setattr($$,"symtab",Swig_symbol_popscope()); + + yyrename = NewString(class_rename); + Classprefix = 0; + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($$); + if ($9) + add_symbols($9); + + } + +/* An unnamed struct, possibly with a typedef */ + + | storage_class cpptype LBRACE { + class_rename = make_name(0,0); + if (strcmp($2,"class") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else { + cplus_mode = CPLUS_PUBLIC; + } + Swig_symbol_newscope(); + cparse_start_line = cparse_line; + inclass = 1; + Classprefix = NewString(""); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + } cpp_members RBRACE declarator c_decl_tail { + String *unnamed; + Node *n, *p, *pp = 0; + Classprefix = 0; + inclass = 0; + unnamed = make_unnamed(); + $$ = new_node("class"); + Setline($$,cparse_start_line); + Setattr($$,"kind",$2); + Setattr($$,"storage",$1); + Setattr($$,"unnamed",unnamed); + Setattr($$,"allows_typedef","1"); + + /* Check for pure-abstract class */ + Setattr($$,"abstract", pure_abstract($5)); + + n = new_node("cdecl"); + Setattr(n,"name",$7.id); + Setattr(n,"unnamed",unnamed); + Setattr(n,"type",unnamed); + Setattr(n,"decl",$7.type); + Setattr(n,"parms",$7.parms); + Setattr(n,"storage",$1); + pp = n; + if ($8) { + set_nextSibling(n,$8); + p = $8; + while (p) { + pp = p; + Setattr(p,"unnamed",unnamed); + Setattr(p,"type",Copy(unnamed)); + Setattr(p,"storage",$1); + p = nextSibling(p); + } + } + set_nextSibling($$,n); + { + /* If a proper typedef name was given, we'll use it to set the scope name */ + String *name = 0; + if ($1 && (strcmp($1,"typedef") == 0)) { + if (!Len($7.type)) { + name = $7.id; + Setattr($$,"tdname",name); + Setattr($$,"name",name); + if (!class_rename) class_rename = NewString(name); + Swig_symbol_setscopename(name); + + /* If a proper name given, we use that as the typedef, not unnamed */ + Clear(unnamed); + Append(unnamed, name); + + n = nextSibling(n); + set_nextSibling($$,n); + + /* Check for previous extensions */ + if (extendhash) { + String *clsname = Swig_symbol_qualifiedscopename(0); + Node *am = Getattr(extendhash,clsname); + if (am) { + /* Merge the extension into the symbol table */ + merge_extensions(am); + appendChild($$,am); + Delattr(extendhash,clsname); + } + Delete(clsname); + } + if (!classes) classes = NewHash(); + Setattr(classes,Swig_symbol_qualifiedscopename(0),$$); + } else { + Swig_symbol_setscopename((char*)"<unnamed>"); + } + } + appendChild($$,$5); + appendChild($$,dump_nested(Char(name))); + } + /* Pop the scope */ + Setattr($$,"symtab",Swig_symbol_popscope()); + if (class_rename) { + yyrename = NewString(class_rename); + } + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($$); + add_symbols(n); + } + ; + +cpp_opt_declarators : SEMI { $$ = 0; } + | declarator c_decl_tail { + $$ = new_node("cdecl"); + Setattr($$,"name",$1.id); + Setattr($$,"decl",$1.type); + Setattr($$,"parms",$1.parms); + set_nextSibling($$,$2); + } + ; +/* ------------------------------------------------------------ + class Name; + ------------------------------------------------------------ */ + +cpp_forward_class_decl : storage_class cpptype idcolon SEMI { + if ($1 && (Strcmp($1,"friend") == 0)) { + /* Ignore */ + $$ = 0; + } else { + $$ = new_node("classforward"); + Setattr($$,"kind",$2); + Setattr($$,"name",$3); + Setattr($$,"sym:weak", "1"); + add_symbols($$); + } + } + ; + +/* ------------------------------------------------------------ + template<...> decl + ------------------------------------------------------------ */ + +cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_parameters = $3; } cpp_temp_possible { + String *tname = 0; + int error = 0; + + template_parameters = 0; + $$ = $6; + if ($$) tname = Getattr($$,"name"); + + /* Check if the class is a template specialization */ + if (($$) && (Strstr(tname,"<")) && (Strncmp(tname,"operator ",9) != 0)) { + /* If a specialization. Check if defined. */ + Node *tempn = 0; + { + String *tbase = SwigType_templateprefix(tname); + tempn = Swig_symbol_clookup_local(tbase,0); + if (!tempn || (Strcmp(nodeType(tempn),"template") != 0)) { + Swig_warning(WARN_PARSE_TEMPLATE_SP_UNDEF, Getfile($$),Getline($$),"Specialization of non-template '%s'.\n", tbase); + tempn = 0; + error = 1; + } + Delete(tbase); + } + Setattr($$,"specialization","1"); + Setattr($$,"templatetype",nodeType($$)); + set_nodeType($$,"template"); + /* Template partial specialization */ + if (tempn && ($3) && ($6)) { + List *tlist; + String *targs = SwigType_templateargs(tname); + tlist = SwigType_parmlist(targs); + /* Printf(stdout,"targs = '%s'\n", targs); */ + if (!Getattr($$,"sym:weak")) { + Setattr($$,"sym:typename","1"); + } + /* Patch the parameter list */ + if (tempn) { + Parm *p,*p1; + ParmList *tp = CopyParmList(Getattr(tempn,"templateparms")); + p = $3; + p1 = tp; + while (p && p1) { + String *pn = Getattr(p,"name"); + if (pn) Setattr(p1,"name",pn); + pn = Getattr(p,"type"); + if (pn) Setattr(p1,"type",pn); + p = nextSibling(p); + p1 = nextSibling(p1); + } + Setattr($$,"templateparms",tp); + } else { + Setattr($$,"templateparms",$3); + } + Delattr($$,"specialization"); + Setattr($$,"partialspecialization","1"); + /* Create a specialized name for matching */ + { + Parm *p = $3; + String *fname = NewString(Getattr($$,"name")); + String *ffname = 0; + + char tmp[32]; + int i; + while (p) { + String *n = Getattr(p,"name"); + if (!n) { + p = nextSibling(p); + continue; + } + for (i = 0; i < Len(tlist); i++) { + if (Strstr(Getitem(tlist,i),n)) { + sprintf(tmp,"$%d",i+1); + Replaceid(fname,n,tmp); + } + } + p = nextSibling(p); + } + /* Patch argument names with typedef */ + { + SwigType *tt; + List *tparms = SwigType_parmlist(fname); + ffname = SwigType_templateprefix(fname); + Append(ffname,"<("); + for (tt = Firstitem(tparms); tt; ) { + SwigType *ttr = Swig_symbol_typedef_reduce(tt,0); + ttr = Swig_symbol_type_qualify(ttr,0); + Append(ffname,ttr); + tt = Nextitem(tparms); + if (tt) Putc(',',ffname); + } + Append(ffname,")>"); + } + { + String *partials = Getattr(tempn,"partials"); + if (!partials) { + partials = NewList(); + Setattr(tempn,"partials",partials); + } + /* Printf(stdout,"partial: fname = '%s', '%s'\n", fname, Swig_symbol_typedef_reduce(fname,0)); */ + Append(partials,ffname); + } + Setattr($$,"partialargs",ffname); + Swig_symbol_cadd(ffname,$$); + } + Delete(tlist); + Delete(targs); + } else { + /* Need to resolve exact specialization name */ + /* This needs to be rewritten */ + List *tparms; + String *fname; + SwigType *tt; + fname = SwigType_templateprefix(tname); + tparms = SwigType_parmlist(tname); + Append(fname,"<("); + for (tt = Firstitem(tparms); tt; ) { + SwigType *ttr = Swig_symbol_typedef_reduce(tt,0); + ttr = Swig_symbol_type_qualify(ttr,0); + Append(fname,ttr); + tt = Nextitem(tparms); + if (tt) Putc(',',fname); + } + Append(fname,")>"); + Swig_symbol_cadd(fname,$$); + } + } else if ($$) { + Setattr($$,"templatetype",nodeType($6)); + set_nodeType($$,"template"); + Setattr($$,"templateparms", $3); + if (!Getattr($$,"sym:weak")) { + Setattr($$,"sym:typename","1"); + } + add_symbols($$); + /* We also place a fully parameterized version in the symbol table */ + { + Parm *p; + String *fname = NewStringf("%s<(",Getattr($$,"name")); + p = $3; + while (p) { + String *n = Getattr(p,"name"); + if (!n) n = Getattr(p,"type"); + Printf(fname,"%s", n); + p = nextSibling(p); + if (p) Putc(',',fname); + } + Printf(fname,")>"); + Swig_symbol_cadd(fname,$$); + } + } + if (error) $$ = 0; + } + ; + +cpp_temp_possible: c_decl { + $$ = $1; + } + | cpp_class_decl { + $$ = $1; + } + | cpp_constructor_decl { + $$ = $1; + } + | cpp_template_decl { + $$ = 0; + } + | cpp_forward_class_decl { + $$ = $1; + } + ; + +template_parms : rawparms { + /* Rip out the parameter names */ + Parm *p = $1; + $$ = $1; + + while (p) { + String *name = Getattr(p,"name"); + if (!name) { + /* Hmmm. Maybe it's a 'class T' parameter */ + char *type = Char(Getattr(p,"type")); + /* Template template parameter */ + if (strncmp(type,"template<class> ",16) == 0) { + type += 16; + } + if ((strncmp(type,"class ",6) == 0) || (strncmp(type,"typename ", 9) == 0)) { + char *t = strchr(type,' '); + Setattr(p,"name", t+1); + } else { + /* + Swig_error(cparse_file, cparse_line, "Missing template parameter name\n"); + $$.rparms = 0; + $$.parms = 0; + break; */ + } + } + p = nextSibling(p); + } + } + ; + +/* Namespace support */ + +cpp_using_decl : USING idcolon SEMI { + $$ = new_node("using"); + Setattr($$,"uname",$2); + Setattr($$,"name", Swig_scopename_last($2)); + add_symbols($$); + } + | USING NAMESPACE idcolon SEMI { + Node *n = Swig_symbol_clookup($3,0); + if (!n) { + Swig_error(cparse_file, cparse_line, "Nothing known about namespace '%s'\n", $3); + $$ = 0; + } else { + + while (Strcmp(nodeType(n),"using") == 0) { + n = Getattr(n,"node"); + } + if (n) { + if (Strcmp(nodeType(n),"namespace") == 0) { + $$ = new_node("using"); + Setattr($$,"node",n); + Setattr($$,"namespace", $3); + Swig_symbol_inherit(Getattr(n,"symtab")); + } else { + Swig_error(cparse_file, cparse_line, "'%s' is not a namespace.\n", $3); + $$ = 0; + } + } else { + $$ = 0; + } + } + } + ; + +cpp_namespace_decl : NAMESPACE idcolon LBRACE { + Hash *h; + $1 = Swig_symbol_current(); + h = Swig_symbol_clookup($2,0); + if (h && (Strcmp(nodeType(h),"namespace") == 0)) { + if (Getattr(h,"alias")) { + h = Getattr(h,"namespace"); + Swig_warning(WARN_PARSE_NAMESPACE_ALIAS, cparse_file, cparse_line, "Namespace alias '%s' not allowed here. Assuming '%s'\n", + $2, Getattr(h,"name")); + $2 = Getattr(h,"name"); + } + Swig_symbol_setscope(Getattr(h,"symtab")); + } else { + Swig_symbol_newscope(); + Swig_symbol_setscopename($2); + } + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + } interface RBRACE { + Node *n = $5; + set_nodeType(n,"namespace"); + Setattr(n,"name",$2); + Setattr(n,"symtab", Swig_symbol_popscope()); + Swig_symbol_setscope($1); + $$ = n; + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($$); + } + | NAMESPACE LBRACE { + Hash *h; + $1 = Swig_symbol_current(); + h = Swig_symbol_clookup("",0); + if (h && (Strcmp(nodeType(h),"namespace") == 0)) { + Swig_symbol_setscope(Getattr(h,"symtab")); + } else { + Swig_symbol_newscope(); + Swig_symbol_setscopename("__unnamed__"); + } + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + } interface RBRACE { + $$ = $4; + set_nodeType($$,"namespace"); + Setattr($$,"unnamed","1"); + Setattr($$,"symtab", Swig_symbol_popscope()); + Swig_symbol_setscope($1); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($$); + } + | NAMESPACE ID EQUAL idcolon SEMI { + /* Namespace alias */ + Node *n; + $$ = new_node("namespace"); + Setattr($$,"name",$2); + Setattr($$,"alias",$4); + n = Swig_symbol_clookup($4,0); + if (!n) { + Swig_error(cparse_file, cparse_line, "Unknown namespace '%s'\n", $4); + $$ = 0; + } else { + if (Strcmp(nodeType(n),"namespace") != 0) { + Swig_error(cparse_file, cparse_line, "'%s' is not a namespace\n",$4); + $$ = 0; + } else { + while (Getattr(n,"alias")) { + n = Getattr(n,"namespace"); + } + Setattr($$,"namespace",n); + add_symbols($$); + /* Set up a scope alias */ + Swig_symbol_alias($2,Getattr(n,"symtab")); + } + } + } + ; + +cpp_members : cpp_member cpp_members { + $$ = $1; + if ($$) { + Node *p = $$; + Node *pp =0; + while (p) { + pp = p; + p = nextSibling(p); + } + set_nextSibling(pp,$2); + } else { + $$ = $2; + } + } + | EXTEND LBRACE { + if (cplus_mode != CPLUS_PUBLIC) { + Swig_error(cparse_file,cparse_line,"%%extend can only be used in a public section\n"); + } + } cpp_members RBRACE cpp_members { + $$ = new_node("extend"); + Swig_tag_nodes($4,"feature:extend",(char*) "1"); + appendChild($$,$4); + set_nextSibling($$,$6); + } + | empty { $$ = 0;} + | error { + skip_decl(); + { + static int last_error_line = -1; + if (last_error_line != cparse_line) { + Swig_error(cparse_file, cparse_line,"Syntax error in input.\n"); + last_error_line = cparse_line; + } + } + } cpp_members { + $$ = $3; + } + ; + +/* ====================================================================== + * C++ Class members + * ====================================================================== */ + +/* A class member. May be data or a function. Static or virtual as well */ + +cpp_member : c_declaration { $$ = $1; } + | cpp_constructor_decl { + $$ = $1; + add_symbols($$); + } + | cpp_destructor_decl { $$ = $1; } + | cpp_protection_decl { $$ = $1; } + | cpp_swig_directive { $$ = $1; } + | cpp_conversion_operator { $$ = $1; } + | cpp_forward_class_decl { $$ = $1; } + | cpp_nested { $$ = $1; } + | storage_class idcolon SEMI { $$ = 0; } + | cpp_using_decl { $$ = $1; } + | cpp_template_decl { $$ = $1; } + | cpp_catch_decl { $$ = 0; } + | template_directive { $$ = $1; } + | warn_directive { $$ = $1; } + | SEMI { $$ = 0; } + ; + +/* Possibly a constructor */ +/* Note: the use of 'type' is here to resolve a shift-reduce conflict. For example: + typedef Foo (); + typedef Foo (*ptr)(); +*/ + +cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { + if (Classprefix) { + SwigType *decl = NewString(""); + $$ = new_node("constructor"); + + /* Since the parse performs type-corrections in template mode, we + have to undo the correction here. Ugh. */ + + /* Check for template names. If the class is a template + and the constructor is missing the template part, we + add it */ + /* { + char *c = Strstr(Classprefix,"<"); + if (c) { + if (!Strstr($2,"<")) { + Append($2,c); + } + } + } + */ + Setattr($$,"name",$2); + Setattr($$,"parms",$4); + SwigType_add_function(decl,$4); + Setattr($$,"decl",decl); + Setattr($$,"throws",$6.throws); + if (Len(scanner_ccode)) { + Setattr($$,"code",Copy(scanner_ccode)); + } + Setattr($$,"feature:new","1"); + } else { + $$ = 0; + } + } + ; + +/* A destructor (hopefully) */ + +cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end { + $$ = new_node("destructor"); + Setattr($$,"name",NewStringf("~%s",$2)); + if (Len(scanner_ccode)) { + Setattr($$,"code",Copy(scanner_ccode)); + } + { + String *decl = NewString(""); + SwigType_add_function(decl,$4); + Setattr($$,"decl",decl); + } + add_symbols($$); + } + +/* A virtual destructor */ + + | VIRTUAL NOT idtemplate LPAREN parms RPAREN cpp_vend { + $$ = new_node("destructor"); + /* Check for template names. If the class is a template + and the constructor is missing the template part, we + add it */ + { + char *c = Strstr(Classprefix,"<"); + if (c) { + if (!Strstr($3,"<")) { + $3 = NewStringf("%s%s",$3,c); + } + } + } + Setattr($$,"storage","virtual"); + Setattr($$,"name",NewStringf("~%s",$3)); + if ($7.val) { + Setattr($$,"value","0"); + } + if (Len(scanner_ccode)) { + Setattr($$,"code",Copy(scanner_ccode)); + } + { + String *decl = NewString(""); + SwigType_add_function(decl,$5); + Setattr($$,"decl",decl); + } + + add_symbols($$); + } + ; + + +/* C++ type conversion operator */ +cpp_conversion_operator : storage_class COPERATOR type pointer LPAREN parms RPAREN cpp_vend { + $$ = new_node("cdecl"); + Setattr($$,"type",$3); + Setattr($$,"name",$2); + + SwigType_add_function($4,$6); + if ($8.qualifier) { + SwigType_push($4,$8.qualifier); + } + Setattr($$,"decl",$4); + Setattr($$,"parms",$6); + Setattr($$,"conversion_operator","1"); + add_symbols($$); + } + | storage_class COPERATOR type AND LPAREN parms RPAREN cpp_vend { + SwigType *decl; + $$ = new_node("cdecl"); + Setattr($$,"type",$3); + Setattr($$,"name",$2); + decl = NewString(""); + SwigType_add_reference(decl); + SwigType_add_function(decl,$6); + if ($8.qualifier) { + SwigType_push(decl,$8.qualifier); + } + Setattr($$,"decl",decl); + Setattr($$,"parms",$6); + Setattr($$,"conversion_operator","1"); + add_symbols($$); + } + + | storage_class COPERATOR type LPAREN parms RPAREN cpp_vend { + String *t = NewString(""); + $$ = new_node("cdecl"); + Setattr($$,"type",$3); + Setattr($$,"name",$2); + SwigType_add_function(t,$5); + if ($7.qualifier) { + SwigType_push(t,$7.qualifier); + } + Setattr($$,"decl",t); + Setattr($$,"parms",$5); + Setattr($$,"conversion_operator","1"); + add_symbols($$); + } + ; + +/* isolated catch clause. */ + +cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE { + skip_balanced('{','}'); + $$ = 0; + } + ; + +/* public: */ +cpp_protection_decl : PUBLIC COLON { + $$ = new_node("access"); + Setattr($$,"kind","public"); + cplus_mode = CPLUS_PUBLIC; + } + +/* private: */ + | PRIVATE COLON { + $$ = new_node("access"); + Setattr($$,"kind","private"); + cplus_mode = CPLUS_PRIVATE; + } + +/* protected: */ + + | PROTECTED COLON { + $$ = new_node("access"); + Setattr($$,"kind","protected"); + cplus_mode = CPLUS_PROTECTED; + } + ; + + +/* ---------------------------------------------------------------------- + Nested structure. This is a sick "hack". If we encounter + a nested structure, we're going to grab the text of its definition and + feed it back into the scanner. In the meantime, we need to grab + variable declaration information and generate the associated wrapper + code later. Yikes! + + This really only works in a limited sense. Since we use the + code attached to the nested class to generate both C/C++ code, + it can't have any SWIG directives in it. It also needs to be parsable + by SWIG or this whole thing is going to puke. + ---------------------------------------------------------------------- */ + +/* A struct sname { } id; declaration */ + +cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); + } nested_decl SEMI { + $$ = 0; + if (cplus_mode == CPLUS_PUBLIC) { + if ($6.id) { + if (strcmp($2,"class") == 0) { + Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested classes not currently supported (ignored).\n"); + /* Generate some code for a new class */ + } else { + Nested *n = (Nested *) malloc(sizeof(Nested)); + n->code = NewString(""); + Printv(n->code, "typedef ", $2, " ", + Char(scanner_ccode), " $classname_", $6.id, ";\n", NIL); + + n->name = Swig_copy_string($6.id); + n->line = cparse_start_line; + n->type = NewString(""); + n->kind = $2; + SwigType_push(n->type, $6.type); + n->next = 0; + add_nested(n); + } + } else { + Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); + } + } + } + +/* An unnamed nested structure definition */ + | storage_class cpptype LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); + } nested_decl SEMI { + $$ = 0; + if (cplus_mode == CPLUS_PUBLIC) { + if (strcmp($2,"class") == 0) { + Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n"); + /* Generate some code for a new class */ + } else if ($5.id) { + /* Generate some code for a new class */ + Nested *n = (Nested *) malloc(sizeof(Nested)); + n->code = NewString(""); + Printv(n->code, "typedef ", $2, " " , + Char(scanner_ccode), " $classname_", $5.id, ";\n",NIL); + n->name = Swig_copy_string($5.id); + n->line = cparse_start_line; + n->type = NewString(""); + n->kind = $2; + SwigType_push(n->type,$5.type); + n->next = 0; + add_nested(n); + } else { + Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); + } + } + } + ; + +nested_decl : declarator { $$ = $1;} + | empty { $$.id = 0; } + ; + + +/* These directives can be included inside a class definition */ + +cpp_swig_directive: pragma_directive { $$ = $1; } + +/* A constant (includes #defines) inside a class */ + | constant_directive { $$ = $1; } + +/* This is the new style rename */ + + | name_directive { $$ = $1; } + +/* rename directive */ + | rename_directive { $$ = $1; } + | feature_directive { $$ = $1; } + | varargs_directive { $$ = $1; } + | insert_directive { $$ = $1; } + | typemap_directive { $$ = $1; } + | apply_directive { $$ = $1; } + | clear_directive { $$ = $1; } + | echo_directive { $$ = $1; } + ; + +cpp_end : cpp_const SEMI { + Clear(scanner_ccode); + } + | cpp_const LBRACE { skip_balanced('{','}'); } + ; + +cpp_vend : cpp_const SEMI { + Clear(scanner_ccode); + $$.val = 0; + $$.qualifier = $1.qualifier; + $$.bitfield = 0; + $$.throws = $1.throws; + } + | cpp_const EQUAL definetype SEMI { + Clear(scanner_ccode); + $$.val = $3.val; + $$.qualifier = $1.qualifier; + $$.bitfield = 0; + $$.throws = $1.throws; + } + | cpp_const LBRACE { + skip_balanced('{','}'); + $$.val = 0; + $$.qualifier = $1.qualifier; + $$.bitfield = 0; + $$.throws = $1.throws; + } + ; + + +/* ====================================================================== + * PRIMITIVES + * ====================================================================== */ + +storage_class : EXTERN { $$ = "extern"; } + | EXTERN string { + if (strcmp($2,"C") == 0) { + $$ = "externc"; + } else { + Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\" (ignored).\n", $2); + $$ = 0; + } + } + | STATIC { $$ = "static"; } + | TYPEDEF { $$ = "typedef"; } + | VIRTUAL { $$ = "virtual"; } + | FRIEND { $$ = "friend"; } + | empty { $$ = 0; } + ; + +/* ------------------------------------------------------------------------------ + Function parameter lists + ------------------------------------------------------------------------------ */ + +parms : rawparms { + Parm *p; + $$ = $1; + p = $1; + while (p) { + Replace(Getattr(p,"type"),"typename ", "", DOH_REPLACE_ANY); + p = nextSibling(p); + } + } + ; + +rawparms : parm ptail { + if (1) { + set_nextSibling($1,$2); + $$ = $1; + } else { + $$ = $2; + } + } + | empty { $$ = 0; } + ; + +ptail : COMMA parm ptail { + set_nextSibling($2,$3); + $$ = $2; + } + | empty { $$ = 0; } + ; + + +parm : rawtype parameter_declarator { + SwigType_push($1,$2.type); + $$ = NewParm($1,$2.id); + Setfile($$,cparse_file); + Setline($$,cparse_line); + if ($2.defarg) { + Setattr($$,"value",$2.defarg); + } + } + + | TEMPLATE LESSTHAN cpptype GREATERTHAN cpptype idcolon { + $$ = NewParm(NewStringf("template<class> %s %s", $5,$6), 0); + Setfile($$,cparse_file); + Setline($$,cparse_line); + } + | PERIOD PERIOD PERIOD { + SwigType *t = NewString("v(...)"); + $$ = NewParm(t, 0); + Setfile($$,cparse_file); + Setline($$,cparse_line); + } + ; + +valparms : rawvalparms { + Parm *p; + $$ = $1; + p = $1; + while (p) { + if (Getattr(p,"type")) { + Replace(Getattr(p,"type"),"typename ", "", DOH_REPLACE_ANY); + } + p = nextSibling(p); + } + } + ; + +rawvalparms : valparm valptail { + if (1) { + set_nextSibling($1,$2); + $$ = $1; + } else { + $$ = $2; + } + } + | empty { $$ = 0; } + ; + +valptail : COMMA valparm valptail { + set_nextSibling($2,$3); + $$ = $2; + } + | empty { $$ = 0; } + ; + + +valparm : parm { + $$ = $1; + { + /* We need to make a possible adjustment for integer parameters. */ + SwigType *type; + Node *n = 0; + + while (!n) { + type = Getattr($1,"type"); + n = Swig_symbol_clookup(type,0); /* See if we can find a node that matches the typename */ + if ((n) && (Strcmp(nodeType(n),"cdecl") == 0)) { + SwigType *decl = Getattr(n,"decl"); + if (!SwigType_isfunction(decl)) { + String *value = Getattr(n,"value"); + if (value) { + Setattr($1,"type",Copy(value)); + n = 0; + } + } + } else { + break; + } + } + } + + } + | exprnum { + $$ = NewParm(0,0); + Setfile($$,cparse_file); + Setline($$,cparse_line); + Setattr($$,"value",$1.val); + } + | STRING { + $$ = NewParm(0,0); + Setfile($$,cparse_file); + Setline($$,cparse_line); + Setattr($$,"value",NewString($1)); + } + ; + +def_args : EQUAL definetype { + $$ = $2; + if ($2.type == T_ERROR) { + Swig_warning(WARN_PARSE_BAD_DEFAULT,cparse_file, cparse_line, "Can't set default argument (ignored)\n"); + $$.val = 0; + $$.rawval = 0; + $$.bitfield = 0; + $$.throws = 0; + } + } + | EQUAL AND idcolon { + Node *n = Swig_symbol_clookup($3,0); + if (n) { + String *q = Swig_symbol_qualified(n); + if (Getattr(n,"access")) { + if (cplus_mode == CPLUS_PUBLIC) { + Swig_warning(WARN_PARSE_PRIVATE, cparse_file, cparse_line,"'%s' is private in this context.\n", $3); + Swig_warning(WARN_PARSE_BAD_DEFAULT, cparse_file, cparse_line,"Can't set default argument value (ignored)\n"); + } + $$.val = 0; + } else { + if (q) { + $$.val = NewStringf("&%s::%s", q,Getattr(n,"name")); + Delete(q); + } else { + $$.val = NewStringf("&%s", $3); + } + } + } else { + $$.val = NewStringf("&%s",$3); + } + $$.rawval = 0; + $$.type = T_USER; + $$.bitfield = 0; + $$.throws = 0; + } + | EQUAL LBRACE { + skip_balanced('{','}'); + $$.val = 0; + $$.rawval = 0; + $$.type = T_INT; + $$.bitfield = 0; + $$.throws = 0; + } + | COLON NUM_INT { + $$.val = 0; + $$.rawval = 0; + $$.type = 0; + $$.bitfield = $2.val; + $$.throws = 0; + } + | empty { + $$.val = 0; + $$.rawval = 0; + $$.type = T_INT; + $$.bitfield = 0; + $$.throws = 0; + } + ; + +parameter_declarator : declarator def_args { + $$ = $1; + $$.defarg = $2.rawval ? $2.rawval : $2.val; + } + | abstract_declarator def_args { + $$ = $1; + $$.defarg = $2.rawval ? $2.rawval : $2.val; + } + | def_args { + $$.type = 0; + $$.id = 0; + $$.defarg = $1.rawval ? $1.rawval : $1.val; + } + ; + +typemap_parameter_declarator : declarator { + $$ = $1; + if (SwigType_isfunction($1.type)) { + Delete(SwigType_pop_function($1.type)); + } else if (SwigType_isarray($1.type)) { + SwigType *ta = SwigType_pop_arrays($1.type); + if (SwigType_isfunction($1.type)) { + Delete(SwigType_pop_function($1.type)); + } else { + $$.parms = 0; + } + SwigType_push($1.type,ta); + Delete(ta); + } else { + $$.parms = 0; + } + } + | abstract_declarator { + $$ = $1; + if (SwigType_isfunction($1.type)) { + Delete(SwigType_pop_function($1.type)); + } else if (SwigType_isarray($1.type)) { + SwigType *ta = SwigType_pop_arrays($1.type); + if (SwigType_isfunction($1.type)) { + Delete(SwigType_pop_function($1.type)); + } else { + $$.parms = 0; + } + SwigType_push($1.type,ta); + Delete(ta); + } else { + $$.parms = 0; + } + } + | empty { + $$.type = 0; + $$.id = 0; + $$.parms = 0; + } + ; + + +declarator : pointer notso_direct_declarator { + $$ = $2; + if ($$.type) { + SwigType_push($1,$$.type); + Delete($$.type); + } + $$.type = $1; + } + | pointer AND notso_direct_declarator { + $$ = $3; + SwigType_add_reference($1); + if ($$.type) { + SwigType_push($1,$$.type); + Delete($$.type); + } + $$.type = $1; + } + | direct_declarator { + $$ = $1; + if (!$$.type) $$.type = NewString(""); + } + | AND notso_direct_declarator { + $$ = $2; + $$.type = NewString(""); + SwigType_add_reference($$.type); + if ($2.type) { + SwigType_push($$.type,$2.type); + Delete($2.type); + } + } + | idcolon DSTAR notso_direct_declarator { + SwigType *t = NewString(""); + + $$ = $3; + SwigType_add_memberpointer(t,$1); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | pointer idcolon DSTAR notso_direct_declarator { + SwigType *t = NewString(""); + $$ = $4; + SwigType_add_memberpointer(t,$2); + SwigType_push($1,t); + if ($$.type) { + SwigType_push($1,$$.type); + Delete($$.type); + } + $$.type = $1; + Delete(t); + } + | pointer idcolon DSTAR AND notso_direct_declarator { + $$ = $5; + SwigType_add_memberpointer($1,$2); + SwigType_add_reference($1); + if ($$.type) { + SwigType_push($1,$$.type); + Delete($$.type); + } + $$.type = $1; + } + | idcolon DSTAR AND notso_direct_declarator { + SwigType *t = NewString(""); + $$ = $4; + SwigType_add_memberpointer(t,$1); + SwigType_add_reference(t); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + ; + +notso_direct_declarator : idcolon { + /* Note: This is non-standard C. Template declarator is allowed to follow an identifier */ + $$.id = Char($1); + $$.type = 0; + $$.parms = 0; + $$.have_parms = 0; + } + + | NOT idcolon { + $$.id = Char(NewStringf("~%s",$2)); + $$.type = 0; + $$.parms = 0; + $$.have_parms = 0; + } + +/* This generate a shift-reduce conflict with constructors */ + | LPAREN idcolon RPAREN { + $$.id = Char($2); + $$.type = 0; + $$.parms = 0; + $$.have_parms = 0; + } + +/* Technically, this should be LPAREN declarator RPAREN, but we get reduce/reduce conflicts */ + | LPAREN pointer notso_direct_declarator RPAREN { + $$ = $3; + if ($$.type) { + SwigType_push($2,$$.type); + Delete($$.type); + } + $$.type = $2; + } + | LPAREN idcolon DSTAR notso_direct_declarator RPAREN { + SwigType *t; + $$ = $4; + t = NewString(""); + SwigType_add_memberpointer(t,$2); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | notso_direct_declarator LBRACKET RBRACKET { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_array(t,(char*)""); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | notso_direct_declarator LBRACKET expr RBRACKET { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_array(t,$3.val); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | notso_direct_declarator LPAREN parms RPAREN { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_function(t,$3); + if (!$$.have_parms) { + $$.parms = $3; + $$.have_parms = 1; + } + if (!$$.type) { + $$.type = t; + } else { + SwigType_push(t, $$.type); + Delete($$.type); + $$.type = t; + } + } + ; + +direct_declarator : idcolon { + /* Note: This is non-standard C. Template declarator is allowed to follow an identifier */ + $$.id = Char($1); + $$.type = 0; + $$.parms = 0; + $$.have_parms = 0; + } + + | NOT idcolon { + $$.id = Char(NewStringf("~%s",$2)); + $$.type = 0; + $$.parms = 0; + $$.have_parms = 0; + } + +/* This generate a shift-reduce conflict with constructors */ +/* + | LPAREN idcolon RPAREN { + $$.id = Char($2); + $$.type = 0; + $$.parms = 0; + $$.have_parms = 0; + } +*/ +/* Technically, this should be LPAREN declarator RPAREN, but we get reduce/reduce conflicts */ + | LPAREN pointer direct_declarator RPAREN { + $$ = $3; + if ($$.type) { + SwigType_push($2,$$.type); + Delete($$.type); + } + $$.type = $2; + } + | LPAREN idcolon DSTAR direct_declarator RPAREN { + SwigType *t; + $$ = $4; + t = NewString(""); + SwigType_add_memberpointer(t,$2); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | direct_declarator LBRACKET RBRACKET { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_array(t,(char*)""); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | direct_declarator LBRACKET expr RBRACKET { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_array(t,$3.val); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | direct_declarator LPAREN parms RPAREN { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_function(t,$3); + if (!$$.have_parms) { + $$.parms = $3; + $$.have_parms = 1; + } + if (!$$.type) { + $$.type = t; + } else { + SwigType_push(t, $$.type); + Delete($$.type); + $$.type = t; + } + } + ; + +abstract_declarator : pointer { + $$.type = $1; + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + } + | pointer direct_abstract_declarator { + $$ = $2; + SwigType_push($1,$2.type); + $$.type = $1; + Delete($2.type); + } + | pointer AND { + $$.type = $1; + SwigType_add_reference($$.type); + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + } + | pointer AND direct_abstract_declarator { + $$ = $3; + SwigType_add_reference($1); + if ($$.type) { + SwigType_push($1,$$.type); + Delete($$.type); + } + $$.type = $1; + } + | direct_abstract_declarator { + $$ = $1; + } + | AND direct_abstract_declarator { + $$ = $2; + $$.type = NewString(""); + SwigType_add_reference($$.type); + if ($2.type) { + SwigType_push($$.type,$2.type); + Delete($2.type); + } + } + | AND { + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + $$.type = NewString(""); + SwigType_add_reference($$.type); + } + | idcolon DSTAR { + $$.type = NewString(""); + SwigType_add_memberpointer($$.type,$1); + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + } + | pointer idcolon DSTAR { + SwigType *t = NewString(""); + $$.type = $1; + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + SwigType_add_memberpointer(t,$2); + SwigType_push($$.type,t); + Delete(t); + } + | pointer idcolon DSTAR direct_abstract_declarator { + $$ = $4; + SwigType_add_memberpointer($1,$2); + if ($$.type) { + SwigType_push($1,$$.type); + Delete($$.type); + } + $$.type = $1; + } + ; + +direct_abstract_declarator : direct_abstract_declarator LBRACKET RBRACKET { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_array(t,(char*)""); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | direct_abstract_declarator LBRACKET expr RBRACKET { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_array(t,$3.val); + if ($$.type) { + SwigType_push(t,$$.type); + Delete($$.type); + } + $$.type = t; + } + | LBRACKET RBRACKET { + $$.type = NewString(""); + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + SwigType_add_array($$.type,(char*)""); + } + | LBRACKET expr RBRACKET { + $$.type = NewString(""); + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + SwigType_add_array($$.type,$2.val); + } + | LPAREN abstract_declarator RPAREN { + $$ = $2; + } + | direct_abstract_declarator LPAREN parms RPAREN { + SwigType *t; + $$ = $1; + t = NewString(""); + SwigType_add_function(t,$3); + if (!$$.type) { + $$.type = t; + } else { + SwigType_push(t,$$.type); + Delete($$.type); + $$.type = t; + } + if (!$$.have_parms) { + $$.parms = $3; + $$.have_parms = 1; + } + } + | LPAREN parms RPAREN { + $$.type = NewString(""); + SwigType_add_function($$.type,$2); + $$.parms = $2; + $$.have_parms = 1; + $$.id = 0; + } + ; + + +pointer : STAR type_qualifier pointer { + $$ = NewString(""); + SwigType_add_pointer($$); + SwigType_push($$,$2); + SwigType_push($$,$3); + Delete($3); + } + | STAR pointer { + $$ = NewString(""); + SwigType_add_pointer($$); + SwigType_push($$,$2); + Delete($2); + } + | STAR type_qualifier { + $$ = NewString(""); + SwigType_add_pointer($$); + SwigType_push($$,$2); + } + | STAR { + $$ = NewString(""); + SwigType_add_pointer($$); + } + ; + +type_qualifier : type_qualifier_raw { + $$ = NewString(""); + SwigType_add_qualifier($$,$1); + } + | type_qualifier_raw type_qualifier { + $$ = $2; + SwigType_add_qualifier($$,$1); + } + ; + +type_qualifier_raw : CONST { $$ = "const"; } + | VOLATILE { $$ = "volatile"; } + ; + +/* Data type must be a built in type or an identifier for user-defined types + This type can be preceded by a modifier. */ + +type : rawtype { + $$ = $1; + Replace($$,"typename ","", DOH_REPLACE_ANY); + } + ; + +rawtype : type_qualifier type_right { + $$ = $2; + SwigType_push($$,$1); + } + | type_right { $$ = $1; } + ; + +type_right : primitive_type { $$ = $1; + /* Printf(stdout,"primitive = '%s'\n", $$);*/ + } + | TYPE_BOOL { $$ = $1; } + | TYPE_VOID { $$ = $1; } + | TYPE_TYPEDEF template_decl { $$ = NewStringf("%s%s",$1,$2); } + | ENUM idcolon { $$ = NewStringf("enum %s", $2); } + | TYPE_RAW { $$ = $1; } + | type_right type_qualifier { + $$ = $1; + SwigType_push($$,$2); + } + + | idcolon { + $$ = $1; + } + | cpptype idcolon { + $$ = NewStringf("%s %s", $1, $2); + } + ; + +primitive_type : primitive_type_list { + if (!$1.type) $1.type = NewString("int"); + if ($1.us) { + $$ = NewStringf("%s %s", $1.us, $1.type); + Delete($1.us); + Delete($1.type); + } else { + $$ = $1.type; + } + if (Cmp($$,"signed int") == 0) { + Delete($$); + $$ = NewString("int"); + } else if (Cmp($$,"signed long") == 0) { + Delete($$); + $$ = NewString("long"); + } else if (Cmp($$,"signed short") == 0) { + Delete($$); + $$ = NewString("short"); + } else if (Cmp($$,"signed long long") == 0) { + Delete($$); + $$ = NewString("long long"); + } + } + ; + +primitive_type_list : type_specifier { + $$ = $1; + } + | type_specifier primitive_type_list { + if ($1.us && $2.us) { + Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $2.us); + } + $$ = $2; + if ($1.us) $$.us = $1.us; + if ($1.type) { + if (!$2.type) $$.type = $1.type; + else { + int err = 0; + if ((Cmp($1.type,"long") == 0)) { + if ((Cmp($2.type,"long") == 0) || (Cmp($2.type,"double") == 0)) { + $$.type = NewStringf("long %s", $2.type); + } else if (Cmp($2.type,"int") == 0) { + $$.type = $1.type; + } else { + err = 1; + } + } else if ((Cmp($1.type,"short")) == 0) { + if (Cmp($2.type,"int") == 0) { + $$.type = $1.type; + } else { + err = 1; + } + } else if (Cmp($1.type,"int") == 0) { + $$.type = $2.type; + } else if (Cmp($1.type,"double") == 0) { + if (Cmp($2.type,"long") == 0) { + $$.type = NewString("long double"); + } else { + err = 1; + } + } + if (err) { + Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $1.type); + } + } + } + } + ; + + +type_specifier : TYPE_INT { + $$.type = NewString("int"); + $$.us = 0; + } + | TYPE_SHORT { + $$.type = NewString("short"); + $$.us = 0; + } + | TYPE_LONG { + $$.type = NewString("long"); + $$.us = 0; + } + | TYPE_CHAR { + $$.type = NewString("char"); + $$.us = 0; + } + | TYPE_FLOAT { + $$.type = NewString("float"); + $$.us = 0; + } + | TYPE_DOUBLE { + $$.type = NewString("double"); + $$.us = 0; + } + | TYPE_SIGNED { + $$.us = NewString("signed"); + $$.type = 0; + } + | TYPE_UNSIGNED { + $$.us = NewString("unsigned"); + $$.type = 0; + } + ; + +definetype : { /* scanner_check_typedef(); */ } expr { + $$ = $2; + $$.rawval = 0; + $$.bitfield = 0; + $$.throws = 0; + scanner_ignore_typedef(); + } + | string { + $$.val = NewString($1); + $$.rawval = NewStringf("\"%(escape)s\"",$$.val); + $$.type = T_STRING; + $$.bitfield = 0; + $$.throws = 0; + } + | CHARCONST { + $$.val = NewString($1); + if (Len($$.val)) { + $$.rawval = NewStringf("\'%(escape)s\'",$$.val); + } else { + $$.rawval = NewString("\'\\0'"); + } + $$.type = T_CHAR; + $$.bitfield = 0; + $$.throws; + } + ; + +/* Some stuff for handling enums */ + +ename : ID { $$ = $1; } + | empty { $$ = (char *) 0;} + ; + +/* SWIG enum list */ + +enumlist : enumlist COMMA edecl { + Node *n = Getattr($1,"_last"); + if (!n) { + set_nextSibling($1,$3); + Setattr($1,"_last",$3); + } else { + set_nextSibling(n,$3); + Setattr($1,"_last",$3); + } + $$ = $1; + } + | edecl { $$ = $1; } + ; + +edecl : ID { + $$ = new_node("enumitem"); + Setattr($$,"name",$1); + Setattr($$,"type",NewSwigType(T_INT)); + Setattr($$,"feature:immutable","1"); + } + | ID EQUAL etype { + $$ = new_node("enumitem"); + Setattr($$,"name",$1); + Setattr($$,"enumvalue", $3.val); + if ($3.type == T_CHAR) { + Setattr($$,"value",$3.val); + Setattr($$,"type",NewSwigType(T_CHAR)); + } else { + Setattr($$,"value",$1); + Setattr($$,"type",NewSwigType(T_INT)); + } + Setattr($$,"feature:immutable","1"); + } + | empty { $$ = 0; } + ; + +etype : expr { + $$ = $1; + if (($$.type != T_INT) && ($$.type != T_UINT) && + ($$.type != T_LONG) && ($$.type != T_ULONG) && + ($$.type != T_SHORT) && ($$.type != T_USHORT) && + ($$.type != T_SCHAR) && ($$.type != T_UCHAR)) { + Swig_error(cparse_file,cparse_line,"Type error. Expecting an int\n"); + } + } + | CHARCONST { + $$.val = NewString($1); + $$.type = T_INT; + } + ; + +/* Arithmetic expressions. Used for constants and other cool stuff. + Really, we're not doing anything except string concatenation, but + this does allow us to parse many constant declarations. + */ + +expr : exprnum { $$ = $1; } + | SIZEOF LPAREN type parameter_declarator RPAREN { + SwigType_push($3,$4.type); + $$.val = NewStringf("sizeof(%s)",SwigType_str($3,0)); + $$.type = T_INT; + } + | exprcompound { $$ = $1; } + | type { + Node *n; + $$.val = $1; + $$.type = T_INT; + /* Check if value is in scope */ + n = Swig_symbol_clookup($1,0); + if (n) { + if (Getattr(n,"access")) { + if (cplus_mode == CPLUS_PUBLIC) { + Swig_warning(WARN_PARSE_PRIVATE,cparse_file, cparse_line, "'%s' is private in this context.\n", $1); + $$.type = T_ERROR; + } + + } + } + } + +/* grouping */ + | LPAREN expr RPAREN %prec CAST { + $$.val = NewStringf("(%s)",$2.val); + $$.type = $2.type; + } + +/* A few common casting operations */ + + | LPAREN expr RPAREN expr %prec CAST { + $$ = $4; + $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $4.val); + } + | LPAREN expr pointer RPAREN expr %prec CAST { + $$ = $5; + SwigType_push($2.val,$3); + $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val); + } + | LPAREN expr AND RPAREN expr %prec CAST { + $$ = $5; + SwigType_add_reference($2.val); + $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val); + } + | LPAREN expr pointer AND RPAREN expr %prec CAST { + $$ = $6; + SwigType_push($2.val,$3); + SwigType_add_reference($2.val); + $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $6.val); + } + ; + +exprnum : NUM_INT { $$ = $1; } + | NUM_FLOAT { $$ = $1; } + | NUM_UNSIGNED { $$ = $1; } + | NUM_LONG { $$ = $1; } + | NUM_ULONG { $$ = $1; } + | NUM_LONGLONG { $$ = $1; } + | NUM_ULONGLONG { $$ = $1; } + ; + +exprcompound : expr PLUS expr { + $$.val = NewStringf("%s+%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr MINUS expr { + $$.val = NewStringf("%s-%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr STAR expr { + $$.val = NewStringf("%s*%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr SLASH expr { + $$.val = NewStringf("%s/%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr AND expr { + $$.val = NewStringf("%s&%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr OR expr { + $$.val = NewStringf("%s|%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr XOR expr { + $$.val = NewStringf("%s^%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr LSHIFT expr { + $$.val = NewStringf("%s<<%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr RSHIFT expr { + $$.val = NewStringf("%s>>%s",$1.val,$3.val); + $$.type = promote($1.type,$3.type); + } + | expr LAND expr { + $$.val = NewStringf("%s&&%s",$1.val,$3.val); + $$.type = T_INT; + } + | expr LOR expr { + $$.val = NewStringf("%s||%s",$1.val,$3.val); + $$.type = T_INT; + } + | MINUS expr %prec UMINUS { + $$.val = NewStringf("-%s",$2.val); + $$.type = $2.type; + } + | NOT expr { + $$.val = NewStringf("~%s",$2.val); + $$.type = $2.type; + } + | LNOT expr { + $$.val = NewStringf("!%s",$2.val); + $$.type = T_INT; + } + | type LPAREN { + skip_balanced('(',')'); + if (SwigType_istemplate($1)) { + $1 = SwigType_namestr($1); + } + $$.val = NewStringf("%s%s",$1,scanner_ccode); + Clear(scanner_ccode); + $$.type = T_INT; + } + ; + +inherit : raw_inherit { + $$ = $1; + } + ; + +raw_inherit : COLON { inherit_list = 1; } base_list { $$ = $3; inherit_list = 0; } + | empty { $$ = 0; } + ; + +base_list : base_specifier { + $$ = NewList(); + if ($1) Append($$,$1); + } + + | base_list COMMA base_specifier { + $$ = $1; + if ($3) Append($$,$3); + } + ; + +base_specifier : opt_virtual idcolon { + if (last_cpptype && (Strcmp(last_cpptype,"struct") != 0)) { + Swig_warning(WARN_PARSE_NO_ACCESS,cparse_file, cparse_line,"No access specifier given for base class %s (ignored).\n",$2); + $$ = (char *) 0; + } else { + $$ = $2; + Setfile($$,cparse_file); + Setline($$,cparse_line); + } + } + | opt_virtual access_specifier opt_virtual idcolon { + $$ = 0; + if (strcmp($2,"public") == 0) { + $$ = $4; + Setfile($$, cparse_file); + Setline($$, cparse_line); + } else { + Swig_warning(WARN_PARSE_PRIVATE_INHERIT, cparse_file, cparse_line, "%s inheritance ignored.\n", $2); + } + } + ; + +access_specifier : PUBLIC { $$ = (char*)"public"; } + | PRIVATE { $$ = (char*)"private"; } + | PROTECTED { $$ = (char*)"protected"; } + ; + + +cpptype : CLASS { + $$ = (char*)"class"; + if (!inherit_list) last_cpptype = $$; + } + | STRUCT { + $$ = (char*)"struct"; + if (!inherit_list) last_cpptype = $$; + } + | UNION { + $$ = (char*)"union"; + if (!inherit_list) last_cpptype = $$; + } + | TYPENAME { + $$ = (char *)"typename"; + if (!inherit_list) last_cpptype = $$; + } + ; + +opt_virtual : VIRTUAL + | empty + ; + +cpp_const : type_qualifier { + $$.qualifier = $1; + $$.throws = 0; + } + | THROW LPAREN parms RPAREN { + $$.qualifier = 0; + $$.throws = $3; + } + | type_qualifier THROW LPAREN parms RPAREN { + $$.qualifier = $1; + $$.throws = $4; + } + | empty { + $$.qualifier = 0; + $$.throws = 0; + } + ; + +ctor_end : cpp_const ctor_initializer SEMI { + Clear(scanner_ccode); + $$.have_parms = 0; + $$.defarg = 0; + $$.throws = $1.throws; + } + | cpp_const ctor_initializer LBRACE { + skip_balanced('{','}'); + $$.have_parms = 0; + $$.defarg = 0; + $$.throws = $1.throws; + } + | LPAREN parms RPAREN SEMI { + Clear(scanner_ccode); + $$.parms = $2; + $$.have_parms = 1; + $$.defarg = 0; + $$.throws = 0; + } + | LPAREN parms RPAREN LBRACE { + skip_balanced('{','}'); + $$.parms = $2; + $$.have_parms = 1; + $$.defarg = 0; + $$.throws = 0; + } + | EQUAL definetype SEMI { + $$.have_parms = 0; + $$.defarg = $2.val; + $$.throws = 0; + } + ; + +ctor_initializer : COLON mem_initializer_list + | empty + ; + +mem_initializer_list : mem_initializer + | mem_initializer_list COMMA mem_initializer + ; + +mem_initializer : idcolon LPAREN { + skip_balanced('(',')'); + Clear(scanner_ccode); + } + ; + +template_decl : LESSTHAN valparms GREATERTHAN { + String *s = NewString(""); + SwigType_add_template(s,$2); + $$ = Char(s); + } + | empty { $$ = (char*)""; } + ; + +idstring : ID { $$ = $1; } + | string { $$ = $1; } + ; + +idstringopt : idstring { $$ = $1; } + | empty { $$ = 0; } + ; + +idcolon : idtemplate idcolontail { + $$ = 0; + if (!$$) $$ = NewStringf("%s%s", $1,$2); + Delete($2); + } + | NONID DCOLON idtemplate idcolontail { + $$ = NewStringf("::%s%s",$3,$4); + Delete($4); + } + | idtemplate { + $$ = NewString($1); + } + | NONID DCOLON idtemplate { + $$ = NewStringf("::%s",$3); + } + | OPERATOR { + $$ = NewString($1); + } + | NONID DCOLON OPERATOR { + $$ = NewStringf("::%s",$3); + } + ; + +idcolontail : DCOLON idtemplate idcolontail { + $$ = NewStringf("::%s%s",$2,$3); + Delete($3); + } + | DCOLON idtemplate { + $$ = NewStringf("::%s",$2); + } + | DCOLON OPERATOR { + $$ = NewStringf("::%s",$2); + } + | DCNOT idtemplate { + $$ = NewStringf("::~%s",$2); + } + ; + + +idtemplate : ID template_decl { + $$ = NewStringf("%s%s",$1,$2); + scanner_last_id(1); + } + ; + +/* Identifier, but no templates */ +idcolonnt : ID idcolontailnt { + $$ = 0; + if (!$$) $$ = NewStringf("%s%s", $1,$2); + Delete($2); + } + | NONID DCOLON ID idcolontailnt { + $$ = NewStringf("::%s%s",$3,$4); + Delete($4); + } + | ID { + $$ = NewString($1); + } + | NONID DCOLON ID { + $$ = NewStringf("::%s",$3); + } + | OPERATOR { + $$ = NewString($1); + } + | NONID DCOLON OPERATOR { + $$ = NewStringf("::%s",$3); + } + ; + +idcolontailnt : DCOLON ID idcolontailnt { + $$ = NewStringf("::%s%s",$2,$3); + Delete($3); + } + | DCOLON ID { + $$ = NewStringf("::%s",$2); + } + | DCOLON OPERATOR { + $$ = NewStringf("::%s",$2); + } + | DCNOT ID { + $$ = NewStringf("::~%s",$2); + } + ; + +/* Concatenated strings */ +string : string STRING { + $$ = (char *) malloc(strlen($1)+strlen($2)+1); + strcpy($$,$1); + strcat($$,$2); + } + | STRING { $$ = $1;} + ; + +stringbrace : string { + $$ = NewString($1); + } + | LBRACE { + skip_balanced('{','}'); + $$ = NewString(scanner_ccode); + } + | HBLOCK { + $$ = $1; + } + ; + +options : LPAREN kwargs RPAREN { + Hash *n; + $$ = NewHash(); + n = $2; + while(n) { + String *name, *value; + name = Getattr(n,"name"); + value = Getattr(n,"value"); + if (!value) value = (String *) "1"; + Setattr($$,name, value); + n = nextSibling(n); + } + } + | empty { $$ = 0; }; + + +/* Keyword arguments */ +kwargs : idstring EQUAL stringnum { + $$ = NewHash(); + Setattr($$,"name",$1); + Setattr($$,"value",$3); + } + | idstring EQUAL stringnum COMMA kwargs { + $$ = NewHash(); + Setattr($$,"name",$1); + Setattr($$,"value",$3); + set_nextSibling($$,$5); + } + | idstring { + $$ = NewHash(); + Setattr($$,"name",$1); + } + | idstring COMMA kwargs { + $$ = NewHash(); + Setattr($$,"name",$1); + set_nextSibling($$,$3); + } + ; + +stringnum : string { + $$ = $1; + } + | exprnum { + $$ = $1.val; + } + ; + +empty : ; + +%% + +/* Called by the parser (yyparse) when an error is found.*/ +void yyerror (const char *e) { +} + +SwigType *Swig_cparse_type(String *s) { + String *ns; + extern void scanner_file(File *); + extern int yyparse(); + extern void scanner_next_token(int); + ns = NewStringf("%s;",s); + Seek(ns,0,SEEK_SET); + scanner_file(ns); + top = 0; + scanner_next_token(PARSETYPE); + yyparse(); + /* Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */ + return top; +} + + + + + + + + + diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c new file mode 100644 index 000000000..b9b7fb4cd --- /dev/null +++ b/Source/CParse/templ.c @@ -0,0 +1,495 @@ +/* ----------------------------------------------------------------------------- + * templ.c + * + * Expands a template into a specialized version. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_templ_c[] = "$Header$"; + +#include "swig.h" +#include "cparse.h" + +static int template_debug = 0; + +static void add_parms(ParmList *p, List *patchlist, List *typelist) { + while (p) { + SwigType *ty = Getattr(p,"type"); + SwigType *val = Getattr(p,"value"); + Append(typelist,ty); + Append(patchlist,val); + p = nextSibling(p); + } +} + +void Swig_cparse_debug_templates(int x) { + template_debug = x; +} + +/* ----------------------------------------------------------------------------- + * Swig_cparse_template_expand() + * + * Expands a template node into a specialized version. This is done by + * patching typenames and other aspects of the node according to a list of + * template parameters + * ----------------------------------------------------------------------------- */ + +static int +cparse_template_expand(Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) { + static int expanded = 0; + int ret; + + if (!n) return 0; + if (Getattr(n,"error")) return 0; + + if (Strcmp(nodeType(n),"template") == 0) { + /* Change the node type back to normal */ + if (!expanded) { + expanded = 1; + set_nodeType(n,Getattr(n,"templatetype")); + ret = cparse_template_expand(n,tname, rname, templateargs, patchlist,typelist, cpatchlist); + expanded = 0; + return ret; + } else { + /* Called when template appears inside another template */ + /* Member templates */ + + set_nodeType(n,Getattr(n,"templatetype")); + ret = cparse_template_expand(n,tname, rname, templateargs, patchlist,typelist, cpatchlist); + set_nodeType(n,"template"); + return ret; + } + } else if (Strcmp(nodeType(n),"cdecl") == 0) { + /* A simple C declaration */ + SwigType *t, *v, *d; + String *code; + t = Getattr(n,"type"); + v = Getattr(n,"value"); + d = Getattr(n,"decl"); + + code = Getattr(n,"code"); + + Append(typelist,t); + Append(typelist,d); + Append(patchlist,v); + Append(cpatchlist,code); + + if (Getattr(n,"conversion_operator")) { + Append(cpatchlist, Getattr(n,"name")); + if (Getattr(n,"sym:name")) { + Append(cpatchlist, Getattr(n,"sym:name")); + } + } + + add_parms(Getattr(n,"parms"), cpatchlist, typelist); + add_parms(Getattr(n,"throws"), cpatchlist, typelist); + + } else if (Strcmp(nodeType(n),"class") == 0) { + /* Patch base classes */ + { + List *bases = Getattr(n,"baselist"); + if (bases) { + int i; + for (i = 0; i < Len(bases); i++) { + String *name = Copy(Getitem(bases,i)); + Setitem(bases,i,name); + Append(typelist,name); + } + } + } + /* Patch children */ + { + Node *cn = firstChild(n); + while (cn) { + cparse_template_expand(cn,tname, rname, templateargs, patchlist,typelist,cpatchlist); + cn = nextSibling(cn); + } + } + } else if (Strcmp(nodeType(n),"constructor") == 0) { + String *name = Getattr(n,"name"); + if (!(Getattr(n,"templatetype"))) { + String *symname; + String *stripped_name = SwigType_templateprefix(name); + if (Strstr(tname,stripped_name)) { + Replaceid(name,stripped_name,tname); + } + Delete(stripped_name); + symname = Getattr(n,"sym:name"); + if (symname) { + stripped_name = SwigType_templateprefix(symname); + if (Strstr(tname,stripped_name)) { + Replaceid(symname,stripped_name,tname); + } + Delete(stripped_name); + } + if (Strstr(name,"<")) { + Append(patchlist,Getattr(n,"name")); + } else { + Append(name,templateargs); + } + name = Getattr(n,"sym:name"); + if (name && (Strstr(name,"<"))) { + Clear(name); + Append(name,rname); + } else { + Replace(name,tname,rname, DOH_REPLACE_ANY); + } + Setattr(n,"sym:name",name); + } + Append(cpatchlist,Getattr(n,"code")); + Append(typelist, Getattr(n,"decl")); + add_parms(Getattr(n,"parms"), cpatchlist, typelist); + add_parms(Getattr(n,"throws"), cpatchlist, typelist); + } else if (Strcmp(nodeType(n),"destructor") == 0) { + String *name = Getattr(n,"name"); + if (Strstr(name,"<")) { + Append(patchlist,Getattr(n,"name")); + } else { + Append(name,templateargs); + } + name = Getattr(n,"sym:name"); + if (name && Strstr(name,"<")) { + Setattr(n,"sym:name", Copy(tname)); + } else { + Replace(name,tname,rname, DOH_REPLACE_ANY); + } + Setattr(n,"sym:name",name); + Append(cpatchlist,Getattr(n,"code")); + } else if (Strcmp(nodeType(n),"using") == 0) { + String *uname = Getattr(n,"uname"); + if (uname) { + if (Strstr(uname,"<")) { + Append(patchlist, uname); + } + } + if (Getattr(n,"namespace")) { + /* Namespace link. This is nasty. Is other namespace defined? */ + + } + } else { + /* Look for obvious parameters */ + Node *cn; + Append(cpatchlist,Getattr(n,"code")); + Append(typelist, Getattr(n,"type")); + Append(typelist, Getattr(n,"decl")); + add_parms(Getattr(n,"parms"), cpatchlist, typelist); + add_parms(Getattr(n,"pattern"), cpatchlist, typelist); + add_parms(Getattr(n,"throws"), cpatchlist, typelist); + cn = firstChild(n); + while (cn) { + cparse_template_expand(cn,tname, rname, templateargs, patchlist, typelist, cpatchlist); + cn = nextSibling(cn); + } + } + return 0; +} + +int +Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) { + List *patchlist, *cpatchlist, *typelist; + String *templateargs; + String *tname; + String *iname; + String *tbase; + patchlist = NewList(); + cpatchlist = NewList(); + typelist = NewList(); + + { + String *tmp = NewString(""); + if (tparms) { + SwigType_add_template(tmp,tparms); + } + templateargs = Copy(tmp); + Delete(tmp); + } + + tname = Copy(Getattr(n,"name")); + tbase = Swig_scopename_last(tname); + + if (0) { + Parm *p = tparms; + while (p) { + Printf(stdout,"tparm: '%s' '%s'\n", Getattr(p,"name"), Getattr(p,"value")); + p = nextSibling(p); + } + } + + cparse_template_expand(n,tname, rname, templateargs, patchlist, typelist, cpatchlist); + + /* Set the name */ + { + String *name = Getattr(n,"name"); + if (name) { + Append(name,templateargs); + } + iname = name; + } + + /* Patch all of the types */ + { + Parm *tp = Getattr(n,"templateparms"); + Parm *p = tparms; + + if (tp) { + while (p && tp) { + String *name, *value, *valuestr, *tydef, *tmp, *tmpr; + int sz, i; + + name = Getattr(tp,"name"); + value = Getattr(p,"value"); + tydef = Getattr(p,"typedef"); + if (name) { + if (!value) { + value = Getattr(p,"type"); + valuestr = SwigType_str(value,0); + } else { + valuestr = SwigType_namestr(value); + } + assert(value); + /* Need to patch default arguments */ + { + Parm *rp = nextSibling(p); + while (rp) { + String *rvalue = Getattr(rp,"value"); + if (rvalue) { + Replace(rvalue,name,value, DOH_REPLACE_ID); + } + rp = nextSibling(rp); + } + } + sz = Len(patchlist); + for (i = 0; i < sz; i++) { + String *s = Getitem(patchlist,i); + Replace(s,name,value, DOH_REPLACE_ID); + } + sz = Len(typelist); + for (i = 0; i < sz; i++) { + String *s = Getitem(typelist,i); + Replace(s,name,value, DOH_REPLACE_ID); + SwigType_typename_replace(s,tbase,iname); + } + + if (!tydef) { + tydef = value; + } + tmp = NewStringf("#%s",name); + tmpr = NewStringf("\"%s\"", value); + + sz = Len(cpatchlist); + for (i = 0; i < sz; i++) { + String *s = Getitem(cpatchlist,i); + Replace(s,tmp,tmpr, DOH_REPLACE_ID); + /* Replace(s,name,tydef, DOH_REPLACE_ID); */ + Replace(s,name,valuestr, DOH_REPLACE_ID); + } + Delete(tmp); + Delete(tmpr); + Delete(valuestr); + } + p = nextSibling(p); + tp = nextSibling(tp); + if (!p) p = tp; + } + } else { + /* No template parameters at all. This could be a specialization */ + int i, sz; + sz = Len(typelist); + for (i = 0; i < sz; i++) { + String *s = Getitem(typelist,i); + SwigType_typename_replace(s,tbase,iname); + } + } + } + + /* Patch bases */ + { + List *bases = Getattr(n,"baselist"); + if (bases) { + String *b; + for (b = Firstitem(bases); b; b = Nextitem(bases)) { + String *qn = Swig_symbol_type_qualify(b,0); + Clear(b); + Append(b,qn); + } + } + } + Delete(patchlist); + Delete(cpatchlist); + Delete(typelist); + Delete(tbase); + + /* set_nodeType(n,"template");*/ + return 0; +} + +/* ----------------------------------------------------------------------------- + * cparse_template_locate() + * + * Search for a template that matches name with given parameters. + * ----------------------------------------------------------------------------- */ + +Node * +Swig_cparse_template_locate(String *name, Parm *tparms) { + Node *n; + String *tname, *rname = 0; + Node *templ; + List *mpartials = 0; + Parm *p; + Parm *parms; + + tname = NewString(name); + parms = CopyParmList(tparms); + + p = parms; + while (p) { + SwigType *ty = Getattr(p,"type"); + if (ty) { + SwigType *nt = Swig_symbol_typedef_reduce(ty,0); + nt = Swig_symbol_type_qualify(nt,0); + Setattr(p,"type",nt); + } + p = nextSibling(p); + } + + SwigType_add_template(tname,parms); + + if (template_debug) { + Printf(stdout,"\n%s:%d: template_debug: Searching for %s\n", cparse_file, cparse_line, tname); + } + + /* Search for an exact specialization. + Example: template<> class name<int> { ... } */ + { + if (template_debug) { + Printf(stdout," searching: '%s' (exact specialization)\n", tname); + } + n = Swig_symbol_clookup_local(tname,0); + if (n) { + Node *tn; + if (Strcmp(nodeType(n),"template") == 0) goto success; + tn = Getattr(n,"template"); + if (tn) { + n = tn; + goto success; /* Previously wrapped by a template return that */ + } + Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); + Delete(tname); + Delete(parms); + return 0; /* Found a match, but it's not a template of any kind. */ + } + } + + /* Search for generic template */ + templ = Swig_symbol_clookup_local(name,0); + + /* Search for partial specialization. + Example: template<typename T> class name<T *> { ... } */ + + /* Generate reduced template name (stripped of extraneous pointers, etc.) */ + + rname = NewStringf("%s<(",name); + p = parms; + while (p) { + String *t; + t = Getattr(p,"type"); + if (t) { + String *tbase = SwigType_base(t); + t = SwigType_default(t); + Replaceid(t,"SWIGTYPE",tbase); + Replaceid(t,"SWIGENUM",tbase); + Printf(rname,"%s",t); + Delete(t); + } else { + String *v = Getattr(p,"value"); + Printf(rname,"%s",v); + } + p = nextSibling(p); + if (p) { + Printf(rname,","); + } + } + Printf(rname,")>"); + + mpartials = NewList(); + if (templ) { + /* First, we search using an exact type prototype */ + Parm *p; + char tmp[32]; + int i; + List *partials; + String *s, *ss; + + partials = Getattr(templ,"partials"); + if (partials) { + for (s = Firstitem(partials); s; s= Nextitem(partials)) { + ss = Copy(s); + p = parms; + i = 1; + while (p) { + String *t,*tn; + sprintf(tmp,"$%d",i); + t = Getattr(p,"type"); + if (t) { + tn = SwigType_base(t); + Replaceid(ss,tmp,tn); + Delete(tn); + } else { + String *v = Getattr(p,"value"); + Replaceid(ss,tmp,v); + } + i++; + p = nextSibling(p); + } + if (template_debug) { + Printf(stdout," searching: '%s' (partial specialization - %s)\n", ss, s); + } + if ((Strcmp(ss,tname) == 0) || (Strcmp(ss,rname) == 0)) { + Append(mpartials,s); + } + Delete(ss); + } + } + } + + if (template_debug) { + Printf(stdout," Matched partials: %s\n", mpartials); + } + + if (Len(mpartials)) { + String *s = Getitem(mpartials,0); + n = Swig_symbol_clookup_local(s,0); + if (Len(mpartials) > 1) { + if (n) { + Swig_warning(WARN_PARSE_TEMPLATE_AMBIG,cparse_file,cparse_line,"Instantiation of template %s is ambiguous. Using %s at %s:%d\n", + SwigType_namestr(tname), SwigType_namestr(Getattr(n,"name")), Getfile(n),Getline(n)); + } + } + } + + if (!n) { + n = templ; + } + if (!n) { + Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name); + } else if (n && (Strcmp(nodeType(n),"template") != 0)) { + Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); + n = 0; + } + success: + Delete(tname); + Delete(rname); + Delete(mpartials); + if ((template_debug) && (n)) { + Printf(stdout,"Node: %x\n", n); + Swig_print_node(n); + } + Delete(parms); + return n; +} + + diff --git a/Source/CParse/util.c b/Source/CParse/util.c new file mode 100644 index 000000000..33f4976c8 --- /dev/null +++ b/Source/CParse/util.c @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------------- + * util.c + * + * Parsing utilities + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_util_c[] = "$Header$"; + +#include "swig.h" + +extern SwigType *Swig_cparse_type(String *); + +/* ----------------------------------------------------------------------------- + * Swig_cparse_replace_descriptor() + * + * Replaces type descriptor string $descriptor() with the SWIG type descriptor + * string. + * ----------------------------------------------------------------------------- */ + +void Swig_cparse_replace_descriptor(String *s) { + char tmp[512]; + String *arg = 0; + SwigType *t; + + while (Strstr(s,"$descriptor(")) { + char *d = tmp; + int level = 0; + char *c = Strstr(s,"$descriptor("); + while (*c) { + if (*c == '(') level++; + if (*c == ')') { + level--; + if (level == 0) { + break; + } + } + *d = *c; + d++; + c++; + } + *d = 0; + arg = NewString(tmp+12); + t = Swig_cparse_type(arg); + Delete(arg); + arg = 0; + + if (t) { + String *mangle; + String *descriptor; + + mangle = SwigType_manglestr(t); + descriptor = NewStringf("SWIGTYPE%s",mangle); + SwigType_remember(t); + *d = ')'; + d++; + *d = 0; + Replace(s,tmp,descriptor,DOH_REPLACE_ANY); + Delete(mangle); + Delete(descriptor); + } else { + Swig_error(Getfile(s),Getline(s),"Bad $descriptor() macro.\n"); + break; + } + } +} + diff --git a/Source/DOH/.cvsignore b/Source/DOH/.cvsignore index 3e4a1f00a..2599bc761 100644 --- a/Source/DOH/.cvsignore +++ b/Source/DOH/.cvsignore @@ -2,3 +2,4 @@ Makefile config.* *.tar.gz configure +autom4te.cache diff --git a/Source/DOH/Doh/Makefile b/Source/DOH/Doh/Makefile deleted file mode 100644 index 0908946e0..000000000 --- a/Source/DOH/Doh/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# Generated automatically from Makefile.in by configure. -####################################################################### -# $Header$ -# DOH -####################################################################### - -#.KEEP_STATE: - -# Set your C++ compiler here. g++ works on most machines, -# but you might have to change it depending on your installation. -# -CC = cc -prefix = /r0/beazley/Projects - -# Comment out the following line if you're on an SGI or don't have ranlib! -RANLIB = ranlib -AR = ar - -######################################################################## -# Normally, you shouldn't have to change anything below this point # -######################################################################## - -LIBOBJS = callable.o void.o fio.o memory.o base.o file.o list.o hash.o string.o - -LIBSRCS = callable.c void.c fio.c memory.c base.c file.c list.c hash.c string.c - -LIBHEADERS = ../Include/doh.h -LIB = ../libdoh.a -INCLUDE = -I../Include -CFLAGS = -DDOH_STRING_UPDATE_LINES -SHELL = /bin/sh - -# -# Rules for creation of a .o file from .cxx -.SUFFIXES: .c -.c.o: - $(CC) $(INCLUDE) $(CFLAGS) -c -o $*.o $< - -all: $(LIB) - -$(LIB): $(LIBOBJS) - @echo "Building library" - $(AR) cr $(LIB) $(LIBOBJS) - $(RANLIB) $(LIB) - -clean:: - rm -f *.o ../libdoh.a -nuke:: - rm -f Makefile *~ #* core a.out - diff --git a/Source/DOH/Doh/Makefile.in b/Source/DOH/Doh/Makefile.in index fadad36e2..44078fd2f 100644 --- a/Source/DOH/Doh/Makefile.in +++ b/Source/DOH/Doh/Makefile.in @@ -24,21 +24,21 @@ DOHOPT = # Normally, you shouldn't have to change anything below this point # ######################################################################## -LIBOBJS = void.o fio.o memory.o base.o file.o list.o hash.o string.o +LIBOBJS = void.@OBJEXT@ fio.@OBJEXT@ memory.@OBJEXT@ base.@OBJEXT@ file.@OBJEXT@ list.@OBJEXT@ hash.@OBJEXT@ string.@OBJEXT@ LIBSRCS = void.c fio.c memory.c base.c file.c list.c hash.c string.c LIBHEADERS = $(srcdir)/../Include/doh.h LIB = libdoh.a -INCLUDE = -I$(srcdir)/../Include +INCLUDES = -I$(srcdir)/../Include CFLAGS = @CFLAGS@ SHELL = /bin/sh # -# Rules for creation of a .o file from .c +# Rules for creation of a .@OBJEXT@ file from .c .SUFFIXES: .c -.c.o: - $(CC) $(DOHOPT) $(INCLUDE) $(CFLAGS) -c -o $*.o $< +.c.@OBJEXT@: + $(CC) $(DOHOPT) $(INCLUDES) $(CFLAGS) -c -o $*.@OBJEXT@ $< all: $(LIB) @@ -49,6 +49,6 @@ $(LIB): $(LIBOBJS) cp -f $(LIB) .. clean:: - rm -f *.o $(LIB) ../$(LIB) + rm -f *.@OBJEXT@ $(LIB) ../$(LIB) nuke:: - rm -f Makefile *~ #* core a.out + rm -f Makefile *~ diff --git a/Source/DOH/Doh/base.c b/Source/DOH/Doh/base.c index 8787d6204..a5063389d 100644 --- a/Source/DOH/Doh/base.c +++ b/Source/DOH/Doh/base.c @@ -10,21 +10,10 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_base_c[] = "$Header$"; #include "dohint.h" -static DohObjInfo *dohtypes[MAX_DOHTYPE]; - -/* ----------------------------------------------------------------------------- - * DohRegisterType() - * ----------------------------------------------------------------------------- */ - -void -DohRegisterType(int type, DohObjInfo *objinfo) { - dohtypes[type] = objinfo; -} - /* ----------------------------------------------------------------------------- * DohDelete() * ----------------------------------------------------------------------------- */ @@ -43,7 +32,7 @@ DohDelete(DOH *obj) { assert(b->refcount > 0); b->refcount--; if (b->refcount <= 0) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_del) { (objinfo->doh_del)(b); } else { @@ -63,9 +52,14 @@ DohCopy(const DOH *obj) { DohObjInfo *objinfo; if (!obj) return 0; - objinfo = dohtypes[b->type]; - if (objinfo->doh_copy) - return (objinfo->doh_copy)(b); + objinfo = b->type; + if (objinfo->doh_copy) { + DohBase *bc = (DohBase *) (objinfo->doh_copy)(b); + if ((bc) && b->meta) { + bc->meta = Copy(b->meta); + } + return (DOH *) bc; + } return 0; } @@ -81,7 +75,7 @@ DohIncref(DOH *obj) { void DohClear(DOH *obj) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_clear) (objinfo->doh_clear)(b); } @@ -96,11 +90,11 @@ DohStr(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(b)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_str) { return (objinfo->doh_str)(b); } - sprintf(buffer,"<Object '%s' at %x>", objinfo->objname, b); + sprintf(buffer,"<Object '%s' at %x>", objinfo->objname, (unsigned int)b); return NewString(buffer); } else { return NewString(obj); @@ -114,7 +108,7 @@ DohStr(const DOH *obj) { int DohDump(const DOH *obj, DOH *out) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_dump) { return (objinfo->doh_dump)(b,out); } @@ -130,7 +124,7 @@ DohLen(const DOH *obj) { DohObjInfo *objinfo; if (!b) return 0; if (DohCheck(b)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_len) { return (objinfo->doh_len)(b); } @@ -149,7 +143,7 @@ DohHashval(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(b)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_hashval) { return (objinfo->doh_hashval)(b); } @@ -166,7 +160,7 @@ DohData(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_data) { return (objinfo->doh_data)(b); } @@ -191,8 +185,8 @@ DohCmp(const DOH *obj1, const DOH *obj2) { if (!b1 && b2) return -1; return strcmp((char *) DohData(b1),(char *) DohData(b2)); } - b1info = dohtypes[b1->type]; - b2info = dohtypes[b2->type]; + b1info = b1->type; + b2info = b2->type; if ((b1info == b2info) && (b1info->doh_cmp)) return (b1info->doh_cmp)(b1,b2); return 1; @@ -206,7 +200,7 @@ DohIsMapping(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (!DohCheck(b)) return 0; - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_hash) return 1; else return 0; } @@ -218,7 +212,7 @@ DohIsMapping(const DOH *obj) { DOH * DohGetattr(DOH *obj, const DOH *name) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_hash && objinfo->doh_hash->doh_getattr) { return (objinfo->doh_hash->doh_getattr)(b,(DOH *) name); } @@ -232,7 +226,7 @@ DohGetattr(DOH *obj, const DOH *name) { int DohSetattr(DOH *obj, const DOH *name, const DOH *value) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_hash && objinfo->doh_hash->doh_setattr) { return (objinfo->doh_hash->doh_setattr)(b,(DOH *) name,(DOH *) value); } @@ -243,13 +237,14 @@ DohSetattr(DOH *obj, const DOH *name, const DOH *value) { * DohDelattr() * ----------------------------------------------------------------------------- */ -void +int DohDelattr(DOH *obj, const DOH *name) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_hash && objinfo->doh_hash->doh_delattr) { - (objinfo->doh_hash->doh_delattr)(b,(DOH *) name); + return (objinfo->doh_hash->doh_delattr)(b,(DOH *) name); } + return 0; } /* ----------------------------------------------------------------------------- @@ -259,7 +254,7 @@ DohDelattr(DOH *obj, const DOH *name) { DOH * DohFirstkey(DOH *obj) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_hash && objinfo->doh_hash->doh_firstkey) { return (objinfo->doh_hash->doh_firstkey)(b); } @@ -273,7 +268,7 @@ DohFirstkey(DOH *obj) { DOH * DohNextkey(DOH *obj) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo && objinfo->doh_hash->doh_nextkey) { return (objinfo->doh_hash->doh_nextkey)(b); } @@ -281,6 +276,20 @@ DohNextkey(DOH *obj) { } /* ----------------------------------------------------------------------------- + * DohNextkey() + * ----------------------------------------------------------------------------- */ + +DOH * +DohKeys(DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo && objinfo->doh_hash->doh_keys) { + return (objinfo->doh_hash->doh_keys)(b); + } + return 0; +} + +/* ----------------------------------------------------------------------------- * DohGetInt() * ----------------------------------------------------------------------------- */ @@ -388,7 +397,7 @@ DohIsSequence(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (!DohCheck(b)) return 0; - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_list) return 1; else return 0; } @@ -400,7 +409,7 @@ DohIsSequence(const DOH *obj) { DOH * DohGetitem(DOH *obj, int index) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_list && objinfo->doh_list->doh_getitem) { return (objinfo->doh_list->doh_getitem)(b,index); } @@ -414,7 +423,7 @@ DohGetitem(DOH *obj, int index) { int DohSetitem(DOH *obj, int index, const DOH *value) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_list && objinfo->doh_list->doh_setitem) { return (objinfo->doh_list->doh_setitem)(b,index,(DOH *) value); } @@ -428,7 +437,7 @@ DohSetitem(DOH *obj, int index, const DOH *value) { int DohDelitem(DOH *obj, int index) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_list && objinfo->doh_list->doh_delitem) { return (objinfo->doh_list->doh_delitem)(b,index); } @@ -442,7 +451,7 @@ DohDelitem(DOH *obj, int index) { int DohInsertitem(DOH *obj, int index, const DOH *value) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_list && objinfo->doh_list->doh_insitem) { return (objinfo->doh_list->doh_insitem)(b,index,(DOH *) value); } @@ -456,7 +465,7 @@ DohInsertitem(DOH *obj, int index, const DOH *value) { DOH * DohFirstitem(DOH *obj) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_list && objinfo->doh_list->doh_firstitem) { return (objinfo->doh_list->doh_firstitem)(b); } @@ -470,7 +479,7 @@ DohFirstitem(DOH *obj) { DOH * DohNextitem(DOH *obj) { DohBase *b = (DohBase *) obj; - DohObjInfo *objinfo = dohtypes[b->type]; + DohObjInfo *objinfo = b->type; if (objinfo->doh_list && objinfo->doh_list->doh_nextitem) { return (objinfo->doh_list->doh_nextitem)(b); } @@ -486,7 +495,7 @@ DohIsFile(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (!DohCheck(b)) return 0; - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_file) return 1; else return 0; } @@ -500,7 +509,7 @@ DohRead(DOH *obj, void *buffer, int length) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if ((objinfo->doh_file) && (objinfo->doh_file->doh_read)) { return (objinfo->doh_file->doh_read)(b,buffer,length); } @@ -519,7 +528,7 @@ DohWrite(DOH *obj, void *buffer, int length) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if ((objinfo->doh_file) && (objinfo->doh_file->doh_write)) { return (objinfo->doh_file->doh_write)(b,buffer,length); } @@ -538,7 +547,7 @@ DohSeek(DOH *obj, long offset, int whence) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if ((objinfo->doh_file) && (objinfo->doh_file->doh_seek)) { return (objinfo->doh_file->doh_seek)(b,offset,whence); } @@ -556,7 +565,7 @@ DohTell(DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if ((objinfo->doh_file) && (objinfo->doh_file->doh_tell)) { return (objinfo->doh_file->doh_tell)(b); } @@ -575,11 +584,11 @@ DohGetc(DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (obj == lastdoh) { - objinfo = dohtypes[b->type]; + objinfo = b->type; return (objinfo->doh_file->doh_getc)(b); } if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_file->doh_getc) { lastdoh = obj; return (objinfo->doh_file->doh_getc)(b); @@ -600,11 +609,11 @@ DohPutc(int ch, DOH *obj) { DohObjInfo *objinfo; if (obj == lastdoh) { - objinfo = dohtypes[b->type]; + objinfo = b->type; return (objinfo->doh_file->doh_putc)(b,ch); } if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_file->doh_putc) { lastdoh = obj; return (objinfo->doh_file->doh_putc)(b,ch); @@ -623,7 +632,7 @@ DohUngetc(int ch, DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_file->doh_ungetc) { return (objinfo->doh_file->doh_ungetc)(b,ch); } @@ -641,7 +650,7 @@ DohClose(DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (DohCheck(obj)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_file->doh_close) { return (objinfo->doh_file->doh_close)(b); } @@ -659,7 +668,7 @@ DohIsString(const DOH *obj) { DohBase *b = (DohBase *) obj; DohObjInfo *objinfo; if (!DohCheck(b)) return 0; - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_string) return 1; else return 0; } @@ -672,8 +681,10 @@ int DohReplace(DOH *src, const DOH *token, const DOH *rep, int flags) { DohBase *b = (DohBase *) src; DohObjInfo *objinfo; + if (!token) return 0; + if (!rep) rep = ""; if (DohIsString(src)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_string->doh_replace) { return (objinfo->doh_string->doh_replace)(b,(DOH *) token, (DOH *) rep,flags); } @@ -690,7 +701,7 @@ DohChop(DOH *src) { DohBase *b = (DohBase *) src; DohObjInfo *objinfo; if (DohIsString(src)) { - objinfo = dohtypes[b->type]; + objinfo = b->type; if (objinfo->doh_string->doh_chop) { (objinfo->doh_string->doh_chop)(b); } @@ -705,7 +716,7 @@ DohSetfile(DOH *ho, DOH *file) { DohBase *h = (DohBase *) ho; DohObjInfo *objinfo; if (!h) return; - objinfo = dohtypes[h->type]; + objinfo = h->type; if (objinfo->doh_setfile) (objinfo->doh_setfile)(h,file); } @@ -718,7 +729,7 @@ DohGetfile(DOH *ho) { DohBase *h = (DohBase *) ho; DohObjInfo *objinfo; if (!h) return 0; - objinfo = dohtypes[h->type]; + objinfo = h->type; if (objinfo->doh_getfile) return (objinfo->doh_getfile)(h); return 0; @@ -732,7 +743,7 @@ DohSetline(DOH *ho, int l) { DohBase *h = (DohBase *) ho; DohObjInfo *objinfo; if (!h) return; - objinfo = dohtypes[h->type]; + objinfo = h->type; if (objinfo->doh_setline) (objinfo->doh_setline)(h,l); } @@ -745,12 +756,60 @@ DohGetline(DOH *ho) { DohBase *h = (DohBase *) ho; DohObjInfo *objinfo; if (!h) return 0; - objinfo = dohtypes[h->type]; + objinfo = h->type; if (objinfo->doh_getline) return (objinfo->doh_getline)(h); return 0; } +/* ----------------------------------------------------------------------------- + * DohGetmeta() + * ----------------------------------------------------------------------------- */ +DOH * +DohGetmeta(DOH *ho, const DOH *name) { + DohBase *h = (DohBase *) ho; + if (!DohCheck(ho)) return 0; + if (!h->meta) return 0; + return DohGetattr(h->meta,name); +} + +/* ----------------------------------------------------------------------------- + * DohGetmeta() + * ----------------------------------------------------------------------------- */ + +int +DohSetmeta(DOH *ho, const DOH *name, const DOH *value) { + DohBase *h = (DohBase *) ho; + if (!DohCheck(ho)) return 0; + if (!h->meta) h->meta = NewHash(); + return DohSetattr(h->meta, name, value); +} + +/* ----------------------------------------------------------------------------- + * DohDelmeta() + * ----------------------------------------------------------------------------- */ + +int +DohDelmeta(DOH *ho, const DOH *name) { + DohBase *h = (DohBase *) ho; + if (!DohCheck(ho)) return 0; + if (!h->meta) return 0; + return DohDelattr(h->meta, name); +} + +/* ----------------------------------------------------------------------------- + * DohSetmark() + * ----------------------------------------------------------------------------- */ +void +DohSetmark(DOH *ho, int x) { + DohBase *h = (DohBase *) ho; + h->flag_usermark = x; +} +int +DohGetmark(DOH *ho) { + DohBase *h = (DohBase *) ho; + return h->flag_usermark; +} diff --git a/Source/DOH/Doh/file.c b/Source/DOH/Doh/file.c index 4e901e91c..70e8c3d4e 100644 --- a/Source/DOH/Doh/file.c +++ b/Source/DOH/Doh/file.c @@ -10,7 +10,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_file_c[] = "$Header$"; #include "dohint.h" @@ -41,6 +41,7 @@ DelFile(DOH *fo) { } #endif } + DohFree(f); } /* ----------------------------------------------------------------------------- @@ -118,12 +119,12 @@ File_tell(DOH *fo) { static int File_putc(DOH *fo, int ch) { - char c; DohFile *f = (DohFile *) ObjData(fo); if (f->filep) { return fputc(ch,f->filep); } else if (f->fd) { #ifdef DOH_INTFILE + char c; c = (char) ch; return write(f->fd,&c,1); #endif @@ -137,12 +138,12 @@ File_putc(DOH *fo, int ch) { static int File_getc(DOH *fo) { - char c; DohFile *f = (DohFile *) ObjData(fo); if (f->filep) { return fgetc(f->filep); } else if (f->fd) { #ifdef DOH_INTFILE + char c; if (read(f->fd,&c,1) < 0) return EOF; return c; #endif @@ -169,6 +170,28 @@ File_ungetc(DOH *fo, int ch) { return -1; } +/* ----------------------------------------------------------------------------- + * File_close() + * + * Close the file + * ----------------------------------------------------------------------------- */ + +static int +File_close(DOH *fo) { + int ret = 0; + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + ret = fclose(f->filep); + f->filep = 0; + } else if (f->fd) { +#ifdef DOH_INTFILE + ret = close(f->fd); + f->fd = 0; +#endif + } + return ret; +} + static DohFileMethods FileFileMethods = { File_read, File_write, @@ -177,7 +200,7 @@ static DohFileMethods FileFileMethods = { File_ungetc, File_seek, File_tell, - 0, /* close */ + File_close, /* close */ }; static DohObjInfo DohFileType = { @@ -209,20 +232,13 @@ static DohObjInfo DohFileType = { * Create a new file from a given filename and mode. * ----------------------------------------------------------------------------- */ -static int init = 0; - DOH * -NewFile(DOH *fn, char *mode) +DohNewFile(DOH *fn, const char *mode) { DohFile *f; FILE *file; char *filename; - if (!init) { - DohRegisterType(DOHTYPE_FILE, &DohFileType); - init = 1; - } - filename = Char(fn); file = fopen(filename,mode); if (!file) return 0; @@ -235,7 +251,7 @@ NewFile(DOH *fn, char *mode) f->filep = file; f->fd = 0; f->closeondel = 1; - return DohObjMalloc(DOHTYPE_FILE,f); + return DohObjMalloc(&DohFileType,f); } /* ----------------------------------------------------------------------------- @@ -245,20 +261,15 @@ NewFile(DOH *fn, char *mode) * ----------------------------------------------------------------------------- */ DOH * -NewFileFromFile(FILE *file) +DohNewFileFromFile(FILE *file) { DohFile *f; - - if (!init) { - DohRegisterType(DOHTYPE_FILE, &DohFileType); - init = 1; - } f = (DohFile *) DohMalloc(sizeof(DohFile)); if (!f) return 0; f->filep = file; f->fd = 0; f->closeondel = 0; - return DohObjMalloc(DOHTYPE_FILE,f); + return DohObjMalloc(&DohFileType,f); } /* ----------------------------------------------------------------------------- @@ -268,17 +279,13 @@ NewFileFromFile(FILE *file) * ----------------------------------------------------------------------------- */ DOH * -NewFileFromFd(int fd) +DohNewFileFromFd(int fd) { DohFile *f; - if (!init) { - DohRegisterType(DOHTYPE_FILE, &DohFileType); - init = 1; - } f = (DohFile *) DohMalloc(sizeof(DohFile)); if (!f) return 0; f->filep = 0; f->fd = fd; f->closeondel = 0; - return DohObjMalloc(DOHTYPE_FILE,f); + return DohObjMalloc(&DohFileType,f); } diff --git a/Source/DOH/Doh/fio.c b/Source/DOH/Doh/fio.c index 2d8e03efd..db7e5eb1c 100644 --- a/Source/DOH/Doh/fio.c +++ b/Source/DOH/Doh/fio.c @@ -10,7 +10,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_fio_c[] = "$Header$"; #include "dohint.h" @@ -265,7 +265,7 @@ DohvPrintf(DOH *so, const char *format, va_list ap) doh = va_arg(ap, DOH *); if (DohCheck(doh)) { /* Is a DOH object. */ - if (DohIsString(doh) && (ObjType(doh) == DOHTYPE_STRING)) { + if (DohIsString(doh)) { Sval = doh; } else { Sval = Str(doh); @@ -411,7 +411,7 @@ int DohPrintv(DOHFile *f, ...) { va_start(ap,f); while(1) { obj = va_arg(ap,void *); - if (!obj) break; + if ((!obj) || (obj == DohNone)) break; if (DohCheck(obj)) { ret += DohDump(obj,f); } else { @@ -459,12 +459,12 @@ DohCopyto(DOH *in, DOH *out) { /* ----------------------------------------------------------------------------- * DohSplit() * - * Split an input stream into a list of strings delimeted by characters in a - * string. Optionally accepts a maximum number of splits to perform. + * Split an input stream into a list of strings delimited by the specified + * character. Optionally accepts a maximum number of splits to perform. * ----------------------------------------------------------------------------- */ DOH * -DohSplit(DOH *in, char *chs, int nsplits) { +DohSplit(DOH *in, char ch, int nsplits) { DOH *list; DOH *str; int c; @@ -479,17 +479,18 @@ DohSplit(DOH *in, char *chs, int nsplits) { str = NewString(""); do { c = Getc(in); - } while ((c != EOF) && (c == *chs)); + } while ((c != EOF) && (c == ch)); if (c != EOF) { Putc(c,str); while (1) { c = Getc(in); - if ((c == EOF) || ((c == *chs) && (nsplits != 0))) break; + if ((c == EOF) || ((c == ch) && (nsplits != 0))) break; Putc(c,str); } nsplits--; } Append(list,str); + Delete(str); if (c == EOF) break; } return list; diff --git a/Source/DOH/Doh/hash.c b/Source/DOH/Doh/hash.c index 246242c20..4738a2312 100644 --- a/Source/DOH/Doh/hash.c +++ b/Source/DOH/Doh/hash.c @@ -9,10 +9,12 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_hash_c[] = "$Header$"; #include "dohint.h" +extern DohObjInfo DohHashType; + /* Hash node */ typedef struct HashNode { DOH *key; @@ -46,6 +48,9 @@ static DOH *find_key (DOH *doh_c) { char *c = (char *) doh_c; KeyValue *r, *s; int d = 0; + /* OK, sure, we use a binary tree for maintaining interned + symbols. Then we use their hash values for accessing secondary + hash tables. */ r = root; s = 0; while (r) { @@ -199,8 +204,10 @@ Hash_setattr(DOH *ho, DOH *k, DOH *obj) { int hv; HashNode *n, *prev; Hash *h = (Hash *) ObjData(ho); - - if (!obj) return 0; + + if (!obj) { + return DohDelattr(ho,k); + } if (!DohCheck(k)) k = find_key(k); if (!DohCheck(obj)) { obj = NewString((char *) obj); @@ -211,16 +218,15 @@ Hash_setattr(DOH *ho, DOH *k, DOH *obj) { prev = 0; while (n) { if (Cmp(n->key,k) == 0) { - HashNode *nn; - if (prev) { - prev->next = n->next; - } else { - h->hashtable[hv] = n->next; + /* Node already exists. Just replace its contents */ + if (n->object == obj) { + /* Whoa. Same object. Do nothing */ + return 1; } - nn = n->next; - DelNode(n); - h->nitems--; - n = nn; + Delete(n->object); + n->object = obj; + Incref(obj); + return 1; /* Return 1 to indicate a replacement */ } else { prev = n; n = n->next; @@ -276,11 +282,17 @@ Hash_delattr(DOH *ho, DOH *k) { while (n) { if (Cmp(n->key, k) == 0) { /* Found it, kill it */ + if (prev) { prev->next = n->next; } else { h->hashtable[hv] = n->next; } + /* Need to check for iterator location */ + if (n == h->current) { + h->current = prev; /* Move back to previous node. When next is called, will move to next node */ + if (!h->current) h->currentindex--; /* No previous node. Move back one slot */ + } DelNode(n); h->nitems--; return 1; @@ -307,10 +319,12 @@ hash_first(DOH *ho) { static HashNode * hash_next(DOH *ho) { Hash *h = (Hash *) ObjData(ho); - if (h->currentindex < 0) return hash_first(h); + if (h->currentindex < 0) return hash_first(ho); /* Try to move to the next entry */ - h->current = h->current->next; + if (h->current) { + h->current = h->current->next; + } if (h->current) { return h->current; } @@ -349,6 +363,26 @@ Hash_nextkey(DOH *ho) { } /* ----------------------------------------------------------------------------- + * Hash_keys(DOH *) + * + * Return a list of keys + * ----------------------------------------------------------------------------- */ + +static DOH * +Hash_keys(DOH *so) { + DOH *keys; + DOH *k; + + keys = NewList(); + k = Firstkey(so); + while (k) { + Append(keys,k); + k = Nextkey(so); + } + return keys; +} + +/* ----------------------------------------------------------------------------- * Hash_str() * * Create a string representation of a hash table (mainly for debugging). @@ -398,26 +432,6 @@ Hash_len(DOH *ho) { } /* ----------------------------------------------------------------------------- - * Hash_keys(DOH *) - * - * Return a list of keys - * ----------------------------------------------------------------------------- */ -DOH * -Hash_keys(DOH *so) { - DOH *keys; - DOH *k; - - keys = NewList(); - k = Firstkey(so); - while (k) { - Append(keys,k); - k = Nextkey(so); - } - /* List_sort(keys); */ - return keys; -} - -/* ----------------------------------------------------------------------------- * CopyHash() * * Make a copy of a hash table. Note: this is a shallow copy. @@ -444,7 +458,7 @@ CopyHash(DOH *ho) { nh->file = h->file; if (nh->file) Incref(nh->file); - nho = DohObjMalloc(DOHTYPE_HASH, nh); + nho = DohObjMalloc(&DohHashType, nh); for (i = 0; i < h->hashsize; i++) { if ((n = h->hashtable[i])) { while (n) { @@ -458,7 +472,8 @@ CopyHash(DOH *ho) { -void Hash_setfile(DOH *ho, DOH *file) { +static void +Hash_setfile(DOH *ho, DOH *file) { DOH *fo; Hash *h = (Hash *) ObjData(ho); @@ -471,17 +486,20 @@ void Hash_setfile(DOH *ho, DOH *file) { h->file = fo; } -DOH *Hash_getfile(DOH *ho) { +static DOH * +Hash_getfile(DOH *ho) { Hash *h = (Hash *) ObjData(ho); return h->file; } -void Hash_setline(DOH *ho, int line) { +static void +Hash_setline(DOH *ho, int line) { Hash *h = (Hash *) ObjData(ho); h->line = line; } -int Hash_getline(DOH *ho) { +static int +Hash_getline(DOH *ho) { Hash *h = (Hash *) ObjData(ho); return h->line; } @@ -496,9 +514,10 @@ static DohHashMethods HashHashMethods = { Hash_delattr, Hash_firstkey, Hash_nextkey, + Hash_keys, }; -static DohObjInfo HashType = { +DohObjInfo DohHashType = { "Hash", /* objname */ DelHash, /* doh_del */ CopyHash, /* doh_copy */ @@ -528,14 +547,9 @@ static DohObjInfo HashType = { * ----------------------------------------------------------------------------- */ DOH * -NewHash() { +DohNewHash() { Hash *h; int i; - static int init = 0; - if (!init) { - DohRegisterType(DOHTYPE_HASH, &HashType); - init = 1; - } h = (Hash *) DohMalloc(sizeof(Hash)); h->hashsize = HASH_INIT_SIZE; h->hashtable = (HashNode **) DohMalloc(h->hashsize*sizeof(HashNode *)); @@ -547,6 +561,5 @@ NewHash() { h->nitems = 0; h->file = 0; h->line = 0; - return DohObjMalloc(DOHTYPE_HASH,h); + return DohObjMalloc(&DohHashType,h); } - diff --git a/Source/DOH/Doh/list.c b/Source/DOH/Doh/list.c index 876fd9120..fff505b39 100644 --- a/Source/DOH/Doh/list.c +++ b/Source/DOH/Doh/list.c @@ -9,7 +9,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_list_c[] = "$Header$"; #include "dohint.h" @@ -22,6 +22,8 @@ typedef struct List { DOH **items; } List; +extern DohObjInfo DohListType; + /* Doubles amount of memory in a list */ static void more(List *l) { @@ -52,7 +54,7 @@ CopyList(DOH *lo) { nl->file = l->file; if (nl->file) Incref(nl->file); nl->line = l->line; - return DohObjMalloc(DOHTYPE_LIST, nl); + return DohObjMalloc(&DohListType, nl); } /* ----------------------------------------------------------------------------- @@ -261,27 +263,8 @@ List_dump(DOH *lo, DOH *out) { return nsent; } - -/* ----------------------------------------------------------------------------- - * List_sort() - * ----------------------------------------------------------------------------- */ - - -static int objcmp(const void *s1, const void *s2) { - DOH **so1, **so2; - so1 = (DOH **) s1; - so2 = (DOH **) s2; - return Cmp(*so1,*so2); -} - -void -List_sort(DOH *lo, int opt) { - List *l = (List *) ObjData(lo); - qsort(l->items,l->nitems,sizeof(DOH *),objcmp); -} - - -void List_setfile(DOH *lo, DOH *file) { +static void +List_setfile(DOH *lo, DOH *file) { DOH *fo; List *l = (List *) ObjData(lo); @@ -294,17 +277,19 @@ void List_setfile(DOH *lo, DOH *file) { l->file = fo; } -DOH *List_getfile(DOH *lo) { +static DOH * +List_getfile(DOH *lo) { List *l = (List *) ObjData(lo); return l->file; } -void List_setline(DOH *lo, int line) { +static void +List_setline(DOH *lo, int line) { List *l = (List *) ObjData(lo); l->line = line; } -int List_getline(DOH *lo) { +static int List_getline(DOH *lo) { List *l = (List *) ObjData(lo); return l->line; } @@ -316,10 +301,9 @@ static DohListMethods ListListMethods = { List_insert, List_first, List_next, - List_sort }; -static DohObjInfo ListType = { +DohObjInfo DohListType = { "List", /* objname */ DelList, /* doh_del */ CopyList, /* doh_copy */ @@ -351,14 +335,9 @@ static DohObjInfo ListType = { #define MAXLISTITEMS 8 DOH * -NewList() { +DohNewList() { List *l; int i; - static int init = 0; - if (!init) { - DohRegisterType(DOHTYPE_LIST, &ListType); - init = 1; - } l = (List *) DohMalloc(sizeof(List)); l->nitems = 0; l->maxitems = MAXLISTITEMS; @@ -369,5 +348,6 @@ NewList() { l->iter = 0; l->file = 0; l->line = 0; - return DohObjMalloc(DOHTYPE_LIST,l); + return DohObjMalloc(&DohListType,l); } + diff --git a/Source/DOH/Doh/memory.c b/Source/DOH/Doh/memory.c index fcf5ba341..b0ddc5ff1 100644 --- a/Source/DOH/Doh/memory.c +++ b/Source/DOH/Doh/memory.c @@ -10,7 +10,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_memory_c[] = "$Header$"; #include "dohint.h" @@ -30,8 +30,7 @@ typedef struct pool { struct pool *next; /* Next pool */ } Pool; -DohBase *FreeList = 0; /* List of free objects */ - +static DohBase *FreeList = 0; /* List of free objects */ static Pool *Pools = 0; static int pools_initialized = 0; @@ -105,7 +104,7 @@ DohIntern(DOH *obj) { * ---------------------------------------------------------------------- */ DOH * -DohObjMalloc(int type, void *data) { +DohObjMalloc(DohObjInfo *type, void *data) { DohBase *obj; if (!pools_initialized) InitPools(); if (FreeList) { @@ -121,9 +120,12 @@ DohObjMalloc(int type, void *data) { } obj->type = type; obj->data = data; + obj->meta = 0; obj->refcount = 1; obj->flag_intern = 0; obj->flag_marked = 0; + obj->flag_user = 0; + obj->flag_usermark = 0; return (DOH *) obj; } @@ -137,6 +139,10 @@ DohObjFree(DOH *ptr) { b = (DohBase *) ptr; if (b->flag_intern) return; b->data = (void *) FreeList; + if (b->meta) { + Delete(b->meta); + b->meta = 0; + } b->type = 0; FreeList = b; } diff --git a/Source/DOH/Doh/string.c b/Source/DOH/Doh/string.c index 96d11d9a7..04e6d184a 100644 --- a/Source/DOH/Doh/string.c +++ b/Source/DOH/Doh/string.c @@ -10,13 +10,11 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_string_c[] = "$Header$"; #include "dohint.h" -#ifndef DOH_STRING_UPDATE_LINES -#define DOH_STRING_UPDATE_LINES -#endif +extern DohObjInfo DohStringType; typedef struct String { DOH *file; @@ -31,7 +29,9 @@ typedef struct String { /* ----------------------------------------------------------------------------- * void *String_data() - Return as a 'void *' * ----------------------------------------------------------------------------- */ -void *String_data(DOH *so) { + +static void * +String_data(DOH *so) { String *s = (String *) ObjData(so); s->str[s->len] = 0; return (void *) s->str; @@ -41,7 +41,8 @@ void *String_data(DOH *so) { * int String_dump() - Serialize a string onto out * ----------------------------------------------------------------------------- */ -int String_dump(DOH *so, DOH *out) { +static int +String_dump(DOH *so, DOH *out) { int nsent; int ret; String *s = (String *) ObjData(so); @@ -57,32 +58,37 @@ int String_dump(DOH *so, DOH *out) { /* ----------------------------------------------------------------------------- * CopyString() - Copy a string * ----------------------------------------------------------------------------- */ -DOH * + +static DOH * CopyString(DOH *so) { - String *s = (String *) ObjData(so); int max; String *str; + String *s = (String *) ObjData(so); str = (String *) DohMalloc(sizeof(String)); str->hashkey = -1; - str->sp = 0; + str->sp = s->sp; str->line = s->line; str->file = s->file; if (str->file) Incref(str->file); max = s->maxsize; - str->str = (char *) DohMalloc(max); + str->str = (char *) DohMalloc(max+1); memmove(str->str, s->str, max); str->maxsize= max; str->len = s->len; str->str[str->len] = 0; - return DohObjMalloc(DOHTYPE_STRING,str); + + return DohObjMalloc(&DohStringType,str); } /* ----------------------------------------------------------------------------- * DelString() - Delete a string * ----------------------------------------------------------------------------- */ -void + +static void DelString(DOH *so) { String *s = (String *) ObjData(so); + s->hashkey = -1; + s->str = 0; DohFree(s->str); DohFree(s); } @@ -91,7 +97,7 @@ DelString(DOH *so) { * String_len() - Length of a string * ----------------------------------------------------------------------------- */ -int +static int String_len(DOH *so) { String *s = (String *) ObjData(so); return s->len; @@ -102,7 +108,7 @@ String_len(DOH *so) { * int String_cmp() - Compare two strings * ----------------------------------------------------------------------------- */ -int +static int String_cmp(DOH *so1, DOH *so2) { String *s1, *s2; @@ -130,7 +136,8 @@ String_cmp(DOH *so1, DOH *so2) * int String_hash() - Compute string hash value * ----------------------------------------------------------------------------- */ -int String_hash(DOH *so) { +static int +String_hash(DOH *so) { String *s = (String *) ObjData(so); char *c; int i, h = 0, len; @@ -179,43 +186,11 @@ add(String *s, const char *newstr) { s->len += l; } -/* Add a single character to s */ -void -String_addchar(String *s, char c) { - register char *tc; - register int len = s->len; - register int maxsize = s->maxsize; - s->hashkey = -1; - if (len > (maxsize-2)) { - s->str = (char *) DohRealloc(s->str,2*maxsize); - assert(s->str); - s->maxsize = 2*maxsize; - } - tc = s->str; - tc[len] = c; - if (s->sp >= len) { - s->sp = len+1; - tc[len+1] = 0; - if (c == '\n') s->line++; - } - s->len++; -} - -/* Expand a string to accomodate a write */ -void -String_expand(String *s, int width) { - if ((s->len + width) > (s->maxsize-1)) { - s->str = (char *) DohRealloc(s->str,(s->len + width)+1); - assert(s->str); - s->maxsize = s->len + width + 1; - } -} - /* ----------------------------------------------------------------------------- * void String_clear() - Clear a string * ----------------------------------------------------------------------------- */ -void +static void String_clear(DOH *so) { String *s = (String *) ObjData(so); @@ -230,7 +205,9 @@ String_clear(DOH *so) * void String_insert() - Insert a string * ----------------------------------------------------------------------------- */ -int String_insert(DOH *so, int pos, DOH *str) { +static int +String_insert(DOH *so, int pos, DOH *str) +{ String *s = (String *) ObjData(so); char *nstr; int len; @@ -274,7 +251,8 @@ int String_insert(DOH *so, int pos, DOH *str) { * int String_delitem() - Delete a character * ----------------------------------------------------------------------------- */ -int String_delitem(DOH *so, int pos) +static int +String_delitem(DOH *so, int pos) { String *s = (String *) ObjData(so); s->hashkey = -1; @@ -297,8 +275,9 @@ int String_delitem(DOH *so, int pos) * DOH *String_str() - Returns a string (used by printing commands) * ----------------------------------------------------------------------------- */ -DOH * -String_str(DOH *so) { +static DOH * +String_str(DOH *so) +{ String *s = (String *) ObjData(so); s->str[s->len] = 0; return NewString(s->str); @@ -307,8 +286,10 @@ String_str(DOH *so) { /* ----------------------------------------------------------------------------- * int String_read() - Read data from a string * ----------------------------------------------------------------------------- */ -int -String_read(DOH *so, void *buffer, int len) { + +static int +String_read(DOH *so, void *buffer, int len) +{ int reallen, retlen; char *cb; String *s = (String *) ObjData(so); @@ -328,8 +309,9 @@ String_read(DOH *so, void *buffer, int len) { /* ----------------------------------------------------------------------------- * int String_write() - Write data to a string * ----------------------------------------------------------------------------- */ -int -String_write(DOH *so, void *buffer, int len) { +static int +String_write(DOH *so, void *buffer, int len) +{ int newlen; String *s = (String *) ObjData(so); s->hashkey = -1; @@ -351,8 +333,10 @@ String_write(DOH *so, void *buffer, int len) { /* ----------------------------------------------------------------------------- * int String_seek() - Seek to a new position * ----------------------------------------------------------------------------- */ -int -String_seek(DOH *so, long offset, int whence) { + +static int +String_seek(DOH *so, long offset, int whence) +{ int pos, nsp, inc; int prev; String *s = (String *) ObjData(so); @@ -391,8 +375,10 @@ String_seek(DOH *so, long offset, int whence) { /* ----------------------------------------------------------------------------- * long String_tell() - Return current position * ----------------------------------------------------------------------------- */ -long -String_tell(DOH *so) { + +static long +String_tell(DOH *so) +{ String *s = (String *) ObjData(so); return (long) (s->sp); } @@ -401,8 +387,9 @@ String_tell(DOH *so) { * int String_putc() * ----------------------------------------------------------------------------- */ -int -String_putc(DOH *so, int ch) { +static int +String_putc(DOH *so, int ch) +{ register int len, maxsize, sp; String *s = (String *) ObjData(so); s->hashkey = -1; @@ -435,7 +422,9 @@ String_putc(DOH *so, int ch) { * int String_getc() * ----------------------------------------------------------------------------- */ -int String_getc(DOH *so) { +static int +String_getc(DOH *so) +{ int c; String *s = (String *) ObjData(so); if (s->sp >= s->len) @@ -450,7 +439,9 @@ int String_getc(DOH *so) { * int String_ungetc() * ----------------------------------------------------------------------------- */ -int String_ungetc(DOH *so, int ch) { +static int +String_ungetc(DOH *so, int ch) +{ String *s = (String *) ObjData(so); if (ch == EOF) return ch; if (s->sp <= 0) return EOF; @@ -466,7 +457,9 @@ int String_ungetc(DOH *so, int ch) { * Replaces count non-overlapping occurrences of token with rep in a string. * ----------------------------------------------------------------------------- */ -static char *end_quote(char *s) { +static char * +end_quote(char *s) +{ char qc; char *q; qc = *s; @@ -478,11 +471,15 @@ static char *end_quote(char *s) { } } -static char *match_simple(char *base, char *s, char *token, int tokenlen) { +static char * +match_simple(char *base, char *s, char *token, int tokenlen) +{ return strstr(s,token); } -static char *match_identifier(char *base, char *s, char *token, int tokenlen) { +static char * +match_identifier(char *base, char *s, char *token, int tokenlen) +{ while (s) { s = strstr(s,token); if (!s) return 0; @@ -499,8 +496,8 @@ static char *match_identifier(char *base, char *s, char *token, int tokenlen) { return 0; } -static -int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match)(char *, char *, char *, int)) +static int +replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match)(char *, char *, char *, int)) { int tokenlen; /* Length of the token */ int replen; /* Length of the replacement */ @@ -513,7 +510,10 @@ int replace_simple(String *str, char *token, char *rep, int flags, int count, ch register char *base; int i; + str->hashkey = -1; + /* Figure out if anything gets replaced */ + if (!strlen(token)) return 0; base = str->str; tokenlen = strlen(token); @@ -706,11 +706,12 @@ int replace_simple(String *str, char *token, char *rep, int flags, int count, ch * int String_replace() * ----------------------------------------------------------------------------- */ -int +static int String_replace(DOH *stro, DOH *token, DOH *rep, int flags) { int count = -1; String *str = (String *) ObjData(stro); + if (flags & DOH_REPLACE_FIRST) count = 1; if (flags & DOH_REPLACE_ID) { @@ -724,8 +725,9 @@ String_replace(DOH *stro, DOH *token, DOH *rep, int flags) * void String_chop(DOH *str) * ----------------------------------------------------------------------------- */ -void -String_chop(DOH *so) { +static void +String_chop(DOH *so) +{ char *c; String *str = (String *) ObjData(so); /* Replace trailing whitespace */ @@ -743,7 +745,9 @@ String_chop(DOH *so) { str->hashkey = -1; } -void String_setfile(DOH *so, DOH *file) { +static void +String_setfile(DOH *so, DOH *file) +{ DOH *fo; String *str = (String *) ObjData(so); @@ -756,17 +760,23 @@ void String_setfile(DOH *so, DOH *file) { str->file = fo; } -DOH *String_getfile(DOH *so) { +static DOH * +String_getfile(DOH *so) +{ String *str = (String *) ObjData(so); return str->file; } -void String_setline(DOH *so, int line) { +static void +String_setline(DOH *so, int line) +{ String *str = (String *) ObjData(so); str->line = line; } -int String_getline(DOH *so) { +static int +String_getline(DOH *so) +{ String *str = (String *) ObjData(so); return str->line; } @@ -778,7 +788,6 @@ static DohListMethods StringListMethods = { String_insert, /* doh_insitem */ 0, /* doh_first */ 0, /* doh_next */ - 0, /* doh_sort */ }; static DohFileMethods StringFileMethods = { @@ -797,7 +806,7 @@ static DohStringMethods StringStringMethods = { String_chop, }; -static DohObjInfo StringType = { +DohObjInfo DohStringType = { "String", /* objname */ DelString, /* doh_del */ CopyString, /* doh_copy */ @@ -823,21 +832,16 @@ static DohObjInfo StringType = { #define INIT_MAXSIZE 16 - /* ----------------------------------------------------------------------------- * NewString(const char *c) - Create a new string * ----------------------------------------------------------------------------- */ + DOHString * -NewString(const DOH *so) +DohNewString(const DOH *so) { int l = 0, max; String *str; char *s; - static int init = 0; - if (!init) { - DohRegisterType(DOHTYPE_STRING, &StringType); - init = 1; - } if (DohCheck(so)) s = Char(so); else s = (char *) so; str = (String *) DohMalloc(sizeof(String)); @@ -860,7 +864,7 @@ NewString(const DOH *so) str->str[0] = 0; str->len = 0; } - return DohObjMalloc(DOHTYPE_STRING,str); + return DohObjMalloc(&DohStringType,str); } /* ----------------------------------------------------------------------------- @@ -870,7 +874,7 @@ NewString(const DOH *so) * ----------------------------------------------------------------------------- */ DOHString * -NewStringf(const DOH *fmt, ...) +DohNewStringf(const DOH *fmt, ...) { va_list ap; DOH *r; @@ -880,3 +884,28 @@ NewStringf(const DOH *fmt, ...) va_end(ap); return (DOHString *) r; } + +/* ----------------------------------------------------------------------------- + * Strcmp() + * Strncmp() + * Strstr() + * Strchr() + * + * Some utility functions. + * ----------------------------------------------------------------------------- */ + +int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) { + return strcmp(Char(s1),Char(s2)); +} + +int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) { + return strncmp(Char(s1),Char(s2),n); +} + +char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) { + return strstr(Char(s1),Char(s2)); +} + +char *DohStrchr(const DOHString_or_char *s1, int ch) { + return strchr(Char(s1),ch); +} diff --git a/Source/DOH/Doh/void.c b/Source/DOH/Doh/void.c index 63a94ea91..387062e1f 100644 --- a/Source/DOH/Doh/void.c +++ b/Source/DOH/Doh/void.c @@ -10,7 +10,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_void_c[] = "$Header$"; #include "dohint.h" @@ -88,15 +88,10 @@ static DohObjInfo DohVoidType = { * ----------------------------------------------------------------------------- */ DOH * -NewVoid(void *obj, void (*del)(void *)) { - static int init = 0; +DohNewVoid(void *obj, void (*del)(void *)) { VoidObj *v; - if (!init) { - DohRegisterType(DOHTYPE_VOID, &DohVoidType); - init = 1; - } v = (VoidObj *) DohMalloc(sizeof(VoidObj)); v->ptr = obj; v->del = del; - return DohObjMalloc(DOHTYPE_VOID,v); + return DohObjMalloc(&DohVoidType,v); } diff --git a/Source/DOH/Include/doh.h b/Source/DOH/Include/doh.h index e40ced2f3..29c4acf95 100644 --- a/Source/DOH/Include/doh.h +++ b/Source/DOH/Include/doh.h @@ -14,6 +14,105 @@ #ifndef _DOH_H #define _DOH_H +/* Set the namespace prefix for DOH API functions. This can be used to control + visibility of the functions in libraries */ + +/* Set this macro if you want to change DOH linkage. You would do this if you + wanted to hide DOH in a library using a different set of names. Note: simply + change "Doh" to a new name. */ + +/* +#define DOH_NAMESPACE(x) Doh ## x +*/ + +#ifdef DOH_NAMESPACE + +/* Namespace control. These macros define all of the public API names in DOH */ + +#define DohCheck DOH_NAMESPACE(Check) +#define DohIntern DOH_NAMESPACE(Intern) +#define DohDelete DOH_NAMESPACE(Delete) +#define DohCopy DOH_NAMESPACE(Copy) +#define DohClear DOH_NAMESPACE(Clear) +#define DohStr DOH_NAMESPACE(Str) +#define DohData DOH_NAMESPACE(Data) +#define DohDump DOH_NAMESPACE(Dump) +#define DohLen DOH_NAMESPACE(Len) +#define DohHashval DOH_NAMESPACE(Hashval) +#define DohCmp DOH_NAMESPACE(Cmp) +#define DohIncref DOH_NAMESPACE(Incref) +#define DohGetattr DOH_NAMESPACE(Getattr) +#define DohSetattr DOH_NAMESPACE(Setattr) +#define DohDelattr DOH_NAMESPACE(Delattr) +#define DohFirstkey DOH_NAMESPACE(Firstkey) +#define DohNextkey DOH_NAMESPACE(Nextkey) +#define DohKeys DOH_NAMESPACE(Keys) +#define DohGetInt DOH_NAMESPACE(GetInt) +#define DohGetDouble DOH_NAMESPACE(GetDouble) +#define DohGetChar DOH_NAMESPACE(GetChar) +#define DohSetChar DOH_NAMESPACE(SetChar) +#define DohSetInt DOH_NAMESPACE(SetInt) +#define DohSetDouble DOH_NAMESPACE(SetDouble) +#define DohSetVoid DOH_NAMESPACE(SetVoid) +#define DohGetVoid DOH_NAMESPACE(GetVoid) +#define DohGetitem DOH_NAMESPACE(Getitem) +#define DohSetitem DOH_NAMESPACE(Setitem) +#define DohDelitem DOH_NAMESPACE(Delitem) +#define DohInsertitem DOH_NAMESPACE(Insertitem) +#define DohFirstitem DOH_NAMESPACE(Firstitem) +#define DohNextitem DOH_NAMESPACE(Nextitem) +#define DohWrite DOH_NAMESPACE(Write) +#define DohRead DOH_NAMESPACE(Read) +#define DohSeek DOH_NAMESPACE(Seek) +#define DohTell DOH_NAMESPACE(Tell) +#define DohGetc DOH_NAMESPACE(Getc) +#define DohPutc DOH_NAMESPACE(Putc) +#define DohUngetc DOH_NAMESPACE(Ungetc) +#define DohGetline DOH_NAMESPACE(Getline) +#define DohSetline DOH_NAMESPACE(Setline) +#define DohGetfile DOH_NAMESPACE(Getfile) +#define DohSetfile DOH_NAMESPACE(Setfile) +#define DohReplace DOH_NAMESPACE(Replace) +#define DohChop DOH_NAMESPACE(Chop) +#define DohGetmeta DOH_NAMESPACE(Getmeta) +#define DohSetmeta DOH_NAMESPACE(Setmeta) +#define DohDelmeta DOH_NAMESPACE(Delmeta) +#define DohEncoding DOH_NAMESPACE(Encoding) +#define DohPrintf DOH_NAMESPACE(Printf) +#define DohvPrintf DOH_NAMESPACE(vPrintf) +#define DohPrintv DOH_NAMESPACE(Printv) +#define DohReadline DOH_NAMESPACE(Readline) +#define DohIsMapping DOH_NAMESPACE(IsMapping) +#define DohIsSequence DOH_NAMESPACE(IsSequence) +#define DohIsString DOH_NAMESPACE(IsString) +#define DohIsFile DOH_NAMESPACE(IsFile) +#define DohNewString DOH_NAMESPACE(NewString) +#define DohNewStringf DOH_NAMESPACE(NewStringf) +#define DohStrcmp DOH_NAMESPACE(Strcmp) +#define DohStrncmp DOH_NAMESPACE(Strncmp) +#define DohStrstr DOH_NAMESPACE(Strstr) +#define DohStrchr DOH_NAMESPACE(Strchr) +#define DohNewFile DOH_NAMESPACE(NewFile) +#define DohNewFileFromFile DOH_NAMESPACE(NewFileFromFile) +#define DohNewFileFromFd DOH_NAMESPACE(NewFileFromFd) +#define DohClose DOH_NAMESPACE(Close) +#define DohCopyto DOH_NAMESPACE(Copyto) +#define DohNewList DOH_NAMESPACE(NewList) +#define DohNewHash DOH_NAMESPACE(NewHash) +#define DohNewVoid DOH_NAMESPACE(NewVoid) +#define DohSplit DOH_NAMESPACE(Split) +#define DohNone DOH_NAMESPACE(None) + +#define DohObjMalloc DOH_NAMESPACE(ObjMalloc) +#define DohObjFree DOH_NAMESPACE(ObjFree) +#define DohStringType DOH_NAMESPACE(StringType) +#define DohListType DOH_NAMESPACE(ListType) +#define DohHashType DOH_NAMESPACE(HashType) +#define DohFileType DOH_NAMESPACE(FileType) +#define DohVoidType DOH_NAMESPACE(VoidType) + +#endif + #include <stdio.h> #include <stdarg.h> @@ -53,8 +152,8 @@ typedef void DOH; #define DohFree free #endif -extern int DohCheck(const DOH *ptr); /* Check if a DOH object */ -extern void DohIntern(DOH *); /* Intern an object */ +extern int DohCheck(const DOH *ptr); /* Check if a DOH object */ +extern void DohIntern(DOH *); /* Intern an object */ /* Basic object methods. Common to most objects */ @@ -71,64 +170,126 @@ extern void DohIncref(DOH *obj); /* Mapping methods */ -extern DOH *DohGetattr(DOH *obj, const DOHString_or_char *name); -extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_char *value); -extern void DohDelattr(DOH *obj, const DOHString_or_char *name); -extern DOH *DohFirstkey(DOH *obj); -extern DOH *DohNextkey(DOH *obj); -extern int DohGetInt(DOH *obj, const DOHString_or_char *name); -extern double DohGetDouble(DOH *obj, const DOHString_or_char *name); -extern char *DohGetChar(DOH *obj, const DOHString_or_char *name); -extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int); -extern void DohSetDouble(DOH *obj, const DOHString_or_char *name, double); -extern void *DohGetVoid(DOH *obj, const DOHString_or_char *name); -extern void DohSetVoid(DOH *obj, const DOHString_or_char *name, void *value); +extern DOH *DohGetattr(DOH *obj, const DOHString_or_char *name); +extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_char *value); +extern int DohDelattr(DOH *obj, const DOHString_or_char *name); +extern DOH *DohFirstkey(DOH *obj); +extern DOH *DohNextkey(DOH *obj); +extern DOH *DohKeys(DOH *obj); +extern int DohGetInt(DOH *obj, const DOHString_or_char *name); +extern double DohGetDouble(DOH *obj, const DOHString_or_char *name); +extern char *DohGetChar(DOH *obj, const DOHString_or_char *name); +extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int); +extern void DohSetDouble(DOH *obj, const DOHString_or_char *name, double); +extern void *DohGetVoid(DOH *obj, const DOHString_or_char *name); +extern void DohSetVoid(DOH *obj, const DOHString_or_char *name, void *value); /* Sequence methods */ -extern DOH *DohGetitem(DOH *obj, int index); -extern int DohSetitem(DOH *obj, int index, const DOHObj_or_char *value); -extern int DohDelitem(DOH *obj, int index); -extern int DohInsertitem(DOH *obj, int index, const DOHObj_or_char *value); -extern DOH *DohFirstitem(DOH *obj); -extern DOH *DohNextitem(DOH *obj); +extern DOH *DohGetitem(DOH *obj, int index); +extern int DohSetitem(DOH *obj, int index, const DOHObj_or_char *value); +extern int DohDelitem(DOH *obj, int index); +extern int DohInsertitem(DOH *obj, int index, const DOHObj_or_char *value); +extern DOH *DohFirstitem(DOH *obj); +extern DOH *DohNextitem(DOH *obj); /* File methods */ -extern int DohWrite(DOHFile *obj, void *buffer, int length); -extern int DohRead(DOHFile *obj, void *buffer, int length); -extern int DohSeek(DOHFile *obj, long offset, int whence); -extern long DohTell(DOHFile *obj); -extern int DohGetc(DOHFile *obj); -extern int DohPutc(int ch, DOHFile *obj); -extern int DohUngetc(int ch, DOHFile *obj); +extern int DohWrite(DOHFile *obj, void *buffer, int length); +extern int DohRead(DOHFile *obj, void *buffer, int length); +extern int DohSeek(DOHFile *obj, long offset, int whence); +extern long DohTell(DOHFile *obj); +extern int DohGetc(DOHFile *obj); +extern int DohPutc(int ch, DOHFile *obj); +extern int DohUngetc(int ch, DOHFile *obj); /* Positional */ -extern int DohGetline(DOH *obj); -extern void DohSetline(DOH *obj, int line); -extern DOH *DohGetfile(DOH *obj); -extern void DohSetfile(DOH *obj, DOH *file); +extern int DohGetline(DOH *obj); +extern void DohSetline(DOH *obj, int line); +extern DOH *DohGetfile(DOH *obj); +extern void DohSetfile(DOH *obj, DOH *file); /* String Methods */ -extern int DohReplace(DOHString *src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags); -extern void DohChop(DOHString *src); +extern int DohReplace(DOHString *src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags); +extern void DohChop(DOHString *src); + +/* Meta-variables */ +extern DOH *DohGetmeta(DOH *, const DOH *); +extern int DohSetmeta(DOH *, const DOH *, const DOH *value); +extern int DohDelmeta(DOH *, const DOH *); /* Utility functions */ -extern void DohEncoding(char *name, DOH *(*fn)(DOH *s)); -extern int DohPrintf(DOHFile *obj, const char *format, ...); -extern int DohvPrintf(DOHFile *obj, const char *format, va_list ap); -extern int DohPrintv(DOHFile *obj, ...); -extern DOH *DohReadline(DOHFile *in); +extern void DohEncoding(char *name, DOH *(*fn)(DOH *s)); +extern int DohPrintf(DOHFile *obj, const char *format, ...); +extern int DohvPrintf(DOHFile *obj, const char *format, va_list ap); +extern int DohPrintv(DOHFile *obj, ...); +extern DOH *DohReadline(DOHFile *in); /* Miscellaneous */ -extern int DohIsMapping(const DOH *obj); -extern int DohIsSequence(const DOH *obj); -extern int DohIsString(const DOH *obj); -extern int DohIsFile(const DOH *obj); +extern int DohIsMapping(const DOH *obj); +extern int DohIsSequence(const DOH *obj); +extern int DohIsString(const DOH *obj); +extern int DohIsFile(const DOH *obj); + +extern void DohSetmark(DOH *obj, int x); +extern int DohGetmark(DOH *obj); + +/* ----------------------------------------------------------------------------- + * Strings. + * ----------------------------------------------------------------------------- */ + +extern DOHString *DohNewString(const DOH *c); +extern DOHString *DohNewStringf(const DOH *fmt, ...); + +extern int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2); +extern int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n); +extern char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2); +extern char *DohStrchr(const DOHString_or_char *s1, int ch); + +/* String replacement flags */ + +#define DOH_REPLACE_ANY 0x01 +#define DOH_REPLACE_NOQUOTE 0x02 +#define DOH_REPLACE_ID 0x04 +#define DOH_REPLACE_FIRST 0x08 + +#define Replaceall(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ANY) +#define Replaceid(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ID) + +/* ----------------------------------------------------------------------------- + * Files + * ----------------------------------------------------------------------------- */ + +extern DOHFile *DohNewFile(DOH *file, const char *mode); +extern DOHFile *DohNewFileFromFile(FILE *f); +extern DOHFile *DohNewFileFromFd(int fd); +extern int DohClose(DOH *file); +extern int DohCopyto(DOHFile *input, DOHFile *output); + + +/* ----------------------------------------------------------------------------- + * List + * ----------------------------------------------------------------------------- */ + +extern DOHList *DohNewList(); + +/* ----------------------------------------------------------------------------- + * Hash + * ----------------------------------------------------------------------------- */ + +extern DOHHash *DohNewHash(); + +/* ----------------------------------------------------------------------------- + * Void + * ----------------------------------------------------------------------------- */ + +extern DOHVoid *DohNewVoid(void *ptr, void (*del)(void *)); +extern DOHList *DohSplit(DOHFile *input, char ch, int nsplits); +extern DOH *DohNone; #ifndef DOH_LONG_NAMES /* Macros to invoke the above functions. Includes the location of @@ -168,6 +329,7 @@ extern int DohIsFile(const DOH *obj); #define Getc DohGetc #define Putc DohPutc #define Ungetc DohUngetc +#define Close DohClose #define vPrintf DohvPrintf #define GetInt DohGetInt #define GetDouble DohGetDouble @@ -182,57 +344,36 @@ extern int DohIsFile(const DOH *obj); #define Readline DohReadline #define Replace DohReplace #define Chop DohChop +#define Getmeta DohGetmeta +#define Setmeta DohSetmeta +#define Delmeta DohDelmeta +#define NewString DohNewString +#define NewStringf DohNewStringf +#define NewHash DohNewHash +#define NewList DohNewList +#define NewFile DohNewFile +#define NewFileFromFile DohNewFileFromFile +#define NewFileFromFd DohNewFileFromFd +#define Close DohClose +#define NewVoid DohNewVoid +#define Keys DohKeys +#define Strcmp DohStrcmp +#define Strncmp DohStrncmp +#define Strstr DohStrstr +#define Strchr DohStrchr +#define Copyto DohCopyto +#define Split DohSplit +#define Setmark DohSetmark +#define Getmark DohGetmark +#define None DohNone #endif -/* ----------------------------------------------------------------------------- - * Strings. - * ----------------------------------------------------------------------------- */ - -extern DOHString *NewString(const DOH *c); -extern DOHString *NewStringf(const DOH *fmt, ...); - -/* String replacement flags */ - -#define DOH_REPLACE_ANY 0x01 -#define DOH_REPLACE_NOQUOTE 0x02 -#define DOH_REPLACE_ID 0x04 -#define DOH_REPLACE_FIRST 0x08 - -/* ----------------------------------------------------------------------------- - * Files - * ----------------------------------------------------------------------------- */ - -extern DOHFile *NewFile(DOH *file, char *mode); -extern DOHFile *NewFileFromFile(FILE *f); -extern DOHFile *NewFileFromFd(int fd); - -extern int DohCopyto(DOHFile *input, DOHFile *output); - -#define Copyto DohCopyto - -/* ----------------------------------------------------------------------------- - * List - * ----------------------------------------------------------------------------- */ - -extern DOHList *NewList(); - -/* ----------------------------------------------------------------------------- - * Hash - * ----------------------------------------------------------------------------- */ - -extern DOHHash *NewHash(); -extern DOHList *Hash_keys(DOHHash *); - -/* ----------------------------------------------------------------------------- - * Void - * ----------------------------------------------------------------------------- */ - -extern DOHVoid *NewVoid(void *ptr, void (*del)(void *)); +#ifdef NIL +#undef NIL +#endif -extern DOHList *DohSplit(DOHFile *input, char *chs, int nsplits); -#define Split DohSplit +#define NIL (char *) NULL -extern DOH *DohNone; #endif /* DOH_H */ diff --git a/Source/DOH/Include/dohobj.h b/Source/DOH/Include/dohobj.h index da270e855..1f3ff19c7 100644 --- a/Source/DOH/Include/dohobj.h +++ b/Source/DOH/Include/dohobj.h @@ -23,6 +23,7 @@ typedef struct { int (*doh_delattr)(DOH *obj, DOH *name); /* Del attribute */ DOH *(*doh_firstkey)(DOH *obj); /* First key */ DOH *(*doh_nextkey)(DOH *obj); /* Next key */ + DOH *(*doh_keys)(DOH *obj); /* All keys as a list */ } DohHashMethods; /* List objects */ @@ -33,7 +34,6 @@ typedef struct { int (*doh_insitem)(DOH *obj, int index, DOH *value); /* Insert item */ DOH *(*doh_firstitem)(DOH *obj); /* Iterators */ DOH *(*doh_nextitem)(DOH *obj); - void (*doh_sort)(DOH *obj, int opt); /* Sort */ } DohListMethods; /* File methods */ @@ -93,37 +93,29 @@ typedef struct DohObjInfo { } DohObjInfo; typedef struct { - void *data; /* Data pointer */ - unsigned int type : 4; /* Object type (max 16 -- deal with it) */ + void *data; /* Data pointer */ + DohObjInfo *type; + void *meta; /* Meta data */ int flag_intern : 1; /* Interned object */ int flag_marked : 1; /* Mark flag. Used to avoid recursive loops in places */ int flag_user : 1; /* User flag */ - int flag_reserved : 1; /* Reserved flag */ - int refcount : 24; /* Reference count (max 16 million) */ + int flag_usermark : 1; /* User marked */ + int refcount : 28; /* Reference count (max 16 million) */ } DohBase; /* Macros for decrefing and increfing (safe for null objects). */ -#define Decref(a) if (a) ((DohBase *) a)->refcount-- -#define Incref(a) if (a) ((DohBase *) a)->refcount++ -#define Refcount(a) ((DohBase *) a)->refcount +#define Decref(a) if (a) ((DohBase *) a)->refcount-- +#define Incref(a) if (a) ((DohBase *) a)->refcount++ +#define Refcount(a) ((DohBase *) a)->refcount /* Macros for manipulating objects in a safe manner */ -#define ObjData(a) ((DohBase *)a)->data -#define ObjSetMark(a,x) ((DohBase *)a)->flag_marked = x -#define ObjGetMark(a) ((DohBase *)a)->flag_marked -#define ObjType(a) ((DohBase *)a)->type +#define ObjData(a) ((DohBase *)a)->data +#define ObjSetMark(a,x) ((DohBase *)a)->flag_marked = x +#define ObjGetMark(a) ((DohBase *)a)->flag_marked +#define ObjType(a) ((DohBase *)a)->type -extern DOH *DohObjMalloc(int type, void *data); /* Allocate a DOH object */ +extern DOH *DohObjMalloc(DohObjInfo *type, void *data); /* Allocate a DOH object */ extern void DohObjFree(DOH *ptr); /* Free a DOH object */ -extern void DohRegisterType(int type, DohObjInfo *objinfo); - -#define MAX_DOHTYPE 16 - -#define DOHTYPE_STRING 1 -#define DOHTYPE_LIST 2 -#define DOHTYPE_HASH 3 -#define DOHTYPE_VOID 4 -#define DOHTYPE_FILE 5 #endif /* DOHOBJ_H */ diff --git a/Source/DOH/Makefile.in b/Source/DOH/Makefile.in index f5d9b775c..bfa253c43 100644 --- a/Source/DOH/Makefile.in +++ b/Source/DOH/Makefile.in @@ -10,8 +10,6 @@ exec_prefix= @exec_prefix@ INCLUDE_DIR = $(prefix)/include LIB_DIR = $(exec_prefix)/lib -DOHOPT = - # Installer INSTALL = ./install-sh -c @@ -19,7 +17,7 @@ INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM= ${INSTALL} -m 755 all: - cd Doh; $(MAKE) DOHOPT='$(DOHOPT)' + cd Doh; $(MAKE) install: @echo "Installing $(LIB_DIR)/libdoh.a..." diff --git a/Source/DOH/configure.in b/Source/DOH/configure.in index 61c8240f9..11f2272ea 100644 --- a/Source/DOH/configure.in +++ b/Source/DOH/configure.in @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(Include/doh.h) -AC_PREREQ(2.0) +AC_PREREQ(2.53) # Set name for machine-dependent library files AC_SUBST(MACHDEP) @@ -41,4 +41,4 @@ dnl Checks for header files. AC_HEADER_STDC dnl Checks for library functions. -AC_OUTPUT(Makefile Doh/Makefile ) +AC_OUTPUT(Makefile Doh/Makefile) diff --git a/Source/Include/.cvsignore b/Source/Include/.cvsignore new file mode 100644 index 000000000..1c3642b87 --- /dev/null +++ b/Source/Include/.cvsignore @@ -0,0 +1,3 @@ +swigconfig.h +swigver.h + diff --git a/Source/Include/swigconfig.h.in b/Source/Include/swigconfig.h.in index 7a02d27fb..f5f3e6e18 100644 --- a/Source/Include/swigconfig.h.in +++ b/Source/Include/swigconfig.h.in @@ -1,6 +1,19 @@ -/* This file contains SWIG specific configuration data for those modules +/* This -*-c-*- file contains SWIG specific configuration data for those modules that care */ -#define SWIG_LIB "@prefix@/lib/swig1.3" -#define SWIG_LANG TCL8 +/* Directory where to find the machine-independent SWIG files */ +#define SWIG_LIB "@-swig_lib-@" + +/* Default language */ + +#define SWIG_LANG "-tcl" + +/* Values returned by swig when invoked with the -ldflags option */ + +#define SWIG_PERL_RUNTIME "-L@-exec_prefix-@/lib -lswigpl@-release_suffix-@" +#define SWIG_PYTHON_RUNTIME "-L@-exec_prefix-@/lib -lswigpy@-release_suffix-@" +#define SWIG_TCL_RUNTIME "-L@-exec_prefix-@/lib -lswigtcl@-release_suffix-@" +#define SWIG_RUBY_RUNTIME "-L@-exec_prefix-@/lib -lswigrb@-release_suffix-@" +#define SWIG_GUILE_RUNTIME "-L@-exec_prefix-@/lib -lswigguile@-release_suffix-@" +#define SWIG_PIKE_RUNTIME "-L@-exec_prefix-@/lib -lswigpike@-release_suffix-@" diff --git a/Source/Include/swigver.h b/Source/Include/swigver.h deleted file mode 100644 index c71b6b080..000000000 --- a/Source/Include/swigver.h +++ /dev/null @@ -1,10 +0,0 @@ - -/* SWIG version information */ - -#ifndef SWIG_VERSION -#define SWIG_VERSION "1.3u-20001219-1815" -#endif - -#ifndef SWIG_SPIN -#define SWIG_SPIN "(Alpha 6)" -#endif diff --git a/Source/Include/swigver.h.in b/Source/Include/swigver.h.in index 3f6f4acdd..7d35580ea 100644 --- a/Source/Include/swigver.h.in +++ b/Source/Include/swigver.h.in @@ -5,6 +5,14 @@ #define SWIG_VERSION "@SWIG_VERSION@" #endif +#ifndef SWIG_MAJOR_VERSION +#define SWIG_MAJOR_VERSION @SWIG_MAJOR_VERSION@ +#endif + +#ifndef SWIG_MINOR_VERSION +#define SWIG_MINOR_VERSION @SWIG_MINOR_VERSION@ +#endif + #ifndef SWIG_SPIN -#define SWIG_SPIN "@SWIG_SPIN@" +#define SWIG_SPIN @SWIG_SPIN@ #endif diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h new file mode 100644 index 000000000..cb4a96346 --- /dev/null +++ b/Source/Include/swigwarn.h @@ -0,0 +1,186 @@ +/* SWIG warning message numbers + + This file serves as the main registry of warning message numbers. Some of these + numbers are used internally in the C/C++ source code of SWIG. However, some + of the numbers are used in SWIG configuration files (swig.swg and others). + + The numbers are roughly organized into a few different classes by functionality. + + Even though symbolic constants are used in the SWIG source, this is + not always the case in SWIG interface files. Do not change the + numbers in this file. + + */ + + + + +#ifndef _SWIGWARN_H +#define _SWIGWARN_H 1 + +#define WARN_NONE 0 + +/* -- Deprecated features -- */ + +#define WARN_DEPRECATED_EXTERN 101 +#define WARN_DEPRECATED_VAL 102 +#define WARN_DEPRECATED_OUT 103 +#define WARN_DEPRECATED_DISABLEDOC 104 +#define WARN_DEPRECATED_ENABLEDOC 105 +#define WARN_DEPRECATED_DOCONLY 106 +#define WARN_DEPRECATED_STYLE 107 +#define WARN_DEPRECATED_LOCALSTYLE 108 +#define WARN_DEPRECATED_TITLE 109 +#define WARN_DEPRECATED_SECTION 110 +#define WARN_DEPRECATED_SUBSECTION 111 +#define WARN_DEPRECATED_SUBSUBSECTION 112 +#define WARN_DEPRECATED_ADDMETHODS 113 +#define WARN_DEPRECATED_READONLY 114 +#define WARN_DEPRECATED_READWRITE 115 +#define WARN_DEPRECATED_EXCEPT 116 +#define WARN_DEPRECATED_NEW 117 +#define WARN_DEPRECATED_EXCEPT_TM 118 +#define WARN_DEPRECATED_IGNORE_TM 119 + +/* -- Preprocessor -- */ + +#define WARN_PP_MISSING_FILE 201 +#define WARN_PP_EVALUATION 202 + +/* -- C/C++ Parser -- */ + +#define WARN_PARSE_CLASS_KEYWORD 301 +#define WARN_PARSE_REDEFINED 302 +#define WARN_PARSE_EXTEND_UNDEF 303 +#define WARN_PARSE_UNSUPPORTED_VALUE 304 +#define WARN_PARSE_BAD_VALUE 305 +#define WARN_PARSE_PRIVATE 306 +#define WARN_PARSE_BAD_DEFAULT 307 +#define WARN_PARSE_NAMESPACE_ALIAS 308 +#define WARN_PARSE_PRIVATE_INHERIT 309 +#define WARN_PARSE_TEMPLATE_REPEAT 310 +#define WARN_PARSE_TEMPLATE_PARTIAL 311 +#define WARN_PARSE_NESTED_CLASS 312 +#define WARN_PARSE_UNDEFINED_EXTERN 313 +#define WARN_PARSE_KEYWORD 314 +#define WARN_PARSE_USING_UNDEF 315 +#define WARN_PARSE_MODULE_REPEAT 316 +#define WARN_PARSE_TEMPLATE_SP_UNDEF 317 +#define WARN_PARSE_TEMPLATE_AMBIG 318 +#define WARN_PARSE_NO_ACCESS 319 + +#define WARN_IGNORE_OPERATOR_NEW 350 /* new */ +#define WARN_IGNORE_OPERATOR_DELETE 351 /* delete */ +#define WARN_IGNORE_OPERATOR_PLUS 352 /* + */ +#define WARN_IGNORE_OPERATOR_MINUS 353 /* - */ +#define WARN_IGNORE_OPERATOR_MUL 354 /* * */ +#define WARN_IGNORE_OPERATOR_DIV 355 /* / */ +#define WARN_IGNORE_OPERATOR_MOD 356 /* % */ +#define WARN_IGNORE_OPERATOR_XOR 357 /* ^ */ +#define WARN_IGNORE_OPERATOR_AND 358 /* & */ +#define WARN_IGNORE_OPERATOR_OR 359 /* | */ +#define WARN_IGNORE_OPERATOR_NOT 360 /* ~ */ +#define WARN_IGNORE_OPERATOR_LNOT 361 /* ! */ +#define WARN_IGNORE_OPERATOR_EQ 362 /* = */ +#define WARN_IGNORE_OPERATOR_LT 363 /* < */ +#define WARN_IGNORE_OPERATOR_GT 364 /* > */ +#define WARN_IGNORE_OPERATOR_PLUSEQ 365 /* += */ +#define WARN_IGNORE_OPERATOR_MINUSEQ 366 /* -= */ +#define WARN_IGNORE_OPERATOR_MULEQ 367 /* *= */ +#define WARN_IGNORE_OPERATOR_DIVEQ 368 /* /= */ +#define WARN_IGNORE_OPERATOR_MODEQ 369 /* %= */ +#define WARN_IGNORE_OPERATOR_XOREQ 370 /* ^= */ +#define WARN_IGNORE_OPERATOR_ANDEQ 371 /* &= */ +#define WARN_IGNORE_OPERATOR_OREQ 372 /* |= */ +#define WARN_IGNORE_OPERATOR_LSHIFT 373 /* << */ +#define WARN_IGNORE_OPERATOR_RSHIFT 374 /* >> */ +#define WARN_IGNORE_OPERATOR_LSHIFTEQ 375 /* <<= */ +#define WARN_IGNORE_OPERATOR_RSHIFTEQ 376 /* >>= */ +#define WARN_IGNORE_OPERATOR_EQUALTO 377 /* == */ +#define WARN_IGNORE_OPERATOR_NOTEQUAL 378 /* != */ +#define WARN_IGNORE_OPERATOR_LTEQUAL 379 /* <= */ +#define WARN_IGNORE_OPERATOR_GTEQUAL 380 /* >= */ +#define WARN_IGNORE_OPERATOR_LAND 381 /* && */ +#define WARN_IGNORE_OPERATOR_LOR 382 /* || */ +#define WARN_IGNORE_OPERATOR_PLUSPLUS 383 /* ++ */ +#define WARN_IGNORE_OPERATOR_MINUSMINUS 384 /* -- */ +#define WARN_IGNORE_OPERATOR_COMMA 385 /* , */ +#define WARN_IGNORE_OPERATOR_ARROWSTAR 386 /* ->* */ +#define WARN_IGNORE_OPERATOR_ARROW 387 /* -> */ +#define WARN_IGNORE_OPERATOR_CALL 388 /* () */ +#define WARN_IGNORE_OPERATOR_INDEX 389 /* [] */ +#define WARN_IGNORE_OPERATOR_UPLUS 390 /* + */ +#define WARN_IGNORE_OPERATOR_UMINUS 391 /* - */ +#define WARN_IGNORE_OPERATOR_UMUL 392 /* * */ +#define WARN_IGNORE_OPERATOR_UAND 393 /* & */ +#define WARN_IGNORE_OPERATOR_NEWARR 394 /* new [] */ +#define WARN_IGNORE_OEPRATOR_DELARR 395 /* delete [] */ + +/* 394-399 are reserved */ + +/* -- Type system and typemaps -- */ + +#define WARN_TYPE_UNDEFINED_CLASS 401 +#define WARN_TYPE_INCOMPLETE 402 +#define WARN_TYPE_ABSTRACT 403 +#define WARN_TYPE_REDEFINED 404 + +#define WARN_TYPEMAP_SOURCETARGET 450 +#define WARN_TYPEMAP_CHARLEAK 451 +#define WARN_TYPEMAP_SWIGTYPE 452 +#define WARN_TYPEMAP_APPLY_UNDEF 453 + +#define WARN_TYPEMAP_IN_UNDEF 460 +#define WARN_TYPEMAP_OUT_UNDEF 461 +#define WARN_TYPEMAP_VARIN_UNDEF 462 +#define WARN_TYPEMAP_VAROUT_UNDEF 463 +#define WARN_TYPEMAP_CONST_UNDEF 464 +#define WARN_TYPEMAP_UNDEF 465 +#define WARN_TYPEMAP_VAR_UNDEF 466 +#define WARN_TYPEMAP_TYPECHECK 467 +#define WARN_TYPEMAP_THROW 468 + +/* -- General code generation -- */ + +#define WARN_LANG_OVERLOAD_DECL 501 +#define WARN_LANG_OVERLOAD_CONSTRUCT 502 +#define WARN_LANG_IDENTIFIER 503 +#define WARN_LANG_RETURN_TYPE 504 +#define WARN_LANG_VARARGS 505 +#define WARN_LANG_VARARGS_KEYWORD 506 +#define WARN_LANG_NATIVE_UNIMPL 507 +#define WARN_LANG_DEREF_SHADOW 508 +#define WARN_LANG_OVERLOAD_SHADOW 509 +#define WARN_LANG_FRIEND_IGNORE 510 +#define WARN_LANG_OVERLOAD_KEYWORD 511 +#define WARN_LANG_OVERLOAD_CONST 512 +#define WARN_LANG_CLASS_UNNAMED 513 + +/* -- Reserved (600-799) -- */ + +/* -- Language module specific warnings (800 - 999) -- */ + +#define WARN_RUBY_WRONG_NAME 801 +#define WARN_RUBY_MULTIPLE_INHERITANCE 802 + +#define WARN_JAVA_TYPEMAP_JNI_UNDEF 810 +#define WARN_JAVA_TYPEMAP_JTYPE_UNDEF 811 +#define WARN_JAVA_TYPEMAP_JSTYPE_UNDEF 812 +#define WARN_JAVA_MULTIPLE_INHERITANCE 813 +#define WARN_JAVA_TYPEMAP_GETCPTR_UNDEF 814 +#define WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF 815 +#define WARN_JAVA_TYPEMAP_PTRCONSTMOD_UNDEF 816 +#define WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF 817 +#define WARN_JAVA_TYPEMAP_JAVAIN_UNDEF 818 + +/* please leave 810-830 free for Java */ + + + +/* Feel free to claim any number in this space that's not currently being used. Just make sure you + add an entry here */ + +#endif + + + diff --git a/Source/Modules1.1/Makefile.in b/Source/Modules1.1/Makefile.in index 509f7effe..bfa308a2f 100644 --- a/Source/Modules1.1/Makefile.in +++ b/Source/Modules1.1/Makefile.in @@ -7,32 +7,25 @@ VPATH = @srcdir@ SHELL = /bin/sh CXX = @CXX@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ @SWILL@ YACC = @YACC@ AR = @AR@ RANLIB = @RANLIB@ TARGET = libmodules11.a -COREOBJS = main.o emit.o lang.o generate.o -CORESRCS = main.cxx emit.cxx lang.cxx generate.cxx +OBJS = main.@OBJEXT@ module.@OBJEXT@ emit.@OBJEXT@ overload.@OBJEXT@ lang.@OBJEXT@ typepass.@OBJEXT@ allocate.@OBJEXT@ browser.@OBJEXT@ contract.@OBJEXT@ swigmain.@OBJEXT@ tcl8.@OBJEXT@ python.@OBJEXT@ perl5.@OBJEXT@ guile.@OBJEXT@ ruby.@OBJEXT@ mzscheme.@OBJEXT@ java.@OBJEXT@ php4.@OBJEXT@ ocaml.@OBJEXT@ xml.@OBJEXT@ pike.@OBJEXT@ s-exp.@OBJEXT@ +SRCS = main.cxx module.cxx emit.cxx overload.cxx lang.cxx typepass.cxx allocate.cxx browser.cxx contract.cxx swigmain.cxx tcl8.cxx python.cxx perl5.cxx guile.cxx ruby.cxx mzscheme.cxx java.cxx php4.cxx ocaml.cxx xml.cxx pike.cxx s-exp.cxx -LANGOBJS = tcl8.o python.o perl5.o guile.o ruby.o mzscheme.o #java.o -LANGSRCS = tcl8.cxx python.cxx perl5.cxx guile.cxx ruby.cxx mzscheme.cxx #java.cxx - -OBJS = $(COREOBJS) $(LANGOBJS) xml.o -SRCS = $(CORESRCS) $(LANGSRCS) xml.cxx - -INCLUDE = -I$(srcdir)/../Include \ - -I$(srcdir)/../Preprocessor \ - -I$(srcdir)/../LParse \ +INCLUDES = -I$(srcdir)/../Include \ -I$(srcdir)/../DOH/Include \ + -I$(srcdir)/../Preprocessor \ -I$(srcdir)/../Swig \ -I../Include -# Rules for creation of a .o file from .cxx +# Rules for creation of a .@OBJEXT@ file from .cxx .SUFFIXES: .cxx -.cxx.o: - $(CXX) $(INCLUDE) $(CFLAGS) -c -o $*.o $< +.cxx.@OBJEXT@: + $(CXX) $(INCLUDES) $(CFLAGS) -c -o $*.@OBJEXT@ $< swig: $(TARGET) @@ -42,7 +35,7 @@ $(TARGET): $(OBJS) $(RANLIB) $(TARGET) clean:: - rm -f *.o *~ $(TARGET) + rm -f *.@OBJEXT@ *~ $(TARGET) nuke:: - rm -f Makefile *~ #* core a.out + rm -f Makefile *~ diff --git a/Source/Modules1.1/README b/Source/Modules1.1/README new file mode 100644 index 000000000..058779d22 --- /dev/null +++ b/Source/Modules1.1/README @@ -0,0 +1,9 @@ +06/25/2002 + +This directory contains all of the SWIG language modules. Many of these +modules contain code that dates back to SWIG1.0. The module API has changed +a lot in the development releases so this is fairly messy. We're working on +cleaning it up, but you'll have to bear with us until it's done. + +-- Dave + diff --git a/Source/Modules1.1/allocate.cxx b/Source/Modules1.1/allocate.cxx new file mode 100644 index 000000000..4d7db5fae --- /dev/null +++ b/Source/Modules1.1/allocate.cxx @@ -0,0 +1,453 @@ +/* ----------------------------------------------------------------------------- + * allocate.cxx + * + * This module tries to figure out which classes and structures support + * default constructors and destructors in C++. There are several rules that + * define this behavior including pure abstract methods, private sections, + * and non-default constructors in base classes. See the ARM or + * Doc/Manual/SWIGPlus.html for details. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2002. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_allocate_cxx[] = "$Header$"; + +#include "swigmod.h" + +class Allocate : public Dispatcher { + Node *inclass; + enum AccessMode { PUBLIC, PRIVATE, PROTECTED }; + AccessMode cplus_mode; + int extendmode; + + /* Checks to see if a class is abstract through inheritance */ + int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) { + if (!first && (base == n)) return 0; + if (!base) { + /* Root node */ + Symtab *stab = Getattr(n,"symtab"); /* Get symbol table for node */ + Symtab *oldtab = Swig_symbol_setscope(stab); + int ret = is_abstract_inherit(n,n,1); + Swig_symbol_setscope(oldtab); + return ret; + } + List *abstract = Getattr(base,"abstract"); + if (abstract) { + for (int i = 0; i < Len(abstract); i++) { + Node *nn = Getitem(abstract,i); + String *name = Getattr(nn,"name"); + String *base_decl = Getattr(nn,"decl"); + if (Strstr(name,"~")) continue; /* Don't care about destructors */ + int implemented = 0; + Node *dn = Swig_symbol_clookup(name,0); + if (!dn) { + Printf(stdout,"node: %x '%s'. base: %x '%s'. member '%s'\n", n, Getattr(n,"name"), base, Getattr(base,"name"), name); + } + assert(dn); // Assertion of doom + while (dn && !implemented) { + String *local_decl = Getattr(dn,"decl"); + if (local_decl && !Strcmp(local_decl, base_decl)) { + if (Getattr(dn,"abstract")) return 1; + implemented++; + } + dn = Getattr(dn,"csym:nextSibling"); + } + if (!implemented && (Getattr(nn,"abstract"))) { + return 1; + } + /* + if (dn && (Getattr(dn,"abstract"))) { + return 1; + } + */ + } + } + List *bases = Getattr(base,"bases"); + if (!bases) return 0; + for (int i = 0; i < Len(bases); i++) { + if (is_abstract_inherit(n,Getitem(bases,i))) { + return 1; + } + } + return 0; + } + + + /* Grab methods used by smart pointers */ + + List *smart_pointer_methods(Node *cls, List *methods) { + if (!methods) { + methods = NewList(); + } + + Node *c = firstChild(cls); + String *kind = Getattr(cls,"kind"); + int mode; + if (Strcmp(kind,"class") == 0) mode = PRIVATE; + else mode = PUBLIC; + + while (c) { + if (Getattr(c,"error") || Getattr(c,"feature:ignore")) { + c = nextSibling(c); + continue; + } + if (Strcmp(nodeType(c),"cdecl") == 0) { + if (!Getattr(c,"feature:ignore")) { + String *storage = Getattr(c,"storage"); + if (!((Cmp(storage,"static") == 0) || (Cmp(storage,"typedef") == 0))) { + String *name = Getattr(c,"name"); + String *symname = Getattr(c,"sym:name"); + Node *e = Swig_symbol_clookup_local(name,0); + if (e && !Getattr(e,"feature:ignore") && (Cmp(symname, Getattr(e,"sym:name")) == 0)) { + Swig_warning(WARN_LANG_DEREF_SHADOW,Getfile(e),Getline(e),"Declaration of '%s' shadows declaration accessible via operator->() at %s:%d\n", + name, Getfile(c),Getline(c)); + } else { + /* Make sure node with same name doesn't already exist */ + int k; + int match = 0; + for (k = 0; k < Len(methods); k++) { + e = Getitem(methods,k); + if (Cmp(symname,Getattr(e,"sym:name")) == 0) { + match = 1; + break; + } + if ((!symname || (!Getattr(e,"sym:name"))) && (Cmp(name,Getattr(e,"name")) == 0)) { + match = 1; + break; + } + } + if (!match) { + Node *cc = c; + while (cc) { + Append(methods,cc); + cc = Getattr(cc,"sym:nextSibling"); + } + } + } + } + } + } + + if (Strcmp(nodeType(c),"access") == 0) { + kind = Getattr(c,"kind"); + if (Strcmp(kind,"public") == 0) mode = PUBLIC; + else mode = PRIVATE; + } + c = nextSibling(c); + } + /* Look for methods in base classes */ + { + Node *bases = Getattr(cls,"bases"); + int k; + for (k = 0; k < Len(bases); k++) { + smart_pointer_methods(Getitem(bases,k),methods); + } + } + /* Remove protected/private members */ + { + for (int i = 0; i < Len(methods); ) { + Node *n = Getitem(methods,i); + if (checkAttribute(n,"access","protected") || checkAttribute(n,"access","private")) { + Delitem(methods,i); + continue; + } + i++; + } + } + return methods; + } + + void mark_exception_classes(ParmList *p) { + while(p) { + SwigType *ty = Getattr(p,"type"); + SwigType *t = SwigType_typedef_resolve_all(ty); + Node *c = Swig_symbol_clookup(t,0); + if (c) { + Setattr(c,"cplus:exceptionclass","1"); + } + p = nextSibling(p); + } + } + +public: + virtual int top(Node *n) { + cplus_mode = PUBLIC; + inclass = 0; + extendmode = 0; + emit_children(n); + return SWIG_OK; + } + + virtual int importDirective(Node *n) { return emit_children(n); } + virtual int includeDirective(Node *n) { return emit_children(n); } + virtual int externDeclaration(Node *n) { return emit_children(n); } + virtual int namespaceDeclaration(Node *n) { return emit_children(n); } + virtual int extendDirective(Node *n) { + extendmode = 1; + emit_children(n); + extendmode = 0; + return SWIG_OK; + } + + virtual int classDeclaration(Node *n) { + Symtab *symtab = Swig_symbol_current(); + Swig_symbol_setscope(Getattr(n,"symtab")); + + if (!CPlusPlus) { + /* Always have default constructors/destructors in C */ + Setattr(n,"allocate:default_constructor","1"); + Setattr(n,"allocate:default_destructor","1"); + } + + if (Getattr(n,"allocate:visit")) return SWIG_OK; + Setattr(n,"allocate:visit","1"); + + /* Always visit base classes first */ + { + List *bases = Getattr(n,"bases"); + if (bases) { + for (int i = 0; i < Len(bases); i++) { + Node *b = Getitem(bases,i); + classDeclaration(b); + } + } + } + + inclass = n; + String *kind = Getattr(n,"kind"); + if (Strcmp(kind,"class") == 0) { + cplus_mode = PRIVATE; + } else { + cplus_mode = PUBLIC; + } + + emit_children(n); + + /* Check if the class is abstract via inheritance. This might occur if a class didn't have + any pure virtual methods of its own, but it didn't implement all of the pure methods in + a base class */ + + if (is_abstract_inherit(n)) { + if ((!Getattr(n,"abstract")) && ((Getattr(n,"allocate:public_constructor") || (!Getattr(n,"feature:nodefault") && !Getattr(n,"allocate:has_constructor"))))) { + if (!Getattr(n,"feature:notabstract")) { + Swig_warning(WARN_TYPE_ABSTRACT,Getfile(n),Getline(n),"Class '%s' might be abstract. No constructors generated. \n", SwigType_namestr(Getattr(n,"name"))); + Setattr(n,"abstract",NewList()); + } + } + } + + if (!Getattr(n,"allocate:has_constructor")) { + /* No constructor is defined. We need to check a few things */ + /* If class is abstract. No default constructor. Sorry */ + if (Getattr(n,"abstract")) { + Delattr(n,"allocate:default_constructor"); + } + if (!Getattr(n,"allocate:default_constructor")) { + /* Check base classes */ + List *bases = Getattr(n,"bases"); + int allows_default = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases,i); + /* If base class does not allow default constructor, we don't allow it either */ + if (!Getattr(n,"allocate:default_constructor") && (!Getattr(n,"allocate:default_base_constructor"))) { + allows_default = 0; + } + } + if (allows_default) { + Setattr(n,"allocate:default_constructor","1"); + } + } + } + if (!Getattr(n,"allocate:has_destructor")) { + /* No destructor was defined. We need to check a few things here too */ + List *bases = Getattr(n,"bases"); + int allows_destruct = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases,i); + /* If base class does not allow default destructor, we don't allow it either */ + if (!Getattr(n,"allocate:default_destructor") && (!Getattr(n,"allocate:default_base_destructor"))) { + allows_destruct = 0; + } + } + if (allows_destruct) { + Setattr(n,"allocate:default_destructor","1"); + } + } + + + /* Check if base classes allow smart pointers, but might be hidden */ + if (!Getattr(n,"allocate:smartpointer")) { + Node *sp = Swig_symbol_clookup((char*)"operator ->",0); + if (sp) { + /* Look for parent */ + Node *p = parentNode(sp); + if (Strcmp(nodeType(p),"extend") == 0) { + p = parentNode(p); + } + if (Strcmp(nodeType(p),"class") == 0) { + if (Getattr(p,"feature:ignore")) { + Setattr(n,"allocate:smartpointer",Getattr(p,"allocate:smartpointer")); + } + } + } + } + + /* Only care about default behavior. Remove temporary values */ + Setattr(n,"allocate:visit","1"); + inclass = 0; + Swig_symbol_setscope(symtab); + return SWIG_OK; + } + + virtual int accessDeclaration(Node *n) { + String *kind = Getattr(n,"kind"); + if (Cmp(kind,"public") == 0) { + cplus_mode = PUBLIC; + } else if (Cmp(kind,"private") == 0) { + cplus_mode = PRIVATE; + } else if (Cmp(kind,"protected") == 0) { + cplus_mode = PROTECTED; + } + return SWIG_OK; + } + + virtual int cDeclaration(Node *n) { + + mark_exception_classes(Getattr(n,"throws")); + + if (inclass) { + String *name = Getattr(n,"name"); + if (cplus_mode != PUBLIC) { + /* Look for a private assignment operator */ + if (Strcmp(name,"operator =") == 0) { + Setattr(inclass,"allocate:noassign","1"); + } + } else { + /* Look for smart pointer operator */ + if ((Strcmp(name,"operator ->") == 0) && (!Getattr(n,"feature:ignore"))) { + /* Look for version with no parameters */ + Node *sn = n; + while (sn) { + if (!Getattr(sn,"parms")) { + SwigType *type = SwigType_typedef_resolve_all(Getattr(sn,"type")); + SwigType_push(type,Getattr(sn,"decl")); + Delete(SwigType_pop_function(type)); + SwigType *base = SwigType_base(type); + Node *sc = Swig_symbol_clookup(base, 0); + if ((sc) && (Strcmp(nodeType(sc),"class") == 0)) { + if (SwigType_check_decl(type,"p.")) { + List *methods = smart_pointer_methods(sc,0); + Setattr(inclass,"allocate:smartpointer",methods); + break; + } else { + /* Hmmm. The return value is not a pointer. If the type is a value + or reference. We're going to chase it to see if another operator->() + can be found */ + + if ((SwigType_check_decl(type,"")) || (SwigType_check_decl(type,"r."))) { + Node *nn = Swig_symbol_clookup((char*)"operator ->", Getattr(sc,"symtab")); + if (nn) { + sn = nn; + continue; + } else { + break; + } + } else { + break; + } + } + } else { + break; + } + } else { + break; + } + } + } + } + } + return SWIG_OK; + } + + virtual int constructorDeclaration(Node *n) { + if (!inclass) return SWIG_OK; + Parm *parms = Getattr(n,"parms"); + + mark_exception_classes(Getattr(n,"throws")); + if (!extendmode) { + if (!ParmList_numrequired(parms)) { + /* Class does define a default constructor */ + /* However, we had better see where it is defined */ + if (cplus_mode == PUBLIC) { + Setattr(inclass,"allocate:default_constructor","1"); + } else if (cplus_mode == PROTECTED) { + Setattr(inclass,"allocate:default_base_constructor","1"); + } + } + /* Class defines some kind of constructor. May or may not be public */ + Setattr(inclass,"allocate:has_constructor","1"); + if (cplus_mode == PUBLIC) { + Setattr(inclass,"allocate:public_constructor","1"); + } + } + + /* See if this is a copy constructor */ + if (parms && (ParmList_numrequired(parms) == 1)) { + /* Look for a few cases. X(const X &), X(X &), X(X *) */ + + String *cc = NewStringf("r.q(const).%s", Getattr(inclass,"name")); + if (Strcmp(cc,Getattr(parms,"type")) == 0) { + Setattr(n,"copy_constructor","1"); + } + Delete(cc); + cc = NewStringf("r.%s", Getattr(inclass,"name")); + if (Strcmp(cc,Getattr(parms,"type")) == 0) { + Setattr(n,"copy_constructor","1"); + } + Delete(cc); + cc = NewStringf("p.%s", Getattr(inclass,"name")); + String *ty = SwigType_strip_qualifiers(Getattr(parms,"type")); + if (Strcmp(cc,ty) == 0) { + Setattr(n,"copy_constructor","1"); + } + Delete(cc); + Delete(ty); + } + return SWIG_OK; + } + + virtual int destructorDeclaration(Node *n) { + if (!inclass) return SWIG_OK; + if (!extendmode) { + Setattr(inclass,"allocate:has_destructor","1"); + if (cplus_mode == PUBLIC) { + Setattr(inclass,"allocate:default_destructor","1"); + } else if (cplus_mode == PROTECTED) { + Setattr(inclass,"allocate:default_base_destructor","1"); + } + } + return SWIG_OK; + } +}; + +void Swig_default_allocators(Node *n) { + if (!n) return; + Allocate *a = new Allocate; + a->top(n); + delete a; +} + + + + + + + diff --git a/Source/Modules1.1/browser.cxx b/Source/Modules1.1/browser.cxx new file mode 100644 index 000000000..da90a81b8 --- /dev/null +++ b/Source/Modules1.1/browser.cxx @@ -0,0 +1,415 @@ +/* ----------------------------------------------------------------------------- + * browser.cxx + * + * A web-base parse tree browser using SWILL. This is an optional + * feature that's normally disabled. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_browser_cxx[] = "$Header$"; + +#include "swigmod.h" + +#ifdef SWIG_SWILL +extern "C" { +#include "swill.h" +} + +static FILE *out = 0; +static Node *view_top = 0; + +class Browser : public Dispatcher { + void show_checkbox(Node *t, Node *n) { + int v = 0; + if (Getmeta(n,"visible")) { + v = 1; + } + if (v) { + Printf(out,"<a name=\"n%x\"></a>[<a href=\"hide.html?node=0x%x&hn=0x%x#n%x\">-</a>] ", n, t, n,n); + } else { + Printf(out,"<a name=\"n%x\"></a>[<a href=\"show.html?node=0x%x&hn=0x%x#n%x\">+</a>] ", n, t, n,n); + } + } + void show_attributes(Node *obj) { + if (!Getmeta(obj,"visible")) return; + String *os = NewString(""); + String *k; + k = Firstkey(obj); + while (k) { + if ((Cmp(k,"nodeType") == 0) || (Cmp(k,"firstChild") == 0) || (Cmp(k,"lastChild") == 0) || + (Cmp(k,"parentNode") == 0) || (Cmp(k,"nextSibling") == 0) || + (Cmp(k,"previousSibling") == 0) || (*(Char(k)) == '$')) { + /* Do nothing */ + } else if (Cmp(k,"parms") == 0) { + String *o = NewString(""); + Printf(o,"%s", ParmList_protostr(Getattr(obj,k))); + Replaceall(o,"&","&"); + Replaceall(o,"<","<"); + Replaceall(o,">",">"); + Printf(os,"<a href=\"data.html?n=0x%x\">?</a> %-12s - %s\n", Getattr(obj,k), k, o); + Delete(o); + } else { + DOH *o; + char *trunc = ""; + if (DohIsString(Getattr(obj,k))) { + o = Str(Getattr(obj,k)); + if (Len(o) > 70) { + trunc = "..."; + } + Replaceall(o,"&","&"); + Replaceall(o,"<","<"); + Printf(os,"<a href=\"data.html?n=0x%x\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj,k), k, o, trunc); + Delete(o); + } else { + Printf(os,"<a href=\"data.html?n=0x%x\">?</a> %-12s - 0x%x\n", Getattr(obj,k), k, Getattr(obj,k)); + } + } + k = Nextkey(obj); + } + Printf(out,"<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os)); + Delete(os); + } + +public: + virtual int emit_one(Node *n) { + char *tag = Char(nodeType(n)); + char *file = Char(Getfile(n)); + int line = Getline(n); + char *name = GetChar(n,"name"); + + show_checkbox(view_top, n); + Printf(out,"<b><a href=\"index.html?node=0x%x\">%s</a></b>", n, tag); + if (name) { + Printf(out," (%s)", name); + } + Printf(out,". %s:%d\n", file, line); + Printf(out,"<br>"); + Dispatcher::emit_one(n); + return SWIG_OK; + } + virtual int emit_children(Node *n) { + if (Getmeta(n,"visible")) { + Printf(out,"<blockquote>\n"); + Dispatcher::emit_children(n); + Printf(out,"</blockquote>\n"); + } + return SWIG_OK; + } + virtual int defaultHandler(Node *n) { + show_attributes(n); + return SWIG_OK; + } + virtual int top(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + virtual int includeDirective(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + virtual int importDirective(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + + virtual int extendDirective(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + virtual int classDeclaration(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + + virtual int templateDeclaration(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + + virtual int enumDeclaration(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + virtual int typemapDirective(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + virtual int namespaceDeclaration(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + virtual int usingDeclaration(Node *n) { + show_attributes(n); + emit_children(n); + return SWIG_OK; + } + +}; + +static int browser_exit = 0; +static Node *tree_top = 0; +static Browser *browse = 0; + +/* ---------------------------------------------------------------------- + * exit_handler() - Force the browser to exit + * ---------------------------------------------------------------------- */ + +void exit_handler(FILE *f) { + browser_exit = 1; + Printf(f,"Terminated.\n"); +} + +/* ---------------------------------------------------------------------- + * node_handler() - Generate information about a specific node + * ---------------------------------------------------------------------- */ + +static void display(FILE *f, Node *n) { + /* Print standard HTML header */ + + Printf(f,"<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", SWIG_VERSION); + Printf(f,"<b>SWIG-%s</b><br>\n", SWIG_VERSION); + Printf(f,"[ <a href=\"exit.html\">Exit</a> ]"); + Printf(f," [ <a href=\"index.html?node=0x%x\">Top</a> ]", tree_top); + if (n != tree_top) { + Printf(f," [ <a href=\"index.html?node=0x%x\">Up</a> ]", parentNode(n)); + } + Printf(f," [ <a href=\"symbol.html\">Symbols</a> ]"); + Printf(f,"<br><hr><p>\n"); + + out = f; + + browse->emit_one(n); + + /* Print standard footer */ + Printf(f,"<br><hr></BODY></HTML>\n"); + +} + +void node_handler(FILE *f) { + Node *n = 0; + if (!swill_getargs("p(node)", &n)) { + n = tree_top; + } + view_top = n; + display(f,n); +} + + +/* ---------------------------------------------------------------------- + * hide_handler() - Hide a node + * ---------------------------------------------------------------------- */ + +void hide_handler(FILE *f) { + Node *n = 0; + if (!swill_getargs("p(hn)", &n)) { + n = 0; + } + if (n) { + Delmeta(n,"visible"); + } + node_handler(f); +} + +void show_handler(FILE *f) { + Node *n = 0; + if (!swill_getargs("p(hn)", &n)) { + n = 0; + } + if (n) { + Setmeta(n,"visible","1"); + } + node_handler(f); +} + +void raw_data(FILE *out, Node *obj) { + if (!obj) return; + if (DohIsMapping(obj)) { + String *k; + String *os = NewString(""); + Printf(os,"Hash {\n"); + k = Firstkey(obj); + while (k) { + DOH *o; + const char *trunc = ""; + if (DohIsString(Getattr(obj,k))) { + o = Str(Getattr(obj,k)); + if (Len(o) > 70) { + trunc = "..."; + } + Replaceall(o,"<","<"); + Printf(os," <a href=\"data.html?n=0x%x\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj,k), k, o, trunc); + Delete(o); + } else { + Printf(os," <a href=\"data.html?n=0x%x\">?</a> %-12s - 0x%x\n", Getattr(obj,k), k, Getattr(obj,k)); + } + k = Nextkey(obj); + } + Printf(os,"}\n"); + Printf(out,"<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os)); + Delete(os); + } else if (DohIsString(obj)) { + String *o = Str(obj); + Replaceall(o,"<","<"); + Printf(out,"<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(o)); + Delete(o); + } else if (DohIsSequence(obj)) { + int i; + String *os = NewString(""); + Printf(os,"List [\n"); + for (i = 0; i < Len(obj); i++) { + DOH *o = Getitem(obj,i); + const char *trunc = ""; + if (DohIsString(o)) { + String *s = Str(o); + if (Len(s) > 70) { + trunc = "..."; + } + Replaceall(o,"<","<"); + Printf(os," <a href=\"data.html?n=0x%x\">?</a> [%d] - \"%(escape)-0.70s%s\"\n", o,i,s, trunc); + Delete(s); + } else { + Printf(os," <a href=\"data.html?n=0x%x\">?</a> [%d] - 0x%x\n", o, i, o); + } + } + Printf(os,"\n]\n"); + Printf(out,"<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os)); + Delete(os); + } +} + +void data_handler(FILE *f) { + DOH *n = 0; + if (!swill_getargs("p(n)", &n)) { + n = 0; + } + Printf(f,"<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", SWIG_VERSION); + Printf(f,"<b>SWIG-%s</b><br>\n", SWIG_VERSION); + Printf(f,"[ <a href=\"exit.html\">Exit</a> ]"); + Printf(f," [ <a href=\"index.html?node=0x%x\">Top</a> ]", tree_top); + Printf(f,"<br><hr><p>\n"); + if (n) { + raw_data(f,n); + } + /* Print standard footer */ + Printf(f,"<br><hr></BODY></HTML>\n"); +} + +void symbol_handler(FILE *f) { + Symtab *sym; + char *name = 0; + + Printf(f,"<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", SWIG_VERSION); + Printf(f,"<b>SWIG-%s</b><br>\n", SWIG_VERSION); + Printf(f,"[ <a href=\"exit.html\">Exit</a> ]"); + Printf(f," [ <a href=\"index.html?node=0x%x\">Top</a> ]", tree_top); + Printf(f," [ <a href=\"symbol.html\">Symbols</a> ]"); + Printf(f,"<br><hr><p>\n"); + + if (!swill_getargs("p(sym)|s(name)", &sym, &name)) { + sym = Swig_symbol_getscope(""); + name = 0; + } + if (!sym) { + Printf(f,"No symbol table specified!\n"); + return; + } + { + String *q = Swig_symbol_qualifiedscopename(sym); + if (!Len(q)) { + Printf(f,"<b>Symbol table: :: (global)</b><br>\n"); + } else { + Printf(f,"<b>Symbol table: %s</b><br>\n", q); + } + Delete(q); + } + + fprintf(f,"<p><form action=\"symbol.html\" method=GET>\n"); + fprintf(f,"Symbol lookup: <input type=text name=name size=40></input><br>\n"); + fprintf(f,"<input type=hidden name=sym value=\"0x%x\">\n", sym); + fprintf(f,"Submit : <input type=submit></input>\n"); + fprintf(f,"</form>"); + + if (name) { + Node *n = Swig_symbol_clookup(name,sym); + Printf(f,"Symbol '%s':\n", name); + Printf(f,"<blockquote>\n"); + if (!n) { + Printf(f,"Not defined!\n"); + } else { + raw_data(f,n); + } + Printf(f,"</blockquote>\n"); + } + + Printf(f,"<p><b>Nested scopes</b><br>\n"); + Printf(f,"<blockquote><pre>\n"); + { + Hash *h; + h = firstChild(sym); + while (h) { + Printf(f,"<a href=\"symbol.html?sym=0x%x\">%s</a>\n", h, Getattr(h,"name")); + h = nextSibling(h); + } + } + Printf(f,"</pre></blockquote>\n"); + + Printf(f,"<p><b>Symbol table contents</b></br>\n"); + raw_data(f,Getattr(sym,"symtab")); + Printf(f,"<br><hr></BODY></HTML>\n"); + +} +#endif + +void +Swig_browser(Node *top, int port) { +#ifdef SWIG_SWILL + int sport; + browser_exit = 0; + + /* Initialize the server */ + sport = swill_init(port); + if (sport < 0) { + Printf(stderr,"Couldn't open socket on port %d. Sorry.\n", port); + return; + } + browse = new Browser(); + Setmeta(top,"visible","1"); + tree_top = top; + + Printf(stderr,"SWIG: Tree browser listening on port %d\n", sport); + + swill_handle("exit.html", exit_handler,0); + swill_handle("index.html", node_handler, 0); + swill_handle("hide.html", hide_handler,0); + swill_handle("show.html", show_handler,0); + swill_handle("data.html", data_handler,0); + swill_handle("symbol.html", symbol_handler, 0); + swill_netscape("index.html"); + + while (!browser_exit) { + swill_serve(); + } + Printf(stderr,"Browser terminated.\n"); + swill_close(); + delete browse; + return; +#endif +} + + + + + diff --git a/Source/Modules1.1/contract.cxx b/Source/Modules1.1/contract.cxx new file mode 100644 index 000000000..fba5827aa --- /dev/null +++ b/Source/Modules1.1/contract.cxx @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- + * contract.cxx + * + * Experimental support for contracts + * + * Author(s) : Aquinas Hobor (aahobor@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_contract_cxx[] = "$Header$"; + +#include "swigmod.h" + +class Contracts : public Dispatcher { + +public: + virtual int top(Node *n) { + emit_children(n); + return SWIG_OK; + } + + virtual int importDirective(Node *n) { return emit_children(n); } + virtual int includeDirective(Node *n) { return emit_children(n); } // ? + virtual int externDeclaration(Node *n) { return emit_children(n); } + + String * strParms(ParmList *l) { + int comma = 0; + int i = 0; + Parm *p = l; + SwigType *pt; + String * returns = NewString(""); + while(p) { + String *pname; + pt = Getattr(p,"type"); + if ((SwigType_type(pt) != T_VOID)) { + if (comma) Printf(returns,","); + pname = Swig_cparm_name(p,i); + Printf(returns,"%s",SwigType_rcaststr(pt,pname)); + comma = 1; + i++; + } + p = nextSibling(p); + } + return returns; + } + + virtual int cDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *k = Getattr(n,"feature:contract"); + + if(k) + { + /* make the names */ + ParmList *l = Getmeta(k,"parms"); + String *params = ParmList_str(l); + String *transformed = strParms(l); + if(DohStrcmp(params,"")==0) { + DohDelete(params); + params = DohNewString("void"); + } + String *contractName = DohNewStringf("__SWIG_precontract_%s",name); + + /* make the contract */ + String *contract = DohNewStringf("int %s(%s,int rt[2])\n{\n",contractName,params); + SwigScanner * ss = NewSwigScanner(); + SwigScanner_clear(ss); + SwigScanner_push(ss,Copy(k)); + SwigScanner_token(ss); // Get rid of the '{' at the begining + + /* loop over the clauses */ + int clauseNum = 1; + int token = -1; + while(1) { + String *clause = DohNewString(""); /*BUG -- should free*/ + while((token=SwigScanner_token(ss))) { + if ((token==SWIG_TOKEN_SEMI)||(token==SWIG_TOKEN_RBRACE)) + break; + // if (token != SWIG_TOKEN_ENDLINE) + Printf(clause,"%s",SwigScanner_text(ss)); + } + if (DohStrcmp(clause,"\n") != 0) { + Printf(contract,"if (!(%s",clause); + Printf(contract,")) {\nrt[0]=__LINE__;\nrt[1]=%i;\nreturn 1;\n}\n",clauseNum); + } + if(token==SWIG_TOKEN_RBRACE) break; + clauseNum++; + } + + /* finish it off and attach it to the main tree */ + Printf(contract,"return 0;\n}\n"); + Setattr(n,"wrap:code",contract); /*BUG -- WHAT IF SOMETHING IS ALREADY THERE*/ + + /* Generate the calling code */ + String * calling = DohNewString("{\nint cfail[2];\nchar message[255];\n"); + Printf(calling,"if (%s(%s,cfail)) {\n",contractName,transformed); + Printf(calling,"sprintf(message,\"Contract %s failed on clause %%i (line %%i)!\",cfail[1],cfail[0]);\n",contractName); + Printf(calling,"PyErr_SetString(PyExc_Exception,message);return NULL;\n}\n"); + Printf(calling,"}\n"); + /* Setattr(n,"feature:preassert",calling); */ + } + /*There are two attributes "feature:preassert" and "feature:postassert".*/ + + + return SWIG_OK; + } + +}; + +void Swig_contracts(Node *n) { + Printf(stdout,"Applying contracts (experimental v0.09)\n"); + + Contracts *a = new Contracts; + a->top(n); + delete a; + +} diff --git a/Source/Modules1.1/emit.cxx b/Source/Modules1.1/emit.cxx index 02b98855d..1f4bcf8bb 100644 --- a/Source/Modules1.1/emit.cxx +++ b/Source/Modules1.1/emit.cxx @@ -12,26 +12,11 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -#include "swig11.h" +#include "swigmod.h" -static char cvsroot[] = "$Header$"; +char cvsroot_emit_cxx[] = "$Header$"; -/* ----------------------------------------------------------------------------- - * new_create_function() - * - * Create a new function - * ----------------------------------------------------------------------------- */ - -void new_create_function(char *name, char *iname, SwigType *type, ParmList *l) { - Hash *h; - h = NewHash(); - Setattr(h,"name",name); - Setattr(h,"scriptname",iname); - Setattr(h,"type",type); - Setattr(h,"parms",l); - lang->function(h); - Delete(h); -} +extern SwigType *cplus_value_type(SwigType *t); /* ----------------------------------------------------------------------------- * emit_args() @@ -43,209 +28,424 @@ void new_create_function(char *name, char *iname, SwigType *type, ParmList *l) { * Returns the number of parameters associated with a function. * ----------------------------------------------------------------------------- */ -int emit_args(DOH *node, Wrapper *f) { +void emit_args(SwigType *rt, ParmList *l, Wrapper *f) { - SwigType *rt; - ParmList *l; Parm *p; - int i; - char *tm; - SwigType *pt; - DOHString *pvalue; - DOHString *pname; - DOHString *lname; - - rt = Getattr(node,"type"); - l = Getattr(node,"parms"); + String *tm; /* Emit function arguments */ Swig_cargs(f, l); - i = 0; - p = l; - while (p != 0) { - lname = Getlname(p); - pt = Gettype(p); - pname = Getname(p); - pvalue = Getvalue(p); + /* Handle return type */ + if (rt && (SwigType_type(rt) != T_VOID)) { + if (!CPlusPlus || (CPlusPlus && !SwigType_isclass(rt))) { + Wrapper_add_local(f,"result", SwigType_lstr(rt,"result")); + } else { + SwigType *vt = 0; + vt = cplus_value_type(rt); + if (!vt) { + Wrapper_add_local(f,"result", SwigType_lstr(rt,"result")); + } else { + Wrapper_add_local(f,"result", SwigType_lstr(vt,"result")); + Delete(vt); + } + } + } + + /* Attach typemaps to parameters */ + /* Swig_typemap_attach_parms("ignore",l,f); */ + + Swig_typemap_attach_parms("default",l,f); + Swig_typemap_attach_parms("arginit",l,f); - tm = Swig_typemap_lookup((char*)"arginit",pt,pname,(char*)"",lname,f); + /* Apply the arginit and default */ + p = l; + while (p) { + tm = Getattr(p,"tmap:arginit"); if (tm) { - Printv(f,tm,"\n",0); + Replace(tm,"$target", Getattr(p,"lname"), DOH_REPLACE_ANY); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:arginit:next"); + } else { + p = nextSibling(p); } - /* Check for ignore or default typemaps */ - tm = Swig_typemap_lookup((char*)"default",pt,pname,(char*)"",lname,f); + } + + /* Apply the default typemap */ + p = l; + while (p) { + tm = Getattr(p,"tmap:default"); if (tm) { - Printv(f,tm,"\n",0); + Replace(tm,"$target", Getattr(p,"lname"), DOH_REPLACE_ANY); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:default:next"); + } else { + p = nextSibling(p); } - tm = Swig_typemap_lookup((char*)"ignore",pt,pname,(char*)"",lname,f); + } + +#ifdef DEPRECATED + /* Apply the ignore typemap */ + p = l; + while (p) { + tm = Getattr(p,"tmap:ignore"); if (tm) { - Printv(f,tm,"\n",0); - Setignore(p,1); + Parm *np; + Replace(tm,"$target", Getattr(p,"lname"), DOH_REPLACE_ANY); + Printv(f->code,tm,"\n",NIL); + np = Getattr(p,"tmap:ignore:next"); + + /* Deprecate this part later */ + while (p && (p != np)) { + Setattr(p,"ignore","1"); + p = nextSibling(p); + } + /* -- end deprecate */ + + } else { + p = nextSibling(p); } - i++; - p = Getnext(p); } - return(i); +#endif + return; } /* ----------------------------------------------------------------------------- - * int emit_func_call(char *decl, DataType *t, ParmList *l, Wrapper*f) - * - * Emits code for a function call (new version). - * - * Exception handling support : + * emit_attach_parmmaps() * - * - This function checks to see if any sort of exception mechanism - * has been defined. If so, we emit the function call in an exception - * handling block. + * Attach the standard parameter related typemaps. * ----------------------------------------------------------------------------- */ -static DOH *fcall = 0; +void emit_attach_parmmaps(ParmList *l, Wrapper *f) { + Swig_typemap_attach_parms("in",l,f); + Swig_typemap_attach_parms("typecheck",l,0); + Swig_typemap_attach_parms("argout",l,f); + Swig_typemap_attach_parms("check",l,f); + Swig_typemap_attach_parms("freearg",l,f); + + { + /* This is compatibility code to deal with the deprecated "ignore" typemap */ + Parm *p = l; + Parm *np; + String *tm; + while (p) { + tm = Getattr(p,"tmap:in"); + if (tm && checkAttribute(p,"tmap:in:numinputs","0")) { + Replaceall(tm,"$target", Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + np = Getattr(p,"tmap:in:next"); + while (p && (p != np)) { + Setattr(p,"ignore","1"); + p = nextSibling(p); + } + } else if (tm) { + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } + } + } -void emit_set_action(DOHString_or_char *decl) { - if (fcall) Delete (fcall); - fcall = NewString(decl); + /* Perform a sanity check on "in" and "freearg" typemaps. These + must exactly match to avoid chaos. If a mismatch occurs, we + nuke the freearg typemap */ + + { + Parm *p = l; + Parm *npin, *npfreearg; + while (p) { + npin = Getattr(p,"tmap:in:next"); + + /* + if (Getattr(p,"tmap:ignore")) { + npin = Getattr(p,"tmap:ignore:next"); + } else if (Getattr(p,"tmap:in")) { + npin = Getattr(p,"tmap:in:next"); + } + */ + + if (Getattr(p,"tmap:freearg")) { + npfreearg = Getattr(p,"tmap:freearg:next"); + if (npin != npfreearg) { + while (p != npin) { + Delattr(p,"tmap:freearg"); + Delattr(p,"tmap:freearg:next"); + p = nextSibling(p); + } + } + } + p = npin; + } + } + + /* Check for variable length arguments with no input typemap. + If no input is defined, we set this to ignore and print a + message. + */ + { + Parm *p = l; + Parm *lp = 0; + while (p) { + if (!checkAttribute(p,"tmap:in:numinputs","0")) { + lp = p; + p = Getattr(p,"tmap:in:next"); + continue; + } + if (SwigType_isvarargs(Getattr(p,"type"))) { + Swig_warning(WARN_LANG_VARARGS,input_file,line_number,"Variable length arguments discarded.\n"); + Setattr(p,"tmap:in",""); + } + lp = 0; + p = nextSibling(p); + } + + /* Check if last input argument is variable length argument */ + if (lp) { + p = lp; + while (p) { + if (SwigType_isvarargs(Getattr(p,"type"))) { + Setattr(l,"emit:varargs",lp); + break; + } + p = nextSibling(p); + } + } + } } -void emit_func_call(DOH *node, Wrapper *f) { - char *decl; - SwigType *t; - ParmList *l; - char *tm; - - decl = GetChar(node,"name"); - t = Getattr(node,"type"); - l = Getattr(node,"parms"); - - if ((tm = Swig_typemap_lookup((char*)"except",t,decl,(char*)"result",(char*)"",0))) { - Printv(f,tm,0); - Replace(f,"$name",decl,DOH_REPLACE_ANY); - } else if ((tm = Swig_except_lookup())) { - Printv(f,tm,0); - Replace(f,"$name",decl,DOH_REPLACE_ANY); - } else { - Printv(f,"$function",0); +/* ----------------------------------------------------------------------------- + * emit_num_arguments() ** new in 1.3.10 + * + * Calculate the total number of arguments. This function is safe for use + * with multi-valued typemaps which may change the number of arguments in + * strange ways. + * ----------------------------------------------------------------------------- */ + +int emit_num_arguments(ParmList *parms) { + Parm *p = parms; + int nargs = 0; + + while (p) { + if (Getattr(p,"tmap:in")) { + nargs += GetInt(p,"tmap:in:numinputs"); + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } } - - if (!fcall) fcall = NewString(Swig_cfunction_call(decl,l)); - if (CPlusPlus) { - Swig_cppresult(f, t, (char*)"result", Char(fcall)); - } else { - Swig_cresult(f, t, (char*)"result", Char(fcall)); +#ifdef DEPRECATED + while (p) { + /* Ignored arguments */ + if (Getattr(p,"tmap:ignore")) { + p = Getattr(p,"tmap:ignore:next"); + } else { + /* Marshalled arguments */ + nargs++; + if (Getattr(p,"tmap:in")) { + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } + } + } +#endif + if (parms && (p = Getattr(parms,"emit:varargs"))) { + if (!nextSibling(p)) { + nargs--; + } } - Delete(fcall); - fcall = 0; + return nargs; } /* ----------------------------------------------------------------------------- - * void emit_set_get() - * - * Emits a pair of functions to set/get the value of a variable. This is - * only used in the event the target language can't provide variable linking - * on its own. - * - * double foo; - * - * Gets translated into the following : + * emit_num_required() ** new in 1.3.10 * - * double foo_set(double x) { - * return foo = x; - * } - * - * double foo_get() { - * return foo; - * } + * Computes the number of required arguments. This is function is safe for + * use with multi-valued typemaps and knows how to skip over everything + * properly. * ----------------------------------------------------------------------------- */ -/* How to assign a C allocated string */ +int emit_num_required(ParmList *parms) { + Parm *p = parms; + int nargs = 0; -static char *c_str = (char *)"\ -if ($target) free($target);\n\ -$target = ($rtype) malloc(strlen($source)+1);\n\ -strcpy((char *)$target,$source);\n\ -return $ltype $target;\n"; + while (p) { + if (Getattr(p,"tmap:in") && checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } else { + if (Getattr(p,"value")) break; + if (Getattr(p,"tmap:default")) break; + nargs+= GetInt(p,"tmap:in:numinputs"); + if (Getattr(p,"tmap:in")) { + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } + } + } -/* How to assign a C allocated string */ + /* Print message for non-default arguments */ + while (p) { + if (Getattr(p,"tmap:in") && checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } else { + if (!Getattr(p,"value") && (!Getattr(p,"tmap:default"))) { + Swig_error(Getfile(p),Getline(p),"Error. Non-optional argument '%s' follows an optional argument.\n",Getattr(p,"name")); + } + if (Getattr(p,"tmap:in")) { + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } + } + } -static char *cpp_str = (char *)"\ -if ($target) delete [] $target;\n\ -$target = ($rtype) (new char[strlen($source)+1]);\n\ -strcpy((char *)$target,$source);\n\ -return ($ltype) $target;\n;"; + if (parms && (p = Getattr(parms,"emit:varargs"))) { + if (!nextSibling(p)) { + nargs--; + } + } + return nargs; +} +/* ----------------------------------------------------------------------------- + * emit_isvarargs() + * + * Checks if a function is a varargs function + * ----------------------------------------------------------------------------- */ -void emit_set_get(DOH *node) { - char *name, *iname; - SwigType *t; - Wrapper *w; - DOHString *new_iname; - char *code = 0; - - name = GetChar(node,"name"); - iname = GetChar(node,"iname"); - t = Getattr(node,"type"); - - /* First write a function to set the variable of the variable */ - if (!ReadOnly) { - - if (SwigType_type(t) == T_STRING) { - if (CPlusPlus) - code = cpp_str; - else - code = c_str; - } - w = Swig_cvarset_wrapper(name, t, code); - Printf(f_header,"%s", w); - new_iname = Swig_name_set(iname); - DohIncref(new_iname); - new_create_function(GetChar(w,"name"), Char(new_iname), Gettype(w), Getparms(w)); - Delete(new_iname); - Delete(w); - } - - w = Swig_cvarget_wrapper(name,t,0); - Printf(f_header,"%s", w); - new_iname = Swig_name_get(iname); - DohIncref(new_iname); - new_create_function(GetChar(w,"name"), Char(new_iname), Gettype(w), Getparms(w)); - Delete(new_iname); - Delete(w); +int +emit_isvarargs(ParmList *p) { + if (!p) return 0; + if (Getattr(p,"emit:varargs")) return 1; + return 0; } -/* ------------------------------------------------------------------ - * int check_numopt() +/* ----------------------------------------------------------------------------- + * replace_args() + * ----------------------------------------------------------------------------- */ + +static +void replace_args(Parm *p, String *s) { + while (p) { + String *n = Getattr(p,"name"); + if (n) { + Replace(s,n,Getattr(p,"lname"), DOH_REPLACE_ID); + } + p = nextSibling(p); + } +} + +/* ----------------------------------------------------------------------------- + * int emit_action() * - * Gets the number of optional arguments for a ParmList. - * ------------------------------------------------------------------ */ - -int check_numopt(ParmList *p) { - int n = 0; - int i = 0; - int state = 0; - - for (;p; p = Getnext(p),i++) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - if (Getvalue(p)) { - n++; - state = 1; - } else if (Swig_typemap_search((char*)"default",pt,pn)) { - n++; - state = 1; - } else if (Swig_typemap_search((char*)"ignore",pt,pn)) { - n++; - } else { - if (state) { - Printf(stderr,"%s:%d. Argument %d must have a default value!\n", Getfile(p), Getline(p),i+1); + * Emits action code for a wrapper and checks for exception handling + * ----------------------------------------------------------------------------- */ + +void emit_action(Node *n, Wrapper *f) { + String *tm; + String *action; + String *wrap; + Parm *p; + SwigType *rt; + ParmList *throws = Getattr(n,"throws"); + + /* Look for fragments */ + { + String *f; + f = Getattr(n,"feature:fragment"); + if (f) { + char *c, *tok; + String *t = Copy(f); + c = Char(t); + tok = strtok(c,","); + while (tok) { + Swig_fragment_emit(tok); + tok = strtok(NULL,","); } + Delete(t); } } - return n; -} + /* Emit wrapper code (if any) */ + wrap = Getattr(n,"wrap:code"); + if (wrap && Swig_filebyname("header")!=Getattr(n,"wrap:code:done") ) { + File *f_code = Swig_filebyname("header"); + if (f_code) { + Printv(f_code,wrap,NIL); + } + Setattr(n,"wrap:code:done",f_code); + } + action = Getattr(n,"feature:action"); + if (!action) + action = Getattr(n,"wrap:action"); + assert(action); + + /* Get the return type */ + + rt = Getattr(n,"type"); + + /* Preassert -- EXPERIMENTAL */ + tm = Getattr(n,"feature:preassert"); + if (tm) { + p = Getattr(n,"parms"); + replace_args(p,tm); + Printv(f->code,tm,"\n",NIL); + } + + /* Exception handling code */ + + /* If we are in C++ mode and there is a throw specifier. We're going to + enclose the block in a try block */ + if (throws) { + Printf(f->code,"try {\n"); + } + + /* Look for except typemap (Deprecated) */ + tm = Swig_typemap_lookup_new("except",n,"result",0); + + /* Look for except feature */ + if (!tm) { + tm = Getattr(n,"feature:except"); + if (tm) tm = Copy(tm); + } + if ((tm) && Len(tm) && (Strcmp(tm,"1") != 0)) { + Replaceall(tm,"$name",Getattr(n,"name")); + Replaceall(tm,"$symname", Getattr(n,"sym:name")); + Replaceall(tm,"$function", action); + Replaceall(tm,"$action", action); + Printv(f->code,tm,"\n", NIL); + Delete(tm); + } else { + Printv(f->code, action, "\n",NIL); + } + + if (throws) { + Printf(f->code,"}\n"); + for (Parm *ep = throws; ep; ep = nextSibling(ep)) { + String *em = Swig_typemap_lookup_new("throws",ep,"_e",0); + if (em) { + Printf(f->code,"catch(%s) {\n", SwigType_str(Getattr(ep,"type"),"&_e")); + Printv(f->code,em,"\n",NIL); + Printf(f->code,"}\n"); + } else { + Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), + "No 'throw' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep,"type"),0)); + } + } + Printf(f->code,"catch(...) { throw; }\n"); + } + + /* Postassert - EXPERIMENTAL */ + tm = Getattr(n,"feature:postassert"); + if (tm) { + p = Getattr(n,"parms"); + replace_args(p,tm); + Printv(f->code,tm,"\n",NIL); + } +} diff --git a/Source/Modules1.1/generate.cxx b/Source/Modules1.1/generate.cxx deleted file mode 100644 index 51b885ed4..000000000 --- a/Source/Modules1.1/generate.cxx +++ /dev/null @@ -1,909 +0,0 @@ -/* ----------------------------------------------------------------------------- - * generate.cxx - * - * This file manages the code generation process and serves as a bridge between - * the new SWIG parser and the old set of C++-based language modules. - * - * Author(s) : David Beazley (beazley@cs.uchicago.edu) - * - * Copyright (C) 1999-2000. The University of Chicago - * See the file LICENSE for information on usage and redistribution. - * ----------------------------------------------------------------------------- */ - -#include "swig11.h" - -static char cvstag[] = "$Header$"; - -int ReadOnly = 0; -int WrapExtern = 0; - -/* Access permissions: public, private, protected */ -enum { PUBLIC, PRIVATE, PROTECTED }; -int Access = PUBLIC; - -/* Miscellaneous modes */ -int Native = 0; - -/* This function tries to locate the module name within the parse tree */ -static String *find_module(DOH *node) { - DOH *n; - - if (!node) return 0; - n = node; - while (n) { - if (Swig_tag_check(n,"module")) { - return Getname(n); - } - if (Swig_tag_check(n,"file")) { - String *ty; - ty = Getattr(n,"type"); - if (Cmp(ty,"include") == 0) { - DOH *m; - /* Might be in an include file */ - m = find_module(Getchild(n)); - if (m) return m; - } - } - n = Getnext(n); - } - return find_module(Getchild(node)); -} - -/* This helper function emits external function declarations */ -static -void emit_extern_func(DOH *node, File *f) { - Parm *p; - SwigType *tc; - char *c; - String *storage; - storage = Getattr(node,"storage"); - if (!storage) return; - c = Char(storage); - if (strncmp(c,"extern",6) == 0) { - List *tl = NewList(); - p = Getparms(node); - while (p) { - Append(tl,Gettype(p)); - p = Getnext(p); - } - tc = Copy(Gettype(node)); - SwigType_add_function(tc,tl); - Printf(f,"%s %s;\n", storage, SwigType_str(tc,Getname(node))); - Delete(tc); - Delete(tl); - } -} - -/* Test if static */ -static int -check_static(DOH *node) { - String *storage = Getattr(node,"storage"); - if (!storage) return 0; - if (Cmp(storage,"static") == 0) return 1; - return 0; -} - -/* Test if extern */ -static int -check_extern(DOH *node) { - String *storage = Getattr(node,"storage"); - if (!storage) return 0; - if (strncmp(Char(storage),"extern",6) == 0) return 1; - return 0; -} - -static String *new_name = 0; - -/* Handle renaming */ -static -void set_scriptname(DOH *node) { - if (new_name) { - Setattr(node,"scriptname",new_name); - } else { - String *aname = Getattr(node,"altname"); - if (aname) { - Setattr(node,"scriptname",aname); - } else { - Setattr(node,"scriptname", Getname(node)); - } - } - new_name = 0; -} - -/* ----------------------------------------------------------------------------- - * C++ Support - * ----------------------------------------------------------------------------- */ - -static DOH *class_hash = 0; /* Hash table of classes that have been seen so far */ -static DOH *current_class = 0; /* Set when wrapping a class */ -static DOH *class_name = 0; /* Real name of current class */ -static DOH *class_types = 0; /* Types defined within this class */ -static String *construct_name = 0; /* Expected name of a constructor */ -int AddMethods = 0; /* Set when in addmethods mode */ -int Abstract = 0; /* Set when the class is determined to be abstract */ -static int have_destructor = 0; -static int have_constructor = 0; - -/* Check for abstract classes */ - -int cplus_check_abstract(DOH *node) { - while (node) { - if (Getattr(node,"abstract")) return 1; - node = Getnext(node); - } - return 0; -} - -/* Given a class object, this function builds an internal symbol table */ -void cplus_build_symbols(DOH *node) { - Hash *sym; - DOH *c; - sym = Getattr(node,"symbols"); - if (!sym) { - sym = NewHash(); - Setattr(node,"symbols",sym); - } - c = Getchild(node); - while (c) { - String *name = Getname(c); - String *tag = Gettag(c); - if (Cmp(tag,"c:destructor") == 0) { - name = NewStringf("~%s",name); - } - if (name) { - DOH *pnode = Getattr(sym,name); - if (pnode) { - Printf(stderr,"%s:%d. '%s' redefined. Previous definition at %s:%d.\n", - Getfile(c),Getline(c), name, Getfile(pnode), Getline(pnode)); - } else { - Setattr(sym,name,c); - } - } - c = Getnext(c); - } - return; -} - -/* Inherit certain types of declarations from another class */ - - - -/* Add a class type */ -static void -class_addtype(String *name, String *cname) { - String *s; - if (!cname) - s = NewStringf("%s::%s", class_name, name); - else - s = NewStringf("%s::%s", cname, name); - - if (!class_types) class_types = NewHash(); - Setattr(class_types,name,s); -} - -/* Updates a type with a fully qualified version */ -static void -class_update_type(String *type) { - String *base, *rep; - if (!type) return; - base = SwigType_base(type); - if (!class_types) return; - rep = Getattr(class_types,base); - if (rep) { - SwigType_setbase(type,rep); - /* Printf(stdout,"updated type = '%s'\n", type); */ - } -} - -/* Updates a list of parms with fully qualified names */ -static void -class_update_parms(ParmList *p) { - while (p) { - class_update_type(Gettype(p)); - p = Getnext(p); - } -} - -/* Traverse the inheritance hierarchy of a class */ -void -cplus_walk_inherit(DOH *cls, void (*action)(DOH *base, void *clientdata), void *clientdata) { - DOH *base; - List *bases; - int i, nbase; - - bases = Getattr(cls,"bases"); - if (bases) { - nbase = Len(bases); - for (i = 0; i < nbase; i++) { - base = Getattr(class_hash, Getitem(bases,i)); - if (base) { - (*action)(base,clientdata); - - } - } - } -} - -/* Action for inheriting type definitions */ -static void inherit_types(DOH *cls, void *clientdata) { - DOH *ty; - ty = Getattr(cls,"types"); - if (ty) { - String *key; - SwigType_merge_scope(ty,0); - for (key = Firstkey(ty); key; key = Nextkey(ty)) { - class_addtype(key, Getname(cls)); - } - } - cplus_walk_inherit(cls,inherit_types,clientdata); -} - -/* Action for inheriting typemaps */ -static void inherit_typemaps(DOH *cls, void *clientdata) { - DOH *ty; - - cplus_walk_inherit(cls,inherit_typemaps,clientdata); - ty = Getattr(cls,"typemaps"); - if (ty) { - if (!clientdata) - Swig_typemap_new_scope(ty); - else - Swig_typemap_pop_scope(); - } -} - -extern "C" { -int swig11_unknown(DOH *node, void *clientdata) { - Printf(stdout,"::: Unknown tag - '%s'\n", Getattr(node,"tag")); - return 0; -} - -int swig11_nil(DOH *node, void *clientdata) { - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_file() - * - * File inclusion directives. %include, %extern, and %import. - * ----------------------------------------------------------------------------- */ - -int swig11_file(DOH *node, void *clientdata) { - DOH *c; - String *type; - int old_we = WrapExtern; - - type = Getattr(node,"type"); - if ((Cmp(type, "extern") == 0) || (Cmp(type,"import") == 0)) { - WrapExtern = 1; - } - c = Getchild(node); - if (Cmp(type,"import") == 0) { - /* If importing a module, we try to find the module name and pass it to - the language modules */ - String *modname; - modname = find_module(c); - if (modname) { - lang->import(modname); - } - } - Swig_emit_all(c,clientdata); - WrapExtern = old_we; - return 0; -} -/* ----------------------------------------------------------------------------- - * swig11_scope() - * - * Handle the %scope directive. This is a new feature not present in SWIG1.1. - * Creates a new typemap scope and has other side effects. - * ----------------------------------------------------------------------------- */ - -int swig11_scope(DOH *node, void *clientdata) { - DOH *c; - String *name; - - c = Getchild(node); - name = Getname(node); - - Swig_typemap_new_scope(0); - if (name) { - if (Cmp(name,"native") == 0) { - int oldnative = Native; - Native = 1; - Swig_emit_all(c,clientdata); - Native = oldnative; - } else if (Cmp(name,"readonly") == 0) { - int oldro = ReadOnly; - ReadOnly = 1; - Swig_emit_all(c,clientdata); - ReadOnly = oldro; - } else { - Swig_emit_all(c,clientdata); - } - } - Hash *scp = Swig_typemap_pop_scope(); - Setattr(node,"typemaps", scp); - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_insert() - * - * Code insertion with various %{ %} directives. - * ----------------------------------------------------------------------------- */ - -int swig11_insert(DOH *node, void *clientdata) { - String *section; - String *filename; - String *code; - File *out; - - if (WrapExtern) return 0; - - section = Getattr(node,"section"); - if (!section) { - section = (void *) "header"; - } - out = Swig_filebyname(section); - if (!out) { - Printf(stderr,"%s:%d. Can't insert code into unknown section '%s'\n", Getfile(node), Getline(node), section); - return 0; - } - filename = Getattr(node,"filename"); - if (filename) { - /* The user is inserting the contents of a file */ - if (Swig_insert_file(filename,out) < 0) { - Printf(stderr,"%s:%d. File '%s' not found.\n", Getfile(node), Getline(node), filename); - } - return 0; - } - code = Getattr(node,"code"); - if (code) { - Printf(out,"%s",code); - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_pragma() - * - * %pragma directive. - * ----------------------------------------------------------------------------- */ - -int swig11_pragma(DOH *node, void *clientdata) { - String *name; - String *value; - - if (WrapExtern) return 0; - - name = Getname(node); - value = Getvalue(node); - - if (Cmp(name,"readonly") == 0) { - ReadOnly = 1; - } else if (Cmp(name,"readwrite") == 0) { - ReadOnly = 0; - } else if (Cmp(name,"name") == 0) { - new_name = value; - } - lang->pragma(node); - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_typemap() - * - * Handle the %typemap directive. - * ----------------------------------------------------------------------------- */ - -int swig11_typemap(DOH *node, void *clientdata) { - String *name; - SwigType *type; - String *code; - DOH *parms; - String *method; - - if (WrapExtern) return 0; - method = Getattr(node,"method"); - name = Getname(node); - type = Gettype(node); - code = Getattr(node,"code"); - parms = Getparms(node); - - if (current_class) { - class_update_type(type); - class_update_type(parms); - } - - if (code) { - Swig_typemap_register(method,type,name,code,parms); - } else { - String *srcname; - String *srctype; - srcname = Getattr(node,"srcname"); - srctype = Getattr(node,"srctype"); - if (srcname && srctype) { - Swig_typemap_copy(method,srctype,srcname,type,name); - } else { - Swig_typemap_clear(method,type,name); - } - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_apply() - * - * The %apply directive. - * ----------------------------------------------------------------------------- */ - -int swig11_apply(DOH *node, void *clientdata) { - DOH *parms; - String *name; - SwigType *type; - - if (WrapExtern) return 0; - - name = Getname(node); - type = Gettype(node); - parms = Getparms(node); - - while (parms) { - Swig_typemap_apply(type,name,Gettype(parms),Getname(parms)); - parms = Getnext(parms); - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_exception() - * - * The %except directive. - * ----------------------------------------------------------------------------- */ - -int swig11_exception(DOH *node, void *clientdata) { - String *code = Getattr(node,"code"); - if (WrapExtern) return 0; - if (code) { - Swig_except_register(code); - } else { - Swig_except_clear(); - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_clear() - * - * The %clear directive. - * ----------------------------------------------------------------------------- */ - -int swig11_clear(DOH *node, void *clientdata) { - DOH *parms = Getattr(node,"parms"); - if (WrapExtern) return 0; - while (parms) { - Swig_typemap_clear_apply(Gettype(parms),Getname(parms)); - parms = Getnext(parms); - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_constant - * - * The %constant directive - * ----------------------------------------------------------------------------- */ - -int swig11_constant(DOH *node, void *clientdata) { - if (WrapExtern) return 0; - if (Access != PUBLIC) return 0; - - set_scriptname(node); - lang->constant(node); - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_function() - * - * Emit a wrapper function. - * ----------------------------------------------------------------------------- */ - -int swig11_function(DOH *node, void *clientdata) { - int is_static; - if (WrapExtern) return 0; - if (Access != PUBLIC) return 0; - - is_static = check_static(node); - set_scriptname(node); - - /* Will need some kind of class check in here */ - - if (current_class) { - /* Function has been declared inside a class definition. */ - class_update_parms(Getparms(node)); - class_update_type(Gettype(node)); - String *name = Getname(node); - if (Cmp(name,construct_name) == 0) { - have_constructor =1; - if (!Abstract) { - lang->cpp_constructor(node); - } - } else { - if (is_static) lang->cpp_staticfunction(node); - else lang->cpp_memberfunction(node); - } - } else { - - /* Can't wrap a static function. Oh well. */ - if (is_static) return 0; - emit_extern_func(node,f_header); - - if (Native) { - lang->nativefunction(node); - } else { - lang->function(node); - } - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_variable() - * - * Wrap a variable. - * ----------------------------------------------------------------------------- */ - -int swig11_variable(DOH *node, void *clientdata) { - int is_static; - SwigType *type; - - if (WrapExtern) return 0; - if (Access != PUBLIC) return 0; - - if (Native) { - Printf(stderr,"%s:%d. Can't wrap variables in %%native mode (ignored).\n", Getfile(node),Getline(node)); - return 0; - } - - type = Gettype(node); - - is_static = check_static(node); - set_scriptname(node); - - if (current_class) { - /* Inside a class definition */ - if (is_static) { - lang->cpp_staticvariable(node); - } else { - lang->cpp_variable(node); - } - } else { - if (check_extern(node)) { - Printf(f_header,"extern %s;\n", SwigType_str(type, Getname(node))); - } - if (is_static) return 0; - - if (SwigType_isconst(type)) { - swig11_constant(node,clientdata); - } else { - lang->variable(node); - } - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_typedef() - * - * Handle a typedef declaration. - * ----------------------------------------------------------------------------- */ - -int swig11_typedef(DOH *node, void *clientdata) { - String *name; - SwigType *type; - - type = Gettype(node); - name = Getname(node); - SwigType_typedef(type,name); - - if (current_class) { - class_addtype(name,0); - } - lang->add_typedef(type, Char(name)); - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_enum() - * - * Support for enumerations. - * ----------------------------------------------------------------------------- */ - -int swig11_enum(DOH *node, void *clientdata) { - DOH *c; - String *name; - if (WrapExtern) return 0; - if (Access != PUBLIC) return 0; - - name = Getname(node); - if (name && CPlusPlus) { - /* Add a typedef */ - String *t = NewStringf("enum %s", name); - SwigType_typedef(t,name); - class_addtype(name,0); - Delete(t); - } - c = Getchild(node); - Swig_emit_all(c,clientdata); - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_enumvalue() - * - * Create a constant corresponding to an enum value. - * ----------------------------------------------------------------------------- */ -int swig11_enumvalue(DOH *node, void *clientdata) { - set_scriptname(node); - Setattr(node,"type","int"); /* Enums wrapped as ints */ - if (!Getvalue(node)) { /* If no value, use the name itself */ - if (class_name) { - Setvalue(node,NewStringf("%s::%s",class_name, Getname(node))); - } else { - Setvalue(node,Getname(node)); - } - } - if (current_class) { - lang->cpp_constant(node); - } else { - swig11_constant(node,clientdata); - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_class() - * - * Wrapping of C++ classes - * ----------------------------------------------------------------------------- */ - -int swig11_class(DOH *node, void *clientdata) { - DOH *c; - List *bases; - - /* Save the class */ - String *name = Getname(node); - Setattr(class_hash,name,node); - if (WrapExtern) return 0; - - if (Native) { - Printf(stderr,"%s:%d. Can't wrap structures or classes in %%native mode (ignored).\n", Getfile(node),Getline(node)); - return 0; - } - - set_scriptname(node); - class_name = name; - class_types = 0; - - have_destructor = 0; - have_constructor = 0; - - /* Need to merge in data from other scopes. For typemaps, can include scopes - for each base class one after the other. For types, need to merge type information */ - - SwigType_new_scope(); - if (name) { - SwigType_set_scope_name(name); - } - - cplus_walk_inherit(node, inherit_types, 0); - - /* Merge in typemaps */ - cplus_walk_inherit(node, inherit_typemaps, 0); - - /* Create a typemap scope for this class */ - Swig_typemap_new_scope(0); - - cplus_build_symbols(node); - lang->cpp_open_class(node); - current_class = node; - - construct_name = Getname(node); - if (!CPlusPlus) { - String *altname = Getattr(node,"altname"); - if (altname) construct_name = altname; - } - - c = Getchild(node); - Abstract = cplus_check_abstract(c); - - Swig_emit_all(c,clientdata); - - bases = Getattr(node,"bases"); - if (bases) { - String *b; - lang->cpp_inherit(bases); - b = Firstitem(bases); - while (b) { - SwigType_inherit(Getname(current_class),b); - b = Nextitem(bases); - } - } - - /* Check for constructors and destructors */ - - if (CPlusPlus) { - if (!have_constructor && !Abstract) { - DOH *cn = NewHash(); - Setname(cn, Getname(current_class)); - Setattr(cn,"scriptname", Getname(current_class)); - lang->cpp_constructor(cn); - } - if (!have_destructor) { - DOH *dn = NewHash(); - Setname(dn, Getname(current_class)); - Setattr(dn,"scriptname", Getname(current_class)); - lang->cpp_destructor(dn); - } - } - - lang->cpp_close_class(); - - /* Pop the type scope and save with the class */ - - Hash *scp = SwigType_pop_scope(); - Setattr(node,"types",scp); - - scp = Swig_typemap_pop_scope(); - Setattr(node,"typemaps",scp); - Setattr(node,"classtypes",class_types); - - /* Pop off all of the typemap scopes we added */ - cplus_walk_inherit(node,inherit_typemaps, (void *) 1); - - current_class = 0; - construct_name = 0; - class_name = 0; - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_classdecl() - * - * Empty class declaration. Used to register classes with language modules. - * ----------------------------------------------------------------------------- */ - -int swig11_classdecl(DOH *node, void *clientdata) { - if (WrapExtern) return 0; - set_scriptname(node); - - lang->cpp_class_decl(node); - return 0; -} - -int swig11_addmethods(DOH *node, void *clientdata) { - DOH *c; - int oldaddmethods = AddMethods; - if (WrapExtern) return 0; - if (!current_class) { - Printf(stderr,"%s:%d. %%addmethods ignored (does not appear inside a class).\n", Getfile(node),Getline(node)); - return 0; - } - AddMethods = 1; - c = Getchild(node); - Swig_emit_all(c,clientdata); - AddMethods = oldaddmethods;; - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_destructor() - * - * C++ Destructor - * ----------------------------------------------------------------------------- */ - -int swig11_destructor(DOH *node, void *clientdata) { - if (WrapExtern) return 0; - if (Access != PUBLIC) return 0; - if (!current_class) return 0; - - set_scriptname(node); - lang->cpp_destructor(node); - have_destructor = 1; - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_access() - * - * Handle an access specifier (public, private, protected) - * ----------------------------------------------------------------------------- */ - -int swig11_access(DOH *node, void *clientdata) { - String *name = Getname(node); - if (Cmp(name,"public") == 0) Access = PUBLIC; - else if (Cmp(name,"private") == 0) Access = PRIVATE; - else if (Cmp(name,"protected") == 0) Access = PROTECTED; - return 0; -} - -/* ----------------------------------------------------------------------------- - * swig11_types() - * - * Handle the types directive. - * ----------------------------------------------------------------------------- */ - -int swig11_types(DOH *node, void *clientdata) { - Parm *p; - p = Getparms(node); - while (p) { - SwigType *t = Gettype(p); - SwigType_remember(t); - p = Getnext(p); - } - return 0; -} - -static SwigRule rules[] = { - { "file", swig11_file}, - { "scope", swig11_scope}, - { "insert", swig11_insert}, - { "pragma", swig11_pragma}, - { "typemap", swig11_typemap}, - { "apply", swig11_apply}, - { "exception", swig11_exception}, - { "clear", swig11_clear}, - { "addmethods", swig11_addmethods}, - { "constant", swig11_constant}, - { "function", swig11_function}, - { "variable", swig11_variable}, - { "typedef", swig11_typedef}, - { "enum", swig11_enum}, - { "enumvalue", swig11_enumvalue}, - { "class", swig11_class}, - { "classdecl", swig11_classdecl}, - { "destructor", swig11_destructor}, - { "access", swig11_access}, - { "types", swig11_types}, - { "module", swig11_nil}, - { "*", swig11_unknown}, - { 0 } -}; - -} - -/* ----------------------------------------------------------------------------- - * generate() - * - * Called by the SWIG1.1 system to emit code - * ----------------------------------------------------------------------------- */ - -void generate(DOH *node) { - DOH *c; - extern String *swig_module; - - /* Initialize globals */ - class_hash = NewHash(); - - Swig_add_rules(rules); - c = Getattr(node,"child"); - - /* Find the module name */ - if (!swig_module) { - swig_module = find_module(c); - } - if (!swig_module) { - Printf(stderr,"SWIG: No module name specified! Please use %%module or -module.\n"); - Swig_exit(EXIT_FAILURE); - } - - lang->initialize(swig_module); - Swig_emit_all(c,0); - lang->close(); - - /* Swig_dump_tags(node,0); */ - -} - - diff --git a/Source/Modules1.1/guile.cxx b/Source/Modules1.1/guile.cxx index 18d59f5b8..a6b53b536 100644 --- a/Source/Modules1.1/guile.cxx +++ b/Source/Modules1.1/guile.cxx @@ -13,7 +13,7 @@ * can be used and distributed. *****************************************************************************/ -static char cvsroot[] = "$Header$"; +char cvsroot_guile_cxx[] = "$Header$"; /*********************************************************************** * $Header$ @@ -23,895 +23,1186 @@ static char cvsroot[] = "$Header$"; * Definitions for adding functions to Guile ***********************************************************************/ -#include "swig11.h" -#include "guile.h" +#include "swigmod.h" -static char *guile_usage = (char*)"\ +#ifndef MACSWIG +#include "swigconfig.h" +#endif +#include <ctype.h> + +static const char *guile_usage = (char*)"\ Guile Options (available with -guile)\n\ - -module name - Set base name of module\n\ + -ldflags - Print runtime libraries to link with\n\ -prefix name - Use NAME as prefix [default \"gswig_\"]\n\ -package name - Set the path of the module [default NULL]\n\ - -Linkage lstyle - Use linkage protocol LSTYLE [default `ltdlmod']\n\ - -procdoc file - Output procedure documentation to file\n\ -\n\ - The module option does not create a guile module with a separate name\n\ - space. It specifies the name of the initialization function and is\n\ - called a module here so that it is compadible with the rest of SWIG.\n\ + -emit-setters - Emit procedures-with-setters for variables\n\ + and structure slots.\n\ + -linkage lstyle - Use linkage protocol LSTYLE [default `module']\n\ + -procdoc file - Output procedure documentation to FILE\n\ + -procdocformat format - Output procedure documentation in FORMAT;\n\ + one of `guile-1.4', `plain', `texinfo'\n\ + -scmstub file - Output Scheme FILE with module declaration and\n\ + exports; only with `passive' and `simple' linkage\n\ \n\ - When unspecified, the default LSTYLE is `ltdlmod' for libtool ltdl\n\ - modules. Other LSTYLE values are: `hobbit' for hobbit modules.\n\ + When unspecified, the default LSTYLE is `simple'. For native Guile\n\ + module linking (for Guile versions >=1.5.0), use `module'. Other\n\ + LSTYLE values are: `passive' for passive linking (no C-level\n\ + module-handling code), `ltdlmod' for Guile's old dynamic module\n\ + convention (versions <= 1.4), or `hobbit' for hobbit modules.\n\ \n"; -// --------------------------------------------------------------------- -// GUILE () -// --------------------------------------------------------------------- +static File *f_runtime = 0; +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; -GUILE::GUILE () -{ - // Set class vars +static char *prefix = (char *) "gswig_"; +static char *module = 0; +static char *package = 0; +static enum { + GUILE_LSTYLE_SIMPLE, // call `SWIG_init()' + GUILE_LSTYLE_PASSIVE, // passive linking (no module code) + GUILE_LSTYLE_MODULE, // native guile module linking (Guile >= 1.4.1) + GUILE_LSTYLE_LTDLMOD_1_4, // old (Guile <= 1.4) dynamic module convention + GUILE_LSTYLE_HOBBIT // use (hobbit4d link) +} linkage = GUILE_LSTYLE_SIMPLE; - prefix = (char*)"gswig_"; - module = NULL; - package = NULL; - linkage = GUILE_LSTYLE_SIMPLE; - procdoc = NULL; - emit_setters = 0; - struct_member = 0; -} +static File *procdoc = 0; +static File *scmstub = 0; +static String *scmtext; + +static enum { + GUILE_1_4, + PLAIN, + TEXINFO +} docformat = GUILE_1_4; + +static int emit_setters = 0; +static int struct_member = 0; + +static String *beforereturn = 0; +static String *return_nothing_doc = 0; +static String *return_one_doc = 0; +static String *return_multi_doc = 0; + +static String *exported_symbols = 0; -// --------------------------------------------------------------------- -// GUILE::parse_args(int argc, char *argv[]) -// -// Parse arguments. -// --------------------------------------------------------------------- +class GUILE : public Language { +public: -void -GUILE::parse_args (int argc, char *argv[]) -{ - int i, orig_len; + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ - Swig_swiglib_set("guile"); + virtual void main (int argc, char *argv[]) { + int i, orig_len; + + SWIG_library_directory("guile"); + SWIG_typemap_lang("guile"); // Look for certain command line options - for (i = 1; i < argc; i++) { - if (argv[i]) { - if (strcmp (argv[i], "-help") == 0) { - fputs (guile_usage, stderr); - Swig_exit (EXIT_SUCCESS); - } - else if (strcmp (argv[i], "-prefix") == 0) { - if (argv[i + 1]) { - prefix = new char[strlen (argv[i + 1]) + 2]; - strcpy (prefix, argv[i + 1]); - Swig_mark_arg (i); - Swig_mark_arg (i + 1); - i++; - } else { - Swig_arg_error(); + for (i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp (argv[i], "-help") == 0) { + fputs (guile_usage, stderr); + SWIG_exit (EXIT_SUCCESS); } - } - else if (strcmp (argv[i], "-package") == 0) { - if (argv[i + 1]) { - package = new char[strlen (argv[i + 1]) + 2]; - strcpy (package, argv [i + 1]); - Swig_mark_arg (i); - Swig_mark_arg (i + 1); + else if (strcmp (argv[i], "-prefix") == 0) { + if (argv[i + 1]) { + prefix = new char[strlen (argv[i + 1]) + 2]; + strcpy (prefix, argv[i + 1]); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + else if (strcmp (argv[i], "-package") == 0) { + if (argv[i + 1]) { + package = new char[strlen (argv[i + 1]) + 2]; + strcpy (package, argv [i + 1]); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_GUILE_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } + else if (strcmp (argv[i], "-Linkage") == 0 + || strcmp (argv[i], "-linkage") == 0) { + if (argv[i + 1]) { + if (0 == strcmp (argv[i + 1], "ltdlmod")) + linkage = GUILE_LSTYLE_LTDLMOD_1_4; + else if (0 == strcmp (argv[i + 1], "hobbit")) + linkage = GUILE_LSTYLE_HOBBIT; + else if (0 == strcmp (argv[i + 1], "simple")) + linkage = GUILE_LSTYLE_SIMPLE; + else if (0 == strcmp (argv[i + 1], "passive")) + linkage = GUILE_LSTYLE_PASSIVE; + else if (0 == strcmp (argv[i + 1], "module")) + linkage = GUILE_LSTYLE_MODULE; + else + Swig_arg_error (); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + else if (strcmp (argv[i], "-procdoc") == 0) { + if (argv[i + 1]) { + procdoc = NewFile(argv[i + 1], (char *) "w"); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + else if (strcmp (argv[i], "-procdocformat") == 0) { + if (strcmp(argv[i+1], "guile-1.4") == 0) + docformat = GUILE_1_4; + else if (strcmp(argv[i+1], "plain") == 0) + docformat = PLAIN; + else if (strcmp(argv[i+1], "texinfo") == 0) + docformat = TEXINFO; + else Swig_arg_error(); + Swig_mark_arg(i); + Swig_mark_arg(i+1); i++; - } else { - Swig_arg_error(); } - } - /* Bogus upcase requirement due to top-level parsing not respecting - language specification. Top-level should stop when it sees "-guile" - or other languages. */ - else if (strcmp (argv[i], "-Linkage") == 0) { - if (argv[i + 1]) { - if (0 == strcmp (argv[i + 1], "ltdlmod")) - linkage = GUILE_LSTYLE_LTDLMOD; - else if (0 == strcmp (argv[i + 1], "hobbit")) - linkage = GUILE_LSTYLE_HOBBIT; - else - Swig_arg_error (); - Swig_mark_arg (i); - Swig_mark_arg (i + 1); - i++; - } else { - Swig_arg_error(); - } - } - else if (strcmp (argv[i], "-procdoc") == 0) { - if (argv[i + 1]) { - procdoc = NewFile(argv[i + 1], "w"); + else if (strcmp (argv[i], "-emit-setters") == 0) { + emit_setters = 1; Swig_mark_arg (i); - Swig_mark_arg (i + 1); - i++; - } else { - Swig_arg_error(); - } - } - else if (strcmp (argv[i], "-emit-setters") == 0) { - emit_setters = 1; - Swig_mark_arg (i); + } + else if (strcmp (argv[i], "-scmstub") == 0) { + if (argv[i + 1]) { + scmstub = NewFile(argv[i + 1], (char *) "w"); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } } } - } - - // Make sure `prefix' ends in an underscore - - orig_len = strlen (prefix); - if (prefix[orig_len - 1] != '_') { - prefix[1 + orig_len] = 0; - prefix[orig_len] = '_'; - } - /* Add a symbol for this module */ - Preprocessor_define ((void *) "SWIGGUILE",0); + // Make sure `prefix' ends in an underscore - /* Read in default typemaps */ - Swig_set_config_file("guile.i"); -} - -// -------------------------------------------------------------------- -// GUILE::initialize() -// -// Output initialization code that registers functions with the -// interface. -// --------------------------------------------------------------------- - -void -GUILE::initialize (String *modname) -{ - printf ("Generating wrappers for Guile\n"); - - Printf(f_runtime, "/* -*- buffer-read-only: t -*- vi: set ro: */\n"); - Swig_banner (f_runtime); - - Printf (f_runtime, "/* Implementation : GUILE */\n\n"); - - // Write out directives and declarations - - if (NoInclude) { - Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); - } + orig_len = strlen (prefix); + if (prefix[orig_len - 1] != '_') { + prefix[1 + orig_len] = 0; + prefix[orig_len] = '_'; + } - if (!module) { - module = new char[Len(modname)+1]; - strcpy(module, Char(modname)); + /* Add a symbol for this module */ + Preprocessor_define ("SWIGGUILE 1",0); + /* Read in default typemaps */ + SWIG_config_file("guile.i"); + allow_overloading(); + } - switch (linkage) { - case GUILE_LSTYLE_SIMPLE: - /* Simple linkage; we have to export the SWIG_init function. The user can - rename the function by a #define. */ - Printf (f_runtime, "extern void\nSWIG_init (void)\n;\n"); - Printf (f_init, "extern void\nSWIG_init (void)\n{\n"); - break; - default: - /* Other linkage; we make the SWIG_init function static */ - Printf (f_runtime, "static void\nSWIG_init (void)\n;\n"); - Printf (f_init, "static void\nSWIG_init (void)\n{\n"); - break; + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + scmtext = NewString(""); + Swig_register_filebyname("scheme", scmtext); + exported_symbols = NewString(""); + + Printf(f_runtime, "/* -*- buffer-read-only: t -*- vi: set ro: */\n"); + Swig_banner (f_runtime); + + Printf (f_runtime, "/* Implementation : GUILE */\n\n"); + + /* Write out directives and declarations */ + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } + + module = Swig_copy_string(Char(Getattr(n,"name"))); + + if (CPlusPlus) { + Printf(f_runtime, "extern \"C\" {\n\n"); + } + + switch (linkage) { + case GUILE_LSTYLE_SIMPLE: + /* Simple linkage; we have to export the SWIG_init function. The user can + rename the function by a #define. */ + Printf (f_runtime, "extern void\nSWIG_init (void)\n;\n"); + Printf (f_init, "extern void\nSWIG_init (void)\n{\n"); + break; + default: + /* Other linkage; we make the SWIG_init function static */ + Printf (f_runtime, "static void\nSWIG_init (void)\n;\n"); + Printf (f_init, "static void\nSWIG_init (void)\n{\n"); + break; + } + Printf (f_init, "\tSWIG_Guile_Init();\n"); + if (CPlusPlus) { + Printf(f_runtime, "\n}\n"); + } + + Language::top(n); + + /* Close module */ + + Printf(f_wrappers,"#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); + + SwigType_emit_type_table (f_runtime, f_wrappers); + + Printf(f_wrappers,"#ifdef __cplusplus\n}\n#endif\n"); + + Printf (f_init, "SWIG_Guile_RegisterTypes(swig_types, swig_types_initial);\n"); + Printf (f_init, "}\n\n"); + char module_name[256]; + + if (!module) + sprintf(module_name, "swig"); + else { + if (package) + sprintf(module_name,"%s/%s", package,module); + else + strcpy(module_name,module); + } + emit_linkage (module_name); + + if (procdoc) { + Delete(procdoc); + procdoc = NULL; + } + if (scmstub) { + Delete(scmstub); + scmstub = NULL; + } + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; } - Printf (f_init, "\tSWIG_Guile_Init();\n"); -} - -void -GUILE::emit_linkage (char *module_name) -{ - DOHString *module_func = NewString(""); - - Printv(module_func,module_name,0); - Replace(module_func,"-", "_", DOH_REPLACE_ANY); - - switch (linkage) { - case GUILE_LSTYLE_SIMPLE: - Printf (f_init, "\n/* Linkage: simple */\n"); - break; - case GUILE_LSTYLE_LTDLMOD: - Printf (f_init, "\n/* Linkage: ltdlmod */\n"); - Replace(module_func,"/", "_", DOH_REPLACE_ANY); - Insert(module_func,0, "scm_init_"); - Append(module_func,"_module"); - Printf (f_init, "SCM\n%s (void)\n{\n", module_func); - { - DOHString *mod = NewString(module_name); - Replace(mod,"/", " ", DOH_REPLACE_ANY); - Printf (f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", - mod); - Printf (f_init, " return SCM_UNSPECIFIED;\n"); - Delete(mod); + + void emit_linkage (char *module_name) { + String *module_func = NewString(""); + + if (CPlusPlus) { + Printf(f_init, "extern \"C\" {\n\n"); } - Printf (f_init, "}\n"); - break; - case GUILE_LSTYLE_HOBBIT: - Printf (f_init, "\n/* Linkage: hobbit */\n"); - Replace(module_func,"/", "_slash_", DOH_REPLACE_ANY); - Insert(module_func,0, "scm_init_"); - Printf (f_init, "SCM\n%s (void)\n{\n", module_func); - { - DOHString *mod = NewString(module_name); - Replace(mod,"/", " ", DOH_REPLACE_ANY); - Printf (f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", - mod); - Printf (f_init, " return SCM_UNSPECIFIED;\n"); + + Printv(module_func,module_name,NIL); + Replaceall(module_func,"-", "_"); + + switch (linkage) { + case GUILE_LSTYLE_SIMPLE: + Printf (f_init, "\n/* Linkage: simple */\n"); + break; + case GUILE_LSTYLE_PASSIVE: + Printf (f_init, "\n/* Linkage: passive */\n"); + Replaceall(module_func,"/", "_"); + Insert(module_func,0, "scm_init_"); + Append(module_func,"_module"); + + Printf (f_init, "SCM\n%s (void)\n{\n", module_func); + Printf (f_init, " SWIG_init();\n"); + Printf (f_init, " return SCM_UNSPECIFIED;\n"); + Printf (f_init, "}\n"); + break; + case GUILE_LSTYLE_LTDLMOD_1_4: + Printf (f_init, "\n/* Linkage: ltdlmod */\n"); + Replaceall(module_func,"/", "_"); + Insert(module_func,0, "scm_init_"); + Append(module_func,"_module"); + Printf (f_init, "SCM\n%s (void)\n{\n", module_func); + { + String *mod = NewString(module_name); + Replaceall(mod,"/", " "); + Printf (f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", + mod); + Printf (f_init, " return SCM_UNSPECIFIED;\n"); + Delete(mod); + } + Printf (f_init, "}\n"); + break; + case GUILE_LSTYLE_MODULE: + Printf (f_init, "\n/* Linkage: module */\n"); + Replaceall(module_func,"/", "_"); + Insert(module_func,0, "scm_init_"); + Append(module_func,"_module"); + + Printf (f_init, "static void SWIG_init_helper(void *data)\n"); + Printf (f_init, "{\n SWIG_init();\n"); + if (Len(exported_symbols) > 0) + Printf (f_init, " scm_c_export(%sNULL);", + exported_symbols); + Printf (f_init, "\n}\n\n"); + + Printf (f_init, "SCM\n%s (void)\n{\n", module_func); + { + String *mod = NewString(module_name); + Replaceall(mod,"/", " "); + Printf(f_init, " SCM module = scm_c_define_module(\"%s\",\n", mod); + Printf(f_init, " SWIG_init_helper, NULL);\n"); + Printf(f_init, " return SCM_UNSPECIFIED;\n"); + Delete(mod); + } + Printf (f_init, "}\n"); + break; + case GUILE_LSTYLE_HOBBIT: + Printf (f_init, "\n/* Linkage: hobbit */\n"); + Replaceall(module_func,"/", "_slash_"); + Insert(module_func,0, "scm_init_"); + Printf (f_init, "SCM\n%s (void)\n{\n", module_func); + { + String *mod = NewString(module_name); + Replaceall(mod,"/", " "); + Printf (f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", + mod); + Printf (f_init, " return SCM_UNSPECIFIED;\n"); + Delete(mod); + } + Printf (f_init, "}\n"); + break; + default: + abort(); // for now + } + + if (scmstub) { + /* Emit Scheme stub if requested */ + String *mod = NewString(module_name); + Replaceall(mod, "/", " "); + Printf (scmstub, ";;; -*- buffer-read-only: t -*- vi: set ro: */\n"); + Printf (scmstub, ";;; Automatically generated by SWIG; do not edit.\n\n"); + if (linkage == GUILE_LSTYLE_SIMPLE + || linkage == GUILE_LSTYLE_PASSIVE) + Printf (scmstub, "(define-module (%s))\n\n", mod); Delete(mod); + Printf (scmstub, "%s", scmtext); + if ((linkage == GUILE_LSTYLE_SIMPLE + || linkage == GUILE_LSTYLE_PASSIVE) + && Len(exported_symbols) > 0) { + String *ex = NewString(exported_symbols); + Replaceall(ex, ", ", "\n "); + Replaceall(ex, "\"", ""); + Chop(ex); + Printf(scmstub, "\n(export %s)\n", ex); + Delete(ex); + } + } + + Delete(module_func); + if (CPlusPlus) { + Printf(f_init, "\n}\n"); } - Printf (f_init, "}\n"); - break; - default: - abort(); // for now - } - Delete(module_func); -} - -// --------------------------------------------------------------------- -// GUILE::close(void) -// -// Wrap things up. Close initialization function. -// --------------------------------------------------------------------- - -void -GUILE::close (void) -{ - SwigType_emit_type_table (f_runtime, f_wrappers); - - Printf (f_init, "SWIG_Guile_RegisterTypes(swig_types);\n"); - Printf (f_init, "}\n\n"); - char module_name[256]; - - if (!module) - sprintf(module_name, "swig"); - else { - if (package) - sprintf(module_name,"%s/%s", package,module); - else - strcpy(module_name,module); - } - emit_linkage (module_name); - - if (procdoc) { - Delete(procdoc); - procdoc = NULL; } -} - -// ---------------------------------------------------------------------- -// get_pointer() -// -// Emits code to get a pointer from a parameter and do type checking. -// parm is the parameter number. This function is only used -// in create_function(). -// ---------------------------------------------------------------------- - -static void -get_pointer (char *iname, int parm, SwigType *t, - Wrapper *f, DOHString_or_char *proc_name, - int num_scheme_parm) -{ - SwigType_remember(t); - /* Pointers are smobs */ - Printf(f, " if (SWIG_Guile_GetPtr(s_%d,(void **) &arg%d", parm, parm); - if (SwigType_type(t) == T_VOID) - Printf(f, ", NULL)) {\n"); - else - Printv(f, ", SWIGTYPE", SwigType_manglestr(t), ")) {\n", 0); - /* Raise exception */ - Printv(f, - tab8, - "scm_wrong_type_arg(\"",proc_name, "\", ", - 0); - Printf(f,"%d, s_%d);\n", num_scheme_parm, parm); - Printv(f, tab4, "}\n", 0); -} -/* Return true iff T is a pointer type */ + /* Return true iff T is a pointer type */ -static int -is_a_pointer (SwigType *t) -{ - return SwigType_ispointer(SwigType_typedef_resolve_all(t)); -} - -/* Same as Swig_typemap_lookup but fall back to `int' when `enum' is - requested -- enum handling is somewhat broken in the 1.1 parser. - But we don't want to change it now since it is deprecated. */ - -static char * -guile_typemap_lookup(const char *op, SwigType *type, const String_or_char *pname, String_or_char *source, - String_or_char *target, Wrapper *f) -{ - char *tm; - tm = Swig_typemap_lookup((char*) op, type, (char*)pname, source, target, f); - if (!tm) { - SwigType *base = SwigType_typedef_resolve_all(type); - if (strncmp(Char(base), "enum ", 5)==0) - tm = Swig_typemap_lookup((char*) op, (char*) "int", (char*)pname, source, target, f); + int is_a_pointer (SwigType *t) { + return SwigType_ispointer(SwigType_typedef_resolve_all(t)); } - return tm; -} -/* Lookup a typemap, replace all relevant parameters and write it to - the given generalized file. Return 0 if no typemap found. */ - -static int -guile_do_typemap(DOHFile *file, const char *op, - SwigType *type, const String_or_char *arg, - String_or_char *source, String_or_char *target, - int argnum, DOHString *name, Wrapper *f, - int nonewline_p) -{ - char *tm; - if ((tm = guile_typemap_lookup(op, type, arg, - source, target, f))) { - String *s = NewString(tm); - char argnum_s[10]; - sprintf(argnum_s, "%d", argnum); - Replace(s,"$argnum", argnum_s, DOH_REPLACE_ANY); - Replace(s,"$arg", arg, DOH_REPLACE_ANY); - Replace(s,"$name", name, DOH_REPLACE_ANY); - if (nonewline_p) - Printv(file, s, 0); - else Printv(file, s, "\n", 0); - Delete(s); - return 1; - } - else return 0; -} + /* Report an error handling the given type. */ -/* Lookup a documentation typemap, replace all relevant parameters and - write it to the given generalized file, providing a sensible - default value. */ - -static void -guile_do_doc_typemap(DOHFile *file, const char *op, - SwigType *type, const String_or_char *arg, - int argnum, DOHString *name, Wrapper *f) -{ - if (!guile_do_typemap(file, op, type, arg, - NULL, NULL, argnum, name, f, 1)) { - /* FIXME: Can't we provide this default via a typemap as well? */ - String *s = NewString(SwigType_str(type, 0)); - Chop(s); - if (arg) Printf(file, "(%s <%s>)", arg, s); - else Printf(file, "<%s>", s); - Delete(s); + void throw_unhandled_guile_type_error (SwigType *d) { + Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, + "Unable to handle type %s.\n", SwigType_str(d,0)); } -} - -/* Report an error handling the given type. */ - -static void -throw_unhandled_guile_type_error (SwigType *d) -{ - Printf (stderr, "%s:%d. Unable to handle type %s.\n",Getfile(d), Getline(d), SwigType_str(d,0)); -} - -// ---------------------------------------------------------------------- -// GUILE::create_function() -// Create a function declaration and register it with the interpreter. -// ---------------------------------------------------------------------- - -void -GUILE::function (DOH *node) { - char *name, *iname; - SwigType *d; - ParmList *l; - Parm *p; - DOHString *proc_name = 0; - char source[256], target[256]; - Wrapper *f = NewWrapper();; - String *cleanup = NewString(""); - String *outarg = NewString(""); - String *signature = NewString(""); - String *returns = NewString(""); - int returns_list = 0; - String *tmp = NewString(""); - int i; - int numargs = 0; - int numopt = 0; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - d = Getattr(node,"type"); - l = Getattr(node,"parms"); - - // Make a wrapper name for this - char * wname = new char [strlen (prefix) + strlen (iname) + 2]; - sprintf (wname, "%s%s", prefix, iname); - - // Build the name for scheme. - proc_name = NewString(iname); - Replace(proc_name,"_", "-", DOH_REPLACE_ANY); - - /* Emit locals etc. into f; figure out which args to ignore */ - emit_args (node, f); - - /* Declare return variable */ - - Wrapper_add_local (f,"gswig_result", "SCM gswig_result"); - - if (procdoc) - guile_do_doc_typemap(returns, "outdoc", d, NULL, - 0, proc_name, f); - - /* Open prototype and signature */ - /* <DB> The function prototype must be produced first */ - - Printv(f, "static SCM\n", wname," (", 0); - for (p = l, i = 0; p; p = Getnext(p), i++) { - if (i != 0) Printf(f,", "); - Printf(f,"SCM s_%d", i); + /* Write out procedure documentation */ + + void write_doc(const String *proc_name, + const String *signature, + const String *doc, + const String *signature2 = NULL) { + switch (docformat) { + case GUILE_1_4: + Printv(procdoc, "\f\n", NIL); + Printv(procdoc, "(", signature, ")\n", NIL); + if (signature2) + Printv(procdoc, "(", signature2, ")\n", NIL); + Printv(procdoc, doc, "\n", NIL); + break; + case PLAIN: + Printv(procdoc, "\f", proc_name, "\n\n", NIL); + Printv(procdoc, "(", signature, ")\n", NIL); + if (signature2) + Printv(procdoc, "(", signature2, ")\n", NIL); + Printv(procdoc, doc, "\n\n", NIL); + break; + case TEXINFO: + Printv(procdoc, "\f", proc_name, "\n", NIL); + Printv(procdoc, "@deffn primitive ", signature, "\n", NIL); + if (signature2) + Printv(procdoc, "@deffnx primitive ", signature2, "\n", NIL); + Printv(procdoc, doc, "\n", NIL); + Printv(procdoc, "@end deffn\n\n", NIL); + break; + } } - Printf(f,")\n{\n"); - - /* Define the scheme name in C. This define is used by several Guile - macros. */ - - Printv(f,"#define FUNC_NAME \"", proc_name, "\"\n", 0); - - Printv(signature, "(", proc_name, 0); - /* Now write code to extract the parameters */ - - for (p = l, i = 0; p; p=Getnext(p), i++) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - int opt_p = (Getvalue(p) - || Swig_typemap_search((char*)"default",pt,pn)); - // Produce names of source and target - sprintf(source,"s_%d",i); - sprintf(target,"%s", Char(Getlname(p))); - - // Handle parameter types. - - if (Getignore(p)) - Printv(f, "/* ", pn, " ignored... */\n", 0); - else { - if (opt_p) { - numopt++; - Printf(f," if (s_%d != GH_NOT_PASSED) {\n", i); - } - ++numargs; - if (guile_do_typemap(f, "in", pt, pn, - source, target, numargs, proc_name, f, 0)) { - /* nothing to do */ + /* returns false if the typemap is an empty string */ + bool handle_documentation_typemap(String *output, + const String *maybe_delimiter, + Parm *p, + const String *typemap, + const String *default_doc) + { + String *tmp = NewString(""); + String *tm; + if (!(tm = Getattr(p, typemap))) { + Printf(tmp, "%s", default_doc); + tm = tmp; + } + bool result = (Len(tm) > 0); + if (maybe_delimiter && Len(output) > 0 && Len(tm) > 0) { + Printv(output, maybe_delimiter, NIL); + } + String *pn = Getattr(p,"name"); + String *pt = Getattr(p,"type"); + Replaceall(tm, "$name", pn); // legacy for $parmname + Replaceall(tm, "$type", SwigType_str(pt,0)); + /* $NAME is like $name, but marked-up as a variable. */ + String *ARGNAME = NewString(""); + if (docformat == TEXINFO) + Printf(ARGNAME, "@var{%s}", pn); + else Printf(ARGNAME, "%(upper)s", pn); + Replaceall(tm, "$NAME", ARGNAME); + Replaceall(tm, "$PARMNAME", ARGNAME); + Printv(output,tm,NIL); + Delete(tmp); + return result; + } + + /* ------------------------------------------------------------ + * functionWrapper() + * Create a function declaration and register it with the interpreter. + * ------------------------------------------------------------ */ + + virtual int functionWrapper(Node *n) { + String *iname = Getattr(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + Parm *p; + String *proc_name = 0; + char source[256], target[256]; + Wrapper *f = NewWrapper();; + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *signature = NewString(""); + String *doc_body = NewString(""); + String *returns = NewString(""); + int num_results = 1; + String *tmp = NewString(""); + String *tm; + int i; + int numargs = 0; + int numreq = 0; + String *overname = 0; + int args_passed_as_array = 0; + + // Make a wrapper name for this + String *wname = Swig_name_wrapper(iname); + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + args_passed_as_array = 1; + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; + } + if (overname) { + Append(wname, overname); + } + Setattr(n,"wrap:name",wname); + + // Build the name for scheme. + proc_name = NewString(iname); + Replaceall(proc_name,"_", "-"); + + /* Emit locals etc. into f->code; figure out which args to ignore */ + emit_args (d, l, f); + + /* Attach the standard typemaps */ + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + + /* Get number of required and total arguments */ + numargs = emit_num_arguments(l); + numreq = emit_num_required(l); + + /* Declare return variable */ + + Wrapper_add_local (f,"gswig_result", "SCM gswig_result"); + Wrapper_add_local (f,"gswig_list_p", "int gswig_list_p = 0"); + + /* Get the output typemap so we can start generating documentation. Don't + worry, the returned string is saved as 'tmap:out' */ + + Swig_typemap_lookup_new("out",n,"result",0); + + if ((tm = Getattr(n,"tmap:out:doc"))) { + Printv(returns,tm,NIL); + if (Len(tm) > 0) num_results = 1; + else num_results = 0; + } else { + String *s = SwigType_str(d,0); + Chop(s); + Printf(returns,"<%s>",s); + Delete(s); + num_results = 1; + } + + /* Open prototype and signature */ + + Printv(f->def, "static SCM\n", wname," (", NIL); + if (args_passed_as_array) { + Printv(f->def, "int argc, SCM *argv", NIL); + } + Printv(signature, proc_name, NIL); + + /* Now write code to extract the parameters */ + + for (i = 0, p = l; i < numargs; i++) { + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); } - else if (is_a_pointer(pt)) { - get_pointer (iname, i, pt, f, proc_name, numargs); + + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); + int opt_p = (i >= numreq); + + // Produce names of source and target + if (args_passed_as_array) + sprintf(source, "argv[%d]", i); + else + sprintf(source,"s_%d",i); + sprintf(target,"%s", Char(ln)); + + if (!args_passed_as_array) { + if (i!=0) Printf(f->def,", "); + Printf(f->def,"SCM s_%d", i); } - else { - throw_unhandled_guile_type_error (pt); + if (opt_p) { + Printf(f->code," if (%s != GH_NOT_PASSED) {\n", source); } - if (procdoc) { - /* Add to signature */ - Printf(signature, " "); - guile_do_doc_typemap(signature, "indoc", pt, pn, - numargs, proc_name, f); + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$source",source); + Replaceall(tm,"$target",target); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input", source); + Printv(f->code,tm,"\n",NIL); + + if (procdoc) { + /* Add to signature (arglist) */ + handle_documentation_typemap(signature, " ", p, "tmap:in:arglist", + "$name"); + /* Document the type of the arg in the documentation body */ + handle_documentation_typemap(doc_body, ", ", p, "tmap:in:doc", + "$NAME is of type <$type>"); + } + p = Getattr(p,"tmap:in:next"); + } else { + throw_unhandled_guile_type_error (pt); + p = nextSibling(p); } if (opt_p) - Printf(f," }\n"); + Printf(f->code," }\n"); + } + if (Len(doc_body) > 0) + Printf(doc_body, ".\n"); + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } } - - /* Check if there are any constraints. */ - - guile_do_typemap(f, "check", pt, pn, - source, target, numargs, proc_name, f, 0); - /* Pass output arguments back to the caller. */ - - guile_do_typemap(outarg, "argout", pt, pn, - source, target, numargs, proc_name, f, 0); - - if (procdoc) { - /* Document output arguments */ - Clear(tmp); - if (guile_do_typemap(tmp, "argoutdoc", pt, pn, - source, target, numargs, proc_name, f, 1)) { - if (Len(returns) == 0) { /* unspecified -> singleton */ - Printv(returns, tmp, 0); - } - else { /* append to list */ - Printv(returns, " ", tmp, 0); - returns_list = 1; + + /* Insert argument output code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target",Getattr(p,"lname")); + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + if (procdoc) { + if (handle_documentation_typemap(returns, ", ", + p, "tmap:argout:doc", + "$NAME (of type $type)")) { + /* A documentation typemap that is not the empty string + indicates that a value is returned to Scheme. */ + num_results++; + } } + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); } } - - // free up any memory allocated for the arguments. - - guile_do_typemap(cleanup, "freearg", pt, pn, - source, target, numargs, proc_name, f, 0); - } - - /* Close prototype and signature */ - - Printv(signature, ")\n", 0); - - - // Now write code to make the function call - Printv(f, tab4, "gh_defer_ints();\n", 0); - emit_func_call (node, f); - Printv(f, tab4, "gh_allow_ints();\n", 0); - - // Now have return value, figure out what to do with it. - - if (guile_do_typemap(f, "out", d, name, - (char*)"result", (char*)"gswig_result", - 0, proc_name, f, 0)) { - /* nothing */ - } - else if (is_a_pointer(d)) { - SwigType_remember(d); - Printv(f, tab4, - "gswig_result = SWIG_Guile_MakePtr (", - "result, ", - "SWIGTYPE", SwigType_manglestr(d), - ");\n", - 0); - } - else { - throw_unhandled_guile_type_error (d); - } - - // Dump the argument output code - Printv(f,outarg,0); - - // Dump the argument cleanup code - Printv(f,cleanup,0); - - // Look for any remaining cleanup - - if (NewObject) { - guile_do_typemap(f, "newfree", d, iname, - (char*)"result", (char*)"", 0, proc_name, f, 0); - } - - // Free any memory allocated by the function being wrapped.. - - guile_do_typemap(f, "ret", d, name, - (char*)"result", (char*)"", 0, proc_name, f, 0); - - // Wrap things up (in a manner of speaking) - - Printv(f, "return gswig_result;\n", 0); - - // Undefine the scheme name - - Printf(f, "#undef FUNC_NAME\n"); - Printf(f, "}\n"); - - Printf(f_wrappers,"%s", f); - - if (numargs > 10) { - int i; - /* gh_new_procedure would complain: too many args */ - /* Build a wrapper wrapper */ - Printv(f_wrappers, "static SCM\n", wname,"_rest (SCM rest)\n", 0); - Printv(f_wrappers, "{\n", 0); - Printf(f_wrappers, "SCM arg[%d];\n", numargs); - Printf(f_wrappers, "SWIG_Guile_GetArgs (arg, rest, %d, %d, \"%s\");\n", - numargs-numopt, numopt, proc_name); - Printv(f_wrappers, "return ", wname, "(", 0); - Printv(f_wrappers, "arg[0]", 0); - for (i = 1; i<numargs; i++) - Printf(f_wrappers, ", arg[%d]", i); - Printv(f_wrappers, ");\n", 0); - Printv(f_wrappers, "}\n", 0); - /* Register it */ - Printf (f_init, "gh_new_procedure(\"%s\", %s_rest, 0, 0, 1);\n", - proc_name, wname, numargs-numopt, numopt); - } - else if (emit_setters && struct_member && strlen(Char(proc_name))>3) { - int len = Len(proc_name); - const char *pc = Char(proc_name); - /* MEMBER-set and MEMBER-get functions. */ - int is_setter = (pc[len - 3] == 's'); - if (is_setter) { - Printf(f_init, "SCM setter = "); - struct_member = 2; /* have a setter */ - } - else Printf(f_init, "SCM getter = "); - Printf (f_init, "gh_new_procedure(\"%s\", %s, %d, %d, 0);\n", - proc_name, wname, numargs-numopt, numopt); - if (!is_setter) { - /* Strip off "-get" */ - char *pws_name = (char*) malloc(sizeof(char) * (len - 3)); - strncpy(pws_name, pc, len - 3); - pws_name[len - 4] = 0; - if (struct_member==2) { - /* There was a setter, so create a procedure with setter */ - Printf (f_init, "gh_define(\"%s\", " - "scm_make_procedure_with_setter(getter, setter));\n", - pws_name); - } - else { - /* There was no setter, so make an alias to the getter */ - Printf (f_init, "gh_define(\"%s\", getter);\n", - pws_name); + + /* Insert cleanup code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); } - free(pws_name); - } - } - else { - /* Register the function */ - Printf (f_init, "gh_new_procedure(\"%s\", %s, %d, %d, 0);\n", - proc_name, wname, numargs-numopt, numopt); - } - if (procdoc) { - /* Write out procedure documentation */ - Printv(signature, "Returns ", 0); - if (Len(returns)==0) Printv(signature, "unspecified", 0); - else if (returns_list) Printv(signature, "list (", returns, ")", 0); - else Printv(signature, returns, 0); - Printv(signature, "\n", 0); - Printv(procdoc, "\f\n", signature, 0); - } - - Delete(proc_name); - Delete(outarg); - Delete(cleanup); - Delete(signature); - Delete(returns); - Delete(tmp); - Delete(f); - delete[] wname; -} - -// ----------------------------------------------------------------------- -// GUILE::variable() -// -// Create a link to a C variable. -// This creates a single function PREFIX_var_VARNAME(). -// This function takes a single optional argument. If supplied, it means -// we are setting this variable to some value. If omitted, it means we are -// simply evaluating this variable. Either way, we return the variables -// value. -// ----------------------------------------------------------------------- - -void -GUILE::variable (DOH *node) -{ - char *name, *iname; - SwigType *t; - - DOHString *proc_name; - char var_name[256]; - char *tm; - Wrapper *f; - - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - - f = NewWrapper(); - // evaluation function names - - sprintf (var_name, "%svar_%s", prefix, iname); - - // Build the name for scheme. - proc_name = NewString(iname); - Replace(proc_name,"_", "-",DOH_REPLACE_ANY); - - if ((SwigType_type(t) != T_USER) || (is_a_pointer(t))) { - - Printf (f_wrappers, "SCM %s(SCM s_0) {\n", var_name); - - if (!(ReadOnly) && SwigType_type(t) == T_STRING) { - Printf (f_wrappers, "\t char *_temp;\n"); - Printf (f_wrappers, "\t int _len;\n"); } - Printf (f_wrappers, "\t SCM gswig_result;\n"); - - // Check for a setting of the variable value - - Printf (f_wrappers, "\t if (s_0 != GH_NOT_PASSED) {\n"); - - // Yup. Extract the type from s_0 and set variable value - - if (ReadOnly) { - Printf (f_wrappers, "\t\t scm_misc_error(\"%s\", " - "\"Unable to set %s. Variable is read only.\", SCM_EOL);\n", - proc_name, proc_name); + + /* Close prototype */ + + Printf(f->def, ")\n{\n"); + + /* Define the scheme name in C. This define is used by several Guile + macros. */ + Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); + + // Now write code to make the function call + Printv(f->code, tab4, "gh_defer_ints();\n", NIL); + emit_action(n,f); + Printv(f->code, tab4, "gh_allow_ints();\n", NIL); + + // Now have return value, figure out what to do with it. + + if ((tm = Getattr(n,"tmap:out"))) { + Replaceall(tm,"$result","gswig_result"); + Replaceall(tm,"$target","gswig_result"); + Replaceall(tm,"$source","result"); + Printv(f->code,tm,"\n",NIL); } - else if ((tm = guile_typemap_lookup ("varin", - t, name, (char*)"s_0", name, f))) { - Printf (f_wrappers, "%s\n", tm); + else { + throw_unhandled_guile_type_error (d); } - else if (is_a_pointer(t)) { - if (SwigType_type(t) == T_STRING) { - Printf (f_wrappers, "\t\t _temp = gh_scm2newstr(s_0, &_len);\n"); - Printf (f_wrappers, "\t\t if (%s) { free(%s);}\n", name, name); - Printf (f_wrappers, "\t\t %s = (char *) " - "malloc((_len+1)*sizeof(char));\n", name); - Printf (f_wrappers, "\t\t strncpy(%s,_temp,_len);\n", name); - Printf (f_wrappers, "\t\t %s[_len] = 0;\n", name); - } else { - // Set the value of a pointer - Printf (f_wrappers, "\t if (SWIG_Guile_GetPtr(s_0, " - "(void **) &%s, ", name); - if (SwigType_type(t) == T_VOID) - Printf (f_wrappers, "NULL)) {\n"); - else - Printf (f_wrappers, "SWIGTYPE%s)) {\n", SwigType_manglestr(t)); - /* Raise exception */ - Printf(f_wrappers, "\tscm_wrong_type_arg(\"%s\", " - "%d, s_0);\n", proc_name, 1); - Printf (f_wrappers, "\t}\n"); + + // Dump the argument output code + Printv(f->code,outarg,NIL); + + // Dump the argument cleanup code + Printv(f->code,cleanup,NIL); + + // Look for any remaining cleanup + + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printv(f->code,tm,"\n",NIL); } } - else { - throw_unhandled_guile_type_error (t); + + // Free any memory allocated by the function being wrapped.. + if ((tm = Swig_typemap_lookup_new("ret",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printv(f->code,tm,"\n",NIL); } - Printf (f_wrappers, "\t}\n"); - - // Now return the value of the variable (regardless - // of evaluating or setting) - - if ((tm = guile_typemap_lookup ("varout", - t, name, name, (char*)"gswig_result", f))) { - Printf (f_wrappers, "%s\n", tm); + + // Wrap things up (in a manner of speaking) + + if (beforereturn) + Printv(f->code, beforereturn, "\n", NIL); + Printv(f->code, "return gswig_result;\n", NIL); + + // Undefine the scheme name + + Printf(f->code, "#undef FUNC_NAME\n"); + Printf(f->code, "}\n"); + + Wrapper_print (f, f_wrappers); + + if (!Getattr(n, "sym:overloaded")) { + if (numargs > 10) { + int i; + /* gh_new_procedure would complain: too many args */ + /* Build a wrapper wrapper */ + Printv(f_wrappers, "static SCM\n", wname,"_rest (SCM rest)\n", NIL); + Printv(f_wrappers, "{\n", NIL); + Printf(f_wrappers, "SCM arg[%d];\n", numargs); + Printf(f_wrappers, "SWIG_Guile_GetArgs (arg, rest, %d, %d, \"%s\");\n", + numreq, numargs-numreq, proc_name); + Printv(f_wrappers, "return ", wname, "(", NIL); + Printv(f_wrappers, "arg[0]", NIL); + for (i = 1; i<numargs; i++) + Printf(f_wrappers, ", arg[%d]", i); + Printv(f_wrappers, ");\n", NIL); + Printv(f_wrappers, "}\n", NIL); + /* Register it */ + Printf (f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s_rest, 0, 0, 1);\n", + proc_name, wname, numreq, numargs-numreq); } - else if (is_a_pointer(t)) { - if (SwigType_type(t) == T_STRING) { - Printf (f_wrappers, "\t gswig_result = gh_str02scm(%s);\n", name); - } else { - // Is an ordinary pointer type. - Printf (f_wrappers, "\t gswig_result = SWIG_Guile_MakePtr (" - "%s, SWIGTYPE%s);\n", name, SwigType_manglestr(t)); + else if (emit_setters && struct_member && strlen(Char(proc_name))>3) { + int len = Len(proc_name); + const char *pc = Char(proc_name); + /* MEMBER-set and MEMBER-get functions. */ + int is_setter = (pc[len - 3] == 's'); + if (is_setter) { + Printf(f_init, "SCM setter = "); + struct_member = 2; /* have a setter */ + } + else Printf(f_init, "SCM getter = "); + Printf (f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s, %d, %d, 0);\n", + proc_name, wname, numreq, numargs-numreq); + if (!is_setter) { + /* Strip off "-get" */ + char *pws_name = (char*) malloc(sizeof(char) * (len - 3)); + strncpy(pws_name, pc, len - 3); + pws_name[len - 4] = 0; + if (struct_member==2) { + /* There was a setter, so create a procedure with setter */ + Printf (f_init, "gh_define(\"%s\", " + "scm_make_procedure_with_setter(getter, setter));\n", + pws_name); + } + else { + /* There was no setter, so make an alias to the getter */ + Printf (f_init, "gh_define(\"%s\", getter);\n", + pws_name); + } + Printf (exported_symbols, "\"%s\", ", pws_name); + free(pws_name); } } else { - throw_unhandled_guile_type_error (t); + /* Register the function */ + Printf (f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s, %d, %d, 0);\n", + proc_name, wname, numreq, numargs-numreq); } - Printf (f_wrappers, "\t return gswig_result;\n"); - Printf (f_wrappers, "}\n"); - - // Now add symbol to the Guile interpreter - - if (!emit_setters - || ReadOnly) { - /* Read-only variables become a simple procedure returning the - value. */ - Printf (f_init, "\t gh_new_procedure(\"%s\", %s, 0, 1, 0);\n", - proc_name, var_name); } - else { - /* Read/write variables become a procedure with setter. */ - Printf (f_init, "\t{ SCM p = gh_new_procedure(\"%s\", %s, 0, 1, 0);\n", - proc_name, var_name); - Printf (f_init, "\t gh_define(\"%s\", " - "scm_make_procedure_with_setter(p, p)); }\n", - proc_name); + else { /* overloaded function; don't export the single methods */ + if (!Getattr(n,"sym:nextSibling")) { + /* Emit overloading dispatch function */ + + int maxargs; + String *dispatch = Swig_overload_dispatch(n,"return %s(argc,argv);",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + + Printv(df->def, + "static SCM\n", dname, + "(SCM rest)\n{\n", + NIL); + Printf(df->code, "SCM argv[%d];\n", maxargs); + Printf(df->code, "int argc = SWIG_Guile_GetArgs (argv, rest, %d, %d, \"%s\");\n", + 0, maxargs, proc_name); + Printv(df->code,dispatch,"\n",NIL); + Printf(df->code,"scm_misc_error(\"%s\", \"No matching method for generic function `%s'\", SCM_EOL);\n", proc_name, iname); + Printv(df->code,"}\n",NIL); + Wrapper_print(df,f_wrappers); + Printf(f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, 0, 1);\n", + proc_name, dname); + DelWrapper(df); + Delete(dispatch); + Delete(dname); + } } - + Printf (exported_symbols, "\"%s\", ", proc_name); if (procdoc) { - /* Compute documentation */ - String *signature = NewString(""); - - if (ReadOnly) { - Printv(signature, "(", proc_name, ")\n", 0); - Printv(signature, "Returns constant ", 0); - guile_do_doc_typemap(signature, "varoutdoc", t, NULL, - 0, proc_name, f); - Printv(signature, "\n", 0); + String *returns_text = NewString(""); + if (num_results == 0) Printv(returns_text, return_nothing_doc, NIL); + else if (num_results == 1) Printv(returns_text, return_one_doc, NIL); + else Printv(returns_text, return_multi_doc, NIL); + /* Substitute documentation variables */ + static const char *numbers[] = {"zero", "one", "two", "three", + "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", + "twelve"}; + if (num_results <= 12) + Replaceall(returns_text, "$num_values", numbers[num_results]); + else { + String *num_results_str = NewStringf("%d", num_results); + Replaceall(returns_text, "$num_values", num_results_str); + Delete(num_results_str); + } + Replaceall(returns_text, "$values", returns); + Printf(doc_body, "\n%s", returns_text); + write_doc(proc_name, signature, doc_body); + Delete(returns_text); + } + + Delete(proc_name); + Delete(outarg); + Delete(cleanup); + Delete(signature); + Delete(doc_body); + Delete(returns); + Delete(tmp); + DelWrapper(f); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * variableWrapper() + * + * Create a link to a C variable. + * This creates a single function PREFIX_var_VARNAME(). + * This function takes a single optional argument. If supplied, it means + * we are setting this variable to some value. If omitted, it means we are + * simply evaluating this variable. Either way, we return the variables + * value. + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *proc_name; + char var_name[256]; + Wrapper *f; + String *tm; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + f = NewWrapper(); + // evaluation function names + + strcpy(var_name, Char(Swig_name_wrapper(iname))); + + // Build the name for scheme. + proc_name = NewString(iname); + Replaceall(proc_name,"_", "-"); + + if (1 || (SwigType_type(t) != T_USER) || (is_a_pointer(t))) { + + Printf (f->def, "static SCM\n%s(SCM s_0)\n{\n", var_name); + + /* Define the scheme name in C. This define is used by several Guile + macros. */ + Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); + + Wrapper_add_local (f, "gswig_result", "SCM gswig_result"); + + if (!Getattr(n,"feature:immutable")) { + /* Check for a setting of the variable value */ + Printf (f->code, "if (s_0 != GH_NOT_PASSED) {\n"); + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","s_0"); + Replaceall(tm,"$input","s_0"); + Replaceall(tm,"$target",name); + Printv(f->code,tm,"\n",NIL); + } + else { + throw_unhandled_guile_type_error (t); + } + Printf (f->code, "}\n"); + } + + // Now return the value of the variable (regardless + // of evaluating or setting) + + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","gswig_result"); + Replaceall(tm,"$result", "gswig_result"); + Printv(f->code,tm,"\n",NIL); + } + else { + throw_unhandled_guile_type_error (t); + } + Printf (f->code, "\nreturn gswig_result;\n"); + Printf (f->code, "#undef FUNC_NAME\n"); + Printf (f->code, "}\n"); + + Wrapper_print (f, f_wrappers); + + // Now add symbol to the Guile interpreter + + if (!emit_setters + || Getattr(n,"feature:immutable")) { + /* Read-only variables become a simple procedure returning the + value; read-write variables become a simple procedure with + an optional argument. */ + Printf (f_init, "\t gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, %d, 0);\n", + proc_name, var_name, Getattr(n,"feature:immutable") ? 0 : 1); } else { - Printv(signature, "(", proc_name, - " #:optional ", 0); - guile_do_doc_typemap(signature, "varindoc", t, "new-value", - 1, proc_name, f); - Printv(signature, ")\n", 0); - Printv(signature, "If NEW-VALUE is provided, " - "set C variable to this value.\n", 0); - Printv(signature, "Returns variable value ", 0); - guile_do_doc_typemap(signature, "varoutdoc", t, NULL, - 0, proc_name, f); - Printv(signature, "\n", 0); + /* Read/write variables become a procedure with setter. */ + Printf (f_init, "\t{ SCM p = gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, 1, 0);\n", + proc_name, var_name); + Printf (f_init, "\t gh_define(\"%s\", " + "scm_make_procedure_with_setter(p, p)); }\n", + proc_name); + } + Printf (exported_symbols, "\"%s\", ", proc_name); + + if (procdoc) { + /* Compute documentation */ + String *signature = NewString(""); + String *signature2 = NULL; + String *doc = NewString(""); + + if (Getattr(n,"feature:immutable")) { + Printv(signature, proc_name, NIL); + Printv(doc, "Returns constant ", NIL); + if ((tm = Getattr(n,"tmap:varout:doc"))) { + Printv(doc,tm,NIL); + } else { + String *s = SwigType_str(t,0); + Chop(s); + Printf(doc,"<%s>",s); + Delete(s); + } + } + else if (emit_setters) { + Printv(signature, proc_name, NIL); + signature2 = NewString(""); + Printv(signature2, "set! (", proc_name, ") ", NIL); + handle_documentation_typemap(signature2, NIL, n, "tmap:varin:arglist", + "new-value"); + Printv(doc, "Get or set the value of the C variable, \n", NIL); + Printv(doc, "which is of type ", NIL); + handle_documentation_typemap(doc, NIL, n, "tmap:varout:doc", + "$1_type"); + Printv(doc, "."); + } + else { + Printv(signature, proc_name, + " #:optional ", NIL); + if ((tm = Getattr(n,"tmap:varin:doc"))) { + Printv(signature,tm,NIL); + } else { + String *s = SwigType_str(t,0); + Chop(s); + Printf(signature,"new-value <%s>",s); + Delete(s); + } + + Printv(doc, "If NEW-VALUE is provided, " + "set C variable to this value.\n", NIL); + Printv(doc, "Returns variable value ", NIL); + if ((tm = Getattr(n,"tmap:varout:doc"))) { + Printv(doc,tm,NIL); + } else { + String *s = SwigType_str(t,0); + Chop(s); + Printf(doc,"<%s>",s); + Delete(s); + } + } + write_doc(proc_name, signature, doc, signature2); + Delete(signature); + if (signature2) Delete(signature2); + Delete(doc); } - Printv(procdoc, "\f\n", signature, 0); - Delete(signature); + + } else { + Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, + "Unsupported variable type %s (ignored).\n", SwigType_str(t,0)); } - - } else { - Printf (stderr, "%s:%d. ** Warning. Unable to link with " - " type %s (ignored).\n", - Getfile(node), Getline(node), SwigType_str(t,0)); + Delete(proc_name); + DelWrapper(f); + return SWIG_OK; } - Delete(proc_name); - Delete(f); -} -// ----------------------------------------------------------------------- -// GUILE::constant() -// -// Makes a constant. Not sure how this is really supposed to work. -// I'm going to fake out SWIG and create a variable instead. -// ------------------------------------------------------------------------ - -void -GUILE::constant(DOH *node) -{ - char *name; - SwigType *type; - char *value; - int OldStatus = ReadOnly; // Save old status flags - DOHString *proc_name; - char var_name[256]; - DOHString *rvalue; - char *tm; - Wrapper *f; - - name = GetChar(node,"name"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - - f = NewWrapper(); - ReadOnly = 1; // Enable readonly mode. - - // Make a static variable; - - sprintf (var_name, "%sconst_%s", prefix, name); - - // Build the name for scheme. - proc_name = NewString(name); - Replace(proc_name,"_", "-", DOH_REPLACE_ANY); - - if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) { - Printf (stderr, "%s:%d. Unsupported constant value.\n", - Getfile(node), Getline(node)); - return; + /* ------------------------------------------------------------ + * constantWrapper() + * + * We create a read-only variable. + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + + String *proc_name; + char var_name[256]; + String *rvalue; + Wrapper *f; + SwigType *nctype; + String *tm; + + f = NewWrapper(); + + // Make a static variable; + + sprintf (var_name, "%sconst_%s", prefix, iname); + + // Strip const qualifier from type if present + + nctype = NewString(type); + if (SwigType_isconst(nctype)) { + Delete(SwigType_pop(nctype)); + } + + // Build the name for scheme. + proc_name = NewString(iname); + Replaceall(proc_name,"_", "-"); + + if ((SwigType_type(nctype) == T_USER) && (!is_a_pointer(nctype))) { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value.\n"); + return SWIG_NOWRAP; + } + + // See if there's a typemap + + if (SwigType_type(nctype) == T_STRING) { + rvalue = NewStringf("\"%s\"", value); + } else if (SwigType_type(nctype) == T_CHAR) { + rvalue = NewStringf("\'%s\'", value); + } else { + rvalue = NewString(value); + } + + if ((tm = Swig_typemap_lookup_new("constant",n,name,0))) { + Replaceall(tm,"$source",rvalue); + Replaceall(tm,"$value",rvalue); + Replaceall(tm,"$target",name); + Printv(f_header,tm,"\n",NIL); + } else { + // Create variable and assign it a value + Printf (f_header, "static %s = %s;\n", SwigType_lstr(nctype,var_name), + rvalue); + } + { + /* Hack alert: will cleanup later -- Dave */ + Node *n = NewHash(); + Setattr(n,"name",var_name); + Setattr(n,"sym:name",iname); + Setattr(n,"type", nctype); + Setattr(n,"feature:immutable", "1"); + variableWrapper(n); + Delete(n); + } + Delete(nctype); + Delete(proc_name); + Delete(rvalue); + DelWrapper(f); + return SWIG_OK; } - // See if there's a typemap - - if (SwigType_type(type) == T_STRING) { - rvalue = NewStringf("\"%s\"", value); - } else if (SwigType_type(type) == T_CHAR) { - rvalue = NewStringf("\'%s\'", value); - } else { - rvalue = NewString(value); + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ + virtual int membervariableHandler(Node *n) { + if (emit_setters) { + struct_member = 1; + Printf(f_init, "{\n"); + Language::membervariableHandler(n); + Printf(f_init, "}\n"); + struct_member = 0; + } + else { + /* Only emit traditional VAR-get and VAR-set procedures */ + Language::membervariableHandler(n); + } + return SWIG_OK; } - if ((tm = guile_typemap_lookup ("const", type, name, - Char(rvalue), name, f))) { - Printf (f_init, "%s\n", tm); - } else { - // Create variable and assign it a value - - Printf (f_header, "static %s %s = ", SwigType_lstr(type,0), var_name); - if (SwigType_type(type) == T_STRING) { - Printf (f_header, "\"%s\";\n", value); - } else if (SwigType_type(type) == T_CHAR) { - Printf (f_header, "\'%s\';\n", value); - } else { - Printf (f_header, "%s;\n", value); + + /* ------------------------------------------------------------ + * pragmaDirective() + * ------------------------------------------------------------ */ + + virtual int pragmaDirective(Node *n) + { + if (!ImportMode) { + String *lang = Getattr(n,"lang"); + String *cmd = Getattr(n,"name"); + String *value = Getattr(n,"value"); + +# define store_pragma(PRAGMANAME) \ + if (Strcmp(cmd, #PRAGMANAME) == 0) { \ + if (PRAGMANAME) Delete(PRAGMANAME); \ + PRAGMANAME = value ? NewString(value) : NULL; \ + } + + if (Strcmp(lang,"guile") == 0) { + store_pragma(beforereturn) + store_pragma(return_nothing_doc) + store_pragma(return_one_doc) + store_pragma(return_multi_doc); +# undef store_pragma + } } - // Now create a variable declaration - - Hash *nnode = Copy(node); - Setattr(nnode,"name",var_name); - variable(nnode); - Delete(nnode); - ReadOnly = OldStatus; + return Language::pragmaDirective(n); } - Delete(proc_name); - Delete(rvalue); - Delete(f); -} -void GUILE::cpp_variable(DOH *node) -{ - if (emit_setters) { - struct_member = 1; - Printf(f_init, "{\n"); - Language::cpp_variable(node); - Printf(f_init, "}\n"); - struct_member = 0; - } - else { - /* Only emit traditional VAR-get and VAR-set procedures */ - Language::cpp_variable(node); + /* ------------------------------------------------------------ + * validIdentifier() + * ------------------------------------------------------------ */ + + virtual int validIdentifier(String *s) { + char *c = Char(s); + /* Check whether we have an R5RS identifier. Guile supports a + superset of R5RS identifiers, but it's probably a bad idea to use + those. */ + /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */ + /* <initial> --> <letter> | <special initial> */ + if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~'))) { + /* <peculiar identifier> --> + | - | ... */ + if ((strcmp(c, "+") == 0) + || strcmp(c, "-") == 0 + || strcmp(c, "...") == 0) return 1; + else return 0; + } + /* <subsequent> --> <initial> | <digit> | <special subsequent> */ + while (*c) { + if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+') + || (*c == '-') || (*c == '.') || (*c == '@'))) return 0; + c++; + } + return 1; } +}; + +/* ----------------------------------------------------------------------------- + * swig_guile() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_guile(void) { + return new GUILE(); } diff --git a/Source/Modules1.1/guile.h b/Source/Modules1.1/guile.h deleted file mode 100644 index a9aef3374..000000000 --- a/Source/Modules1.1/guile.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************** - * Simplified Wrapper and Interface Generator (SWIG) - * - * Author : David Beazley - * - * Department of Computer Science - * University of Chicago - * 1100 E 58th Street - * Chicago, IL 60637 - * beazley@cs.uchicago.edu - * - * Please read the file LICENSE for the copyright and terms by which SWIG - * can be used and distributed. - *****************************************************************************/ - -/************************************************************************** - * $Header$ - * - * class GUILE - * - * Guile implementation - * - **************************************************************************/ - -#include "swig.h" - -class GUILE : public Language -{ -private: - char *prefix; - char *module; - char *package; - enum { - GUILE_LSTYLE_SIMPLE, // call `SWIG_init()' - GUILE_LSTYLE_LTDLMOD, // "native" guile? - GUILE_LSTYLE_HOBBIT // use (hobbit4d link) - } linkage; - File *procdoc; - int emit_setters; - int struct_member; - void emit_linkage(char *module_name); - -public : - GUILE (); - void parse_args (int, char *argv[]); - void initialize(String *module); - void function (DOH *node); - void variable (DOH *node); - void constant (DOH *node); - void close (void); - void create_command (String *, String *) { }; - void cpp_variable(DOH *node); -}; - -/* guile.h ends here */ diff --git a/Source/Modules1.1/java.cxx b/Source/Modules1.1/java.cxx index 18b7011d5..499a58b24 100644 --- a/Source/Modules1.1/java.cxx +++ b/Source/Modules1.1/java.cxx @@ -1,1347 +1,1900 @@ -/******************************************************************************* - * SWIG Java module - * Author: Harco de Hilster - * AT Consultancy - * Toernooiveld 104 - * P.O. Box 1428 - * 6501 BK Nijmegen - * +31 24 3527282 - * harcoh@ATConsultancy.nl +/* ----------------------------------------------------------------------------- + * java.cxx * - * thanks to the following persons for submitting bug-reports: + * Java wrapper module. * - * James Hicks <jamey@crl.dec.com> - * Lars Schmidt-Thieme <lschmidt@ix.urz.uni-heidelberg.de> - * Per OEyvind Hvidsten Per-Oyvind.Hvidsten@ffi.no - * Geoff Dillon <gdillon@pervasive.com> - * Michael Haller <haller@lionbio.co.uk> - * "Simon J. Julier" <sjulier@erols.com> - * "Pritam Kamat" <pritam@alier.com> - * Marc Hadley <marc_hadley@chrystal.co.uk> - ******************************************************************************* -*/ - -/* !!!!!!! - * DB 7/24/00: Is there any way to clean up the implementation of this module? - * I've tried to bring it as far as I can with core changes, but it's getting - * to be a little rough. - * !!!!!!! - */ + * Author(s) : Harco de Hilster + * William Fulton + * + * Copyright (C) 1999-2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_java_cxx[] = "$Header$"; #include <ctype.h> +#include <limits.h> // for INT_MAX +#include "swigmod.h" + +class JAVA : public Language { + static const char *usage; + const String *empty_string; + + Hash *swig_types_hash; + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + + bool proxy_flag; // Flag for generating shadow classes + bool have_default_constructor_flag; + bool native_function_flag; // Flag for when wrapping a native function + bool enum_constant_flag; // Flag for when wrapping an enum or constant + bool static_flag; // Flag for when wrapping a static functions or member variables + bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable + bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const + bool global_variable_flag; // Flag for when wrapping a global variable + + String *jniclass_name; // JNI class name + String *module_class_name; // module class name + String *jniclass_class_code; // JNI class Java code - that is the native methods + String *shadow_classdef; + String *shadow_code; + String *module_class_code; + String *shadow_classname; + String *variable_name; //Name of a variable being wrapped + String *shadow_constants_code; + String *module_constants_code; + String *package; // Package name + String *jnipackage; // JNI package name + String *jniclass_imports; //jniclass imports from %pragma + String *module_imports; //module imports from %pragma + String *jniclass_baseclass; //inheritance for jniclass class from %pragma + String *module_baseclass; //inheritance for module class from %pragma + String *jniclass_interfaces; //interfaces for jniclass class from %pragma + String *module_interfaces; //interfaces for module class from %pragma + String *jniclass_class_modifiers; //class modifiers for jniclass class overriden by %pragma + String *module_class_modifiers; //class modifiers for module class overriden by %pragma + String *wrapper_conversion_code; //C++ casts for inheritance hierarchies JNI code + String *jniclass_cppcasts_code; //C++ casts up inheritance hierarchies JNI class Java code + String *destructor_call; //Destructor (delete) call if any + + enum type_additions {none, pointer, reference}; + + public: + + /* ----------------------------------------------------------------------------- + * JAVA() + * ----------------------------------------------------------------------------- */ + + JAVA() : + empty_string(NewString("")), + + swig_types_hash(NULL), + f_runtime(NULL), + f_header(NULL), + f_wrappers(NULL), + f_init(NULL), + + proxy_flag(true), + have_default_constructor_flag(false), + native_function_flag(false), + enum_constant_flag(false), + static_flag(false), + variable_wrapper_flag(false), + wrapping_member_flag(false), + global_variable_flag(false), + + jniclass_name(NULL), + module_class_name(NULL), + jniclass_class_code(NULL), + shadow_classdef(NULL), + shadow_code(NULL), + module_class_code(NULL), + shadow_classname(NULL), + variable_name(NULL), + shadow_constants_code(NULL), + module_constants_code(NULL), + package(NULL), + jnipackage(NULL), + jniclass_imports(NULL), + module_imports(NULL), + jniclass_baseclass(NULL), + module_baseclass(NULL), + jniclass_interfaces(NULL), + module_interfaces(NULL), + jniclass_class_modifiers(NULL), + module_class_modifiers(NULL), + wrapper_conversion_code(NULL), + jniclass_cppcasts_code(NULL), + destructor_call(NULL) + + { + } -#include "mod11.h" -#include "java.h" - -char bigbuf[1024]; - -static char *usage = (char*)"\ -Java Options\n\ - -jnic - use c syntax for jni calls\n\ - -jnicpp - use c++ syntax for jni calls\n\ - -module name - set name of module\n\ - -package name - set name of package\n\ - -shadow - enable shadow classes\n\ - -finalize - generate finalize methods\n\ - -rn - generate register natives code\n\n"; - -static char *module = 0; // Name of the module -static char *java_path = (char*)"java"; -static char *package = 0; // Name of the package -static char *c_pkgstr; // Name of the package -static char *jni_pkgstr; // Name of the package -static char *shadow_classname; -static char *jimport = 0; -static char *method_modifiers = (char*)"public final static"; -static FILE *f_java = 0; -static FILE *f_shadow = 0; -static int shadow = 0; -static DOHHash *shadow_classes; -static DOHString *shadow_classdef; -static char *shadow_name = 0; -static char *shadow_baseclass = 0; -static int classdef_emitted = 0; -static int shadow_classdef_emitted = 0; -static int have_default_constructor = 0; -static int native_func = 0; // Set to 1 when wrapping a native function -static int member_func = 0; // Set to 1 when wrapping a member function -static int jnic = -1; // 1: use c syntax jni; 0: use c++ syntax jni -static int finalize = 0; // generate finalize methods -static int useRegisterNatives = 0; // Set to 1 when doing stuff with register natives -static DOHString *registerNativesList = 0; - -char *JAVA::SwigTcToJniType(DataType *t, int ret) { - if(DataType_is_pointer(t) == 1) { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"jintArray"; - case T_SHORT: return (char*)"jshortArray"; - case T_LONG: return (char*)"jlongArray"; - case T_CHAR: return (char*)"jstring"; - case T_FLOAT: return (char*)"jfloatArray"; - case T_DOUBLE: return (char*)"jdoubleArray"; - case T_UINT: return (char*)"jintArray"; - case T_USHORT: return (char*)"jshortArray"; - case T_ULONG: return (char*)"jlongArray"; - case T_UCHAR: return (char*)"jbyteArray"; - case T_SCHAR: return (char*)"jbyteArray"; - case T_BOOL: return (char*)"jbooleanArray"; - case T_VOID: - case T_USER: return (char*)"jlong"; - } - } else if(DataType_is_pointer(t) > 1) { - if(ret) - return (char*)"jlong"; - else return (char*)"jlongArray"; - } else { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"jint"; - case T_SHORT: return (char*)"jshort"; - case T_LONG: return (char*)"jlong"; - case T_CHAR: return (char*)"jbyte"; - case T_FLOAT: return (char*)"jfloat"; - case T_DOUBLE: return (char*)"jdouble"; - case T_UINT: return (char*)"jint"; - case T_USHORT: return (char*)"jshort"; - case T_ULONG: return (char*)"jlong"; - case T_UCHAR: return (char*)"jbyte"; - case T_SCHAR: return (char*)"jbyte"; - case T_BOOL: return (char*)"jboolean"; - case T_VOID: return (char*)"void"; - case T_USER: return (char*)"jlong"; - } + /* ----------------------------------------------------------------------------- + * is_shadow() + * + * Test to see if a type corresponds to something wrapped with a shadow/proxy class + * Return NULL if not otherwise the shadow name + * ----------------------------------------------------------------------------- */ + + String *is_shadow(SwigType *t) { + if (proxy_flag) { + Node *n = classLookup(t); + if (n) { + return Getattr(n,"sym:name"); + } + } + return NULL; } - Printf(stderr, "SwigTcToJniType: unhandled SWIG type %s\n", DataType_str(t,0)); - return NULL; -} -char *JAVA::SwigTcToJavaType(DataType *t, int ret, int inShadow) { - if(DataType_is_pointer(t) == 1) { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"int []"; - case T_SHORT: return (char*)"short []"; - case T_LONG: return (char*)"long []"; - case T_CHAR: return (char*)"String"; - case T_FLOAT: return (char*)"float []"; - case T_DOUBLE: return (char*)"double []"; - case T_UINT: return (char*)"int []"; - case T_USHORT: return (char*)"short []"; - case T_ULONG: return (char*)"long []"; - case T_UCHAR: return (char*)"byte []"; - case T_SCHAR: return (char*)"byte []"; - case T_BOOL: return (char*)"boolean []"; - case T_VOID: - case T_USER: if(inShadow && Getattr(shadow_classes,DataType_Getname(t))) - return GetChar(shadow_classes,DataType_Getname(t)); - else return (char*)"long"; - } - } else if(DataType_is_pointer(t) > 1) { - if(ret) - return (char*)"long"; - else return (char*)"long []"; - } else { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"int"; - case T_SHORT: return (char*)"short"; - case T_LONG: return (char*)"long"; - case T_CHAR: return (char*)"byte"; - case T_FLOAT: return (char*)"float"; - case T_DOUBLE: return (char*)"double"; - case T_UINT: return (char*)"int"; - case T_USHORT: return (char*)"short"; - case T_ULONG: return (char*)"long"; - case T_UCHAR: return (char*)"byte"; - case T_SCHAR: return (char*)"byte"; - case T_BOOL: return (char*)"boolean"; - case T_VOID: return (char*)"void"; - case T_USER: return (char*)"long"; - } - } - Printf(stderr, "SwigTcToJavaType: unhandled SWIG type %s\n", DataType_str(t,0)); - return NULL; -} + /* ----------------------------------------------------------------------------- + * makeValidJniName() + * ----------------------------------------------------------------------------- */ -char *JAVA::SwigTcToJniScalarType(DataType *t) { - if(DataType_is_pointer(t) == 1) { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"Int"; - case T_SHORT: return (char*)"Short"; - case T_LONG: return (char*)"Long"; - case T_CHAR: return (char*)"Byte"; - case T_FLOAT: return (char*)"Float"; - case T_DOUBLE: return (char*)"Double"; - case T_UINT: return (char*)"Int"; - case T_USHORT: return (char*)"Short"; - case T_ULONG: return (char*)"Long"; - case T_UCHAR: return (char*)"Byte"; - case T_SCHAR: return (char*)"Byte"; - case T_BOOL: return (char*)"Boolean"; - case T_VOID: - case T_USER: return (char*)"Long"; - } - } else { - return (char*)"Long"; + String *makeValidJniName(const String *name) { + String *valid_jni_name = NewString(name); + Replaceall(valid_jni_name,"_","_1"); + return valid_jni_name; } - Printf(stderr, "SwigTcToJniScalarType: unhandled SWIG type %s\n", DataType_str(t,0)); - return NULL; -} + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ -char *JAVA::JavaMethodSignature(DataType *t, int ret, int inShadow) { - if(DataType_is_pointer(t) == 1) { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"[I"; - case T_SHORT: return (char*)"[S"; - case T_LONG: return (char*)"[J"; - case T_CHAR: return (char*)"Ljava/lang/String;"; - case T_FLOAT: return (char*)"[F"; - case T_DOUBLE: return (char*)"[D"; - case T_UINT: return (char*)"[I"; - case T_USHORT: return (char*)"[S"; - case T_ULONG: return (char*)"[J"; - case T_UCHAR: return (char*)"[B"; - case T_SCHAR: return (char*)"[B"; - case T_BOOL: return (char*)"[Z"; - case T_VOID: - case T_USER: if(inShadow && Getattr(shadow_classes,DataType_Getname(t))) - return GetChar(shadow_classes,DataType_Getname(t)); - else return (char*)"J"; - } - } else if(DataType_is_pointer(t) > 1) { - if(ret) return (char*)"J"; - else return (char*)"[J"; - } else { - switch(DataType_Gettypecode(t)) { - case T_INT: return (char*)"I"; - case T_SHORT: return (char*)"S"; - case T_LONG: return (char*)"J"; - case T_CHAR: return (char*)"B"; - case T_FLOAT: return (char*)"F"; - case T_DOUBLE: return (char*)"D"; - case T_UINT: return (char*)"I"; - case T_USHORT: return (char*)"S"; - case T_ULONG: return (char*)"J"; - case T_UCHAR: return (char*)"B"; - case T_SCHAR: return (char*)"B"; - case T_BOOL: return (char*)"Z"; - case T_VOID: return (char*)"V"; - case T_USER: return (char*)"J"; - } - } - Printf(stderr, "JavaMethodSignature: unhandled SWIG type %s\n", DataType_str(t,0)); - return NULL; -} + virtual void main(int argc, char *argv[]) { -char *JAVA::JavaTypeFromTypemap(char *op, char *lang, DataType *t, char *pname) { - char *tm; - char *c = bigbuf; - if(!(tm = typemap_lookup(op, lang, t, pname, (char*)"", (char*)""))) return NULL; - while(*tm && (isspace(*tm) || *tm == '{')) tm++; - while(*tm && *tm != '}') *c++ = *tm++; - *c='\0'; + SWIG_library_directory("java"); - return strdup(bigbuf); -} + // Look for certain command line options + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp(argv[i],"-package") == 0) { + if (argv[i+1]) { + package = NewString(""); + Printf(package, argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if ((strcmp(argv[i],"-shadow") == 0) || ((strcmp(argv[i],"-proxy") == 0))) { + Printf(stderr,"Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]); + Swig_mark_arg(i); + proxy_flag = true; + } else if ((strcmp(argv[i],"-noproxy") == 0)) { + Swig_mark_arg(i); + proxy_flag = false; + } else if (strcmp(argv[i],"-jnic") == 0) { + Swig_mark_arg(i); + Printf(stderr,"Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n"); + } else if (strcmp(argv[i],"-nofinalize") == 0) { + Swig_mark_arg(i); + Printf(stderr,"Deprecated command line option: -nofinalize. Use the new javafinalize typemaps instead.\n"); + } else if (strcmp(argv[i],"-jnicpp") == 0) { + Swig_mark_arg(i); + Printf(stderr,"Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n"); + } else if (strcmp(argv[i],"-help") == 0) { + Printf(stderr,"%s\n", usage); + } + } + } + + // Add a symbol to the parser for conditional compilation + Preprocessor_define("SWIGJAVA 1",0); -char *JAVA::makeValidJniName(char *name) { - char *c = name; - char *b = bigbuf; + // Add typemap definitions + SWIG_typemap_lang("java"); + SWIG_config_file("java.swg"); - while(*c) { - *b++ = *c; - if(*c == '_') *b++ = '1'; - c++; + allow_overloading(); } - *b = '\0'; - return strdup(bigbuf); -} + /* --------------------------------------------------------------------- + * top() + * --------------------------------------------------------------------- */ -// !! this approach fails for functions without arguments -char *JAVA::JNICALL(DOHString_or_char *func) { - if(jnic) - sprintf(bigbuf, "(*jenv)->%s(jenv, ", Char(func)); - else - sprintf(bigbuf, "jenv->%s(", Char(func)); + virtual int top(Node *n) { - return strdup(bigbuf); -} + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); -void JAVA::writeRegisterNatives() -{ - if(Len(registerNativesList) == 0) - return; - - Printf(f_wrappers,"\n"); - Printf(f_wrappers,"JNINativeMethod nativeMethods[] = {\n"); - Printv(f_wrappers, registerNativesList, 0); - Printf(f_wrappers, "};\n"); - - Printf(f_wrappers,"\nint numberOfNativeMethods=sizeof(nativeMethods)/sizeof(JNINativeMethod);\n\n"); - - // The registerNatives function - - Printv(f_wrappers, - "jint registerNatives(JNIEnv *jenv) {", "\n", - tab4, "jclass nativeClass = ", JNICALL((char*)"FindClass"), - "\"", jni_pkgstr, module, "\");","\n", - 0); - - Printv(f_wrappers, - tab4, "if (nativeClass == 0)", "\n", tab8, "return -1;", "\n", - tab4, "return ", JNICALL((char*)"RegisterNatives"), "nativeClass, nativeMethods, ", "numberOfNativeMethods);", "\n", - "}", "\n", "\n", - 0); - - // The unregisterNatives function - - Printv(f_wrappers, - "jint unregisterNatives(JNIEnv *jenv) {", "\n", - tab4, "jclass nativeClass = ", JNICALL((char*)"FindClass"), - "\"", jni_pkgstr, module, "\");","\n", - 0); - - Printv(f_wrappers, - tab4, "if (nativeClass == 0)", "\n", tab8, "return -1;", "\n", - tab4, "// Sun documentation suggests that this method should not be invoked in ", - "\"normal native code\".", "\n", - tab4, "// return ", JNICALL((char*)"UnregisterNatives"), "nativeClass);", "\n", - tab4, "return 0;", "\n", - "}", "\n", - 0); -} + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"Unable to open %s\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + swig_types_hash = NewHash(); + + // Make the JNI class and module class names. The jniclassname can be set in the module directive. + Node* optionsnode = Getattr( Getattr(n,"module") ,"options"); + if (optionsnode) + if (Getattr(optionsnode,"jniclassname")) + jniclass_name = Copy(Getattr(optionsnode,"jniclassname")); + if (!jniclass_name) { + jniclass_name = NewStringf("%sJNI", Getattr(n,"name")); + module_class_name = Copy(Getattr(n,"name")); + } else { + // Rename the module name if it is the same as JNI class name - a backwards compatibility solution + if (Cmp(jniclass_name, Getattr(n,"name")) == 0) + module_class_name = NewStringf("%sModule", Getattr(n,"name")); + else + module_class_name = Copy(Getattr(n,"name")); + } -// --------------------------------------------------------------------- -// JAVA::parse_args(int argc, char *argv[]) -// -// Parse my command line options and initialize by variables. -// --------------------------------------------------------------------- - -void JAVA::parse_args(int argc, char *argv[]) { - - // file::set_library(java_path); - sprintf(LibDir,"%s", "java"); - - - // Look for certain command line options - for (int i = 1; i < argc; i++) { - if (argv[i]) { - if (strcmp(argv[i],"-module") == 0) { - if (argv[i+1]) { - set_module(argv[i+1],0); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if (strcmp(argv[i],"-package") == 0) { - if (argv[i+1]) { - package = new char[strlen(argv[i+1])+1]; - strcpy(package, argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if (strcmp(argv[i],"-shadow") == 0) { - Swig_mark_arg(i); - shadow = 1; - } else if (strcmp(argv[i],"-jnic") == 0) { - Swig_mark_arg(i); - jnic = 1; - } else if (strcmp(argv[i],"-finalize") == 0) { - Swig_mark_arg(i); - finalize = 1; - } else if (strcmp(argv[i],"-rn") == 0) { - Swig_mark_arg(i); - useRegisterNatives = 1; - } else if (strcmp(argv[i],"-jnicpp") == 0) { - Swig_mark_arg(i); - jnic = 0; - } else if (strcmp(argv[i],"-help") == 0) { - Printf(stderr,"%s\n", usage); + + jniclass_class_code = NewString(""); + shadow_classdef = NewString(""); + shadow_code = NewString(""); + module_constants_code = NewString(""); + jniclass_baseclass = NewString(""); + jniclass_interfaces = NewString(""); + jniclass_class_modifiers = NewString(""); // package access only to the JNI class by default + module_class_code = NewString(""); + module_baseclass = NewString(""); + module_interfaces = NewString(""); + module_imports = NewString(""); + module_class_modifiers = NewString("public"); + jniclass_imports = NewString(""); + jniclass_cppcasts_code = NewString(""); + wrapper_conversion_code = NewString(""); + if (!package) package = NewString(""); + jnipackage = NewString(""); + + Swig_banner(f_runtime); // Print the SWIG banner message + + if (NoInclude) { + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); + } + + String *wrapper_name = NewString(""); + + if(Len(package)) { + String *jniname = makeValidJniName(package); + Printv(jnipackage, jniname, NIL); + Delete(jniname); + Replaceall(jnipackage,".","_"); + Append(jnipackage, "_"); + } + String *jniname = makeValidJniName(jniclass_name); + Printf(wrapper_name, "Java_%s%s_%%f", Char(jnipackage), jniname); + Delete(jniname); + + Swig_name_register((char*)"wrapper", Char(wrapper_name)); + Swig_name_register((char*)"set", (char*)"set_%v"); + Swig_name_register((char*)"get", (char*)"get_%v"); + Swig_name_register((char*)"member", (char*)"%c_%m"); + + Delete(wrapper_name); + + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"extern \"C\" {\n"); + Printf(f_wrappers,"#endif\n"); + + /* Emit code */ + Language::top(n); + + // Generate the Java JNI class + { + String *filen = NewStringf("%s.java", jniclass_name); + File *f_java = NewFile(filen,"w"); + if(!f_java) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit(EXIT_FAILURE); } + Delete(filen); filen = NULL; + + // Start writing out the Java JNI class + if(Len(package) > 0) + Printf(f_java, "package %s;\n\n", package); + + emitBanner(f_java); + if(jniclass_imports) + Printf(f_java, "%s\n", jniclass_imports); + + if (Len(jniclass_class_modifiers) > 0) + Printf(f_java, "%s ", jniclass_class_modifiers); + Printf(f_java, "class %s ", jniclass_name); + + if (jniclass_baseclass && *Char(jniclass_baseclass)) + Printf(f_java, "extends %s ", jniclass_baseclass); + if (Len(jniclass_interfaces) > 0) + Printv(f_java, "implements ", jniclass_interfaces, " ", NIL); + Printf(f_java, "{\n"); + + // Add the native methods + Printv(f_java, jniclass_class_code, NIL); + Printv(f_java, jniclass_cppcasts_code, NIL); + + // Finish off the Java class + Printf(f_java, "}\n"); + Close(f_java); } - } - if(jnic == -1) { - if(CPlusPlus) - jnic = 0; - else jnic = 1; - } + // Generate the Java module class + { + String *filen = NewStringf("%s.java", module_class_name); + File *f_module = NewFile(filen,"w"); + if(!f_module) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit(EXIT_FAILURE); + } + Delete(filen); filen = NULL; - // Add a symbol to the parser for conditional compilation - // cpp::define("SWIGJAVA"); - Preprocessor_define((void *) "SWIGJAVA 1",0); + // Start writing out the Java module class + if(Len(package) > 0) + Printf(f_module, "package %s;\n\n", package); - // Add typemap definitions - typemap_lang = (char*)"java"; -} + emitBanner(f_module); + if(module_imports) + Printf(f_module, "%s\n", module_imports); -// --------------------------------------------------------------------- -// void JAVA::parse() -// -// Start parsing an interface file for JAVA. -// --------------------------------------------------------------------- + if (Len(module_class_modifiers) > 0) + Printf(f_module, "%s ", module_class_modifiers); + Printf(f_module, "class %s ", module_class_name); -void JAVA::parse() { + if (module_baseclass && *Char(module_baseclass)) + Printf(f_module, "extends %s ", module_baseclass); + if (Len(module_interfaces) > 0) + Printv(f_module, "implements ", module_interfaces, " ", NIL); + Printf(f_module, "{\n"); - Printf(stderr,"Generating wrappers for Java\n"); + // Add the wrapper methods + Printv(f_module, module_class_code, NIL); - shadow_classes = NewHash(); - shadow_classdef = NewString(""); - registerNativesList = NewString(""); + // Write out all the enums constants + if (Len(module_constants_code) != 0 ) + Printv(f_module, " // enums and constants\n", module_constants_code, NIL); - headers(); // Emit header files and other supporting code - yyparse(); // Run the SWIG parser -} + // Finish off the Java class + Printf(f_module, "}\n"); + Close(f_module); + } -// --------------------------------------------------------------------- -// JAVA::set_module(char *mod_name,char **mod_list) -// -// Sets the module name. Does nothing if it's already set (so it can -// be overriddent as a command line option). -// -// mod_list is a NULL-terminated list of additional modules. This -// is really only useful when building static executables. -//---------------------------------------------------------------------- - -void JAVA::set_module(char *mod_name, char **mod_list) { - if (module) return; - module = new char[strlen(mod_name)+1]; - strcpy(module,mod_name); -} + if(wrapper_conversion_code) + Printv(f_wrappers,wrapper_conversion_code,NIL); -// --------------------------------------------------------------------- -// JAVA::headers(void) -// -// Generate the appropriate header files for JAVA interface. -// ---------------------------------------------------------------------- - -void JAVA::headers(void) -{ - Swig_banner(f_header); // Print the SWIG banner message - Printf(f_header,"/* Implementation : Java */\n\n"); - - // Include header file code fragment into the output - // if (file::include("java.swg",f_header) == -1) { - if (Swig_insert_file("java.swg",f_header) == -1) { - Printf(stderr,"Fatal Error. Unable to locate 'java.swg'.\n"); - SWIG_exit (EXIT_FAILURE); - } -} + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"}\n"); + Printf(f_wrappers,"#endif\n"); -// -------------------------------------------------------------------- -// JAVA::initialize(void) -// -// Produces an initialization function. Assumes that the init function -// name has already been specified. -// --------------------------------------------------------------------- - -void JAVA::initialize() -{ - if (!module) { - Printf(stderr,"*** Error. No module name specified.\n"); - SWIG_exit(1); - } + // Output a Java class for each SWIG type + for (String *swig_type = Firstkey(swig_types_hash); swig_type; swig_type = Nextkey(swig_types_hash)) { + emitJavaClass(swig_type, Getattr(swig_types_hash, swig_type)); + } - if(package) { - DOHString *s = NewString(package); - Replace(s,".","_", DOH_REPLACE_ANY); - Append(s,"_"); - c_pkgstr = Swig_copy_string(Char(s)); - Delete(s); - - DOHString *s2 = NewString(package); - Replace(s2,".","/", DOH_REPLACE_ANY); - Append(s2,"/"); - jni_pkgstr = Swig_copy_string(Char(s2)); - Delete(s2); - } else { - package = c_pkgstr = jni_pkgstr = (char*)""; + Delete(swig_types_hash); swig_types_hash = NULL; + Delete(jniclass_name); jniclass_name = NULL; + Delete(jniclass_class_code); jniclass_class_code = NULL; + Delete(shadow_classdef); shadow_classdef = NULL; + Delete(shadow_code); shadow_code = NULL; + Delete(module_constants_code); module_constants_code = NULL; + Delete(jniclass_baseclass); jniclass_baseclass = NULL; + Delete(jniclass_interfaces); jniclass_interfaces = NULL; + Delete(jniclass_class_modifiers); jniclass_class_modifiers = NULL; + Delete(module_class_name); module_class_name = NULL; + Delete(module_class_code); module_class_code = NULL; + Delete(module_baseclass); module_baseclass = NULL; + Delete(module_interfaces); module_interfaces = NULL; + Delete(module_imports); module_imports = NULL; + Delete(module_class_modifiers); module_class_modifiers = NULL; + Delete(jniclass_imports); jniclass_imports = NULL; + Delete(jniclass_cppcasts_code); jniclass_cppcasts_code = NULL; + Delete(wrapper_conversion_code); wrapper_conversion_code = NULL; + Delete(package); package = NULL; + Delete(jnipackage); jnipackage = NULL; + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; } - sprintf(bigbuf, "Java_%s%s", c_pkgstr, module); - c_pkgstr = Swig_copy_string(bigbuf); - sprintf(bigbuf, "%s_%%f", c_pkgstr); - Swig_name_register((char*)"wrapper", Swig_copy_string(bigbuf)); - Swig_name_register((char*)"set", (char*)"set_%v"); - Swig_name_register((char*)"get", (char*)"get_%v"); - Swig_name_register((char*)"member", (char*)"%c_%m"); - - // Generate the java class - sprintf(bigbuf, "%s.java", module); - if((f_java = fopen(bigbuf, "w")) == 0) { - Printf(stderr,"Unable to open %s\n", bigbuf); - SWIG_exit(1); + /* ----------------------------------------------------------------------------- + * emitBanner() + * ----------------------------------------------------------------------------- */ + + void emitBanner(File *f) { + Printf(f, "/* ----------------------------------------------------------------------------\n"); + Printf(f, " * This file was automatically generated by SWIG (http://www.swig.org).\n"); + Printf(f, " * Version: %s\n", SWIG_VERSION); + Printf(f, " *\n"); + Printf(f, " * Do not make changes to this file unless you know what you are doing--modify\n"); + Printf(f, " * the SWIG interface file instead.\n"); + Printf(f, " * ----------------------------------------------------------------------------- */\n\n"); } - Printf(f_header, "#define J_CLASSNAME %s\n", module); - if(package && *package) { - Printf(f_java, "package %s;\n\n", package); - Printf(f_header, "#define J_PACKAGE %s\n", package); - } else { - Printf(f_header, "#define J_PACKAGE\n"); - } -} + /* ---------------------------------------------------------------------- + * nativeWrapper() + * ---------------------------------------------------------------------- */ -void JAVA::emit_classdef() { - if(!classdef_emitted) - Printf(f_java, "public class %s {\n", module); - classdef_emitted = 1; -} + virtual int nativeWrapper(Node *n) { + String *wrapname = Getattr(n,"wrap:name"); -// --------------------------------------------------------------------- -// JAVA::close(void) -// -// Wrap things up. Close initialization function. -// --------------------------------------------------------------------- + if (!addSymbol(wrapname,n)) return SWIG_ERROR; -void JAVA::close(void) -{ - if(!classdef_emitted) emit_classdef(); + if (Getattr(n,"type")) { + Swig_save(&n,"name",NIL); + Setattr(n,"name", wrapname); + native_function_flag = true; + functionWrapper(n); + Swig_restore(&n); + native_function_flag = false; + } else { + Printf(stderr,"%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n,"wrap:name")); + } - // Finish off the java class - Printf(f_java, "}\n"); - fclose(f_java); + return SWIG_OK; + } - if(useRegisterNatives) - writeRegisterNatives(); -} + /* ---------------------------------------------------------------------- + * functionWrapper() + * ---------------------------------------------------------------------- */ + + virtual int functionWrapper(Node *n) { + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *tm; + Parm *p; + int i; + String *jnirettype = NewString(""); + String *javarettype = NewString(""); + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *body = NewString(""); + String *javaParameterSignature = NewString(""); + int num_arguments = 0; + int num_required = 0; + bool is_void_return; + String *overloaded_name = getOverloadedName(n); + + if (!Getattr(n,"sym:overloaded")) { + if (!addSymbol(Getattr(n,"sym:name"),n)) return SWIG_ERROR; + } -// ---------------------------------------------------------------------- -// JAVA::create_command(char *cname, char *iname) -// -// Creates a JAVA command from a C function. -// ---------------------------------------------------------------------- + /* + Generate the java class wrapper function ie the java shadow class. Only done for public + member variables. That is this generates the getters/setters for member variables. + Not for enums and constants. + */ + if(proxy_flag && wrapping_member_flag && !enum_constant_flag) { + // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name + String *getter_setter_name = NewString(""); + if(Cmp(symname, Swig_name_set(Swig_name_member(shadow_classname, variable_name))) == 0) + Printf(getter_setter_name,"set"); + else + Printf(getter_setter_name,"get"); + Putc(toupper((int) *Char(variable_name)), getter_setter_name); + Printf(getter_setter_name, "%s", Char(variable_name)+1); + + Setattr(n,"java:shadowfuncname", getter_setter_name); + Setattr(n,"java:funcname", symname); + + javaShadowFunctionHandler(n); + + Delete(getter_setter_name); + } -void JAVA::create_command(char *cname, char *iname) { -} + /* + The rest of this function deals with generating the java wrapper function (that wraps + a c/c++ function) and generating the JNI c code. Each java wrapper function has a + matching JNI c function call. + */ -void JAVA::add_native(char *name, char *iname, DataType *t, ParmList *l) { - native_func = 1; - create_function(name, iname, t, l); - native_func = 0; -} + // A new wrapper function object + Wrapper *f = NewWrapper(); -// ---------------------------------------------------------------------- -// JAVA::create_function(char *name, char *iname, DataType *d, ParmList *l) -// -// Create a function declaration and register it with the interpreter. -// ---------------------------------------------------------------------- - -void JAVA::create_function(char *name, char *iname, DataType *t, ParmList *l) -{ - char source[256], target[256]; - char *tm; - DOHString *cleanup, *outarg, *body; - char *javaReturnSignature = 0; - DOHString *javaParameterSignature; - Parm *p; - - cleanup = NewString(""); - outarg = NewString(""); - body = NewString(""); - javaParameterSignature = NewString(""); - - // A new wrapper function object - Wrapper *f = NewWrapper(); - - if(!classdef_emitted) emit_classdef(); - - // Make a wrapper name for this function - - char *jniname = makeValidJniName(iname); - char *wname = Swig_name_wrapper(jniname); - free(jniname); - - char *jnirettype = JavaTypeFromTypemap((char*)"jni", typemap_lang, t, iname); - if(!jnirettype) jnirettype = SwigTcToJniType(t, 1); - char *javarettype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, t, iname); - if(!javarettype) javarettype = SwigTcToJavaType(t, 1, 0); - - // If dumping the registerNative outputs, store the method return type - // signature - if (useRegisterNatives) { - javaReturnSignature = JavaMethodSignature(t, 1, 0); - } + // Make a wrapper name for this function + String *jniname = makeValidJniName(overloaded_name); + String *wname = Swig_name_wrapper(jniname); + Delete(jniname); - if (DataType_type(t) != T_VOID) { - Wrapper_add_localv(f,"_jresult", jnirettype, "_jresult = 0",0); - } + /* Attach the non-standard typemaps to the parameter list. */ + Swig_typemap_attach_parms("jni", l, f); + Swig_typemap_attach_parms("jtype", l, f); - Printf(f_java, " %s ", method_modifiers); - Printf(f_java, "native %s %s(", javarettype, iname); - if(shadow && member_func) { - DOHString *member_name = NewString(""); - if(strcmp(iname, Swig_name_set(Swig_name_member(shadow_classname, shadow_name))) == 0) - Printf(member_name,"set"); - else Printf(member_name,"get"); - Putc(toupper((int) *shadow_name), member_name); - Printf(member_name, "%s", shadow_name+1); - Printf(f_shadow, " public %s %s(", javarettype, member_name); - Printv(body, tab4, "return ", module, ".", iname, "(_self", 0); - Delete(member_name); - } + /* Get Java return types */ + if ((tm = Swig_typemap_lookup_new("jni",n,"",0))) { + Printf(jnirettype,"%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, + "No jni typemap defined for %s\n", SwigType_str(t,0)); + } - if(!jnic) Printf(f->def,"extern \"C\"\n"); - Printv(f->def, "JNIEXPORT ", jnirettype, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", 0); - - // Emit all of the local variables for holding arguments. - int pcount = emit_args(t,l,f); - - int gencomma = 0; - - // Now walk the function parameter list and generate code to get arguments - p = l; - for (int i = 0; i < pcount ; i++, p = Getnext(p)) { - DataType *pt = Gettype(p); - char *pn = Getname(p); - char *target_copy = NULL; - char *target_length = NULL; - char *local_i = NULL; - - // Produce string representation of source and target arguments - sprintf(source,"jarg%d",i); - sprintf(target,"%s", Getlname(p)); - - char *jnitype = JavaTypeFromTypemap((char*)"jni", typemap_lang, pt, pn); - if(!jnitype) jnitype = SwigTcToJniType(pt, 0); - char *jtype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, pt, pn); - if(!jtype) jtype = SwigTcToJavaType(pt, 0, 0); - if (useRegisterNatives) { - Printv(javaParameterSignature, JavaMethodSignature(pt, 0, 0), 0); + if ((tm = Swig_typemap_lookup_new("jtype",n,"",0))) { + Printf(javarettype,"%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, + "No jtype typemap defined for %s\n", SwigType_str(t,0)); } - if(Getignore(p)) continue; + is_void_return = (Cmp(jnirettype, "void") == 0); + if (!is_void_return) + Wrapper_add_localv(f,"jresult", jnirettype, "jresult = 0",NIL); - // Add to java function header - if(shadow && member_func) { - if(i > 0) { - if(i>1) Printf(f_shadow, ", "); - Printf(f_shadow, "%s %s", jtype, source); - Printv(body,", ", source, 0); - } + Printf(jniclass_class_code, " public final static native %s %s(", javarettype, overloaded_name); + + Printv(f->def, "JNIEXPORT ", jnirettype, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL); + + // Usually these function parameters are unused - The code below ensures that compilers do not issue such a warning if configured to do so. + Printv(f->code," (void)jenv;\n",NIL); + Printv(f->code," (void)jcls;\n",NIL); + + // Emit all of the local variables for holding arguments. + emit_args(t,l,f); + + /* Attach the standard typemaps */ + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + + /* Get number of required and total arguments */ + num_arguments = emit_num_arguments(l); + num_required = emit_num_required(l); + + int gencomma = 0; + + // Now walk the function parameter list and generate code to get arguments + for (i = 0, p=l; i < num_arguments; i++) { + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); + String *javaparamtype = NewString(""); + String *jni_param_type = NewString(""); + String *arg = NewString(""); + + Printf(arg,"j%s", ln); + + /* Get the jni types of the parameter */ + if ((tm = Getattr(p,"tmap:jni"))) { + Printv(jni_param_type, tm, NIL); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, + "No jni typemap defined for %s\n", SwigType_str(pt,0)); } - if(gencomma) Printf(f_java, ", "); - Printf(f_java, "%s %s", jtype, source); + /* Get the java types of the parameter */ + if ((tm = Getattr(p,"tmap:jtype"))) { + Printv(javaparamtype, tm, NIL); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, + "No jtype typemap defined for %s\n", SwigType_str(pt,0)); + } + + /* Add to java function header */ + if(gencomma) Printf(jniclass_class_code, ", "); + Printf(jniclass_class_code, "%s %s", javaparamtype, arg); gencomma = 1; // Add to Jni function header - Printv(f->def, ", ", jnitype, " ", source, 0); + Printv(f->def, ", ", jni_param_type, " ", arg, NIL); // Get typemap for this argument - tm = typemap_lookup((char*)"in",typemap_lang,pt,pn,source,target,f); - if (tm) { - Printf(f->code,"%s\n", tm); - Replace(f->code,"$arg",source, DOH_REPLACE_ANY); + if ((tm = Getattr(p,"tmap:in"))) { + addThrows(n, "tmap:in", p); + Replaceall(tm,"$source",arg); /* deprecated */ + Replaceall(tm,"$target",ln); /* deprecated */ + Replaceall(tm,"$arg",arg); /* deprecated? */ + Replaceall(tm,"$input", arg); + Setattr(p,"emit:input", arg); + Printf(f->code,"%s\n", tm); + p = Getattr(p,"tmap:in:next"); } else { - if(!DataType_is_pointer(pt)) - Printv(f->code, tab4, target, " = (", DataType_lstr(pt,0), ") ", source, ";\n", 0); - else if((DataType_Gettypecode(pt) == T_VOID && (DataType_is_pointer(pt) == 1)) || - (DataType_Gettypecode(pt) == T_USER && (DataType_is_pointer(pt) == 1))) { - DataType_add_pointer(pt); - Printv(f->code, tab4, target, " = *(", DataType_lstr(pt,0), ")&", source, ";\n", 0); - DataType_del_pointer(pt); - } else { - if(DataType_type(pt) == T_STRING) { - Printv(f->code, tab4, target, " = (", source, ") ? (char *)", JNICALL((char*)"GetStringUTFChars"), source, ", 0) : NULL;\n", 0); - } else { - char *scalarType = SwigTcToJniScalarType(pt); - - DataType_del_pointer(pt); - const char *basic_jnitype = (DataType_is_pointer(pt) > 0) ? "jlong" : SwigTcToJniType(pt, 0); - char *ctype = DataType_lstr(pt,0); - if(scalarType == NULL || basic_jnitype == NULL) { - Printf(stderr, "\'%s\' does not have a in/jni typemap, and is not a basic type.\n", ctype); - SWIG_exit(1); - }; - DataType_add_pointer(pt); - - DOHString *basic_jniptrtype = NewStringf("%s*",basic_jnitype); - DOHString *source_length = NewStringf("%s%s)", JNICALL((char*)"GetArrayLength"), source); - - target_copy = Swig_copy_string(Wrapper_new_localv(f,target,Char(basic_jniptrtype), target, 0)); - target_length = Swig_copy_string(Wrapper_new_localv(f,target,"jsize", target, "=", Char(source_length),0)); - if(local_i == NULL) local_i = Swig_copy_string(Wrapper_new_local(f,"i","int i")); - - DOHString *scalarFunc = NewStringf("Get%sArrayElements",scalarType); - - Printv(f->code, tab4, target_copy, " = ", JNICALL(scalarFunc), source, ", 0);\n", 0); - Printv(f->code, tab4, target, " = (", DataType_lstr(pt,0), ") malloc(", target_length, " * sizeof(", ctype, "));\n", 0); - Printv(f->code, tab4, "for(i=0; i<", target_length, "; i++)\n", 0); - if(DataType_is_pointer(pt) > 1) { - Printv(f->code, tab8, target, "[i] = *(", DataType_lstr(pt,0), ")&", target_copy, "[i];\n", 0); - } else { - DataType_del_pointer(pt); - Printv(f->code, tab8, target, "[i] = (", DataType_lstr(pt,0), ")", target_copy, "[i];\n", 0); - DataType_add_pointer(pt); - } - Delete(scalarFunc); - Delete(source_length); - Delete(basic_jniptrtype); - } - } + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument.\n",SwigType_str(pt,0)); + p = nextSibling(p); } - - // Check to see if there was any sort of a constaint typemap - if ((tm = typemap_lookup((char*)"check",typemap_lang,pt,pn,source,target))) { - // Yep. Use it instead of the default - Printf(f->code,"%s\n", tm); - Replace(f->code,"$arg",source, DOH_REPLACE_ANY); + Delete(javaparamtype); + Delete(jni_param_type); + Delete(arg); } - // Check if there was any cleanup code (save it for later) - if ((tm = typemap_lookup((char*)"freearg",typemap_lang,pt,pn,source,target))) { - // Yep. Use it instead of the default - Printf(cleanup,"%s\n", tm); - Replace(cleanup,"$arg",source, DOH_REPLACE_ANY); + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + addThrows(n, "tmap:check", p); + Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */ + Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */ + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } } - if ((tm = typemap_lookup((char*)"argout",typemap_lang,pt,pn,source,target))) { - // Yep. Use it instead of the default - Printf(outarg,"%s\n", tm); - Replace(outarg,"$arg",source, DOH_REPLACE_ANY); - } else { - // if(pt->is_pointer && pt->type != T_USER && pt->type != T_VOID) { - if(DataType_is_pointer(pt)) { - if(DataType_type(pt) == T_STRING) { - Printv(outarg, tab4, "if(", target,") ", JNICALL((char*)"ReleaseStringUTFChars"), source, ", ", target, ");\n", 0); - } else if(((DataType_Gettypecode(pt) == T_VOID) && DataType_is_pointer(pt) == 1) || - ((DataType_Gettypecode(pt) == T_USER) && DataType_is_pointer(pt) == 1)) { - // nothing to do - } else { - char *scalarType = SwigTcToJniScalarType(pt); - - DataType_del_pointer(pt); - const char *basic_jnitype = (DataType_is_pointer(pt) > 0) ? "jlong" : SwigTcToJniType(pt, 0); - char *ctype = DataType_lstr(pt,0); - if(scalarType == NULL || basic_jnitype == NULL) { - Printf(stderr, "\'%s\' does not have a argout/jni typemap, and is not a basic type.\n", ctype); - SWIG_exit(1); - }; - DataType_add_pointer(pt); - Printf(outarg, " for(i=0; i< %d; i++)\n", target_length); - if(DataType_is_pointer(pt) > 1) { - Printv(outarg, tab8, "*(", DataType_lstr(pt,0), ")&", target_copy, "[i] = ", target, "[i];\n", 0); - } else { - Printv(outarg, tab8, target_copy, "[i] = (", basic_jnitype, ") ", target, "[i];\n", 0); - } - DOHString *scalarFunc = NewStringf("Release%sArrayElements",scalarType); - Printv(outarg, tab4, JNICALL(scalarFunc), source, ", ", target_copy, ", 0);\n", 0); - Printv(outarg, tab4, "free(", target, ");\n", 0); - Delete(scalarFunc); - free(target_copy); - free(target_length); - free(local_i); - } - } + /* Insert cleanup code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:freearg"))) { + addThrows(n, "tmap:freearg", p); + Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */ + Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */ + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } } - } - Printf(f_java, ");\n"); - if(shadow && member_func) { - Printf(f_shadow, ") {\n"); - Printf(body,")"); - Printf(f_shadow, "%s;\n }\n\n",body); - } - Printf(f->def,") {"); + /* Insert argument output code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:argout"))) { + addThrows(n, "tmap:argout", p); + Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */ + Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */ + Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */ + Replaceall(tm,"$result","jresult"); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); + } + } - // Now write code to make the function call + // Get any Java exception classes in the throw typemap + if (ParmList *throw_parm_list = Getattr(n,"throws")) { + Swig_typemap_attach_parms("throws", throw_parm_list, f); + for (p = throw_parm_list; p; p=nextSibling(p)) { + if ((tm = Getattr(p,"tmap:throws"))) { + addThrows(n, "tmap:throws", p); + } + } + } - if(!native_func) - emit_func_call(name,t,l,f); + if (Cmp(nodeType(n), "constant") == 0) { + // Wrapping a constant hack + Swig_save(&n,"wrap:action",NIL); - // Return value if necessary + // below based on Swig_VargetToFunction() + SwigType *ty = Swig_wrapped_var_type(Getattr(n,"type")); + Setattr(n,"wrap:action", NewStringf("result = (%s) %s;\n", SwigType_lstr(ty,0), Getattr(n, "value"))); + } - if((DataType_type(t) != T_VOID) && !native_func) { - if ((tm = typemap_lookup((char*)"out",typemap_lang,t,iname,(char*)"result",(char*)"_jresult"))) { - Printf(f->code,"%s\n", tm); - } else { - if(DataType_type(t) == T_USER) { /* return by value */ - DataType_add_pointer(t); - DataType_add_pointer(t); - Printv(f->code, tab4, "*(", DataType_lstr(t,0), ")&_jresult = result;\n", 0); - DataType_del_pointer(t); - DataType_del_pointer(t); - } else if(DataType_is_pointer(t) == 0 && (DataType_Gettypecode(t) != T_USER)) { - Printv(f->code, tab4, "_jresult = (", jnirettype, ") result;\n", 0); - } else if(((DataType_Gettypecode(t) == T_VOID) && DataType_is_pointer(t) == 1) || - ((DataType_Gettypecode(t) == T_USER) && DataType_is_pointer(t) == 1)) { - DataType_add_pointer(t); - Printv(f->code, tab4, "*(", DataType_lstr(t,0), ")&_jresult = result;\n", 0); - DataType_del_pointer(t); + // Now write code to make the function call + if(!native_function_flag) + emit_action(n,f); + + if (Cmp(nodeType(n), "constant") == 0) + Swig_restore(&n); + + /* Return value if necessary */ + if(!native_function_flag) { + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + addThrows(n, "tmap:out", n); + Replaceall(tm,"$source", "result"); /* deprecated */ + Replaceall(tm,"$target", "jresult"); /* deprecated */ + Replaceall(tm,"$result","jresult"); + Printf(f->code,"%s", tm); + if (Len(tm)) + Printf(f->code,"\n"); } else { - if(DataType_type(t) == T_STRING) { - Printv(f->code, tab4, "if(result != NULL)\n", 0); - Printv(f->code, tab8, "_jresult = (jstring)", JNICALL((char*)"NewStringUTF"), "result);\n", 0); - } else { - Printf(stderr,"%s : Line %d. Warning: no return typemap for datatype %s\n", input_file,line_number,DataType_str(t,0)); - DataType_add_pointer(t); - Printv(f->code, tab4, "*(", DataType_lstr(t,0), ")&_jresult = result;\n", 0); - DataType_del_pointer(t); - } + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s in function %s.\n", SwigType_str(t,0), Getattr(n,"name")); } } - } - // Dump argument output code; - Printv(f->code, outarg, 0); + /* Output argument output code */ + Printv(f->code,outarg,NIL); - // Dump the argument cleanup code - Printv(f->code,cleanup, 0); + /* Output cleanup code */ + Printv(f->code,cleanup,NIL); - // Look for any remaining cleanup + /* Look to see if there is any newfree cleanup code */ + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); /* deprecated */ + Printf(f->code,"%s\n",tm); + } + } - if (NewObject) { - if ((tm = typemap_lookup((char*)"newfree",typemap_lang,t,iname,(char*)"result",(char*)""))) { - Printf(f->code,"%s\n", tm); + /* See if there is any return cleanup code */ + if(!native_function_flag) { + if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) { + Replaceall(tm,"$source","result"); /* deprecated */ + Printf(f->code,"%s\n",tm); + } } - } - if((DataType_type(t) != T_VOID) && !native_func) { - if ((tm = typemap_lookup((char*)"ret",typemap_lang,t,iname,(char*)"result",(char*)"_jresult", NULL))) { - Printf(f->code,"%s\n", tm); + /* Finish JNI C function and JNI class native function definitions */ + Printf(jniclass_class_code, ")"); + generateThrowsClause(n, jniclass_class_code); + Printf(jniclass_class_code, ";\n"); + Printf(f->def,") {"); + + if(!is_void_return) + Printv(f->code, " return jresult;\n", NIL); + Printf(f->code, "}\n"); + + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); + + if(!is_void_return) + Replaceall(f->code,"$null","0"); + else + Replaceall(f->code,"$null",""); + + /* Dump the function out */ + if(!native_function_flag) + Wrapper_print(f,f_wrappers); + + Setattr(n,"wrap:name", wname); + + /* Emit warnings for the few cases that can't be overloaded in Java */ + if (Getattr(n,"sym:overloaded")) { + if (!Getattr(n,"sym:nextSibling")) + Swig_overload_rank(n); + } + + if(!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) { + moduleClassFunctionHandler(n); } - } - // Wrap things up (in a manner of speaking) - if(DataType_type(t) != T_VOID) - Printv(f->code, tab4, "return _jresult;\n", 0); - Printf(f->code, "}\n"); + Delete(jnirettype); + Delete(javarettype); + Delete(cleanup); + Delete(outarg); + Delete(body); + Delete(javaParameterSignature); + Delete(overloaded_name); + DelWrapper(f); + return SWIG_OK; + } - // Substitute the cleanup code (some exception handlers like to have this) - Replace(f->code,"$cleanup",cleanup, DOH_REPLACE_ANY); + /* ----------------------------------------------------------------------- + * variableWrapper() + * + * Create a JAVA link to a C variable. + * ----------------------------------------------------------------------- */ - // Emit the function + virtual int variableWrapper(Node *n) { + Language::variableWrapper(n); /* Default to functions */ + return SWIG_OK; + } - if(!native_func) - Wrapper_print(f,f_wrappers); + /* ----------------------------------------------------------------------- + * globalvariableHandler() + * ------------------------------------------------------------------------ */ - // If registerNatives is active, store the table entry for this method - if (useRegisterNatives) { - Printv(registerNativesList, - tab4, "{", - "\"", name, "\", \"(", javaParameterSignature, ")", javaReturnSignature, "\", ", wname, - "},\n", - 0); + virtual int globalvariableHandler(Node *n) { + variable_name = Getattr(n,"sym:name"); + global_variable_flag = true; + int ret = Language::globalvariableHandler(n); + global_variable_flag = false; + return ret; } - Delete(cleanup); - Delete(outarg); - Delete(body); - Delete(javaParameterSignature); - DelWrapper(f); -} + /* ----------------------------------------------------------------------- + * constantWrapper() + * ------------------------------------------------------------------------ */ -// ----------------------------------------------------------------------- -// JAVA::link_variable(char *name, char *iname, DataType *t) -// -// Create a JAVA link to a C variable. -// ----------------------------------------------------------------------- + virtual int constantWrapper(Node *n) { + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *tm; + String *shadowrettype = NewString(""); + String *constants_code = NewString(""); -void JAVA::link_variable(char *name, char *iname, DataType *t) -{ - emit_set_get(name,iname, t); -} + if (!addSymbol(symname,n)) return SWIG_ERROR; -// ----------------------------------------------------------------------- -// JAVA::declare_const(char *name, char *iname, DataType *type, char *value) -// ------------------------------------------------------------------------ + /* Attach the non-standard typemaps to the parameter list. */ + Swig_typemap_attach_parms("jstype", l, NULL); -void JAVA::declare_const(char *name, char *iname, DataType *type, char *value) { - char *tm; - FILE *jfile; - char *jname; + /* Get Java return types */ + bool is_return_type_java_class = false; + if ((tm = Swig_typemap_lookup_new("jstype",n,"",0))) { + is_return_type_java_class = substituteJavaclassname(t, tm); + Printf(shadowrettype, "%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, + "No jstype typemap defined for %s\n", SwigType_str(t,0)); + } - if(!classdef_emitted) emit_classdef(); + // Add the stripped quotes back in + String *new_value = NewString(""); + Swig_save(&n,"value",NIL); + if(SwigType_type(t) == T_STRING) { + Printf(new_value, "\"%s\"", Copy(Getattr(n, "value"))); + Setattr(n, "value", new_value); + } + else if(SwigType_type(t) == T_CHAR) { + Printf(new_value, "\'%s\'", Copy(Getattr(n, "value"))); + Setattr(n, "value", new_value); + } - if(shadow && member_func) { - jfile = f_shadow; - jname = shadow_name; - } else { - jfile = f_java; - jname = name; - } + // enums are wrapped using a public final static int in java. + // Other constants are wrapped using a public final static [jstype] in Java. + Printf(constants_code, " public final static %s %s = ", shadowrettype, ((proxy_flag && wrapping_member_flag) ? variable_name : symname)); - if ((tm = typemap_lookup((char*)"const",typemap_lang,type,name,name,iname))) { - DOHString *str = NewString(tm); - Replace(str,"$value",value, DOH_REPLACE_ANY); - Printf(jfile," %s\n\n", str); - Delete(str); - } else { - if((DataType_is_pointer(type) == 0)) { - char *jtype = typemap_lookup((char*)"jtype", typemap_lang, type, name, name, iname); - if(!jtype) jtype = SwigTcToJavaType(type, 0, 0); - if(strcmp(jname, value) == 0 || strstr(value,"::") != NULL) { - Printf(stderr, "ignoring enum constant: %s\n", jname); - } else - Printf(jfile, " public final static %s %s = %s;\n\n", jtype, jname, value); + // The %javaconst directive determines how the constant value is obtained + String *javaconst = Getattr(n,"feature:java:const"); + if (Cmp(nodeType(n), "enumitem") == 0 || !javaconst || Cmp(javaconst, "0") == 0) { + // Enums and default constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call. + + if(is_return_type_java_class) // This handles function pointers using the %constant directive + Printf(constants_code, "new %s(%s.%s(), false);\n", shadowrettype, jniclass_name, Swig_name_get(symname)); + else + Printf(constants_code, "%s.%s();\n", jniclass_name, Swig_name_get(symname)); + + // Each constant and enum value is wrapped with a separate JNI function call + enum_constant_flag = true; + variableWrapper(n); + enum_constant_flag = false; } else { - if(DataType_type(type) == T_STRING) { - Printf(jfile, " public final static String %s = \"%s\";\n\n", jname, value); - } else { - emit_set_get(name,iname, type); + // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code + Printf(constants_code, "%s;\n", Getattr(n,"value")); + } + + if(proxy_flag && wrapping_member_flag) + Printv(shadow_constants_code, constants_code, NIL); + else + Printv(module_constants_code, constants_code, NIL); + + Swig_restore(&n); + Delete(new_value); + Delete(shadowrettype); + Delete(constants_code); + return SWIG_OK; + } + + /* ----------------------------------------------------------------------------- + * pragmaDirective() + * + * Valid Pragmas: + * jniclassbase - base (extends) for the JNI class + * jniclassclassmodifiers - class modifiers for the JNI class + * jniclasscode - text (java code) is copied verbatim to the JNI class + * jniclassimports - import statements for the JNI class + * jniclassinterfaces - interface (implements) for the JNI class + * + * modulebase - base (extends) for the module class + * moduleclassmodifiers - class modifiers for the module class + * modulecode - text (java code) is copied verbatim to the module class + * moduleimports - import statements for the module class + * moduleinterfaces - interface (implements) for the module class + * + * ----------------------------------------------------------------------------- */ + + virtual int pragmaDirective(Node *n) { + if (!ImportMode) { + String *lang = Getattr(n,"lang"); + String *code = Getattr(n,"name"); + String *value = Getattr(n,"value"); + + if(Strcmp(lang, "java") == 0) { + + String *strvalue = NewString(value); + Replaceall(strvalue,"\\\"", "\""); + + if(Strcmp(code, "jniclassbase") == 0) { + Delete(jniclass_baseclass); + jniclass_baseclass = Copy(strvalue); + } + else if(Strcmp(code, "jniclassclassmodifiers") == 0) { + Delete(jniclass_class_modifiers); + jniclass_class_modifiers = Copy(strvalue); + } + else if(Strcmp(code, "jniclasscode") == 0) { + Printf(jniclass_class_code, "%s\n", strvalue); + } + else if(Strcmp(code, "jniclassimports") == 0) { + Delete(jniclass_imports); + jniclass_imports = Copy(strvalue); + } + else if(Strcmp(code, "jniclassinterfaces") == 0) { + Delete(jniclass_interfaces); + jniclass_interfaces = Copy(strvalue); + } + else if(Strcmp(code, "modulebase") == 0) { + Delete(module_baseclass); + module_baseclass = Copy(strvalue); + } + else if(Strcmp(code, "moduleclassmodifiers") == 0) { + Delete(module_class_modifiers); + module_class_modifiers = Copy(strvalue); + } + else if(Strcmp(code, "modulecode") == 0) { + Printf(module_class_code, "%s\n", strvalue); + } + else if(Strcmp(code, "moduleimports") == 0) { + Delete(module_imports); + module_imports = Copy(strvalue); + } + else if(Strcmp(code, "moduleinterfaces") == 0) { + Delete(module_interfaces); + module_interfaces = Copy(strvalue); + } + else if(Strcmp(code, "moduleimport") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use the moduleimports pragma.\n", input_file, line_number); + } + else if(Strcmp(code, "moduleinterface") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use the moduleinterfaces pragma.\n", input_file, line_number); + } + else if(Strcmp(code, "modulemethodmodifiers") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %javamethodmodifiers.\n", input_file, line_number); + } + else if(Strcmp(code, "allshadowimport") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javaimports).\n", input_file, line_number); + } + else if(Strcmp(code, "allshadowcode") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javacode).\n", input_file, line_number); + } + else if(Strcmp(code, "allshadowbase") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javabase).\n", input_file, line_number); + } + else if(Strcmp(code, "allshadowinterface") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javainterfaces).\n", input_file, line_number); + } + else if(Strcmp(code, "allshadowclassmodifiers") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javaclassmodifiers).\n", input_file, line_number); + } + else if (proxy_flag) { + if (Strcmp(code,"shadowcode") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javacode).\n", input_file, line_number); + } + else if (Strcmp(code,"shadowimport") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javaimports).\n", input_file, line_number); + } + else if (Strcmp(code,"shadowbase") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javabase).\n", input_file, line_number); + } + else if (Strcmp(code,"shadowinterface") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javainterfaces).\n", input_file, line_number); + } + else if (Strcmp(code,"shadowclassmodifiers") == 0) { + Printf(stderr,"%s : Line %d. Ignored: Deprecated pragma. Please use %typemap(javaclassmodifiers).\n", input_file, line_number); + } else { + Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number); + } + } else { + Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number); + } + Delete(strvalue); } } + return Language::pragmaDirective(n); } -} -void emit_shadow_banner(FILE *f) { - Printf(f, "/*\n"); - Printf(f, " *\n"); - Printf(f, " * This file was automatically generated by :\n"); - Printf(f, " * Simplified Wrapper and Interface Generator (SWIG)\n"); - Printf(f, " * Version: %s\n", SWIG_VERSION); - Printf(f, " *\n"); - Printf(f, " * Portions Copyright (c) 1995-1997\n"); - Printf(f, " * The University of Utah and The Regents of the University of California.\n"); - Printf(f, " * Permission is granted to distribute this file in any manner provided\n"); - Printf(f, " * this notice remains intact.\n"); - Printf(f, " *\n"); - Printf(f, " * Portions Copyright (c) 1997-1999\n"); - Printf(f, " * Harco de Hilster, Harco.de.Hilster@ATConsultancy.nl\n"); - Printf(f, " *\n"); - Printf(f, " * Do not make changes to this file--changes will be lost!\n"); - Printf(f, " *\n"); - Printf(f, " */\n\n\n"); -} + /* ----------------------------------------------------------------------------- + * emitShadowClassDefAndCPPCasts() + * ----------------------------------------------------------------------------- */ + + void emitShadowClassDefAndCPPCasts(Node *n) { + String *c_classname = SwigType_namestr(Getattr(n,"name")); + String *c_baseclass = NULL; + String *baseclass = NULL; + String *c_baseclassname = NULL; + + /* Deal with inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist) { + Node *base = Firstitem(baselist); + c_baseclassname = Getattr(base,"name"); + baseclass = Copy(is_shadow(c_baseclassname)); + if (baseclass){ + c_baseclass = SwigType_namestr(Getattr(base,"name")); + } + base = Nextitem(baselist); + if (base) { + Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s: Base %s ignored. Multiple inheritance is not supported in Java.\n", shadow_classname, Getattr(base,"name")); + } + } + + bool derived = baseclass && is_shadow(c_baseclassname); + if (!baseclass) + baseclass = NewString(""); + + // Inheritance from pure Java classes + const String *pure_java_baseclass = javaTypemapLookup("javabase", shadow_classname, WARN_NONE); + if (Len(pure_java_baseclass) > 0 && Len(baseclass) > 0) { + Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s: Base %s ignored. Multiple inheritance is not supported in Java.\n", shadow_classname, pure_java_baseclass); + } -void JAVA::pragma(char *lang, char *code, char *value) { - if(strcmp(lang, "java") != 0) return; - - DOHString *s = NewString(value); - Replace(s,"\\\"", "\"", DOH_REPLACE_ANY); - if(strcmp(code, "import") == 0) { - jimport = Swig_copy_string(Char(s)); - Printf(f_java, "// pragma\nimport %s;\n\n", jimport); - } else if(strcmp(code, "module") == 0) { - if(!classdef_emitted) emit_classdef(); - Printf(f_java, "// pragma\n"); - Printf(f_java, "%s", s); - Printf(f_java, "\n\n"); - } else if(strcmp(code, "shadow") == 0) { - if(shadow && f_shadow) { - Printf(f_shadow, "// pragma\n"); - Printf(f_shadow, "%s", s); - Printf(f_shadow, "\n\n"); + // Pure Java interfaces + const String *pure_java_interfaces = javaTypemapLookup("javainterfaces", shadow_classname, WARN_NONE); + + // Start writing the shadow class + Printv(shadow_classdef, + javaTypemapLookup("javaimports", shadow_classname, WARN_NONE), // Import statements + "\n", + javaTypemapLookup("javaclassmodifiers", shadow_classname, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + " class $javaclassname", // Class name and bases + (derived || *Char(pure_java_baseclass)) ? + " extends " : + "", + baseclass, + pure_java_baseclass, + *Char(pure_java_interfaces) ? // Pure Java interfaces + " implements " : + "", + pure_java_interfaces, + " {\n", + " private long swigCPtr;\n", // Member variables for memory handling + derived ? + "" : + " protected boolean swigCMemOwn;\n", + "\n", + " ", + javaTypemapLookup("javaptrconstructormodifiers", shadow_classname, WARN_JAVA_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers + " $javaclassname(long cPtr, boolean cMemoryOwn) {\n", // Constructor used for wrapping pointers + derived ? + " super($jniclassname.SWIG$javaclassnameTo$baseclass(cPtr), cMemoryOwn);\n" : + " swigCMemOwn = cMemoryOwn;\n", + " swigCPtr = cPtr;\n", + " }\n", + NIL); + + if(!have_default_constructor_flag) { // All Java classes need a constructor + Printv(shadow_classdef, + "\n", + " protected $javaclassname() {\n", + " this(0, false);\n", + " }\n", + NIL); + } + + Printv(shadow_classdef, + javaTypemapLookup("javafinalize", shadow_classname, WARN_NONE), // finalize method + "\n", + *Char(destructor_call) ? + " public void delete() {\n" : + " protected void delete() {\n", + " if(swigCPtr != 0 && swigCMemOwn) {\n", + destructor_call, + "", + " swigCMemOwn = false;\n", + derived ? // Zero all pointers up any inheritance hierarchy + " super.delete();\n" : + "", + " }\n", + " swigCPtr = 0;\n", + " }\n", + javaTypemapLookup("javagetcptr", shadow_classname, WARN_JAVA_TYPEMAP_GETCPTR_UNDEF), // getCPtr method + javaTypemapLookup("javacode", shadow_classname, WARN_NONE), // extra Java code + "\n", + NIL); + + // Substitute various strings into the above template + Replaceall(shadow_code, "$javaclassname", shadow_classname); + Replaceall(shadow_classdef, "$javaclassname", shadow_classname); + + Replaceall(shadow_classdef, "$baseclass", baseclass); + Replaceall(shadow_code, "$baseclass", baseclass); + + Replaceall(shadow_classdef, "$jniclassname", jniclass_name); + Replaceall(shadow_code, "$jniclassname", jniclass_name); + + // Add JNI code to do C++ casting to base class (only for classes in an inheritance hierarchy) + if(derived){ + Printv(jniclass_cppcasts_code," public final static native long ", + "SWIG$javaclassnameTo$baseclass(long jarg1);\n", + NIL); + + Replaceall(jniclass_cppcasts_code, "$javaclassname", shadow_classname); + Replaceall(jniclass_cppcasts_code, "$baseclass", baseclass); + + Printv(wrapper_conversion_code, + "JNIEXPORT jlong JNICALL Java_$jnipackage$jnijniclass_SWIG$jniclazznameTo$jnibaseclass", + "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", + " jlong baseptr = 0;\n" + " (void)jenv;\n" + " (void)jcls;\n" + " *($cbaseclass **)&baseptr = *($cclass **)&jarg1;\n" + " return baseptr;\n" + "}\n", + "\n", + NIL); + + String *jnijniclass = makeValidJniName(jniclass_name); + String *jniclazzname = makeValidJniName(shadow_classname); + String *jnibaseclass = makeValidJniName(baseclass); + Replaceall(wrapper_conversion_code, "$jnibaseclass",jnibaseclass); + Replaceall(wrapper_conversion_code, "$cbaseclass", c_baseclass); + Replaceall(wrapper_conversion_code, "$jniclazzname",jniclazzname); + Replaceall(wrapper_conversion_code, "$cclass", c_classname); + Replaceall(wrapper_conversion_code, "$jnipackage", jnipackage); + Replaceall(wrapper_conversion_code, "$jnijniclass", jnijniclass); + + Delete(jnibaseclass); + Delete(jniclazzname); + Delete(jnijniclass); } - } else if(strcmp(code, "modifiers") == 0) { - method_modifiers = Swig_copy_string(value); - } else { - Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file,line_number); + Delete(baseclass); } - Delete(s); -} -// --------------------------------------------------------------------- -// C++ Handling -// -// The following functions provide some support for C++ classes and -// C structs. -// --------------------------------------------------------------------- + /* ---------------------------------------------------------------------- + * classHandler() + * ---------------------------------------------------------------------- */ + + virtual int classHandler(Node *n) { -void JAVA::add_typedef(DataType *t, char *name) { - if(!shadow) return; + File *f_shadow = NULL; + if (proxy_flag) { + shadow_classname = NewString(Getattr(n,"sym:name")); - // First check to see if there aren't too many pointers + if (!addSymbol(shadow_classname,n)) return SWIG_ERROR; + + if (Cmp(shadow_classname, jniclass_name) == 0) { + Printf(stderr, "Class name cannot be equal to JNI class name: %s\n", shadow_classname); + SWIG_exit(EXIT_FAILURE); + } - if (DataType_is_pointer(t) > 1) return; + if (Cmp(shadow_classname, module_class_name) == 0) { + Printf(stderr, "Class name cannot be equal to module class name: %s\n", shadow_classname); + SWIG_exit(EXIT_FAILURE); + } - if(Getattr(shadow_classes,name)) return; // Already added + String *filen = NewStringf("%s.java", shadow_classname); + f_shadow = NewFile(filen,"w"); + if(!f_shadow) { + Printf(stderr, "Unable to create proxy class file: %s\n", filen); + SWIG_exit(EXIT_FAILURE); + } + Delete(filen); filen = NULL; - // Now look up the datatype in our shadow class hash table + emitBanner(f_shadow); - if (Getattr(shadow_classes,DataType_Getname(t))) { + if(Len(package) > 0) + Printf(f_shadow, "package %s;\n\n", package); - // Yep. This datatype is in the hash - // Put this types 'new' name into the hash - Setattr(shadow_classes,name,GetChar(shadow_classes,DataType_Getname(t))); - } -} + Clear(shadow_classdef); + Clear(shadow_code); -void JAVA::cpp_open_class(char *classname, char *rename, char *ctype, int strip) { + have_default_constructor_flag = false; + destructor_call = NewString(""); + shadow_constants_code = NewString(""); + } + Language::classHandler(n); - this->Language::cpp_open_class(classname,rename,ctype,strip); + if (proxy_flag) { - if(!shadow) return; + emitShadowClassDefAndCPPCasts(n); - if(rename) - shadow_classname = Swig_copy_string(rename); - else shadow_classname = Swig_copy_string(classname); + Printv(f_shadow, shadow_classdef, shadow_code, NIL); - if (strcmp(shadow_classname, module) == 0) { - Printf(stderr, "class name cannot be equal to module name: %s\n", shadow_classname); - SWIG_exit(1); - } + // Write out all the enums and constants + if (Len(shadow_constants_code) != 0 ) + Printv(f_shadow, " // enums and constants\n", shadow_constants_code, NIL); - Setattr(shadow_classes,classname, shadow_classname); - if(ctype && strcmp(ctype, "struct") == 0) { - sprintf(bigbuf, "struct %s", classname); - Setattr(shadow_classes, bigbuf, shadow_classname); - } + Printf(f_shadow, "}\n"); + Close(f_shadow); + f_shadow = NULL; - sprintf(bigbuf, "%s.java", shadow_classname); - if(!(f_shadow = fopen(bigbuf, "w"))) { - Printf(stderr, "Unable to create shadow class file: %s\n", bigbuf); + Delete(shadow_classname); shadow_classname = NULL; + Delete(destructor_call); destructor_call = NULL; + Delete(shadow_constants_code); shadow_constants_code = NULL; + } + return SWIG_OK; } - emit_shadow_banner(f_shadow); + /* ---------------------------------------------------------------------- + * memberfunctionHandler() + * ---------------------------------------------------------------------- */ - if(*package) - Printf(f_shadow, "package %s;\n\n", package); - else Printf(f_shadow, "import %s;\n\n", module); - if(jimport != NULL) - Printf(f_shadow, "import %s;\n\n", jimport); + virtual int memberfunctionHandler(Node *n) { + Language::memberfunctionHandler(n); - Clear(shadow_classdef); - Printv(shadow_classdef, "public class ", shadow_classname, " %BASECLASS% ", "{\n", 0); + if (proxy_flag) { + String *overloaded_name = getOverloadedName(n); + String *java_function_name = Swig_name_member(shadow_classname, overloaded_name); + Setattr(n,"java:shadowfuncname", Getattr(n, "sym:name")); + Setattr(n,"java:funcname", java_function_name); + javaShadowFunctionHandler(n); + Delete(overloaded_name); + } + return SWIG_OK; + } - shadow_baseclass = (char*) ""; - shadow_classdef_emitted = 0; - have_default_constructor = 0; -} + /* ---------------------------------------------------------------------- + * staticmemberfunctionHandler() + * ---------------------------------------------------------------------- */ -void JAVA::emit_shadow_classdef() { - if(*shadow_baseclass) { - sprintf(bigbuf, "extends %s", shadow_baseclass); - Replace(shadow_classdef,"%BASECLASS%", bigbuf, DOH_REPLACE_ANY); - Printv(shadow_classdef, " public ", shadow_classname, "(java.lang.Long obj) {\n", tab4, "_self = obj.longValue();\n }\n\n", 0); - } else { - Replace(shadow_classdef,"%BASECLASS%", "",DOH_REPLACE_ANY); + virtual int staticmemberfunctionHandler(Node *n) { - Printv(shadow_classdef, - " public long _self = 0;\n", - " public boolean _selfown = false;\n\n", - " public static Object newInstance(long p) {\n", - " return new ", shadow_classname, "(new Long(p));\n", - " };\n\n", - - " public ", shadow_classname, "(java.lang.Long obj) {\n", tab4, "_self = obj.longValue();\n }\n\n", - 0); + static_flag = true; + Language::staticmemberfunctionHandler(n); + + if (proxy_flag) { + String *overloaded_name = getOverloadedName(n); + String *java_function_name = Swig_name_member(shadow_classname, overloaded_name); + Setattr(n,"java:shadowfuncname", Getattr(n,"sym:name")); + Setattr(n,"java:funcname", java_function_name); + javaShadowFunctionHandler(n); + Delete(overloaded_name); + } + static_flag = false; + + return SWIG_OK; } - Printv(shadow_classdef, " public Class _selfClass() {\n", tab4, "return ", shadow_classname, ".class;\n", " };\n\n", 0); - Printv(f_shadow, shadow_classdef,0); - shadow_classdef_emitted = 1; -} + /* ----------------------------------------------------------------------------- + * javaShadowFunctionHandler() + * + * Function called for creating a java class wrapper function around a c++ function in the + * java wrapper class. Used for both static and non static functions. + * C++ static functions map to java static functions. + * Two extra attributes in the Node must be available. These are "java:shadowfuncname" - the name of the java class shadow + * function, which in turn will call "java:funcname" - the java native function name which wraps the c++ function. + * ----------------------------------------------------------------------------- */ + + void javaShadowFunctionHandler(Node *n) { + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *java_function_name = Getattr(n,"java:funcname"); + String *java_shadow_function_name = Getattr(n,"java:shadowfuncname"); + String *tm; + Parm *p; + int i; + String *nativecall = NewString(""); + String *shadowrettype = NewString(""); + String *user_arrays = NewString(""); + + if(!proxy_flag) return; + + if (l) { + if (SwigType_type(Getattr(l,"type")) == T_VOID) { + l = nextSibling(l); + } + } + + /* Attach the non-standard typemaps to the parameter list */ + Swig_typemap_attach_parms("in", l, NULL); + Swig_typemap_attach_parms("jstype", l, NULL); + Swig_typemap_attach_parms("javain", l, NULL); + + /* Get Java return types */ + if ((tm = Swig_typemap_lookup_new("jstype",n,"",0))) { + substituteJavaclassname(t, tm); + Printf(shadowrettype, "%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, + "No jstype typemap defined for %s\n", SwigType_str(t,0)); + } -void JAVA::cpp_close_class() { - this->Language::cpp_close_class(); - if(!shadow) return; + /* Start generating the shadow function */ + Printf(shadow_code, " %s ", Getattr(n,"feature:java:methodmodifiers")); + if (static_flag) + Printf(shadow_code, "static "); + Printf(shadow_code, "%s %s(", shadowrettype, java_shadow_function_name); - if(!shadow_classdef_emitted) emit_shadow_classdef(); + Printv(nativecall, jniclass_name, ".", java_function_name, "(", NIL); + if (!static_flag) + Printv(nativecall, "swigCPtr", NIL); - if(have_default_constructor == 0) { - Printf(f_shadow, " public %s() {}\n\n", shadow_classname); - } + int gencomma = !static_flag; - Printf(f_shadow, "}\n"); - fclose(f_shadow); - f_shadow = NULL; + /* Output each parameter */ + for (i = 0, p=l; p; i++) { - free(shadow_classname); - shadow_classname = NULL; -} + /* Ignored parameters */ + if (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + continue; + } -void JAVA::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) { - char arg[256]; - DOHString *nativecall; + /* Ignore the 'this' argument for variable wrappers */ + if (!(variable_wrapper_flag && i==0)) + { + SwigType *pt = Getattr(p,"type"); + String *javaparamtype = NewString(""); - nativecall = NewString(""); + /* Get the java type of the parameter */ + if ((tm = Getattr(p,"tmap:jstype"))) { + substituteJavaclassname(pt, tm); + Printf(javaparamtype, "%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, + "No jstype typemap defined for %s\n", SwigType_str(pt,0)); + } - this->Language::cpp_member_func(name,iname,t,l); + if (gencomma) + Printf(nativecall, ", "); - if(!shadow) return; - if(!shadow_classdef_emitted) emit_shadow_classdef(); + String *arg = makeParameterName(n, p, i); - char *javarettype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, t, iname); - if(!javarettype) javarettype = SwigTcToJavaType(t, 1, 0); - char *shadowrettype = JavaTypeFromTypemap((char*)"jstype", typemap_lang, t, iname); - if(!shadowrettype && (DataType_Gettypecode(t) == T_USER) && DataType_is_pointer(t) <= 1) { - shadowrettype = GetChar(shadow_classes,DataType_Getname(t)); - } + // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in native function (in JNI class) + if ((tm = Getattr(p,"tmap:javain"))) { + substituteJavaclassname(pt, tm); + Replaceall(tm, "$javainput", arg); + Printv(nativecall, tm, NIL); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, + "No javain typemap defined for %s\n", SwigType_str(pt,0)); + } - Printf(f_shadow, " public %s %s(", (shadowrettype) ? shadowrettype : javarettype, iname); + /* Add to java shadow function header */ + if (gencomma >= 2) + Printf(shadow_code, ", "); + gencomma = 2; + Printf(shadow_code, "%s %s", javaparamtype, arg); + + Delete(arg); + Delete(javaparamtype); + } + p = Getattr(p,"tmap:in:next"); + } - if(DataType_type(t) != T_VOID) { - Printf(nativecall,"return "); - if(shadowrettype) { - Printv(nativecall, "new ", shadowrettype, "(new Long(", 0); + Printf(nativecall, ")"); + Printf(shadow_code, ")"); + generateThrowsClause(n, shadow_code); + + // Transform return type used in native function (in JNI class) to type used in Java wrapper function (in proxy class) + if ((tm = Swig_typemap_lookup_new("javaout",n,"",0))) { + if (Getattr(n,"feature:new")) + Replaceall(tm,"$owner","true"); + else + Replaceall(tm,"$owner","false"); + substituteJavaclassname(t, tm); + Replaceall(tm, "$jnicall", nativecall); + Printf(shadow_code, " %s\n\n", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, + "No javaout typemap defined for %s\n", SwigType_str(t,0)); } + + Delete(shadowrettype); + Delete(nativecall); + Delete(user_arrays); } - Printv(nativecall, module, ".", Swig_name_member(shadow_classname,iname), "(_self", 0); - int pcount = ParmList_len(l); + /* ---------------------------------------------------------------------- + * constructorHandler() + * ---------------------------------------------------------------------- */ - Parm *p = l; - for (int i = 0; i < pcount ; i++, p = Getnext(p)) { - DataType *pt = Gettype(p); - char *pn = Getname(p); + virtual int constructorHandler(Node *n) { - // Produce string representation of source and target arguments - if(pn && *(pn)) - strcpy(arg,pn); - else { - sprintf(arg,"arg%d",i); - } + ParmList *l = Getattr(n,"parms"); + String *tm; + Parm *p; + int i; + String *user_arrays = NewString(""); - if((DataType_Gettypecode(pt) == T_USER) && (DataType_is_pointer(pt) <= 1) && Getattr(shadow_classes,DataType_Getname(pt))) { - Printv(nativecall, ", ", arg, "._self", 0); - } else Printv(nativecall, ", ", arg, 0); + Language::constructorHandler(n); - char *jtype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, pt, pn); - if(!jtype) jtype = SwigTcToJavaType(pt, 0, 0); + if(proxy_flag) { + String *overloaded_name = getOverloadedName(n); + String *nativecall = NewString(""); - char *jstype = JavaTypeFromTypemap((char*)"jstype", typemap_lang, pt, pn); - if(!jstype && (DataType_Gettypecode(pt) == T_USER) && (DataType_is_pointer(pt) <= 1)) { - jstype = GetChar(shadow_classes,DataType_Getname(pt)); - } + Printf(shadow_code, " %s %s(", Getattr(n,"feature:java:methodmodifiers"), shadow_classname); + Printv(nativecall, "this(", jniclass_name, ".", Swig_name_construct(overloaded_name), "(", NIL); - // Add to java function header - Printf(f_shadow, "%s %s", (jstype) ? jstype : jtype, arg); - if(i != pcount-1) { - Printf(f_shadow, ", "); - } - } + /* Attach the non-standard typemaps to the parameter list */ + Swig_typemap_attach_parms("in", l, NULL); + Swig_typemap_attach_parms("jstype", l, NULL); + Swig_typemap_attach_parms("javain", l, NULL); - if((DataType_Gettypecode(t) != T_VOID) && shadowrettype) - Printf(nativecall, "))"); + int gencomma = 0; - Printf(nativecall,");\n"); + /* Output each parameter */ + for (i = 0, p=l; p; i++) { - Printf(f_shadow, ") {\n"); - Printf(f_shadow, "\t%s\n", nativecall); - Printf(f_shadow, " }\n\n"); - Delete(nativecall); + /* Ignored parameters */ + if (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + continue; + } -} + SwigType *pt = Getattr(p,"type"); + String *javaparamtype = NewString(""); -void JAVA::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l) { - char arg[256]; - DOHString *nativecall; + /* Get the java type of the parameter */ + if ((tm = Getattr(p,"tmap:jstype"))) { + substituteJavaclassname(pt, tm); + Printf(javaparamtype, "%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, + "No jstype typemap defined for %s\n", SwigType_str(pt,0)); + } - this->Language::cpp_static_func(name,iname,t,l); + if (gencomma) + Printf(nativecall, ", "); - if(!shadow) return; - nativecall = NewString(""); - if(!shadow_classdef_emitted) emit_shadow_classdef(); + String *arg = makeParameterName(n, p, i); - char *javarettype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, t, iname); - if(!javarettype) javarettype = SwigTcToJavaType(t, 1, 0); - char *shadowrettype = JavaTypeFromTypemap((char*)"jstype", typemap_lang, t, iname); - if(!shadowrettype && (DataType_Gettypecode(t) == T_USER) && (DataType_is_pointer(t) <= 1)) { - shadowrettype = GetChar(shadow_classes,DataType_Getname(t)); - } + // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in native function (in JNI class) + if ((tm = Getattr(p,"tmap:javain"))) { + substituteJavaclassname(pt, tm); + Replaceall(tm, "$javainput", arg); + Printv(nativecall, tm, NIL); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, + "No javain typemap defined for %s\n", SwigType_str(pt,0)); + } - Printf(f_shadow, " public static %s %s(", (shadowrettype) ? shadowrettype : javarettype, iname); + /* Add to java shadow function header */ + if(gencomma) + Printf(shadow_code, ", "); + Printf(shadow_code, "%s %s", javaparamtype, arg); + gencomma = 1; - if(DataType_type(t) != T_VOID) { - Printf(nativecall, "return "); - if(shadowrettype) { - Printv(nativecall, "new ", shadowrettype, "(new Long(", 0); - } - } - Printv(nativecall, module, ".", Swig_name_member(shadow_classname,iname), "(", 0); + Delete(arg); + Delete(javaparamtype); + p = Getattr(p,"tmap:in:next"); + } + + Printf(nativecall, "), true);\n"); - int pcount = ParmList_len(l); - int gencomma = 0; + Printf(shadow_code, ")"); + generateThrowsClause(n, shadow_code); + Printf(shadow_code, " {\n"); + Printv(shadow_code, user_arrays, NIL); + Printf(shadow_code, " %s", nativecall); + Printf(shadow_code, " }\n\n"); - Parm *p = l; - for (int i = 0; i < pcount ; i++, p = Getnext(p)) { - DataType *pt = Gettype(p); - char *pn = Getname(p); + if(!gencomma) // We must have a default constructor + have_default_constructor_flag = true; - // Produce string representation of source and target arguments - if(pn && *(pn)) - strcpy(arg,pn); - else { - sprintf(arg,"arg%d",i); + Delete(overloaded_name); + Delete(nativecall); } - if(gencomma) Printf(nativecall,", "); + Delete(user_arrays); - if((DataType_Gettypecode(pt) == T_USER) && (DataType_is_pointer(pt) <= 1) && Getattr(shadow_classes,DataType_Getname(pt))) { - Printv(nativecall, arg, "._self", 0); - } else Printv(nativecall,arg,0); + return SWIG_OK; + } - gencomma = 1; + /* ---------------------------------------------------------------------- + * destructorHandler() + * ---------------------------------------------------------------------- */ - char *jtype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, pt, pn); - if(!jtype) jtype = SwigTcToJavaType(pt, 0, 0); + virtual int destructorHandler(Node *n) { + Language::destructorHandler(n); + String *symname = Getattr(n,"sym:name"); - char *jstype = JavaTypeFromTypemap((char*)"jstype", typemap_lang, pt, pn); - if(!jstype && (DataType_Gettypecode(pt) == T_USER) && (DataType_is_pointer(pt) <= 1)) { - jstype = GetChar(shadow_classes, DataType_Getname(pt)); + if(proxy_flag) { + Printv(destructor_call, " ", jniclass_name, ".", Swig_name_destroy(symname), "(swigCPtr);\n", NIL); } + return SWIG_OK; + } - // Add to java function header - Printf(f_shadow, "%s %s", (jstype) ? jstype : jtype, arg); - if(i != pcount-1) { - Printf(f_shadow, ", "); - } + /* ---------------------------------------------------------------------- + * membervariableHandler() + * ---------------------------------------------------------------------- */ + + virtual int membervariableHandler(Node *n) { + variable_name = Getattr(n,"sym:name"); + wrapping_member_flag = true; + variable_wrapper_flag = true; + Language::membervariableHandler(n); + wrapping_member_flag = false; + variable_wrapper_flag = false; + return SWIG_OK; } + /* ---------------------------------------------------------------------- + * staticmembervariableHandler() + * ---------------------------------------------------------------------- */ + + virtual int staticmembervariableHandler(Node *n) { + variable_name = Getattr(n,"sym:name"); + wrapping_member_flag = true; + static_flag = true; + Language::staticmembervariableHandler(n); + wrapping_member_flag = false; + static_flag = false; + return SWIG_OK; + } - if((DataType_type(t) != T_VOID) && shadowrettype) - Printf(nativecall,"))"); + /* ---------------------------------------------------------------------- + * memberconstantHandler() + * ---------------------------------------------------------------------- */ - Printf(nativecall,");\n"); + virtual int memberconstantHandler(Node *n) { + variable_name = Getattr(n,"sym:name"); + wrapping_member_flag = true; + Language::memberconstantHandler(n); + wrapping_member_flag = false; + return SWIG_OK; + } - Printf(f_shadow, ") {\n"); - Printf(f_shadow, "\t%s\n", nativecall); - Printf(f_shadow, " }\n\n"); - Delete(nativecall); -} + /* ----------------------------------------------------------------------------- + * getOverloadedName() + * ----------------------------------------------------------------------------- */ -void JAVA::cpp_constructor(char *name, char *iname, ParmList *l) { - this->Language::cpp_constructor(name,iname,l); + String *getOverloadedName(Node *n) { - if(!shadow) return; - if(!shadow_classdef_emitted) emit_shadow_classdef(); + /* Although the JNI is designed to handle overloaded Java functions, a Java long is used for all classes in the SWIG + * JNI native interface. The JNI native interface function is thus mangled when overloaded to give a unique name. */ + String *overloaded_name = NewStringf("%s", Getattr(n,"sym:name")); - DOHString *nativecall = NewString(""); - char arg[256]; + if (Getattr(n,"sym:overloaded")) { + Printv(overloaded_name, Getattr(n,"sym:overname"), NIL); + } - Printf(f_shadow, " public %s(", shadow_classname); + return overloaded_name; + } - Printv(nativecall, " if(_self == 0 && ", shadow_classname, ".class == _selfClass()) {\n", 0); - if (iname != NULL) - Printv(nativecall, tab8, " _self = ", module, ".", Swig_name_construct(iname), "(", 0); - else - Printv(nativecall, tab8, " _self = ", module, ".", Swig_name_construct(shadow_classname), "(", 0); + /* ----------------------------------------------------------------------------- + * moduleClassFunctionHandler() + * ----------------------------------------------------------------------------- */ + + void moduleClassFunctionHandler(Node *n) { + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *tm; + Parm *p; + int i; + String *nativecall = NewString(""); + String *shadowrettype = NewString(""); + String *user_arrays = NewString(""); + int num_arguments = 0; + int num_required = 0; + String *overloaded_name = getOverloadedName(n); + String *func_name = NULL; + + if (l) { + if (SwigType_type(Getattr(l,"type")) == T_VOID) { + l = nextSibling(l); + } + } - int pcount = ParmList_len(l); - if(pcount == 0) // We must have a default constructor - have_default_constructor = 1; + /* Attach the non-standard typemaps to the parameter list */ + Swig_typemap_attach_parms("jstype", l, NULL); + Swig_typemap_attach_parms("javain", l, NULL); - Parm *p = l; - for (int i = 0; i < pcount ; i++, p = Getnext(p)) { - DataType *pt = Gettype(p); - char *pn = Getname(p); + /* Get Java return types */ + if ((tm = Swig_typemap_lookup_new("jstype",n,"",0))) { + substituteJavaclassname(t, tm); + Printf(shadowrettype, "%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, + "No jstype typemap defined for %s\n", SwigType_str(t,0)); + } - // Produce string representation of source and target arguments - if(pn && *(pn)) - strcpy(arg,pn); - else { - sprintf(arg,"arg%d",i); + /* Change function name for global variables */ + if (proxy_flag && global_variable_flag) { + // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name + func_name = NewString(""); + if(Cmp(Getattr(n,"sym:name"), Swig_name_set(variable_name)) == 0) + Printf(func_name,"set"); + else + Printf(func_name,"get"); + Putc(toupper((int) *Char(variable_name)), func_name); + Printf(func_name, "%s", Char(variable_name)+1); + } else { + func_name = Copy(Getattr(n,"sym:name")); } - char *jtype = JavaTypeFromTypemap((char*)"jtype", typemap_lang, pt, pn); - if(!jtype) jtype = SwigTcToJavaType(pt, 0, 0); + /* Start generating the function */ + Printf(module_class_code, " %s static %s %s(", Getattr(n,"feature:java:methodmodifiers"), shadowrettype, func_name); + Printv(nativecall, jniclass_name, ".", overloaded_name, "(", NIL); - char *jstype = JavaTypeFromTypemap((char*)"jstype", typemap_lang, pt, pn); - if(!jstype && (DataType_Gettypecode(pt) == T_USER) && (DataType_is_pointer(pt) <= 1)) { - jstype = GetChar(shadow_classes, DataType_Getname(pt)); - } + /* Get number of required and total arguments */ + num_arguments = emit_num_arguments(l); + num_required = emit_num_required(l); - // Add to java function header - Printf(f_shadow, "%s %s", (jstype) ? jstype : jtype, arg); + int gencomma = 0; - if((DataType_Gettypecode(pt) == T_USER) && (DataType_is_pointer(pt) <= 1) && Getattr(shadow_classes,DataType_Getname(pt))) { - Printv(nativecall,arg, "._self", 0); - } else Printv(nativecall, arg, 0); + /* Output each parameter */ + for (i = 0, p=l; i < num_arguments; i++) { - if(i != pcount-1) { - Printf(nativecall, ", "); - Printf(f_shadow, ", "); - } - } + /* Ignored parameters */ + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + SwigType *pt = Getattr(p,"type"); + String *javaparamtype = NewString(""); - Printf(f_shadow, ") {\n"); - Printv(nativecall, - ");\n", - tab8, " _selfown = true;\n", - " }\n", - 0); + /* Get the java type of the parameter */ + if ((tm = Getattr(p,"tmap:jstype"))) { + substituteJavaclassname(pt, tm); + Printf(javaparamtype, "%s", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, + "No jstype typemap defined for %s\n", SwigType_str(pt,0)); + } - Printf(f_shadow, "%s", nativecall); - Printf(f_shadow, " }\n\n"); - Delete(nativecall); -} + if (gencomma) + Printf(nativecall, ", "); -void JAVA::cpp_destructor(char *name, char *newname) { - this->Language::cpp_destructor(name,newname); + String *arg = makeParameterName(n, p, i); - if(!shadow) return; - if(!shadow_classdef_emitted) emit_shadow_classdef(); + // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in native function (in JNI class) + if ((tm = Getattr(p,"tmap:javain"))) { + substituteJavaclassname(pt, tm); + Replaceall(tm, "$javainput", arg); + Printv(nativecall, tm, NIL); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, + "No javain typemap defined for %s\n", SwigType_str(pt,0)); + } - char *realname = (newname) ? newname : name; + /* Add to java shadow function header */ + if (gencomma >= 2) + Printf(module_class_code, ", "); + gencomma = 2; + Printf(module_class_code, "%s %s", javaparamtype, arg); - if(finalize) { - Printf(f_shadow, " protected void finalize() {\n"); - Printf(f_shadow, " if(_selfown) {\n"); - Printf(f_shadow, " _delete();\n"); - Printf(f_shadow, " }\n"); - Printf(f_shadow, " };\n\n"); + p = Getattr(p,"tmap:in:next"); + Delete(arg); + Delete(javaparamtype); + } + + Printf(nativecall, ")"); + Printf(module_class_code, ")"); + generateThrowsClause(n, module_class_code); + + // Transform return type used in native function (in JNI class) to type used in Java wrapper function (in module class) + if ((tm = Swig_typemap_lookup_new("javaout",n,"",0))) { + if (Getattr(n,"feature:new")) + Replaceall(tm,"$owner","true"); + else + Replaceall(tm,"$owner","false"); + substituteJavaclassname(t, tm); + Replaceall(tm, "$jnicall", nativecall); + Printf(module_class_code, " %s\n\n", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, + "No javaout typemap defined for %s\n", SwigType_str(t,0)); + } + + Delete(shadowrettype); + Delete(nativecall); + Delete(user_arrays); + Delete(func_name); } - Printf(f_shadow, " public void _delete() {\n"); - Printf(f_shadow, " if(_self != 0 && %s.class == _selfClass()) {\n", shadow_classname); - Printf(f_shadow, "\t%s.%s(_self);\n", module, Swig_name_destroy(realname)); - Printf(f_shadow, "\t_self = 0;\n"); - Printf(f_shadow, " }\n"); - Printf(f_shadow, " }\n\n"); -} + /* ----------------------------------------------------------------------------- + * substituteJavaclassname() + * + * Substitute $javaclassname with either the shadow class name for classes/structs/unions that SWIG knows about. + * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution + * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. + * Inputs: + * pt - parameter type + * tm - jstype typemap + * Outputs: + * tm - jstype typemap with $javaclassname substitution + * Return: + * is_java_class - flag indicating if a substitution was performed + * ----------------------------------------------------------------------------- */ + + bool substituteJavaclassname(SwigType *pt, String *tm) { + bool is_java_class = false; + if (Strstr(tm, "$javaclassname") || Strstr(tm,"$&javaclassname")) { + String *javaclassname = is_shadow(pt); + if (javaclassname) { + Replaceall(tm,"$&javaclassname", javaclassname); // is_shadow() works for pointers to classes too + Replaceall(tm,"$javaclassname", javaclassname); + } + else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved. + String *descriptor = NULL; + SwigType *type = Copy(SwigType_typedef_resolve_all(pt)); + + if (Strstr(tm, "$&javaclassname")) { + SwigType_add_pointer(type); + descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type)); + Replaceall(tm, "$&javaclassname", descriptor); + } + else { // $javaclassname + descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type)); + Replaceall(tm, "$javaclassname", descriptor); + } -void JAVA::cpp_class_decl(char *name, char *rename, char *type) { - this->Language::cpp_class_decl(name,rename, type); + // Add to hash table so that the SWIGTYPE Java classes can be created later + Setattr(swig_types_hash, descriptor, type); + Delete(descriptor); + Delete(type); + } + is_java_class = true; + } + return is_java_class; + } - if(!shadow) return; + /* ----------------------------------------------------------------------------- + * makeParameterName() + * + * Inputs: + * n - Node + * p - parameter node + * arg_num - parameter argument number + * Return: + * arg - a unique parameter name + * ----------------------------------------------------------------------------- */ + + String *makeParameterName(Node *n, Parm *p, int arg_num) { + + // Use C parameter name unless it is a duplicate or an empty parameter name + String *pn = Getattr(p,"name"); + int count = 0; + ParmList *plist = Getattr(n,"parms"); + while (plist) { + if ((Cmp(pn, Getattr(plist,"name")) == 0)) + count++; + plist = nextSibling(plist); + } + String *arg = (!pn || (count > 1)) ? NewStringf("arg%d",arg_num) : Copy(Getattr(p,"name")); - char *realname = (rename) ? rename : name; + return arg; + } - Setattr(shadow_classes,name, realname); - if(type && strcmp(type, "struct") == 0) { - sprintf(bigbuf, "struct %s", name); - Setattr(shadow_classes, bigbuf, rename); + /* ----------------------------------------------------------------------------- + * emitJavaClass() + * ----------------------------------------------------------------------------- */ + + void emitJavaClass(String *javaclassname, SwigType *type) { + String *filen = NewStringf("%s.java", javaclassname); + File *f_swigtype = NewFile(filen,"w"); + String *swigtype = NewString(""); + + // Emit banner and package name + emitBanner(f_swigtype); + if(Len(package) > 0) + Printf(f_swigtype, "package %s;\n\n", package); + + // Pure Java baseclass and interfaces + const String *pure_java_baseclass = javaTypemapLookup("javabase", type, WARN_NONE); + const String *pure_java_interfaces = javaTypemapLookup("javainterfaces", type, WARN_NONE); + + // Emit the class + Printv(swigtype, + javaTypemapLookup("javaimports", type, WARN_NONE), // Import statements + "\n", + javaTypemapLookup("javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + " class $javaclassname", // Class name and bases + *Char(pure_java_baseclass) ? + " extends " : + "", + pure_java_baseclass, + *Char(pure_java_interfaces) ? // Pure Java interfaces + " implements " : + "", + pure_java_interfaces, + " {\n", + " private long swigCPtr;\n", + "\n", + " ", + javaTypemapLookup("javaptrconstructormodifiers", type, WARN_JAVA_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers + " $javaclassname(long cPtr, boolean bFutureUse) {\n", // Constructor used for wrapping pointers + " swigCPtr = cPtr;\n", + " }\n", + "\n", + " protected $javaclassname() {\n", // Default constructor + " swigCPtr = 0;\n", + " }\n", + javaTypemapLookup("javagetcptr", type, WARN_JAVA_TYPEMAP_GETCPTR_UNDEF), // getCPtr method + javaTypemapLookup("javacode", type, WARN_NONE), // extra Java code + "}\n", + "\n", + NIL); + + Replaceall(swigtype, "$javaclassname", javaclassname); + Printv(f_swigtype, swigtype, NIL); + + Close(f_swigtype); + Delete(filen); + Delete(swigtype); } -} -void JAVA::cpp_inherit(char **baseclass, int) { - this->Language::cpp_inherit(baseclass, 0); + /* ----------------------------------------------------------------------------- + * javaTypemapLookup() + * ----------------------------------------------------------------------------- */ - if(!shadow) return; + const String *javaTypemapLookup(const String *op, String *type, int warning) { + String *tm = NULL; + const String *code = NULL; - int cnt = 0; - char **bc = baseclass; - while(*bc++) cnt++; + if((tm = Swig_typemap_search(op, type, NULL, NULL))) { + code = Getattr(tm,"code"); + } - if(cnt > 1) - Printf(stderr, "Warning: %s inherits from multiple base classes. Multiple inheritance is not supported.\n", shadow_classname); + if (!code) { + code = empty_string; + if (warning != WARN_NONE) + Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type); + } - shadow_baseclass = Swig_copy_string(*baseclass); -} + return code ? code : empty_string; + } -void JAVA::cpp_variable(char *name, char *iname, DataType *t) { - if(shadow && !shadow_classdef_emitted) emit_shadow_classdef(); + /* ----------------------------------------------------------------------------- + * addThrows() + * ----------------------------------------------------------------------------- */ - if(shadow) member_func = 1; - shadow_name = Swig_copy_string((iname) ? iname : name); - this->Language::cpp_variable(name, iname, t); - member_func = 0; -} + void addThrows(Node *n, const String *typemap, Node *parameter) { + // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in + String *throws_attribute = NewStringf("%s:throws", typemap); + String *throws = Getattr(parameter,throws_attribute); -void JAVA::cpp_static_var(char *name, char *iname, DataType *t) { - if(shadow) member_func = 1; - shadow_name = Swig_copy_string((iname) ? iname : name); - this->Language::cpp_static_var(name, iname, t); - member_func = 0; -} + if (throws) { + String *throws_list = Getattr(n,"java:throwslist"); + if (!throws_list) { + throws_list = NewList(); + Setattr(n,"java:throwslist", throws_list); + } -void JAVA::cpp_declare_const(char *name, char *iname, DataType *type, char *value) { - if(shadow && !shadow_classdef_emitted) emit_shadow_classdef(); + // Put the exception classes in the throws clause into a temporary List + List *temp_classes_list = Split(throws,',',INT_MAX); + + // Add the exception classes to the node throws list, but don't duplicate if already in list + if (temp_classes_list && Len(temp_classes_list) > 0) { + for (String *cls = Firstitem(temp_classes_list); cls; cls = Nextitem(temp_classes_list)) { + String *javacls = NewString(cls); + Replaceall(javacls," ",""); // remove spaces + Replaceall(javacls,"\t",""); // remove tabs + if (Len(javacls) > 0) { + // $javaclassname substitution + SwigType *pt = Getattr(parameter,"type"); + substituteJavaclassname(pt, javacls); + + // Don't duplicate the Java class in the throws clause + bool found_flag = false; + for (String *item = Firstitem(throws_list); item; item = Nextitem(throws_list)) { + if (Strcmp(item, javacls) == 0) + found_flag = true; + } + if (!found_flag) + Append(throws_list, javacls); + } + Delete(javacls); + } + } + Delete(temp_classes_list); + } + Delete(throws_attribute); + } + + /* ----------------------------------------------------------------------------- + * generateThrowsClause() + * ----------------------------------------------------------------------------- */ + + void generateThrowsClause(Node *n, String *code) { + // Add the throws clause into code + List *throws_list = Getattr(n,"java:throwslist"); + if (throws_list) { + String *cls = Firstitem(throws_list); + Printf(code, " throws %s", cls); + while ( (cls = Nextitem(throws_list)) ) + Printf(code, ", %s", cls); + } + } - if(shadow) member_func = 1; - shadow_name = Swig_copy_string((iname) ? iname : name); - this->Language::cpp_declare_const(name, iname, type, value); - member_func = 0; +}; /* class JAVA */ + +/* ----------------------------------------------------------------------------- + * swig_java() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_java(void) { + return new JAVA(); } +/* ----------------------------------------------------------------------------- + * Static member variables + * ----------------------------------------------------------------------------- */ + +const char *JAVA::usage = (char*)"\ +Java Options (available with -java)\n\ + -package <name> - set name of the Java package\n\ + -noproxy - Generate the low-level functional interface instead of proxy classes\n"; diff --git a/Source/Modules1.1/java.h b/Source/Modules1.1/java.h deleted file mode 100644 index 6c86b452e..000000000 --- a/Source/Modules1.1/java.h +++ /dev/null @@ -1,49 +0,0 @@ - -// ------------------------------------------------------------------------ -// A Java SWIG Language module -// -// ------------------------------------------------------------------------ - -class JAVA : public Language { -public : - - // Virtual functions required by the SWIG parser - - void parse_args(int, char *argv[]); - void parse(); - void add_native(char *, char *, SwigType *, ParmList *); - void create_function(char *, char *, SwigType *, ParmList *); - void link_variable(char *, char *, SwigType *); - void declare_const(char *, char *, SwigType *, char *); - void initialize(void); - void headers(void); - void close(void); - void set_module(char *,char **); - void create_command(char *, char *); - - void pragma(char *lang, char *code, char *value); - void add_typedef(SwigType *t, char *name); - void cpp_open_class(char *classname, char *rename, char *ctype, int strip); - void cpp_close_class(); - void cpp_member_func(char *name, char *iname, SwigType *t, ParmList *l); - void cpp_static_func(char *name, char *iname, SwigType *t, ParmList *l); - void cpp_constructor(char *name, char *iname, ParmList *l); - void cpp_destructor(char *name, char *newname); - void cpp_class_decl(char *name, char *rename, char *type); - void cpp_inherit(char **baseclass, int); - void cpp_variable(char *name, char *iname, SwigType *t); - void cpp_static_var(char *, char *, SwigType *); - void cpp_declare_const(char *name, char *iname, SwigType *type, char *value); - - /* Java Module methods */ - void emit_classdef(); - void emit_shadow_classdef(); - char *JNICALL(DOHString_or_char *func); - char *SwigTcToJniType(SwigType *t, int ret); - char *SwigTcToJavaType(SwigType *t, int ret, int inShadow); - char *SwigTcToJniScalarType(SwigType *t); - char *JavaTypeFromTypemap(char *op, char *lang, SwigType *t, char *pname); - char *makeValidJniName(char *name); - char *JavaMethodSignature(SwigType *t, int ret, int inShadow); - void writeRegisterNatives(); -}; diff --git a/Source/Modules1.1/lang.cxx b/Source/Modules1.1/lang.cxx index faf69918f..4245b7193 100644 --- a/Source/Modules1.1/lang.cxx +++ b/Source/Modules1.1/lang.cxx @@ -12,464 +12,1842 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_lang_cxx[] = "$Header$"; -#include "swig11.h" +#include "swigmod.h" +#include <ctype.h> -/* ----------------------------------------------------------------- - * Language::create_command() - * ----------------------------------------------------------------- */ +/* Some status variables used during parsing */ -void Language::create_command(String *, String *) { - Printf(stderr,"SWIG Warning. No command creation procedure defined.\n"); - Printf(stderr,"C++ inheritance may not work correctly.\n"); +static int InClass = 0; /* Parsing C++ or not */ +static String *ClassName = 0; /* This is the real name of the current class */ +static String *ClassPrefix = 0; /* Class prefix */ +static String *ClassType = 0; /* Fully qualified type name to use */ +int Abstract = 0; +int ImportMode = 0; +int IsVirtual = 0; +static String *AttributeFunctionGet = 0; +static String *AttributeFunctionSet = 0; +static int cplus_mode = 0; +static Node *CurrentClass = 0; +int line_number = 0; +char *input_file = 0; +int SmartPointer = 0; + +extern int GenerateDefault; +extern int ForceExtern; +extern int NoExtern; + +/* import modes */ + +#define IMPORT_MODE 1 +#define IMPORT_MODULE 2 + +/* C++ access modes */ + +#define CPLUS_PUBLIC 0 +#define CPLUS_PROTECTED 1 +#define CPLUS_PRIVATE 2 + +/* ---------------------------------------------------------------------- + * Dispatcher::emit_one() + * + * Dispatch a single node + * ---------------------------------------------------------------------- */ + +int Dispatcher::emit_one(Node *n) { + String *wrn; + int ret = SWIG_OK; + + char *tag = Char(nodeType(n)); + if (!tag) { + Printf(stderr,"SWIG: Fatal internal error. Malformed parse tree node!\n"); + return SWIG_ERROR; + } + + /* Do not proceed if marked with an error */ + + if (Getattr(n,"error")) return SWIG_OK; + + /* Look for warnings */ + wrn = Getattr(n,"feature:warnfilter"); + if (wrn) { + Swig_warnfilter(wrn,1); + } + + /* ============================================================ + * C/C++ parsing + * ============================================================ */ + + if (strcmp(tag,"extern") == 0) { + ret = externDeclaration(n); + } else if (strcmp(tag,"cdecl") == 0) { + ret = cDeclaration(n); + } else if (strcmp(tag,"enum") == 0) { + ret = enumDeclaration(n); + } else if (strcmp(tag,"enumitem") == 0) { + ret = enumvalueDeclaration(n); + } else if (strcmp(tag,"class") == 0) { + ret = classDeclaration(n); + } else if (strcmp(tag,"classforward") == 0) { + ret = classforwardDeclaration(n); + } else if (strcmp(tag,"constructor") == 0) { + ret = constructorDeclaration(n); + } else if (strcmp(tag,"destructor") == 0) { + ret = destructorDeclaration(n); + } else if (strcmp(tag,"access") == 0) { + ret = accessDeclaration(n); + } else if (strcmp(tag,"using") == 0) { + ret = usingDeclaration(n); + } else if (strcmp(tag,"namespace") == 0) { + ret = namespaceDeclaration(n); + } else if (strcmp(tag,"template") == 0) { + ret = templateDeclaration(n); + } + + /* =============================================================== + * SWIG directives + * =============================================================== */ + + else if (strcmp(tag,"top") == 0) { + ret = top(n); + } else if (strcmp(tag,"extend") == 0) { + ret = extendDirective(n); + } else if (strcmp(tag,"apply") == 0) { + ret = applyDirective(n); + } else if (strcmp(tag,"clear") == 0) { + ret = clearDirective(n); + } else if (strcmp(tag,"constant") == 0) { + ret = constantDirective(n); + } else if (strcmp(tag,"fragment") == 0) { + ret = fragmentDirective(n); + } else if (strcmp(tag,"import") == 0) { + ret = importDirective(n); + } else if (strcmp(tag,"include") == 0) { + ret = includeDirective(n); + } else if (strcmp(tag,"insert") == 0) { + ret = insertDirective(n); + } else if (strcmp(tag,"module") == 0) { + ret = moduleDirective(n); + } else if (strcmp(tag,"native") == 0) { + ret = nativeDirective(n); + } else if (strcmp(tag,"pragma") == 0) { + ret = pragmaDirective(n); + } else if (strcmp(tag,"typemap") == 0) { + ret = typemapDirective(n); + } else if (strcmp(tag,"typemapcopy") == 0) { + ret = typemapcopyDirective(n); + } else if (strcmp(tag,"typemapitem") == 0) { + ret = typemapitemDirective(n); + } else if (strcmp(tag,"types") == 0) { + ret = typesDirective(n); + } else { + Printf(stderr,"%s:%d. Unrecognized parse tree node type '%s'\n", input_file, line_number, tag); + ret = SWIG_ERROR; + } + if (wrn) { + Swig_warnfilter(wrn,0); + } + return ret; } -/* ----------------------------------------------------------------- - * Language::nativefunction() - * ----------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * Dispatcher::emit_children() + * + * Emit all children. + * ---------------------------------------------------------------------- */ -void -Language::nativefunction(DOH *node) { - Printf(stderr,"%s:%d. Adding native function %s not supported (ignored).\n", Getfile(node), Getline(node), Getattr(node,"scriptname")); +int Dispatcher::emit_children(Node *n) { + Node *c; + for (c = firstChild(n); c; c = nextSibling(c)) { + emit_one(c); + } + return SWIG_OK; } +/* Stubs for dispatcher class. We don't do anything by default---up to derived class + to fill in traversal code */ + +int Dispatcher::defaultHandler(Node *) { return SWIG_OK; } +int Dispatcher::extendDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::applyDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::clearDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::constantDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::fragmentDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::importDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::includeDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::insertDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::moduleDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::nativeDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::pragmaDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::typemapDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::typemapitemDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::typemapcopyDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::typesDirective(Node *n) { return defaultHandler(n); } +int Dispatcher::cDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::externDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::enumDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::enumvalueDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::classDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::templateDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::classforwardDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::constructorDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::destructorDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::accessDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::usingDeclaration(Node *n) { return defaultHandler(n); } +int Dispatcher::namespaceDeclaration(Node *n) { return defaultHandler(n); } + +/* Allocators */ +Language::Language() { + symbols = NewHash(); + classtypes = NewHash(); + overloading = 0; + multiinput = 0; +} -/* The following strings are used during code generation and contain various - permutations of the class name: +Language::~Language() { + Delete(symbols); + Delete(classtypes); +} - ClassName - This is the name of the class as it appears in C/C++ - source code. It does not include a type specifier - such as "struct" or "class" +/* ---------------------------------------------------------------------- + emit_one() + ---------------------------------------------------------------------- */ - ClassRename - If non-NULL, the class has been renamed. - ClassType - The type of the class (struct, class, union) - ClassFullname - The full name of the class including its type specifier. - For example, "class Foo" or "struct Vector". - ClassPrefix - The class prefix as used in the scripting language - interface. This is either ClassName or ClassRename. -*/ +int Language::emit_one(Node *n) { + int ret; + int oldext; + if (!n) return SWIG_OK; -static String *ClassName = 0; -static String *ClassRename = 0; -static String *ClassType = 0; -static String *ClassFullname = 0; -static String *ClassPrefix = 0; + if (Getattr(n,"feature:ignore")) return SWIG_OK; -/* ----------------------------------------------------------------------------- - * Language::cpp_open_class() - * ----------------------------------------------------------------------------- */ + oldext = Extend; + if (Getattr(n,"feature:extend")) Extend = 1; + + line_number = Getline(n); + input_file = Char(Getfile(n)); -void Language::cpp_open_class(DOH *node) { - String *classname; - String *classrename; - String *ctype; - String *altname; - int strip = CPlusPlus; + /* + symtab = Getattr(n,"symtab"); + if (symtab) { + symtab = Swig_symbol_setscope(symtab); + } + */ + ret = Dispatcher::emit_one(n); + /* + if (symtab) { + Swig_symbol_setscope(symtab); + } + */ + Extend = oldext; + return ret; +} - classname = Getname(node); - classrename = Getattr(node,"scriptname"); - ctype = Getattr(node,"classtype"); - altname = Getattr(node,"altname"); - if (altname) { - strip = 1; - classname = altname; /* Use the alt name instead of the class name */ +static Parm *nonvoid_parms(Parm *p) { + if (p) { + SwigType *t = Getattr(p,"type"); + if (SwigType_type(t) == T_VOID) return 0; } + return p; +} - if (strip) SetInt(node,"strip",1); +/* This is a hack */ +SwigType *cplus_value_type(SwigType *t) { + Node *n; + if (!CPlusPlus) return 0; + if (SwigType_isclass(t)) { + SwigType *td = SwigType_typedef_resolve_all(t); + if ((n = Swig_symbol_clookup(td,0))) { + if ((Strcmp(nodeType(n),"class") == 0) && (!Getattr(n,"allocate:default_constructor") || (Getattr(n,"allocate:noassign")))) { + String *s = NewStringf("SwigValueWrapper< %s >",t); + Delete(td); + return s; + } + } + if (SwigType_issimple(td) && SwigType_istemplate(td)) { + String *s = NewStringf("SwigValueWrapper< %s >",t); + Delete(td); + return s; + } + Delete(td); + } + return 0; +} - /* Copy the class name */ - if (ClassName) Delete(ClassName); - ClassName = NewString(classname); +/* Patch C++ pass-by-value */ +void Language::patch_parms(Parm *p) { + while (p) { + SwigType *t = Getattr(p,"type"); + SwigType *s = cplus_value_type(t); + if (s) { + Setattr(p,"alttype",s); + Delete(s); + } + p = nextSibling(p); + } +} - /* Copy the class renaming */ +static Node *first_nontemplate(Node *n) { + while (n) { + if (Strcmp(nodeType(n),"template") != 0) return n; + n = Getattr(n,"sym:nextSibling"); + } + return n; +} - if (ClassRename) Delete(ClassRename); - ClassRename = NewString(classrename); +/* -------------------------------------------------------------------------- + * swig_pragma() + * + * Handle swig pragma directives. + * -------------------------------------------------------------------------- */ + +void swig_pragma(char *lang, char *name, char *value) { + if (strcmp(lang,"swig") == 0) { + if ((strcmp(name,"make_default") == 0) || ((strcmp(name,"makedefault") == 0))) { + GenerateDefault = 1; + } else if ((strcmp(name,"no_default") == 0) || ((strcmp(name,"nodefault") == 0))) { + GenerateDefault = 0; + } else if (strcmp(name,"attributefunction") == 0) { + String *nvalue = NewString(value); + char *s = strchr(Char(nvalue),':'); + if (!s) { + Swig_error(input_file, line_number, "Bad value for attributefunction. Expected \"fmtget:fmtset\".\n"); + } else { + *s = 0; + AttributeFunctionGet = NewString(Char(nvalue)); + AttributeFunctionSet = NewString(s+1); + } + Delete(nvalue); + } else if (strcmp(name,"noattributefunction") == 0) { + AttributeFunctionGet = 0; + AttributeFunctionSet = 0; + } + } +} + +/* ---------------------------------------------------------------------- + * Language::top() - Top of parsing tree + * ---------------------------------------------------------------------- */ + +int Language::top(Node *n) { + return emit_children(n); +} + +/* ---------------------------------------------------------------------- + * Language::extendDirective() + * ---------------------------------------------------------------------- */ - if (ClassType) Delete(ClassType); - ClassType = strip ? 0 : NewString(ctype); +int Language::extendDirective(Node *n) { + int oldam = Extend; + int oldmode = cplus_mode; + Extend = CWRAP_EXTEND; + cplus_mode = CPLUS_PUBLIC; - if (ClassFullname) Delete(ClassFullname); + emit_children(n); - ClassFullname = ClassType ? NewStringf("%s %s", ClassType, ClassName) : NewString(ClassName); - ClassPrefix = ClassRename; + Extend = oldam; + cplus_mode = oldmode; + return SWIG_OK; } -/* ----------------------------------------------------------------------------- - * Language::cpp_close_class() - * ----------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * Language::applyDirective() + * ---------------------------------------------------------------------- */ -void Language::cpp_close_class() { +int Language::applyDirective(Node *n) { - /* Doesn't really do anything */ + Parm *pattern = Getattr(n,"pattern"); + Node *c = firstChild(n); + while (c) { + Parm *apattern = Getattr(c,"pattern"); + if (ParmList_len(pattern) != ParmList_len(apattern)) { + Swig_error(input_file, line_number, "Can't apply (%s) to (%s). Number of arguments don't match.\n", + ParmList_str(pattern), ParmList_str(apattern)); + } else { + if (!Swig_typemap_apply(pattern,apattern)) { + Swig_warning(WARN_TYPEMAP_APPLY_UNDEF,input_file,line_number,"Can't apply (%s). No typemaps are defined.\n", ParmList_str(pattern)); + } + } + c = nextSibling(c); + } + return SWIG_OK; } -/* ----------------------------------------------------------------------------- - * Language::cpp_memberfunction() - * ----------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * Language::clearDirective() + * ---------------------------------------------------------------------- */ + +int Language::clearDirective(Node *n) { + Node *p; + for (p = firstChild(n); p; p = nextSibling(p)) { + ParmList *pattern = Getattr(p,"pattern"); + Swig_typemap_clear_apply(pattern); + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::constantDirective() + * ---------------------------------------------------------------------- */ + +int Language::constantDirective(Node *n) { + + if (CurrentClass && (cplus_mode != CPLUS_PUBLIC)) return SWIG_NOWRAP; + + if (!ImportMode) { + Swig_require(&n,"name", "?value",NIL); + String *name = Getattr(n,"name"); + String *value = Getattr(n,"value"); + if (!value) { + value = Copy(name); + } else { + value = NewStringf("%(escape)s", value); + } + Setattr(n,"value", value); + this->constantWrapper(n); + Swig_restore(&n); + return SWIG_OK; + } + return SWIG_NOWRAP; +} -void Language::cpp_memberfunction(DOH *node) { - String *name; - String *iname; - String *ccode; - String *script_name; - SwigType *type; - ParmList *parms; - Wrapper *w; +/* ---------------------------------------------------------------------- + * Language::fragmentDirective() + * ---------------------------------------------------------------------- */ - name = Getattr(node,"name"); - iname = Getattr(node,"scriptname"); - type = Getattr(node,"type"); - parms = Getattr(node,"parms"); - ccode = Getattr(node,"code"); +int Language::fragmentDirective(Node *n) { + String *name = Getattr(n,"name"); + String *code = Getattr(n,"code"); + String *section = Getattr(n,"section"); + Swig_fragment_register(name,section,code); + return SWIG_OK; +} - /* Generate the C wrapper function name and interpreter name of this function*/ - /* Create the actual function name */ +/* ---------------------------------------------------------------------- + * Language::importDirective() + * ---------------------------------------------------------------------- */ - script_name = Swig_name_member(ClassPrefix, iname ? iname : name); +int Language::importDirective(Node *n) { + int oldim = ImportMode; + ImportMode = IMPORT_MODE; + emit_children(n); + ImportMode = oldim; + return SWIG_OK; +} - /* Now do a symbol table lookup on it */ +/* ---------------------------------------------------------------------- + * Language::includeDirective() + * ---------------------------------------------------------------------- */ - /* Create the C wrapper function for this */ - w = Swig_cmethod_wrapper(ClassFullname, name, type, parms, ccode); - if (AddMethods && ccode) { - /* Dump the C wrappers */ - Printf(f_wrappers,"%s",w); - } else if (!AddMethods) { - /* Just create a string that does what we want */ - emit_set_action(Swig_cmethod_call(name, Getparms(w))); +int Language::includeDirective(Node *n) { + emit_children(n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::insertDirective() + * ---------------------------------------------------------------------- */ + +int Language::insertDirective(Node *n) { + /* %insert directive */ + if ((!ImportMode) || Getattr(n,"generated")) { + String *code = Getattr(n,"code"); + String *section = Getattr(n,"section"); + File *f = 0; + if (!section) { /* %{ ... %} */ + f = Swig_filebyname("header"); + } else { + f = Swig_filebyname(section); + } + if (f) { + Printf(f,"%s\n",code); + } else { + Swig_error(input_file,line_number,"Unknown target '%s' for %%insert directive.\n", section); + } + return SWIG_OK; + } else { + return SWIG_NOWRAP; } - Setattr(w,"scriptname",script_name); - lang->function(w); - Delete(w); } -/* ----------------------------------------------------------------------------- - * Language::cpp_constructor() - * ----------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * Language::moduleDirective() + * ---------------------------------------------------------------------- */ + +int Language::moduleDirective(Node *n) { + /* %module directive */ + return SWIG_OK; +} -void Language::cpp_constructor(DOH *node) { - String *name; - String *iname; - String *cname; - String *ccode; - ParmList *parms; - Wrapper *w; +/* ---------------------------------------------------------------------- + * Language::nativeDirective() + * ---------------------------------------------------------------------- */ - name = Getattr(node,"name"); - iname = Getattr(node,"scriptname"); - parms = Getattr(node,"parms"); - ccode = Getattr(node,"code"); +int Language::nativeDirective(Node *n) { + if (!ImportMode) { + return nativeWrapper(n); + } else { + return SWIG_NOWRAP; + } +} - if ((Cmp(name,ClassName))) { - Printf(stderr,"%s:%d. Function %s must have a return type.\n", - Getfile(node), Getline(node), name); - return; +/* ---------------------------------------------------------------------- + * Language::pragmaDirective() + * ---------------------------------------------------------------------- */ + +int Language::pragmaDirective(Node *n) { + /* %pragma directive */ + if (!ImportMode) { + String *lan = Getattr(n,"lang"); + String *name = Getattr(n,"name"); + String *value = Getattr(n,"value"); + swig_pragma(Char(lan),Char(name),Char(value)); + /* pragma(Char(lan),Char(name),Char(value)); */ + return SWIG_OK; } - - cname = Swig_name_construct(iname ? iname : ClassPrefix); + return SWIG_OK; +} - /* Add this function to the SWIG symbol table */ +/* ---------------------------------------------------------------------- + * Language::typemapDirective() + * ---------------------------------------------------------------------- */ + +extern "C" void Swig_cparse_replace_descriptor(String *s); + +int Language::typemapDirective(Node *n) { + /* %typemap directive */ + String *method = Getattr(n,"method"); + String *code = Getattr(n,"code"); + Parm *kwargs = Getattr(n,"kwargs"); + Node *items = firstChild(n); + static int namewarn = 0; + + + if (code && (Strstr(code,"$source") || (Strstr(code,"$target")))) { + Swig_warning(WARN_TYPEMAP_SOURCETARGET,Getfile(n),Getline(n),"Deprecated typemap feature ($source/$target).\n"); + if (!namewarn) { + Swig_warning(WARN_TYPEMAP_SOURCETARGET, Getfile(n), Getline(n), + "The use of $source and $target in a typemap declaration is deprecated.\n\ +For typemaps related to argument input (in,ignore,default,arginit,check), replace\n\ +$source by $input and $target by $1. For typemaps related to return values (out,\n\ +argout,ret,except), replace $source by $1 and $target by $result. See the file\n\ +Doc/Manual/Typemaps.html for complete details.\n"); + namewarn = 1; + } + } + + /* + if (Strcmp(method,"except") == 0) { + Swig_warning(WARN_DEPRECATED_EXCEPT_TM, Getfile(n), Getline(n), + "%%typemap(except) is deprecated. Use the %%exception directive.\n"); + } + */ + + if (Strcmp(method,"in") == 0) { + Hash *k; + k = kwargs; + while (k) { + if (checkAttribute(k,"name","numinputs")) { + if (!multiinput && (GetInt(k,"value") > 1)) { + Swig_error(Getfile(n),Getline(n),"Multiple-input typemaps (numinputs > 1) not supported by this target language module.\n"); + return SWIG_ERROR; + } + break; + } + k = nextSibling(k); + } + if (!k) { + k = NewHash(); + Setattr(k,"name","numinputs"); + Setattr(k,"value","1"); + set_nextSibling(k,kwargs); + Setattr(n,"kwargs",k); + kwargs = k; + } + } + + if (Strcmp(method,"ignore") == 0) { + Swig_warning(WARN_DEPRECATED_IGNORE_TM, Getfile(n), Getline(n), + "%%typemap(ignore) has been replaced by %%typemap(in,numinputs=0).\n"); + + Clear(method); + Append(method,"in"); + Hash *k = NewHash(); + Setattr(k,"name","numinputs"); + Setattr(k,"value","0"); + set_nextSibling(k,kwargs); + Setattr(n,"kwargs",k); + kwargs = k; + } + + /* Replace $descriptor() macros */ + + if (code) { + Setfile(code,Getfile(n)); + Setline(code,Getline(n)); + Swig_cparse_replace_descriptor(code); + } - if (CPlusPlus) { - w = Swig_cppconstructor_wrapper(ClassFullname, parms, ccode); + while (items) { + Parm *pattern = Getattr(items,"pattern"); + Parm *parms = Getattr(items,"parms"); + if (code) { + Swig_typemap_register(method,pattern,code,parms,kwargs); + } else { + Swig_typemap_clear(method,pattern); + } + items = nextSibling(items); + } + return SWIG_OK; + +} + +/* ---------------------------------------------------------------------- + * Language::typemapcopyDirective() + * ---------------------------------------------------------------------- */ + +int Language::typemapcopyDirective(Node *n) { + String *method = Getattr(n,"method"); + Parm *pattern = Getattr(n,"pattern"); + Node *items = firstChild(n); + int nsrc = 0; + nsrc = ParmList_len(pattern); + while (items) { + ParmList *npattern = Getattr(items,"pattern"); + if (nsrc != ParmList_len(npattern)) { + Swig_error(input_file,line_number,"Can't copy typemap. Number of types differ.\n"); + } else { + if (Swig_typemap_copy(method,pattern,npattern) < 0) { + Swig_error(input_file, line_number, "Can't copy typemap.\n"); + } + } + items = nextSibling(items); + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::typesDirective() + * ---------------------------------------------------------------------- */ + +int Language::typesDirective(Node *n) { + Parm *parms = Getattr(n,"parms"); + while (parms) { + SwigType *t = Getattr(parms,"type"); + String *v = Getattr(parms,"value"); + if (!v) { + SwigType_remember(t); + } else { + if (SwigType_issimple(t)) { + SwigType_inherit(t,v,0); + } + } + parms = nextSibling(parms); + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::cDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::cDeclaration(Node *n) { + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + SwigType *decl = Getattr(n,"decl"); + String *storage = Getattr(n,"storage"); + Node *over; + File *f_header = 0; + SwigType *ty, *fullty; + + if (CurrentClass && (cplus_mode != CPLUS_PUBLIC)) return SWIG_NOWRAP; + + if (Cmp(storage,"typedef") == 0) { + Swig_save(&n,"type",NIL); + SwigType *t = Copy(type); + if (t) { + SwigType_push(t,decl); + Setattr(n,"type",t); + typedefHandler(n); + } + Swig_restore(&n); + return SWIG_OK; + } else if (Cmp(storage,"friend") == 0) { + Swig_warning(WARN_LANG_FRIEND_IGNORE, Getfile(n), Getline(n), + "friend function '%s' ignored.\n", name); + return SWIG_NOWRAP; + } + + /* If in import mode, we proceed no further */ + if (ImportMode) return SWIG_NOWRAP; + + /* Overloaded symbol check */ + over = Swig_symbol_isoverloaded(n); + if (!overloading) { + if (over) over = first_nontemplate(over); + if (over && (over != n)) { + SwigType *tc = Copy(decl); + SwigType *td = SwigType_pop_function(tc); + String *oname; + String *cname; + if (CurrentClass) { + oname = NewStringf("%s::%s",ClassName,name); + cname = NewStringf("%s::%s",ClassName,Getattr(over,"name")); + } else { + oname = NewString(name); + cname = NewString(Getattr(over,"name")); + } + + SwigType *tc2 = Copy(Getattr(over,"decl")); + SwigType *td2 = SwigType_pop_function(tc2); + + Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", SwigType_str(td,SwigType_namestr(oname))); + Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over),"Previous declaration is %s\n", SwigType_str(td2,SwigType_namestr(cname))); + + Delete(tc2); + Delete(td2); + Delete(tc); + Delete(td); + Delete(oname); + Delete(cname); + return SWIG_NOWRAP; + } + } + + if (symname && !validIdentifier(symname)) { + Swig_warning(WARN_LANG_IDENTIFIER,input_file, line_number, "Can't wrap '%s' unless renamed to a valid identifier.\n", + symname); + return SWIG_NOWRAP; + } + + ty = NewString(type); + SwigType_push(ty,decl); + fullty = SwigType_typedef_resolve_all(ty); + if (SwigType_isfunction(fullty)) { + if (!SwigType_isfunction(ty)) { + Delete(ty); + ty = fullty; + fullty = 0; + ParmList *parms = SwigType_function_parms(ty); + Setattr(n,"parms",parms); + } + /* Transform the node into a 'function' node and emit */ + if (!CurrentClass) { + f_header = Swig_filebyname("header"); + + if (!NoExtern) { + if (f_header) { + if ((Cmp(storage,"extern") == 0) || (ForceExtern && !storage)) { + Printf(f_header,"extern %s;\n", SwigType_str(ty,name)); + } else if (Cmp(storage,"externc") == 0) { + Printf(f_header,"extern \"C\" %s;\n", SwigType_str(ty,name)); + } + } + } + } + /* This needs to check qualifiers */ + if (SwigType_isqualifier(ty)) { + Setattr(n,"qualifier", SwigType_pop(ty)); + } + Delete(SwigType_pop_function(ty)); + DohIncref(type); + Setattr(n,"type",ty); + functionHandler(n); + Setattr(n,"type",type); + Delete(ty); + Delete(type); + return SWIG_OK; } else { - w = Swig_cconstructor_wrapper(ClassFullname, parms, ccode); + /* Some kind of variable declaration */ + Delattr(n,"decl"); + if (Getattr(n,"nested")) Setattr(n,"feature:immutable","1"); + if (!CurrentClass) { + if ((Cmp(storage,"extern") == 0) || ForceExtern) { + f_header = Swig_filebyname("header"); + if (!NoExtern) { + if (f_header) { + Printf(f_header,"extern %s;\n", SwigType_str(ty,name)); + } + } + } + } + if (!SwigType_ismutable(ty)) { + Setattr(n,"feature:immutable","1"); + } + /* If an array and elements are const, then read-only */ + if (SwigType_isarray(ty)) { + SwigType *tya = SwigType_array_type(ty); + if (SwigType_isconst(tya)) { + Setattr(n,"feature:immutable","1"); + } + } + DohIncref(type); + Setattr(n,"type",ty); + variableHandler(n); + Setattr(n,"type",type); + Setattr(n,"decl",decl); + Delete(ty); + Delete(type); + Delete(fullty); + return SWIG_OK; } - Setattr(w,"scriptname", cname); +} + +/* ---------------------------------------------------------------------- + * Language::functionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::functionHandler(Node *n) { + Parm *p; + p = Getattr(n,"parms"); + if (CPlusPlus) patch_parms(p); + if (!CurrentClass) { + globalfunctionHandler(n); + } else { + String *storage = Getattr(n,"storage"); + if (Cmp(storage,"static") == 0) { + staticmemberfunctionHandler(n); + } else { + memberfunctionHandler(n); + } + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::globalfunctionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::globalfunctionHandler(Node *n) { + + Swig_require(&n,"name","sym:name","type","?parms",NIL); + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *storage = Getattr(n,"storage"); + ParmList *parms = Getattr(n,"parms"); + + if (0 && (Cmp(storage,"static") == 0)) { + Swig_restore(&n); + return SWIG_NOWRAP; /* Can't wrap static functions */ + } else { + /* Check for callback mode */ + String *cb = Getattr(n,"feature:callback"); + if (cb) { + String *cbname = NewStringf(cb,symname); + callbackfunctionHandler(n); + if (Cmp(cbname, symname) == 0) { + Delete(cbname); + Swig_restore(&n); + return SWIG_NOWRAP; + } + Delete(cbname); + } + Setattr(n,"parms",nonvoid_parms(parms)); + Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cfunction_call(name,parms))); + functionWrapper(n); + } + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::callbackfunctionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::callbackfunctionHandler(Node *n) { + Swig_require(&n,"name","*sym:name","*type","?value",NIL); + String *symname = Getattr(n,"sym:name"); + String *type = Getattr(n,"type"); + String *name = Getattr(n,"name"); + String *parms = Getattr(n,"parms"); + String *cb = Getattr(n,"feature:callback"); + String *cbname = NewStringf(cb,symname); + SwigType *cbty = Copy(type); + SwigType_add_function(cbty,parms); + SwigType_add_pointer(cbty); + + Setattr(n,"sym:name", cbname); + Setattr(n,"type", cbty); + Setattr(n,"value", name); + + constantWrapper(n); + Delete(cbname); + Delete(cbty); + + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::memberfunctionHandler() + * ---------------------------------------------------------------------- */ - if (!AddMethods) { - if (CPlusPlus) { - emit_set_action(Swig_cppconstructor_call(ClassFullname, parms)); +int +Language::memberfunctionHandler(Node *n) { + + Swig_require(&n,"*name","*sym:name","*type","?parms","?value",NIL); + + String *storage = Getattr(n,"storage"); + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + ParmList *parms = Getattr(n,"parms"); + String *cb; + + if (Cmp(storage,"virtual") == 0) { + if (Cmp(value,"0") == 0) { + IsVirtual = PURE_VIRTUAL; } else { - emit_set_action(Swig_cconstructor_call(ClassFullname)); + IsVirtual = PLAIN_VIRTUAL; } } else { - if (ccode) { - Printf(f_wrappers,"%s",w); + IsVirtual = 0; + } + cb = Getattr(n,"feature:callback"); + if (cb) { + Node *cb = NewHash(); + String *cbname = NewStringf(cb,symname); + String *cbvalue; + SwigType *cbty = Copy(type); + SwigType_add_function(cbty,parms); + SwigType_add_memberpointer(cbty,ClassName); + cbvalue = NewStringf("&%s::%s",ClassName,name); + Setattr(cb,"sym:name", cbname); + Setattr(cb,"type", cbty); + Setattr(cb,"value", cbvalue); + Setattr(cb,"name", name); + + memberconstantHandler(n); + + Delete(cb); + Delete(cbvalue); + Delete(cbty); + Delete(cbname); + if (Cmp(cbname,symname) == 0) { + Swig_restore(&n); + return SWIG_NOWRAP; } } - lang->function(w); - Delete(w); - /* Call our default method */ - /* cplus_emit_constructor(Char(ClassName), Char(ClassType), Char(ClassRename), name, iname, l, AddMethods); */ + String *fname = Swig_name_member(ClassPrefix, symname); + /* Transformation */ + Swig_MethodToFunction(n,ClassType, Getattr(n,"template") ? 0 : Extend | SmartPointer); + Setattr(n,"sym:name",fname); + functionWrapper(n); + /* DelWrapper(w);*/ + Delete(fname); + Swig_restore(&n); + return SWIG_OK; } -/* ----------------------------------------------------------------------------- - * Language::cpp_destructor() - * ----------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * Language::staticmemberfunctionHandler() + * ---------------------------------------------------------------------- */ -void Language::cpp_destructor(DOH *node) { - String *name; - String *iname; - String *cname; - String *ccode; - Wrapper *w; +int +Language::staticmemberfunctionHandler(Node *n) { - name = Getattr(node,"name"); - iname = Getattr(node,"scriptname"); - cname = Swig_name_destroy(ClassRename ? ClassRename : ClassName); - ccode = Getattr(node,"code"); + Swig_require(&n,"*name","*sym:name","*type",NIL); + Swig_save(&n,"storage",NIL); + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + ParmList *parms = Getattr(n,"parms"); + String *code = Getattr(n,"code"); + String *cname, *mrename; - /* Add this function to the SWIG symbol table */ + if (!Extend) { + cname = NewStringf("%s::%s",ClassName,name); + } else { + cname = Copy(Swig_name_member(ClassPrefix,name)); + } + mrename = Swig_name_member(ClassPrefix, symname); + + Setattr(n,"name",cname); + Setattr(n,"sym:name",mrename); + + if ((Extend) && (code)) { + /* Hmmm. An added static member. We have to create a little wrapper for this */ + String *tmp = NewStringf("%s(%s)", cname, ParmList_str(parms)); + String *wrap = SwigType_str(type,tmp); + Printv(wrap,code,"\n",NIL); + Setattr(n,"wrap:code",wrap); + Delete(tmp); + Delete(wrap); + } + Delattr(n,"storage"); + globalfunctionHandler(n); - if (CPlusPlus) { - w = Swig_cppdestructor_wrapper(ClassFullname,ccode); + Delete(cname); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::variableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::variableHandler(Node *n) { + if (!CurrentClass) { + globalvariableHandler(n); } else { - w = Swig_cdestructor_wrapper(ClassFullname, ccode); - } - Setattr(w,"scriptname",cname); - if (AddMethods && ccode) { - Printf(f_wrappers,"%s", w); - lang->function(w); - } else if (AddMethods) { - lang->function(w); + String *storage = Getattr(n,"storage"); + if ((Cmp(storage,"static") == 0)) { + if (!SmartPointer) { + staticmembervariableHandler(n); + } + } else { + membervariableHandler(n); + } + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::globalvariableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::globalvariableHandler(Node *n) { + String *storage = Getattr(n,"storage"); + if (0 && (Cmp(storage,"static") == 0)) return SWIG_NOWRAP; + variableWrapper(n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::membervariableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::membervariableHandler(Node *n) { + + Swig_require(&n,"*name","*sym:name","*type",NIL); + Swig_save(&n,"parms",NIL); + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + + /* If not a smart-pointer access or added method. We clear + feature:except. There is no way C++ or C would throw + an exception merely for accessing a member data + */ + + if (!(Extend | SmartPointer)) { + Delattr(n,"feature:except"); + } + + if (!AttributeFunctionGet) { + + String *mrename_get, *mrename_set; + + mrename_get = Swig_name_get(Swig_name_member(ClassPrefix, symname)); + mrename_set = Swig_name_set(Swig_name_member(ClassPrefix, symname)); + + /* Create a function to set the value of the variable */ + + if (!Getattr(n,"feature:immutable")) { + int make_wrapper = 1; + String *tm = 0; + String *target = 0; + if (!Extend) { + target = NewStringf("%s->%s", Swig_cparm_name(0,0),name); + tm = Swig_typemap_lookup_new("memberin",n,target,0); + } + Swig_MembersetToFunction(n,ClassType,Extend | SmartPointer); + if (!Extend) { + /* Check for a member in typemap here */ + + /* String *tm = Swig_typemap_lookup((char *) "memberin",type,name,target,Swig_cparm_name(0,1),target,0);*/ + if (!tm) { + if (SwigType_isarray(type)) { + /* Printf(stderr,"%s:%d. Warning. Array member %s will be read-only.\n", input_file, line_number, name);*/ + make_wrapper = 0; + } + } else { + Replace(tm,"$source", Swig_cparm_name(0,1), DOH_REPLACE_ANY); + Replace(tm,"$target", target, DOH_REPLACE_ANY); + Replace(tm,"$input",Swig_cparm_name(0,1),DOH_REPLACE_ANY); + Replace(tm,"$self",Swig_cparm_name(0,0),DOH_REPLACE_ANY); + Setattr(n,"wrap:action", tm); + Delete(tm); + } + Delete(target); + } + if (make_wrapper) { + Setattr(n,"sym:name", mrename_set); + functionWrapper(n); + } else { + Setattr(n,"feature:immutable","1"); + } + /* Restore parameters */ + Setattr(n,"type",type); + Setattr(n,"name",name); + Setattr(n,"sym:name",symname); + } + /* Emit get function */ + { + Swig_MembergetToFunction(n,ClassType,Extend | SmartPointer); + Setattr(n,"sym:name", mrename_get); + functionWrapper(n); + } + Delete(mrename_get); + Delete(mrename_set); + } else { - if (CPlusPlus) - emit_set_action(Swig_cppdestructor_call()); - else - emit_set_action(Swig_cdestructor_call()); - lang->function(w); - } - Delete(w); + + /* This code is used to support the attributefunction directive + where member variables are converted automagically to + accessor functions */ + +#if 0 + Parm *p; + String *gname; + SwigType *vty; + p = NewParm(type,0); + gname = NewStringf(AttributeFunctionGet,symname); + if (!Extend) { + ActionFunc = Copy(Swig_cmemberget_call(name,type)); + cpp_member_func(Char(gname),Char(gname),type,0); + Delete(ActionFunc); + } else { + String *cname = Copy(Swig_name_get(name)); + cpp_member_func(Char(cname),Char(gname),type,0); + Delete(cname); + } + Delete(gname); + if (!Getattr(n,"feature:immutable")) { + gname = NewStringf(AttributeFunctionSet,symname); + vty = NewString("void"); + if (!Extend) { + ActionFunc = Copy(Swig_cmemberset_call(name,type)); + cpp_member_func(Char(gname),Char(gname),vty,p); + Delete(ActionFunc); + } else { + String *cname = Copy(Swig_name_set(name)); + cpp_member_func(Char(cname),Char(gname),vty,p); + Delete(cname); + } + Delete(gname); + } + ActionFunc = 0; +#endif + } + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::staticmembervariableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::staticmembervariableHandler(Node *n) +{ + Swig_require(&n,"*name","*sym:name","*type", "?value", NIL); + String *value = Getattr(n,"value"); + if (!value) { + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + String *cname, *mrename; + + /* Create the variable name */ + mrename = Swig_name_member(ClassPrefix, symname); + cname = NewStringf("%s::%s", ClassName,name); + + Setattr(n,"sym:name",mrename); + Setattr(n,"name", cname); + + /* Wrap as an ordinary global variable */ + variableWrapper(n); + + Delete(mrename); + Delete(cname); + } else { + String *name = Getattr(n,"name"); + String *cname = NewStringf("%s::%s", ClassName,name); + String* value = SwigType_namestr(cname); + Setattr(n, "value", value); + + SwigType *t1 = SwigType_typedef_resolve_all(Getattr(n,"type")); + SwigType *t2 = SwigType_strip_qualifiers(t1); + Setattr(n, "type", t2); + Delete(t1); + Delete(t2); + + memberconstantHandler(n); + Delete(cname); + } + + Swig_restore(&n); + return SWIG_OK; +} + + +/* ---------------------------------------------------------------------- + * Language::externDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::externDeclaration(Node *n) { + return emit_children(n); +} + +/* ---------------------------------------------------------------------- + * Language::enumDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::enumDeclaration(Node *n) { + if (!ImportMode) { + emit_children(n); + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::enumvalueDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::enumvalueDeclaration(Node *n) { + if (CurrentClass && (cplus_mode != CPLUS_PUBLIC)) return SWIG_NOWRAP; + + Swig_require(&n,"*name", "?value",NIL); + String *value = Getattr(n,"value"); + String *name = Getattr(n,"name"); + String *tmpValue; + + if (value) + tmpValue = NewString(value); + else + tmpValue = NewString(name); + Setattr(n, "value", tmpValue); + + if (!CurrentClass) { + Setattr(n,"name",tmpValue); /* for wrapping of enums in a namespace when emit_action is used */ + constantWrapper(n); + } else { + memberconstantHandler(n); + } + + Delete(tmpValue); + Swig_restore(&n); + return SWIG_OK; } /* ----------------------------------------------------------------------------- - * Language::cpp_inherit() + * Language::memberconstantHandler() * ----------------------------------------------------------------------------- */ -void Language::cpp_inherit(List *bases) { +int Language::memberconstantHandler(Node *n) { - if (!bases) return; - /* - while (baseclass[i]) { - // cplus_inherit_members(baseclass[i],mode); - i++; - } + Swig_require(&n,"*name","*sym:name","*value",NIL); + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + String *value = Getattr(n,"value"); + + String *mrename; + String *new_value; + + mrename = Swig_name_member(ClassPrefix, symname); + /* Fixed by namespace-enum patch + if ((!value) || (Cmp(value,name) == 0)) { + new_value = NewStringf("%s::%s",ClassName,name); + } else { + new_value = NewString(value); + } */ + new_value = Copy(value); + Setattr(n,"sym:name", mrename); + Setattr(n,"value", new_value); + Setattr(n,"name", NewStringf("%s::%s", ClassName,name)); + constantWrapper(n); + Delete(mrename); + Delete(new_value); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::typedefHandler() + * ---------------------------------------------------------------------- */ + +int Language::typedefHandler(Node *) { + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::classDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::classDeclaration(Node *n) { + String *kind = Getattr(n,"kind"); + String *name = Getattr(n,"name"); + String *tdname = Getattr(n,"tdname"); + String *symname = Getattr(n,"sym:name"); + + char *classname = tdname ? Char(tdname) : Char(name); + char *iname = Char(symname); + int strip = (tdname || CPlusPlus) ? 1 : 0; + + + if (!classname) { + Swig_warning(WARN_LANG_CLASS_UNNAMED, input_file, line_number, "Can't generate wrappers for unnamed struct/class.\n"); + return SWIG_NOWRAP; + } + + /* Check symbol name for template. If not renamed. Issue a warning */ + /* Printf(stdout,"sym:name = %s\n", symname); */ + + if (!validIdentifier(symname)) { + Swig_warning(WARN_LANG_IDENTIFIER, input_file, line_number, "Can't wrap class %s unless renamed to a valid identifier.\n", + SwigType_namestr(symname)); + return SWIG_NOWRAP; + } + + Swig_save(&n,"name",NIL); + Setattr(n,"name",classname); + + if (Cmp(kind,"class") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else { + cplus_mode = CPLUS_PUBLIC; + } + + ClassName = NewString(classname); + ClassPrefix = NewString(iname); + if (strip) { + ClassType = NewString(classname); + } else { + ClassType = NewStringf("%s %s", kind, classname); + } + Setattr(n,"classtype", SwigType_namestr(ClassType)); + + InClass = 1; + CurrentClass = n; + + if (Getattr(n,"abstract")) { + Abstract = 1; + } else { + Abstract = 0; + } + + /* Call classHandler() here */ + if (!ImportMode) + classHandler(n); + else + Language::classHandler(n); + + InClass = 0; + CurrentClass = 0; + Delete(ClassType); ClassType = 0; + Delete(ClassPrefix); ClassPrefix = 0; + Delete(ClassName); ClassName = 0; + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::classHandler() + * ---------------------------------------------------------------------- */ + +int Language::classHandler(Node *n) { + + /* Emit all of the class members */ + emit_children(n); + + /* Look for smart pointer handling */ + if (Getattr(n,"allocate:smartpointer")) { + List *methods = Getattr(n,"allocate:smartpointer"); + cplus_mode = CPLUS_PUBLIC; + SmartPointer = CWRAP_SMART_POINTER; + Node *c; + for (c = Firstitem(methods); c; c= Nextitem(methods)) { + /* Swig_print_node(c); */ + emit_one(c); + } + SmartPointer = 0; + } + + cplus_mode = CPLUS_PUBLIC; + if (!ImportMode && (GenerateDefault && !Getattr(n,"feature:nodefault"))) { + if (!Getattr(n,"has_constructor") && !Getattr(n,"allocate:has_constructor") && (Getattr(n,"allocate:default_constructor"))) { + /* Note: will need to change this to support different kinds of classes */ + if (!Abstract) { + Setattr(CurrentClass,"feature:new","1"); + constructorHandler(CurrentClass); + Delattr(CurrentClass,"feature:new"); + } + } + if (!Getattr(n,"has_destructor") && (!Getattr(n,"allocate:has_destructor")) && (Getattr(n,"allocate:default_destructor"))) { + destructorHandler(CurrentClass); + } + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::classforwardDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::classforwardDeclaration(Node *n) { + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::constructorDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::constructorDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + + if (!CurrentClass) return SWIG_NOWRAP; + if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP; + if (ImportMode) return SWIG_NOWRAP; + + /* Name adjustment for %name */ + Swig_save(&n,"sym:name",NIL); + + { + String *base = Swig_scopename_last(name); + if ((Strcmp(base,symname) == 0) && (Strcmp(symname, ClassPrefix) != 0)) { + Setattr(n,"sym:name", ClassPrefix); + } + Delete(base); + } + /* Only create a constructor if the class is not abstract */ + + if (!Abstract) { + Node *over; + over = Swig_symbol_isoverloaded(n); + if (over) over = first_nontemplate(over); + if ((over) && (!overloading)) { + /* If the symbol is overloaded. We check to see if it is a copy constructor. If so, + we invoke copyconstructorHandler() as a special case. */ + if (Getattr(n,"copy_constructor") && (!Getattr(CurrentClass,"has_copy_constructor"))) { + copyconstructorHandler(n); + Setattr(CurrentClass,"has_copy_constructor","1"); + } else { + if (Getattr(over,"copy_constructor")) over = Getattr(over,"sym:nextSibling"); + if (over != n) { + String *oname = NewStringf("%s::%s", ClassName, Swig_scopename_last(SwigType_namestr(name))); + String *cname = NewStringf("%s::%s", ClassName, Swig_scopename_last(SwigType_namestr(Getattr(over,"name")))); + SwigType *decl = Getattr(n,"decl"); + Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, input_file, line_number, + "Overloaded constructor ignored. %s\n", SwigType_str(decl,SwigType_namestr(oname))); + Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, Getfile(over), Getline(over), + "Previous declaration is %s\n", SwigType_str(Getattr(over,"decl"),SwigType_namestr(cname))); + Delete(oname); + Delete(cname); + } else { + constructorHandler(n); + } + } + } else { + if (name && (Cmp(name,ClassName)) && !(Getattr(n,"template"))) { + Printf(stdout,"name = '%s', ClassName='%s'\n", name, ClassName); + Swig_warning(WARN_LANG_RETURN_TYPE, input_file,line_number,"Function %s must have a return type.\n", + name); + Swig_restore(&n); + return SWIG_NOWRAP; + } + constructorHandler(n); + } + } + Setattr(CurrentClass,"has_constructor","1"); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::constructorHandler() + * ---------------------------------------------------------------------- */ + +int +Language::constructorHandler(Node *n) { + Swig_require(&n,"?name","*sym:name","?type","?parms",NIL); + String *symname = Getattr(n,"sym:name"); + String *mrename; + Parm *parms = Getattr(n,"parms"); + + mrename = Swig_name_construct(symname); + if (CPlusPlus) patch_parms(parms); + Swig_ConstructorToFunction(n,ClassType,CPlusPlus,Getattr(n,"template") ? 0 :Extend); + Setattr(n,"sym:name", mrename); + functionWrapper(n); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::copyconstructorHandler() + * ---------------------------------------------------------------------- */ + +int +Language::copyconstructorHandler(Node *n) { + Swig_require(&n,"?name","*sym:name","?type","?parms", NIL); + String *symname = Getattr(n,"sym:name"); + String *mrename; + Parm *parms = Getattr(n,"parms"); + if (CPlusPlus) patch_parms(parms); + mrename = Swig_name_copyconstructor(symname); + Swig_ConstructorToFunction(n,ClassType, CPlusPlus, Getattr(n,"template") ? 0 : Extend); + Setattr(n,"sym:name", mrename); + functionWrapper(n); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::destructorDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::destructorDeclaration(Node *n) { + + if (!CurrentClass) return SWIG_NOWRAP; + if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP; + if (ImportMode) return SWIG_NOWRAP; + + Swig_save(&n,"name", "sym:name",NIL); + + char *c = GetChar(n,"name"); + if (c && (*c == '~')) Setattr(n,"name",c+1); + + c = GetChar(n,"sym:name"); + if (c && (*c == '~')) Setattr(n,"sym:name",c+1); + + /* Name adjustment for %name */ + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + + if ((Strcmp(name,symname) == 0) || (Strcmp(symname,ClassPrefix) != 0)) { + Setattr(n,"sym:name", ClassPrefix); + } + + destructorHandler(n); + + Setattr(CurrentClass,"has_destructor","1"); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::destructorHandler() + * ---------------------------------------------------------------------- */ + +int Language::destructorHandler(Node *n) { + Swig_require(&n,"?name","*sym:name",NIL); + Swig_save(&n,"type","parms",NIL); + + String *symname = Getattr(n,"sym:name"); + String *mrename; + char *csymname = Char(symname); + if (csymname && (*csymname == '~')) csymname +=1; + + mrename = Swig_name_destroy(csymname); + + Swig_DestructorToFunction(n,ClassType,CPlusPlus,Extend); + Setattr(n,"sym:name", mrename); + functionWrapper(n); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::accessDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::accessDeclaration(Node *n) { + String *kind = Getattr(n,"kind"); + if (Cmp(kind,"public") == 0) { + cplus_mode = CPLUS_PUBLIC; + } else if (Cmp(kind,"private") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else if (Cmp(kind,"protected") == 0) { + cplus_mode = CPLUS_PROTECTED; + } + return SWIG_OK; } /* ----------------------------------------------------------------------------- - * Language::cpp_variable() + * Language::namespaceDeclaration() * ----------------------------------------------------------------------------- */ -void Language::cpp_variable(DOH *node) { - String *name; - String *iname; - String *cname; - String *setcode, *getcode; - SwigType *type; - Wrapper *w; - - name = Getattr(node,"name"); - iname = Getattr(node,"scriptname"); - type = Getattr(node,"type"); - setcode = Getattr(node,"setcode"); - getcode = Getattr(node,"getcode"); - - /* Set the class prefix */ - - cname = Swig_name_get(Swig_name_member(ClassPrefix, iname ? iname : name)); - - /* Check the symbol table */ - - /* Create a function to set the value of the variable */ - if (!ReadOnly) { - w = Swig_cmemberset_wrapper(ClassFullname, name, type, setcode); - Setattr(w,"scriptname",Swig_name_set(Swig_name_member(ClassPrefix,iname ? iname : name))); - if (AddMethods && setcode) { - Printf(f_wrappers,"%s",w); - } else if (!AddMethods) { - /* Check for a member in typemap here */ - String *target = NewStringf("%s->%s", Swig_cparm_name(0,0),name); - char *tm = Swig_typemap_lookup("memberin",type,name,Swig_cparm_name(0,1),target,0); - if (!tm) - emit_set_action(Swig_cmemberset_call(name,type)); - else - emit_set_action(tm); - Delete(target); - } - lang->function(w); - Delete(w); - } - w = Swig_cmemberget_wrapper(ClassFullname, name, type, getcode); - Setattr(w,"scriptname", Swig_name_get(Swig_name_member(ClassPrefix, iname ? iname : name))); - if (AddMethods && getcode) { - Printf(f_wrappers,"%s",w); - } else if (!AddMethods) { - emit_set_action(Swig_cmemberget_call(name,type)); - } - lang->function(w); - Delete(w); +int Language::namespaceDeclaration(Node *n) { + if (Getattr(n,"alias")) return SWIG_OK; + emit_children(n); + return SWIG_OK; +} + +int Language::validIdentifier(String *s) { + char *c = Char(s); + while (*c) { + if (!(isalnum(*c) || (*c == '_'))) return 0; + c++; + } + return 1; } /* ----------------------------------------------------------------------------- - * Language::cpp_static_func() + * Language::usingDeclaration() * ----------------------------------------------------------------------------- */ -void Language::cpp_staticfunction(DOH *node) { - String *name; - String *iname; - SwigType *type; - ParmList *parms; - String *ccode; - String *script_name; - String *real_name; - DOH *nnode; - Wrapper *w; - - name = Getattr(node,"name"); - iname = Getattr(node,"scriptname"); - type = Getattr(node,"type"); - parms = Getattr(node,"parms"); - ccode = Getattr(node,"code"); - - /* Set the member function name */ - script_name = Swig_name_member(ClassPrefix,iname ? iname : name); - - /* Now do a symbol table lookup on it : */ - - /* Figure out the name of the function */ - if (AddMethods) { - real_name = Swig_name_member(ClassName, name); - if (!ccode) { - nnode = Copy(node); - Setattr(nnode,"name", real_name); - Setattr(nnode,"scriptname", script_name); - lang->function(nnode); - Delete(nnode); - } else { - w = Swig_cfunction_wrapper(real_name,type,parms,ccode); - Printf(f_wrappers,"%s",w); - Setattr(w,"scriptname",script_name); - lang->function(w); - Delete(w); +int Language::usingDeclaration(Node *n) { + if (cplus_mode == CPLUS_PUBLIC) { + emit_children(n); + } + return SWIG_OK; +} + +/* Stubs. Language modules need to implement these */ + +/* ---------------------------------------------------------------------- + * Language::constantWrapper() + * ---------------------------------------------------------------------- */ + +int Language::constantWrapper(Node *n) { + String *name = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + + Printf(stdout,"constantWrapper : %s = %s\n", SwigType_str(type,name), value); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::variableWrapper() + * ---------------------------------------------------------------------- */ +int Language::variableWrapper(Node *n) { + Swig_require(&n,"*name","*sym:name","*type","?parms",NIL); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *name = Getattr(n,"name"); + + /* If no way to set variables. We simply create functions */ + if (!Getattr(n,"feature:immutable")) { + int make_wrapper = 1; + String *tm = Swig_typemap_lookup_new("globalin", n, name, 0); + + Swig_VarsetToFunction(n); + Setattr(n,"sym:name", Swig_name_set(symname)); + + /* String *tm = Swig_typemap_lookup((char *) "globalin",type,name,name,Swig_cparm_name(0,0),name,0);*/ + + if (!tm) { + if (SwigType_isarray(type)) { + /* Printf(stderr,"%s:%d. Warning. Array member %s will be read-only.\n", input_file, line_number, name);*/ + make_wrapper = 0; + } + } else { + Replace(tm,"$source", Swig_cparm_name(0,0), DOH_REPLACE_ANY); + Replace(tm,"$target", name, DOH_REPLACE_ANY); + Replace(tm,"$input",Swig_cparm_name(0,0),DOH_REPLACE_ANY); + Setattr(n,"wrap:action", tm); + Delete(tm); } - } else { - nnode = Copy(node); - real_name = NewStringf("%s::%s", ClassName, name); - Setattr(nnode,"name", real_name); - Setattr(nnode,"scriptname", script_name); - lang->function(nnode); - Delete(nnode); - Delete(real_name); + if (make_wrapper) { + functionWrapper(n); + } + Setattr(n,"sym:name",symname); + Setattr(n,"type",type); + Setattr(n,"name",name); } + Swig_VargetToFunction(n); + Setattr(n,"sym:name", Swig_name_get(symname)); + functionWrapper(n); + Swig_restore(&n); + return SWIG_OK; } -/* ----------------------------------------------------------------------------- - * Language::cpp_constant() - * ----------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * Language::functionWrapper() + * ---------------------------------------------------------------------- */ -void Language::cpp_constant(DOH *node) -{ - String *name; - String *iname; - String *value; - SwigType *type; - String *cname; - String *mname; - String *new_value; +int Language::functionWrapper(Node *n) { + String *name = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + ParmList *parms = Getattr(n,"parms"); - name = Getattr(node,"name"); - iname = Getattr(node,"scriptname"); - value = Getattr(node,"value"); - type = Getattr(node,"type"); + Printf(stdout,"functionWrapper : %s\n", SwigType_str(type, NewStringf("%s(%s)", name, ParmList_str(parms)))); + Printf(stdout," action : %s\n", Getattr(n,"wrap:action")); + return SWIG_OK; +} - /* Set the constant name */ +/* ----------------------------------------------------------------------------- + * Language::nativeWrapper() + * ----------------------------------------------------------------------------- */ - cname = Swig_name_member(ClassPrefix, iname ? iname : name); +int Language::nativeWrapper(Node *n) { + return SWIG_OK; +} - /* Now do a symbol table lookup on it : */ +void Language::main(int argc, char *argv[]) { +} - /* Form correct C++ name */ - mname = NewStringf("%s::%s", ClassName,name); +/* ----------------------------------------------------------------------------- + * Language::addSymbol() + * + * Adds a symbol entry. Returns 1 if the symbol is added successfully. + * Prints an error message and returns 0 if a conflict occurs. + * ----------------------------------------------------------------------------- */ - /* Declare a constant */ - if (!value) { - new_value = NewStringf("%s::%s", ClassName, name); - } else { - new_value = NewString(value); +int +Language::addSymbol(String *s, Node *n) { + Node *c = Getattr(symbols,s); + if (c && (c != n)) { + Swig_error(input_file, line_number, "Error. '%s' is multiply defined in the generated module.\n", s); + Swig_error(Getfile(c),Getline(c), "Previous declaration of '%s'\n", s); + return 0; } - Hash *n; - n = NewHash(); - Setattr(n,"name",cname); - Setattr(n,"scriptname",cname); - Setattr(n,"type",type); - Setattr(n,"value",new_value); - lang->constant(n); - Delete(n); - Delete(new_value); - Delete(mname); + Setattr(symbols,s,n); + return 1; } /* ----------------------------------------------------------------------------- - * Language::cpp_staticvariable() + * Language::symbolLookup() * ----------------------------------------------------------------------------- */ -void Language::cpp_staticvariable(DOH *node) { - char *name, *iname; - SwigType *t; - char *cname; - char mname[256]; +Node * +Language::symbolLookup(String *s) { + return Getattr(symbols,s); +} - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); +/* ----------------------------------------------------------------------------- + * Language::classLookup() + * + * Tries to locate a class from a type definition + * ----------------------------------------------------------------------------- */ - /* Create the variable name */ +Node * +Language::classLookup(SwigType *s) { + Node *n = 0; + SwigType *lt, *ty1,*ty2; + String *base; + String *prefix; + Symtab *stab = 0; + + /* Look in hash of cached values */ + n = Getattr(classtypes,s); + if (n) return n; + + lt = SwigType_ltype(s); + ty1 = SwigType_typedef_resolve_all(lt); + ty2 = SwigType_strip_qualifiers(ty1); + Delete(lt); + Delete(ty1); + + base = SwigType_base(ty2); + + Replaceall(base,"class ",""); + Replaceall(base,"struct ",""); + Replaceall(base,"union ",""); + + prefix = SwigType_prefix(ty2); + + while (!n) { + Hash *nstab; + n = Swig_symbol_clookup(base,stab); + if (!n) break; + if (Strcmp(nodeType(n),"class") == 0) break; + n = parentNode(n); + if (!n) break; + nstab = Getattr(n,"sym:symtab"); + n = 0; + if ((!nstab) || (nstab == stab)) { + break; + } + stab = nstab; + } + /* Do a symbol table search on the base type */ + /* n = Swig_symbol_clookup(base,0); */ + if (n) { + /* Found a match. Look at the prefix. We only allow + a few cases: pointers, references, and simple */ + if ((Len(prefix) == 0) || /* Simple type */ + (Strcmp(prefix,"p.") == 0) || /* pointer */ + (Strcmp(prefix,"r.") == 0)) { /* reference */ + Setattr(classtypes,Copy(s),n); + } else { + n = 0; + } + } + Delete(ty2); + Delete(base); + Delete(prefix); - cname = Char(Swig_name_member(ClassPrefix, iname ? iname : name)); + if (n && (Getattr(n,"feature:ignore"))) return 0; + return n; +} - /* Now do a symbol table lookup on it : */ +/* ----------------------------------------------------------------------------- + * Language::allow_overloading() + * ----------------------------------------------------------------------------- */ - /* Form correct C++ name */ - sprintf(mname,"%s::%s",Char(ClassName),name); +void Language::allow_overloading(int val) { + overloading = val; +} - /* Link with this variable */ +/* ----------------------------------------------------------------------------- + * Language::allow_multiple_input() + * ----------------------------------------------------------------------------- */ - Hash *n = NewHash(); - Setattr(n,"name",mname); - Setattr(n,"scriptname", cname); - Setattr(n,"type",t); - lang->variable(n); - Delete(n); +void Language::allow_multiple_input(int val) { + multiinput = val; } /* ----------------------------------------------------------------------------- - * Language::cpp_class_decl() + * Language::is_wrapping_class() * ----------------------------------------------------------------------------- */ -void Language::cpp_class_decl(DOH *) { - /* Does nothing by default */ +int Language::is_wrapping_class() { + return InClass; } /* ----------------------------------------------------------------------------- - * Language::add_typedef() + * Language::getCurrentClass() * ----------------------------------------------------------------------------- */ -void Language::add_typedef(SwigType *, String *) { - /* Does nothing by default */ +Node * Language::getCurrentClass() const { + return CurrentClass; } /* ----------------------------------------------------------------------------- - * Language::pragma() + * Language::getClassName() * ----------------------------------------------------------------------------- */ -void Language::pragma(DOH *node) { - /* Does nothing by default */ +String * Language::getClassName() const { + return ClassName; } /* ----------------------------------------------------------------------------- - * Language::import() + * Language::getClassPrefix() * ----------------------------------------------------------------------------- */ -void Language::import(String *) { - /* Does nothing by default */ +String * Language::getClassPrefix() const { + return ClassPrefix; } +/* ----------------------------------------------------------------------------- + * Language::getClassType() + * ----------------------------------------------------------------------------- */ - +String * Language::getClassType() const { + return ClassType; +} diff --git a/Source/Modules1.1/main.cxx b/Source/Modules1.1/main.cxx index c3e221f61..2cbdbec66 100644 --- a/Source/Modules1.1/main.cxx +++ b/Source/Modules1.1/main.cxx @@ -12,54 +12,77 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_main_cxx[] = "$Header$"; -#include "swig11.h" +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +#include "swigmod.h" #ifndef MACSWIG #include "swigconfig.h" #endif -#include <time.h> -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> +#include "swigwarn.h" + extern "C" { #include "preprocessor.h" } -#ifndef SWIG_LANG -#define SWIG_LANG PYTHON +#include <ctype.h> + +#ifndef SWIG_LIB +#define SWIG_LIB "/usr/local/lib/swig1.3" #endif -#include "tcl8.h" -#include "python.h" -#include "perl5.h" -#include "guile.h" -#ifdef OLD -#include "java.h" +#ifndef SWIG_CC +#define SWIG_CC "CC" #endif -#include "mzscheme.h" -#include "ruby.h" -#include "xml.h" // Global variables - FILE *f_runtime = 0; - DOH *f_header = 0; // Some commonly used - DOH *f_wrappers = 0; // FILE pointers - DOH *f_init = 0; + char LibDir[512]; // Library directory Language *lang; // Language method int CPlusPlus = 0; - int NewObject = 0; // NewObject flag + int Extend = 0; // Extend flag int ForceExtern = 0; // Force extern mode - int GenerateDefault = 0; // Generate default constructors + int GenerateDefault = 1; // Generate default constructors + char *Config = 0; int NoInclude = 0; int Verbose = 0; - String *swig_module = 0; + int NoExtern = 0; + int NoExcept = 0; + +extern "C" { +extern String *ModuleName; +} static char *usage = (char*)"\ -\nSWIG1.1 Options\n\ -"; +\nGeneral Options\n\ + -c - Produce raw wrapper code (omit support code)\n\ + -c++ - Enable C++ processing\n\ + -co - Check a file out of the SWIG library\n\ + -Dsymbol - Define a symbol (for conditional compilation)\n\ + -I<dir> - Look for SWIG files in <dir>\n\ + -includeall - Follow all #include statements\n\ + -importall - Follow all #include statements as imports\n\ + -ignoremissing - Ignore missing include files.\n\ + -l<ifile> - Include SWIG library file.\n\ + -M - List all dependencies. \n\ + -MM - List dependencies, but omit files in SWIG library.\n\ + -makedefault - Create default constructors/destructors (the default)\n\ + -module - Set module name\n\ + -nodefault - Do not generate constructors/destructors\n\ + -noexcept - Do not wrap exception specifiers.\n\ + -noextern - Do not generate extern declarations.\n\ + -o outfile - Set name of the output file.\n\ + -swiglib - Report location of SWIG library and exit\n\ + -v - Run in verbose mode\n\ + -version - Print SWIG version number\n\ + -Wall - Enable all warning messages\n\ + -wn - Suppress warning number n\n\ + -help - This output.\n\n"; // ----------------------------------------------------------------------------- // check_suffix(char *name) @@ -67,18 +90,11 @@ static char *usage = (char*)"\ // Checks the suffix of a file to see if we should emit extern declarations. // ----------------------------------------------------------------------------- -static int check_suffix(char *name) { char *c; if (!name) return 0; - if (strlen(name) == 0) return 0; - c = name+strlen(name)-1; - while (c != name) { - if (*c == '.') break; - c--; - } - if (c == name) return 0; + c = Swig_file_suffix(name); if ((strcmp(c,".c") == 0) || (strcmp(c,".C") == 0) || (strcmp(c,".cc") == 0) || @@ -90,208 +106,517 @@ check_suffix(char *name) { return 0; } +// ----------------------------------------------------------------------------- +// install_opts(int argc, char *argv[]) +// Install all command line options as preprocessor symbols +// ----------------------------------------------------------------------------- + +static void +install_opts(int argc, char *argv[]) { + int i; + int noopt = 0; + char *c; + for (i = 1; i < (argc-1); i++) { + if (argv[i]) { + if ((*argv[i] == '-') && (!isupper(*(argv[i]+1)))) { + String *opt = NewStringf("SWIGOPT%(upper)s", argv[i]); + Replaceall(opt,"-","_"); + c = Char(opt); + noopt = 0; + while (*c) { + if (!(isalnum(*c) || (*c == '_'))) { + noopt = 1; + break; + } + c++; + } + if (((i+1) < (argc-1)) && (argv[i+1]) && (*argv[i+1] != '-')) { + Printf(opt," %s", argv[i+1]); + i++; + } else { + Printf(opt," 1"); + } + if (!noopt) { + /* Printf(stdout,"%s\n", opt); */ + Preprocessor_define(opt, 0); + } + } + } + } +} //----------------------------------------------------------------- // main() // // Main program. Initializes the files and starts the parser. //----------------------------------------------------------------- -char infilename[256]; -char filename[256]; -char output_dir[512]; -char fn_runtime[256]; -static char *outfile_name = 0; - char *SwigLib; +static int freeze = 0; +static String *lang_config = 0; +static char *cpp_extension = (char *) "cxx"; + +/* This function sets the name of the configuration file */ + +void SWIG_config_file(const String_or_char *filename) { + lang_config = NewString(filename); +} + +void SWIG_library_directory(const char *filename) { + strcpy(LibDir,filename); +} -extern "C" -int swig11_init(int argc, char *argv[]) { +void SWIG_config_cppext(const char *ext) { + cpp_extension = (char *) ext; +} + +extern "C" Node *Swig_cparse(File *); +extern "C" void Swig_cparse_cplusplus(int); +extern "C" void Swig_cparse_debug_templates(int); + +int SWIG_main(int argc, char *argv[], Language *l) { int i; char *c; - char infile[512]; + char temp[512]; + char *outfile_name = 0; int help = 0; + int checkout = 0; + int cpp_only = 0; + int tm_debug = 0; + char *includefiles[256]; + int includecount = 0; + extern int check_suffix(char *); + int dump_tags = 0; + int dump_tree = 0; + int contracts = 0; + int browse = 0; + int dump_typedef = 0; + int dump_classes = 0; + int werror = 0; + int depend = 0; + + DOH *libfiles = 0; + DOH *cpps = 0 ; + extern void Swig_contracts(Node *n); + extern void Swig_browser(Node *n, int); + extern void Swig_default_allocators(Node *n); + extern void Swig_process_types(Node *n); + + + /* Initialize the SWIG core */ + Swig_init(); + + /* Suppress warning messages for private inheritance, preprocessor evaluation, + might be abstract, and overloaded const */ + + Swig_warnfilter("202,309,403,512",1); + + // Initialize the preprocessor + Preprocessor_init(); + + lang = l; + + // Set up some default symbols (available in both SWIG interface files + // and C files) + + Preprocessor_define((DOH *) "SWIG 1", 0); + Preprocessor_define((DOH *) "__STDC__", 0); +#ifdef MACSWIG + Preprocessor_define((DOH *) "SWIGMAC 1", 0); +#endif +#ifdef SWIGWIN32 + Preprocessor_define((DOH *) "SWIGWIN32 1", 0); +#endif + + // Set the SWIG version value + String *vers; + vers = NewStringf("SWIG_VERSION 0x%02d%02d%02d", SWIG_MAJOR_VERSION, SWIG_MINOR_VERSION, SWIG_SPIN); + Preprocessor_define(vers,0); - lang = new SWIG_LANG; - f_wrappers = 0; - f_init = 0; - f_header = 0; + // Check for SWIG_LIB environment variable + + if ((c = getenv("SWIG_LIB")) == (char *) 0) { +#if defined(_WIN32) + char buf[MAX_PATH]; + char *p; + if (GetModuleFileName(0, buf, MAX_PATH) == 0 + || (p = strrchr(buf, '\\')) == 0) { + Printf(stderr, "Warning: Could not determine SWIG library location. Assuming " SWIG_LIB "\n"); + sprintf(LibDir,"%s",SWIG_LIB); // Build up search paths + } else { + strcpy(p+1, "Lib"); + strcpy(LibDir, buf); + } +#else + sprintf(LibDir,"%s",SWIG_LIB); // Build up search paths +#endif + } else { + strcpy(LibDir,c); + } + + SwigLib = Swig_copy_string(LibDir); // Make a copy of the real library location + + libfiles = NewList(); // Get options for (i = 1; i < argc; i++) { - if (argv[i]) { - if(strcmp(argv[i],"-tcl") == 0) { - fprintf(stderr,"swig: -tcl option now implies -tcl8\n"); - lang = new TCL8; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-tcl8") == 0) { - lang = new TCL8; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-python") == 0) { - lang = new PYTHON; - Swig_mark_arg(i); - - } else if (strcmp(argv[i],"-perl5") == 0) { - lang = new PERL5; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-guile") == 0) { - lang = new GUILE; - Swig_mark_arg(i); -#ifdef OLD - } else if (strcmp(argv[i],"-java") == 0) { - lang = new JAVA; - Swig_mark_arg(i); -#endif - } else if (strcmp(argv[i],"-mzscheme") == 0) { - lang = new MZSCHEME; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-ruby") == 0) { - lang = new RUBY; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-help") == 0) { - fputs(usage,stderr); - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-c++") == 0) { - CPlusPlus=1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-c") == 0) { - NoInclude=1; - Preprocessor_define((void *) "SWIG_NOINCLUDE 1", 0); - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-make_default") == 0) { - GenerateDefault = 1; - Swig_mark_arg(i); - } else if(strcmp(argv[i],"-module") == 0) { - if (argv[i+1]) { - swig_module = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if (strcmp(argv[i],"-o") == 0) { - if (argv[i+1]) { - outfile_name = argv[i+1]; - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } - } else if (strcmp(argv[i],"-help") == 0) { - fputs(usage,stderr); - Swig_mark_arg(i); - help = 1; + if (argv[i]) { + if (strncmp(argv[i],"-I",2) == 0) { + // Add a new directory search path + includefiles[includecount++] = Swig_copy_string(argv[i]+2); + Swig_mark_arg(i); + } else if (strncmp(argv[i],"-D",2) == 0) { + DOH *d = NewString(argv[i]+2); + Replace(d,(char*)"=",(char*)" ", DOH_REPLACE_ANY | DOH_REPLACE_FIRST); + Preprocessor_define((DOH *) d,0); + // Create a symbol + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-E") == 0) { + cpp_only = 1; + Swig_mark_arg(i); + } else if ((strcmp(argv[i],"-verbose") == 0) || + (strcmp(argv[i],"-v") == 0)) { + Verbose = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-c++") == 0) { + CPlusPlus=1; + Preprocessor_define((DOH *) "__cplusplus 1", 0); + Swig_cparse_cplusplus(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-c") == 0) { + NoInclude=1; + Preprocessor_define((DOH *) "SWIG_NOINCLUDE 1", 0); + Swig_mark_arg(i); + } else if ((strcmp(argv[i],"-make_default") == 0) || (strcmp(argv[i],"-makedefault") == 0)) { + GenerateDefault = 1; + Swig_mark_arg(i); + } else if ((strcmp(argv[i],"-no_default") == 0) || (strcmp(argv[i],"-nodefault") == 0)) { + GenerateDefault = 0; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-noexcept") == 0) { + NoExcept = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-noextern") == 0) { + NoExtern = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-show_templates") == 0) { + Swig_cparse_debug_templates(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-swiglib") == 0) { + printf("%s\n", LibDir); + SWIG_exit (EXIT_SUCCESS); + } else if (strcmp(argv[i],"-o") == 0) { + Swig_mark_arg(i); + if (argv[i+1]) { + outfile_name = Swig_copy_string(argv[i+1]); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i],"-version") == 0) { + fprintf(stderr,"\nSWIG Version %s\n", + SWIG_VERSION); + fprintf(stderr,"Copyright (c) 1995-1998\n"); + fprintf(stderr,"University of Utah and the Regents of the University of California\n"); + fprintf(stderr,"Copyright (c) 1998-2002\n"); + fprintf(stderr,"University of Chicago\n"); + fprintf(stderr,"\nCompiled with %s\n", SWIG_CC); + SWIG_exit (EXIT_SUCCESS); + } else if (strncmp(argv[i],"-l",2) == 0) { + // Add a new directory search path + Append(libfiles,argv[i]+2); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-co") == 0) { + checkout = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-freeze") == 0) { + freeze = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-includeall") == 0) { + Preprocessor_include_all(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-importall") == 0) { + Preprocessor_import_all(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-ignoremissing") == 0) { + Preprocessor_ignore_missing(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-tm_debug") == 0) { + tm_debug = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-module") == 0) { + Swig_mark_arg(i); + if (argv[i+1]) { + ModuleName = NewString(argv[i+1]); + Swig_mark_arg(i+1); + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i],"-M") == 0) { + depend = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-MM") == 0) { + depend = 2; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-Wall") == 0) { + Swig_mark_arg(i); + Swig_warnall(); + } else if (strcmp(argv[i],"-Werror") == 0) { + werror = 1; + Swig_mark_arg(i); + } else if (strncmp(argv[i],"-w",2) == 0) { + Swig_mark_arg(i); + Swig_warnfilter(argv[i]+2,1); + } else if (strcmp(argv[i],"-dump_tags") == 0) { + dump_tags = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-dump_tree") == 0) { + dump_tree = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-contracts") == 0) { + Swig_mark_arg(i); + contracts = 1; + } else if (strcmp(argv[i],"-browse") == 0) { + browse = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-dump_typedef") == 0) { + dump_typedef = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-dump_classes") == 0) { + dump_classes = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + Swig_mark_arg(i); + help = 1; + } } - } } + + for (i = 0; i < includecount; i++) { + Swig_add_directory((DOH *) includefiles[i]); + } + + // Define the __cplusplus symbol + if (CPlusPlus) + Preprocessor_define((DOH *) "__cplusplus 1", 0); + // Parse language dependent options - lang->parse_args(argc,argv); + lang->main(argc,argv); - if (help) return 0; + if (help) SWIG_exit (EXIT_SUCCESS); // Exit if we're in help mode - // Create names of temporary files that are created - sprintf(infilename,"%s", argv[argc-1]); + // Check all of the options to make sure we're cool. + Swig_check_options(); - // Check the suffix for a .c file. If so, we're going to - // declare everything we see as "extern" + install_opts(argc, argv); - ForceExtern = check_suffix(infilename); - // Strip off suffix + // Add language dependent directory to the search path + { + DOH *rl = NewString(""); + Printf(rl,"%s%s%s", SwigLib, SWIG_FILE_DELIMETER, LibDir); + Swig_add_directory(rl); + rl = NewString(""); + Printf(rl,".%sswig_lib%s%s", SWIG_FILE_DELIMETER, SWIG_FILE_DELIMETER, LibDir); + Swig_add_directory(rl); + } - c = infilename + strlen(infilename); - while (c != infilename) { - if (*c == '.') { - *c = 0; - break; - } else { - c--; + sprintf(temp,"%s%sconfig", SwigLib, SWIG_FILE_DELIMETER); + Swig_add_directory((DOH *) temp); + Swig_add_directory((DOH *) "." SWIG_FILE_DELIMETER "swig_lib" SWIG_FILE_DELIMETER "config"); + Swig_add_directory((DOH *) SwigLib); + Swig_add_directory((DOH *) "." SWIG_FILE_DELIMETER "swig_lib"); + + if (Verbose) { + printf ("LibDir: %s\n", LibDir); + List *sp = Swig_search_path(); + String *s; + for (s = Firstitem(sp); s; s = Nextitem(sp)) { + Printf(stdout," %s\n", s); } } - if (!outfile_name) { - char *cc = infilename + strlen(infilename); - while (cc != infilename) { - if (*cc == '/') { - cc++; - break; + + // If we made it this far, looks good. go for it.... + + input_file = argv[argc-1]; + + // If the user has requested to check out a file, handle that + if (checkout) { + DOH *s; + char *outfile = input_file; + if (outfile_name) + outfile = outfile_name; + + if (Verbose) + printf ("Handling checkout...\n"); + + s = Swig_include(input_file); + if (!s) { + fprintf(stderr,"Unable to locate '%s' in the SWIG library.\n", input_file); + } else { + FILE *f = fopen(outfile,"r"); + if (f) { + fclose(f); + fprintf(stderr,"File '%s' already exists. Checkout aborted.\n", outfile); + } else { + f = fopen(outfile,"w"); + if (!f) { + fprintf(stderr,"Unable to create file '%s'\n", outfile); + } else { + fprintf(stderr,"'%s' checked out from the SWIG library.\n", input_file); + fputs(Char(s),f); + fclose(f); + } } - cc--; } - sprintf(fn_runtime,"%s_wrap.c",infilename); - strcpy(infile,infilename); - outfile_name = fn_runtime; } else { - sprintf(fn_runtime,"%s",outfile_name); - } - { - // Try to identify the output directory - char *cc = outfile_name; - char *lastc = outfile_name; - while (*cc) { - if (*cc == '/') lastc = cc+1; - cc++; - } - cc = outfile_name; - char *dd = output_dir; - while (cc != lastc) { - *dd = *cc; - dd++; - cc++; - } - *dd = 0; - // Patch up the input filename - cc = infilename + strlen(infilename); - while (cc != infilename) { - if (*cc == '/') { - cc++; - break; + // Check the suffix for a .c file. If so, we're going to + // declare everything we see as "extern" + + ForceExtern = check_suffix(input_file); + + // Run the preprocessor + if (Verbose) + printf ("Preprocessing...\n"); + { + int i; + String *fs = NewString(""); + FILE *df = Swig_open(input_file); + if (!df) { + Printf(stderr,"Unable to find '%s'\n", input_file); + SWIG_exit (EXIT_FAILURE); + } + fclose(df); + Printf(fs,"%%include \"swig.swg\"\n"); + if (lang_config) { + Printf(fs,"\n%%include \"%s\"\n", lang_config); + } + Printf(fs,"%%include \"%s\"\n", Swig_last_file()); + for (i = 0; i < Len(libfiles); i++) { + Printf(fs,"\n%%include \"%s\"\n", Getitem(libfiles,i)); + } + Seek(fs,0,SEEK_SET); + cpps = Preprocessor_parse(fs); + if (Swig_error_count()) { + SWIG_exit(EXIT_FAILURE); + } + if (cpp_only) { + Printf(stdout,"%s", cpps); + while (freeze); + SWIG_exit (EXIT_SUCCESS); + } + if (depend) { + String *outfile; + if (!outfile_name) { + if (CPlusPlus) { + outfile = NewStringf("%s_wrap.%s", Swig_file_basename(input_file),cpp_extension); + } else { + outfile = NewStringf("%s_wrap.c", Swig_file_basename(input_file)); + } + } else { + outfile = NewString(outfile_name); + } + Printf(stdout,"%s: ", outfile); + List *files = Preprocessor_depend(); + for (int i = 0; i < Len(files); i++) { + if ((depend != 2) || ((depend == 2) && (Strncmp(Getitem(files,i),SwigLib, Len(SwigLib)) != 0))) { + Printf(stdout,"\\\n %s ", Getitem(files,i)); + } + } + Printf(stdout,"\n"); + SWIG_exit(EXIT_SUCCESS); } - cc--; + Seek(cpps, 0, SEEK_SET); } - strcpy(infile,cc); - } - return 0; -} + /* Register a null file with the file handler */ + Swig_register_filebyname("null", NewString("")); -extern void generate(DOH *top); + // Pass control over to the specific language interpreter + if (Verbose) { + fprintf (stdout, "Starting language-specific parse...\n"); + fflush (stdout); + } -extern "C" -DOH *swig11_run(DOH *node) { - if ((f_runtime = fopen(fn_runtime,"w")) == 0) { - fprintf(stderr,"Unable to open %s\n", fn_runtime); - Swig_exit(1); - } - f_header = NewString(""); - f_wrappers = NewString(""); - f_init = NewString(""); + Node *top = Swig_cparse(cpps); - Swig_register_filebyname("header",f_header); - Swig_register_filebyname("runtime", f_runtime); - Swig_register_filebyname("wrapper", f_wrappers); - Swig_register_filebyname("init", f_init); + if (Verbose) { + Printf(stdout,"Processing types...\n"); + } + Swig_process_types(top); - // Set up the typemap for handling new return strings - if (CPlusPlus) - Swig_typemap_register((char*)"newfree",(char*)"p.char",(char*)"",(char*)"delete [] $source;\n",0); - else - Swig_typemap_register((char*)"newfree",(char*)"p.char",(char*)"",(char*)"free($source);\n",0); + if (Verbose) { + Printf(stdout,"C++ analysis...\n"); + } + Swig_default_allocators(top); - generate(node); + if (Verbose) { + Printf(stdout,"Generating wrappers...\n"); + } + + if (dump_classes) { + Hash *classes = Getattr(top,"classes"); + if (classes) { + Printf(stdout,"Classes\n"); + Printf(stdout,"------------\n"); + String *key; + for (key = Firstkey(classes); key; key = Nextkey(classes)) { + Printf(stdout,"%s\n", key); + } + } + } - Dump(f_header,f_runtime); - Dump(f_wrappers, f_runtime); - Wrapper_pretty_print(f_init,f_runtime); - fclose(f_runtime); - return node; + if (dump_typedef) { + SwigType_print_scope(0); + } + if (dump_tags) { + Swig_print_tags(top,0); + } + if (dump_tree) { + Swig_print_tree(top); + } + if (top) { + if (!Getattr(top,"name")) { + Printf(stderr,"*** No module name specified using %%module or -module.\n"); + SWIG_exit(EXIT_FAILURE); + } else { + /* Set some filename information on the object */ + Setattr(top,"infile", input_file); + if (!outfile_name) { + if (CPlusPlus) { + Setattr(top,"outfile", NewStringf("%s_wrap.%s", Swig_file_basename(input_file),cpp_extension)); + } else { + Setattr(top,"outfile", NewStringf("%s_wrap.c", Swig_file_basename(input_file))); + } + } else { + Setattr(top,"outfile", outfile_name); + } + if (contracts) { + Swig_contracts(top); + } + lang->top(top); + if (browse) { + Swig_browser(top,0); + } + } + } + } + if (tm_debug) Swig_typemap_debug(); + while (freeze); + if ((werror) && (Swig_warn_count())) { + return Swig_warn_count(); + } + return Swig_error_count(); } -extern "C" -void swig11module() { - Swig_register_module("tcl8","swig:top", swig11_init, swig11_run); - Swig_register_module("python","swig:top", swig11_init, swig11_run); - Swig_register_module("perl5","swig:top", swig11_init, swig11_run); - Swig_register_module("ruby","swig:top", swig11_init, swig11_run); - Swig_register_module("guile","swig:top", swig11_init, swig11_run); - Swig_register_module("mzscheme","swig:top", swig11_init, swig11_run); - Swig_register_module("swig11","swig:top", swig11_init, swig11_run); - Swig_register_module("xml","swig:top", xml_init, xml_run); +// -------------------------------------------------------------------------- +// SWIG_exit(int exit_code) +// +// Cleanup and either freeze or exit +// -------------------------------------------------------------------------- + +void SWIG_exit(int exit_code) { + while (freeze); + exit (exit_code); } + diff --git a/Source/Modules1.1/module.cxx b/Source/Modules1.1/module.cxx new file mode 100644 index 000000000..57aa6c304 --- /dev/null +++ b/Source/Modules1.1/module.cxx @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + * module.cxx + * + * This file is responsible for the module system. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_module_cxx[] = "$Header$"; + +#include "swigmod.h" + +struct Module { + ModuleFactory fac; + char *name; + Module *next; + Module(const char *n, ModuleFactory f) { + fac = f; + name = new char[strlen(n)+1]; + strcpy(name, n); + next = 0; + } +}; + +static Module *modules = 0; + +/* ----------------------------------------------------------------------------- + * void Swig_register_module() + * + * Register a module. + * ----------------------------------------------------------------------------- */ + +void Swig_register_module(const char *n, ModuleFactory f) { + Module *m = new Module(n,f); + m->next = modules; + modules = m; +} + +/* ----------------------------------------------------------------------------- + * Language *Swig_find_module() + * + * Given a command line option, locates the factory function. + * ----------------------------------------------------------------------------- */ + +ModuleFactory Swig_find_module(const char *name) { + Module *m = modules; + while (m) { + if (strcmp(m->name,name) == 0) { + return m->fac; + } + m = m->next; + } + return 0; +} diff --git a/Source/Modules1.1/mzscheme.cxx b/Source/Modules1.1/mzscheme.cxx index f3ac22096..14e4a3ac2 100644 --- a/Source/Modules1.1/mzscheme.cxx +++ b/Source/Modules1.1/mzscheme.cxx @@ -13,7 +13,7 @@ * can be used and distributed. *****************************************************************************/ -static char cvsroot[] = "$Header$"; +char cvsroot_mzscheme_cxx[] = "$Header$"; /*********************************************************************** * $Header$ @@ -23,751 +23,646 @@ static char cvsroot[] = "$Header$"; * Definitions for adding functions to Mzscheme 101 ***********************************************************************/ -#include "swig11.h" -#include "mzscheme.h" +#include "swigmod.h" -static char *mzscheme_usage = (char*)"\ +#include <ctype.h> + +static const char *mzscheme_usage = (char*)"\ \n\ Mzscheme Options (available with -mzscheme)\n\ -help - Print this help\n\ --module name - Set base name of module (not implemented) \n\ --prefix name - Set a prefix to be appended to all name\n\ +-prefix name - Set a prefix to be appended to all names\n\ +-declaremodule - Create extension that declares a module\n\ \n" ; static char *prefix=0; -static char *module=0; +static bool declaremodule = false; +static String *module=0; static char *mzscheme_path=(char*)"mzscheme"; static String *init_func_def = 0; -// --------------------------------------------------------------------- -// MZSCHEME::parse_args(int argc, char *argv[]) -// -// Parse arguments. -// --------------------------------------------------------------------- - -void -MZSCHEME::parse_args (int argc, char *argv[]) -{ - int i; - - Swig_swiglib_set("mzscheme"); - - // Look for certain command line options - for (i = 1; i < argc; i++) { - if (argv[i]) { - if (strcmp (argv[i], "-help") == 0) { - fputs (mzscheme_usage, stderr); - Swig_exit (0); - } - else if (strcmp (argv[i], "-prefix") == 0) { - if (argv[i + 1]) { - prefix = new char[strlen(argv[i + 1]) + 2]; - strcpy(prefix, argv[i + 1]); - Swig_mark_arg (i); - Swig_mark_arg (i + 1); - i++; - } else { - Swig_arg_error(); +static File *f_runtime = 0; +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; + +class MZSCHEME : public Language { +public: + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main (int argc, char *argv[]) { + + int i; + + SWIG_library_directory(mzscheme_path); + + // Look for certain command line options + for (i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp (argv[i], "-help") == 0) { + fputs (mzscheme_usage, stderr); + SWIG_exit (0); } - } - } - } - - // If a prefix has been specified make sure it ends in a '_' - - if (prefix) { - if (prefix[strlen (prefix)] != '_') { - prefix[strlen (prefix) + 1] = 0; - prefix[strlen (prefix)] = '_'; - } - } else - prefix = (char*)"swig_"; - - // Add a symbol for this module - - Preprocessor_define ((void *) "SWIGMZSCHEME",0); -} - -// -------------------------------------------------------------------- -// MZSCHEME::initialize() -// -// Output initialization code that registers functions with the -// interface. -// --------------------------------------------------------------------- - -void -MZSCHEME::initialize (String *modname) -{ - init_func_def = NewString(""); - printf ("Generating wrappers for Mzscheme\n"); - init_func_def = NewString(""); - - Swig_banner (f_header); - - Printf (f_header, "/* Implementation : MZSCHEME */\n\n"); - Printf (f_header, "#include <stdio.h>\n"); - Printf (f_header, "#include <string.h>\n"); - Printf (f_header, "#include <stdlib.h>\n"); - - // insert mzscheme.swg - - if (!NoInclude) { - if (Swig_insert_file ("mzscheme.swg", f_header) == -1) { - Printf (stderr, "SWIG : Fatal error. "); - Printf (stderr, "Unable to locate 'mzscheme.swg' in SWIG library.\n"); - Swig_exit (1); - } - } - - if (!module) { - module = new char[Len(modname)+1]; - strcpy(module, Char(modname)); - } - - Printf (f_init, "static void\nSWIG_init (void)\n{\n"); -} - -// --------------------------------------------------------------------- -// MZSCHEME::close(void) -// -// Wrap things up. Close initialization function. -// --------------------------------------------------------------------- - -void -MZSCHEME::close (void) -{ - Printf (f_init, "}\n\n"); - Printf(f_init, "Scheme_Object *scheme_reload(Scheme_Env *env) {\n"); - Printf(f_init, "%s\n", Char(init_func_def)); - Printf (f_init, "\treturn scheme_void;\n}\n"); - Printf(f_init, "Scheme_Object *scheme_initialize(Scheme_Env *env) {\n"); - Printf(f_init, "\treturn scheme_reload(env);\n"); - Printf (f_init, "}\n"); -} - -// ---------------------------------------------------------------------- -// MZSCHEME::get_pointer(int parm, SwigType *t, Wrapper *f) -// -// Emits code to get a pointer from a parameter and do type checking. -// parm is the parameter number. This function is only used -// in create_function(). -// ---------------------------------------------------------------------- - -void -MZSCHEME::get_pointer (String *name, int parm, SwigType *t, Wrapper *f) -{ - char p[256]; - sprintf(p, "%d", parm); - Printv(f, tab4, "if (!swig_get_c_pointer(argv[", p, "], \"", SwigType_manglestr(t), - "\", (void **) &arg", p, "))\n",0); - Printv(f, tab8, "scheme_wrong_type(\"", name, - "\", \"", SwigType_manglestr(t), "\", ", p, ", argc, argv);\n",0); -} -// ---------------------------------------------------------------------- -// MZSCHEME::create_function() -// -// Create a function declaration and register it with the interpreter. -// ---------------------------------------------------------------------- - -static void -mreplace (String *s, String *argnum, String *arg, String *proc_name) -{ - Replace(s, "$argnum", argnum, DOH_REPLACE_ANY); - Replace(s, "$arg", arg, DOH_REPLACE_ANY); - Replace(s, "$name", proc_name, DOH_REPLACE_ANY); -} - -static void -throw_unhandled_mzscheme_type_error (SwigType *d) -{ - fflush (stdout); - fprintf (stderr, "ERROR: Unhandled MZSCHEME type error.\n"); - fprintf (stderr, "str: %s\n", Char(SwigType_str(d,0))); - fprintf (stderr, "lstr: %s\n", Char(SwigType_lstr(d,0))); - fprintf (stderr, "manglestr: %s\n", Char(SwigType_manglestr(d))); - Printf (stderr, "\n\nBAILING...\n"); // for now -ttn - abort(); // for now -ttn -} - -void -MZSCHEME::function(DOH *node) -{ - char *name, *iname; - SwigType *d; - ParmList *l; - Parm *p; - Wrapper *f = NewWrapper(); - String *proc_name = NewString(""); - String *source = NewString(""); - String *target = NewString(""); - String *argnum = NewString(""); - String *arg = NewString(""); - String *cleanup = NewString(""); - String *outarg = NewString(""); - String *build = NewString(""); - SwigType *t; - char *tm; - int need_len = 0; - int need_tempc = 0; - int have_build = 0; - int argout_set = 0; - int i = 0; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - d = Getattr(node,"type"); - l = Getattr(node,"parms"); - - // Make a wrapper name for this - char *wname = Char(Swig_name_wrapper(iname)); - - // Build the name for Scheme. - Printv(proc_name, iname,0); - Replace(proc_name, "_", "-", DOH_REPLACE_ANY); - - // writing the function wrapper function - Printv(f, "static Scheme_Object *", wname, " (", 0); - Printv(f, "int argc, Scheme_Object **argv", 0); - Printv(f, ")\n{\n", 0); - - // Declare return variable and arguments - // number of parameters - // they are called arg0, arg1, ... - // the return value is called result - - int pcount = emit_args(node, f); - int numargs = 0; - int numopt = 0; - - // adds local variables - Wrapper_add_local(f, "_tempc", "char *_tempc"); - Wrapper_add_local(f, "_len", "int _len"); - Wrapper_add_local(f, "swig_result", "Scheme_Object *swig_result"); - - // Now write code to extract the parameters (this is super ugly) - - for(p = l; p; p = Getnext(p)) { - // Produce names of source and target - Clear(source); - Clear(target); - Clear(argnum); - Clear(arg); - Printf(source, "argv[%d]", i); - Printf(target, "arg%d", i); - Printf(argnum, "%d", i); - Printv(arg, Getname(p),0); - - // Handle parameter types. - - if (Getignore(p)) - Printv(f, "/* ", Char(Getname(p)), " ignored... */\n", 0); - else { - ++numargs; - if ((tm = Swig_typemap_lookup ((char*)"in", - Gettype(p), Getname(p), source, target, f))) { - Printv(f, tm, "\n", 0); - mreplace (f, argnum, arg, proc_name); - } - // no typemap found - // check if typedef and resolve - else if (SwigType_istypedef(Gettype(p))) { - t = SwigType_typedef_resolve(Gettype(p)); - - // if a pointer then get it - if (SwigType_ispointer(t)) { - get_pointer (proc_name, i, t, f); + else if (strcmp (argv[i], "-prefix") == 0) { + if (argv[i + 1]) { + prefix = new char[strlen(argv[i + 1]) + 2]; + strcpy(prefix, argv[i + 1]); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + else if (strcmp (argv[i], "-declaremodule") == 0) { + declaremodule = true; + Swig_mark_arg (i); } - // not a pointer - else throw_unhandled_mzscheme_type_error (Gettype(p)); } } + + // If a prefix has been specified make sure it ends in a '_' + + if (prefix) { + if (prefix[strlen (prefix)] != '_') { + prefix[strlen (prefix) + 1] = 0; + prefix[strlen (prefix)] = '_'; + } + } else + prefix = (char*)"swig_"; + + // Add a symbol for this module + + Preprocessor_define ("SWIGMZSCHEME 1",0); + + // Set name of typemaps + + SWIG_typemap_lang("mzscheme"); + + // Read in default typemaps */ + SWIG_config_file("mzscheme.i"); + allow_overloading(); - // Check if there are any constraints. - - if ((tm = Swig_typemap_lookup ((char*)"check", - Gettype(p), Getname(p), source, target, f))) { - // Yep. Use it instead of the default - Printv(f, tm, "\n", 0); - mreplace (f, argnum, arg, proc_name); - } - - // Pass output arguments back to the caller. - - if ((tm = Swig_typemap_lookup ((char*)"argout", - Gettype(p), Getname(p), source, target, f))) { - // Yep. Use it instead of the default - Printv(outarg, tm, "\n",0); - mreplace (outarg, argnum, arg, proc_name); - argout_set = 1; + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); } - - // Free up any memory allocated for the arguments. - if ((tm = Swig_typemap_lookup ((char*)"freearg", - Gettype(p), Getname(p), source, target, f))) { - // Yep. Use it instead of the default - Printv(cleanup, tm, "\n",0); - mreplace (cleanup, argnum, arg, proc_name); + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + + init_func_def = NewString(""); + Swig_register_filebyname("init",init_func_def); + + Printf(f_runtime, "/* -*- buffer-read-only: t -*- vi: set ro: */\n"); + Swig_banner (f_runtime); + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); } - i++; - } - - // Now write code to make the function call - - emit_func_call (node, f); - - // Now have return value, figure out what to do with it. - - if (SwigType_type(d) == T_VOID) { - if(!argout_set) - Printv(f, tab4, "swig_result = scheme_void;\n",0); - } - - else if ((tm = Swig_typemap_lookup ((char*)"out", - d, name, (char*)"result", (char*)"swig_result", f))) { - Printv(f, tm, "\n",0); - mreplace (f, argnum, arg, proc_name); - } - // no typemap found and not void then create a Scheme_Object holding - // the C pointer and return it - else if (SwigType_ispointer(d)) { - Printv(f, tab4, - "swig_result = swig_make_c_pointer(", - "result, \"", - SwigType_manglestr(d), - "\");\n", 0); + + module = Getattr(n,"name"); + + Language::top(n); + + SwigType_emit_type_table (f_runtime, f_wrappers); + Printf(f_init, "Scheme_Object *scheme_reload(Scheme_Env *env) {\n"); + Printf(f_init, "\tScheme_Env *menv = env;\n"); + if (declaremodule) { + Printf(f_init, "\tmenv = scheme_primitive_module(scheme_intern_symbol(\"%s\"), env);\n", module); + } + Printf (f_init, "\tSWIG_RegisterTypes(swig_types, swig_types_initial);\n"); + Printf(f_init, "%s\n", Char(init_func_def)); + if (declaremodule) { + Printf(f_init, "\tscheme_finish_primitive_module(menv);\n"); + } + Printf (f_init, "\treturn scheme_void;\n}\n"); + Printf(f_init, "Scheme_Object *scheme_initialize(Scheme_Env *env) {\n"); + Printf(f_init, "\treturn scheme_reload(env);\n"); + Printf (f_init, "}\n"); + + Printf(f_init,"Scheme_Object *scheme_module_name(void) {\n"); + if (declaremodule) { + Printf(f_init, " return scheme_intern_symbol((char*)\"%s\");\n", module); + } + else { + Printf(f_init," return scheme_make_symbol((char*)\"%s\");\n", module); + } + Printf(f_init,"}\n"); + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; } - else { - throw_unhandled_mzscheme_type_error (d); + + /* ------------------------------------------------------------ + * functionWrapper() + * Create a function declaration and register it with the interpreter. + * ------------------------------------------------------------ */ + + void throw_unhandled_mzscheme_type_error (SwigType *d) + { + Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, + "Unable to handle type %s.\n", SwigType_str(d,0)); } - // Dump the argument output code - Printv(f, Char(outarg),0); - - // Dump the argument cleanup code - Printv(f, Char(cleanup),0); + /* Return true iff T is a pointer type */ - // Look for any remaining cleanup - - if (NewObject) { - if ((tm = Swig_typemap_lookup ((char*)"newfree", - d, iname, (char*)"result", (char*)"", f))) { - Printv(f, tm, "\n",0); - mreplace (f, argnum, arg, proc_name); - } - } - - // Free any memory allocated by the function being wrapped.. - - if ((tm = Swig_typemap_lookup ((char*)"ret", - d, name, (char*)"result", (char*)"", f))) { - // Yep. Use it instead of the default - Printv(f, tm, "\n",0); - mreplace (f, argnum, arg, proc_name); + int + is_a_pointer (SwigType *t) + { + return SwigType_ispointer(SwigType_typedef_resolve_all(t)); } - // returning multiple values - if(argout_set) { - if(SwigType_type(d) == T_VOID) { - Wrapper_add_local(f, "_lenv", "int _lenv = 0"); - Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]"); - Printv(f, tab4, "swig_result = scheme_values(_lenv, _values);\n",0); - } - else { - Wrapper_add_local(f, "_lenv", "int _lenv = 1"); - Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]"); - Printv(f, tab4, "_values[0] = swig_result;\n",0); - Printv(f, tab4, "swig_result = scheme_values(_lenv, _values);\n",0); + virtual int functionWrapper(Node *n) { + char *iname = GetChar(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + Parm *p; + + Wrapper *f = NewWrapper(); + String *proc_name = NewString(""); + String *source = NewString(""); + String *target = NewString(""); + String *arg = NewString(""); + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *build = NewString(""); + String *tm; + int argout_set = 0; + int i = 0; + int numargs; + int numreq; + String *overname = 0; + + // Make a wrapper name for this + String *wname = Swig_name_wrapper(iname); + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; } - } - - // Wrap things up (in a manner of speaking) - - Printv(f, tab4, "return swig_result;\n",0); - Printv(f, "}\n",0); - - Printf(f_wrappers,"%s", f); - - // Now register the function - char temp[256]; - sprintf(temp, "%d", numargs); - Printv(init_func_def, "scheme_add_global(\"", proc_name, - "\", scheme_make_prim_w_arity(", wname, - ", \"", proc_name, "\", ", temp, ", ", temp, - "), env);\n",0); - - Delete(proc_name); - Delete(source); - Delete(target); - Delete(argnum); - Delete(arg); - Delete(outarg); - Delete(cleanup); - Delete(build); - Delete(f); -} - -// ----------------------------------------------------------------------- -// MZSCHEME::variable() -// -// Create a link to a C variable. -// This creates a single function _wrap_swig_var_varname(). -// This function takes a single optional argument. If supplied, it means -// we are setting this variable to some value. If omitted, it means we are -// simply evaluating this variable. Either way, we return the variables -// value. -// ----------------------------------------------------------------------- - -void -MZSCHEME::variable (DOH *node) -{ - char *name, *iname; - SwigType *t; - String *proc_name = NewString(""); - char var_name[256]; - char *tm; - String *tm2 = NewString("");; - String *argnum = NewString("0"); - String *arg = NewString("argv[0]"); - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - - // evaluation function names - - sprintf (var_name, "_wrap_%svar_%s", prefix, iname); - - // Build the name for scheme. - Printv(proc_name, iname,0); - Replace(proc_name, "_", "-", DOH_REPLACE_ANY); - - if ((SwigType_type(t) != T_USER) || (SwigType_ispointer(t))) { - - Printf (f_wrappers, "static Scheme_Object *%s(int argc, Scheme_Object** argv) {\n", var_name); - - if ((SwigType_type(t) == T_CHAR) || (SwigType_ispointer(t))){ - Printf (f_wrappers, "\t char *_temp, _ptemp[128];\n"); - Printf (f_wrappers, "\t int _len;\n"); + if (overname) { + Append(wname, overname); } - Printf (f_wrappers, "\t Scheme_Object *swig_result;\n"); - - // Check for a setting of the variable value - - Printf (f_wrappers, "\t if (argc) {\n"); - - // Yup. Extract the type from argv[0] and set variable value - - // if (Status & STAT_READONLY) { - // Printf (f_wrappers, "\t\t GSWIG_ASSERT(0,\"Unable to set %s. " - // "Variable is read only.\", argv[0]);\n", iname); - // } - if (ReadOnly) { - Printf (f_wrappers, "\t\t scheme_signal_error(\"Unable to set %s. " - "Variable is read only.\");\n", iname); + Setattr(n,"wrap:name",wname); + + // Build the name for Scheme. + Printv(proc_name, iname,NIL); + Replaceall(proc_name, "_", "-"); + + // writing the function wrapper function + Printv(f->def, "static Scheme_Object *", wname, " (", NIL); + Printv(f->def, "int argc, Scheme_Object **argv", NIL); + Printv(f->def, ")\n{", NIL); + + /* Define the scheme name in C. This define is used by several + macros. */ + Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); + + // Declare return variable and arguments + // number of parameters + // they are called arg0, arg1, ... + // the return value is called result + + emit_args(d, l, f); + + /* Attach the standard typemaps */ + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + + numargs = emit_num_arguments(l); + numreq = emit_num_required(l); + + // adds local variables + Wrapper_add_local(f, "_len", "int _len"); + Wrapper_add_local(f, "lenv", "int lenv = 1"); + Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]"); + + // Now write code to extract the parameters (this is super ugly) + + for (i = 0, p = l; i < numargs; i++) { + /* Skip ignored arguments */ + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); + + // Produce names of source and target + Clear(source); + Clear(target); + Clear(arg); + Printf(source, "argv[%d]", i); + Printf(target, "%s",ln); + Printv(arg, Getattr(p,"name"),NIL); + + if (i >= numreq) { + Printf(f->code,"if (argc > %d) {\n",i); + } + // Handle parameter types. + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$source",source); + Replaceall(tm,"$target",target); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",source); + Printv(f->code, tm, "\n", NIL); + p = Getattr(p,"tmap:in:next"); + } else { + // no typemap found + // check if typedef and resolve + throw_unhandled_mzscheme_type_error (pt); + p = nextSibling(p); + } + if (i >= numreq) { + Printf(f->code,"}\n"); + } } - else if ((tm = Swig_typemap_lookup ((char*)"varin", - t, name, (char*)"argv[0]", name,0))) { - Printv(tm2, tm,0); - mreplace(tm2, argnum, arg, proc_name); - Printv(f_wrappers, tm2, "\n",0); + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } } - else if (SwigType_ispointer(t)) { - if ((SwigType_type(t) == T_CHAR) && (SwigType_ispointer(t) == 1)) { - Printf (f_wrappers, "\t\t _temp = SCHEME_STR_VAL(argv[0]);\n"); - Printf (f_wrappers, "\t\t _len = SCHEME_STRLEN_VAL(argv[0]);\n"); - Printf (f_wrappers, "\t\t if (%s) { free(%s);}\n", name, name); - Printf (f_wrappers, "\t\t %s = (char *) " - "malloc((_len+1)*sizeof(char));\n", name); - Printf (f_wrappers, "\t\t strncpy(%s,_temp,_len);\n", name); + + // Pass output arguments back to the caller. + + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"emit:input")); /* Deprecated */ + Replaceall(tm,"$target",Getattr(p,"lname")); /* Deprecated */ + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + argout_set = 1; } else { - // Set the value of a pointer - Printf(f_wrappers, "\t\tif (!swig_get_c_pointer(argv[0], \"%s\", (void **) &arg0))\n", - SwigType_manglestr(t)); - Printf(f_wrappers, "\t\t\tscheme_wrong_type(\"%s\", %s, 0, argc, argv", \ - var_name, SwigType_manglestr(t)); + p = nextSibling(p); } } - else { - throw_unhandled_mzscheme_type_error (t); + + // Free up any memory allocated for the arguments. + + /* Insert cleanup code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } } - Printf (f_wrappers, "\t}\n"); - - // Now return the value of the variable (regardless - // of evaluating or setting) - - if ((tm = Swig_typemap_lookup ((char*)"varout", - t, name, name, (char*)"swig_result",0))) { - Printf (f_wrappers, "%s\n", tm); + + // Now write code to make the function call + + emit_action(n,f); + + // Now have return value, figure out what to do with it. + + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","values[0]"); + Replaceall(tm,"$result","values[0]"); + Printv(f->code, tm, "\n",NIL); + } else { + throw_unhandled_mzscheme_type_error (d); } - else if (SwigType_ispointer(t)) { - if ((SwigType_type(t) == T_CHAR) && (SwigType_ispointer(t) == 1)) { - Printf (f_wrappers, "\t swig_result = scheme_make_string(%s);\n", name); - } else { - // Is an ordinary pointer type. - Printf(f_wrappers, "\tswig_result = swig_make_c_pointer(%s, \"%s\");\n", - name, SwigType_manglestr(t)); + + // Dump the argument output code + Printv(f->code, Char(outarg),NIL); + + // Dump the argument cleanup code + Printv(f->code, Char(cleanup),NIL); + + // Look for any remaining cleanup + + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printv(f->code, tm, "\n",NIL); } } - else { - throw_unhandled_mzscheme_type_error (t); + + // Free any memory allocated by the function being wrapped.. + + if ((tm = Swig_typemap_lookup_new("ret",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printv(f->code, tm, "\n",NIL); } - Printf (f_wrappers, "\t return swig_result;\n"); - Printf (f_wrappers, "}\n"); - - // Now add symbol to the MzScheme interpreter - - Printv(init_func_def, - "scheme_add_global(\"", - proc_name, - "\", scheme_make_prim_w_arity(", - var_name, - ", \"", - proc_name, - "\", ", - "0", - ", ", - "1", - "), env);\n",0); - - } else { - Printf (stderr, "%s:%d. ** Warning. Unable to link with " - " type %s (ignored).\n", - Getfile(node), Getline(node), SwigType_manglestr(t)); - } - Delete(proc_name); - Delete(argnum); - Delete(arg); - Delete(tm2); -} + + // Wrap things up (in a manner of speaking) + + Printv(f->code, tab4, "return swig_package_values(lenv, values);\n", NIL); + Printf(f->code, "#undef FUNC_NAME\n"); + Printv(f->code, "}\n",NIL); + + Wrapper_print(f, f_wrappers); + + if (!Getattr(n,"sym:overloaded")) { + + // Now register the function + char temp[256]; + sprintf(temp, "%d", numargs); + Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", + proc_name, wname, proc_name, numreq, numargs); -// ----------------------------------------------------------------------- -// MZSCHEME::constant() -// -// Makes a constant. Not sure how this is really supposed to work. -// I'm going to fake out SWIG and create a variable instead. -// ------------------------------------------------------------------------ - -void -MZSCHEME::constant(DOH *node) -{ - char *name; - SwigType *type; - char *value; - - int OldStatus = ReadOnly; // Save old status flags - char var_name[256]; - String *proc_name = NewString(""); - String *rvalue = NewString(""); - String *temp = NewString(""); - char *tm; - - name = GetChar(node,"name"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - - ReadOnly = 1; - - // Make a static variable; - - sprintf (var_name, "_wrap_const_%s", name); - - // Build the name for scheme. - Printv(proc_name, name,0); - Replace(proc_name, "_", "-", DOH_REPLACE_ANY); - - if ((SwigType_type(type) == T_USER) && (!SwigType_ispointer(type))) { - fprintf (stderr, "%s:%d. Unsupported constant value.\n", - Getfile(node), Getline(node)); - return; - } - - // See if there's a typemap - - Printv(rvalue, value,0); - if ((SwigType_type(type) == T_CHAR) && (SwigType_ispointer(type) == 1)) { - temp = Copy(rvalue); - Clear(rvalue); - Printv(rvalue, "\"", temp, "\"",0); - } - if ((SwigType_type(type) == T_CHAR) && (SwigType_ispointer(type) == 0)) { - Delete(temp); - temp = Copy(rvalue); - Clear(rvalue); - Printv(rvalue, "'", temp, "'",0); - } - if ((tm = Swig_typemap_lookup ((char*)"const", type, name, - rvalue, name,0))) { - // Yep. Use it instead of the default - Printf (f_init, "%s\n", tm); - } else { - // Create variable and assign it a value - - Printf (f_header, "static %s %s = ", SwigType_str(type,0), var_name); - if ((SwigType_type(type) == T_CHAR) && (SwigType_ispointer(type) <= 1)) { - Printf (f_header, "\"%s\";\n", value); } else { - Printf (f_header, "%s;\n", value); + if (!Getattr(n,"sym:nextSibling")) { + /* Emit overloading dispatch function */ + + int maxargs; + String *dispatch = Swig_overload_dispatch(n,"return %s(argc,argv);",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + + Printv(df->def, + "static Scheme_Object *\n", dname, + "(int argc, Scheme_Object **argv) {", + NIL); + Printv(df->code,dispatch,"\n",NIL); + Printf(df->code,"scheme_signal_error(\"No matching function for overloaded '%s'\");\n", iname); + Printv(df->code,"}\n",NIL); + Wrapper_print(df,f_wrappers); + Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", + proc_name, dname, proc_name, 0, maxargs); + DelWrapper(df); + Delete(dispatch); + Delete(dname); + } } - - // Now create a variable declaration - - Hash *nnode = Copy(node); - Setattr(nnode,"name",var_name); - variable (nnode); - Delete(nnode); - ReadOnly = OldStatus; + + Delete(proc_name); + Delete(source); + Delete(target); + Delete(arg); + Delete(outarg); + Delete(cleanup); + Delete(build); + DelWrapper(f); + return SWIG_OK; } - Delete(proc_name); - Delete(rvalue); - Delete(temp); -} - -// ---------------------------------------------------------------------- -// MZSCHEME::usage_var(char *iname, SwigType *t, String &usage) -// -// Produces a usage string for a MzScheme variable. -// ---------------------------------------------------------------------- - -void -MZSCHEME::usage_var (char *iname, SwigType *t, String *usage) -{ - // char temp[1024], *c; - - // usage << "(" << iname << " [value])"; - // if (!((t->type != T_USER) || (t->is_pointer))) { - // usage << " - unsupported"; - // } -} - -// --------------------------------------------------------------------------- -// MZSCHEME::usage_func(char *iname, SwigType *t, ParmList *l, String &usage) -// -// Produces a usage string for a function in MzScheme -// --------------------------------------------------------------------------- - -void -MZSCHEME::usage_func (char *iname, SwigType *d, ParmList *l, DOHString *usage) -{ - Parm *p; - - // Print the function name. - - Printv(usage,"(",iname,0); - - // Now go through and print parameters - for (p = l; p != 0; p = Getnext(p)) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - - if (Getignore(p)) - continue; - - // Print the type. If the parameter has been named, use that as well. - - if (SwigType_type(pt) != T_VOID) { - - // Print the type. - Printv(usage," <", Getname(pt), 0); - if (SwigType_ispointer(pt)) { - for (int j = 0; j < SwigType_ispointer(pt); j++) { - Putc('*', usage); + /* ------------------------------------------------------------ + * variableWrapper() + * + * Create a link to a C variable. + * This creates a single function _wrap_swig_var_varname(). + * This function takes a single optional argument. If supplied, it means + * we are setting this variable to some value. If omitted, it means we are + * simply evaluating this variable. Either way, we return the variables + * value. + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *proc_name = NewString(""); + char var_name[256]; + String *tm; + String *tm2 = NewString("");; + String *argnum = NewString("0"); + String *arg = NewString("argv[0]"); + Wrapper *f; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + f = NewWrapper(); + + // evaluation function names + + strcpy(var_name, Char(Swig_name_wrapper(iname))); + + // Build the name for scheme. + Printv(proc_name, iname,NIL); + Replaceall(proc_name, "_", "-"); + + if ((SwigType_type(t) != T_USER) || (is_a_pointer(t))) { + + Printf (f->def, "static Scheme_Object *%s(int argc, Scheme_Object** argv) {\n", var_name); + Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); + + Wrapper_add_local (f, "swig_result", "Scheme_Object *swig_result"); + + if (!Getattr(n,"feature:immutable")) { + /* Check for a setting of the variable value */ + Printf (f->code, "if (argc) {\n"); + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","argv[0]"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","argv[0]"); + Printv(f->code, tm, "\n",NIL); + } + else { + throw_unhandled_mzscheme_type_error (t); } + Printf (f->code, "}\n"); } - Putc('>',usage); - - // Print the name if it exists. - if (strlen (Char(pn)) > 0) { - Printv(usage," ", pn, 0); + + // Now return the value of the variable (regardless + // of evaluating or setting) + + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","swig_result"); + Replaceall(tm,"$result","swig_result"); + Printf (f->code, "%s\n", tm); + } + else { + throw_unhandled_mzscheme_type_error (t); } + Printf (f->code, "\nreturn swig_result;\n"); + Printf (f->code, "#undef FUNC_NAME\n"); + Printf (f->code, "}\n"); + + Wrapper_print (f, f_wrappers); + + // Now add symbol to the MzScheme interpreter + + Printv(init_func_def, + "scheme_add_global(\"", + proc_name, + "\", scheme_make_prim_w_arity(", + var_name, + ", \"", + proc_name, + "\", ", + "0", + ", ", + "1", + "), menv);\n",NIL); + + } else { + Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, + "Unsupported variable type %s (ignored).\n", SwigType_str(t,0)); } - Delete(pn); + Delete(proc_name); + Delete(argnum); + Delete(arg); + Delete(tm2); + DelWrapper(f); + return SWIG_OK; } - Putc(')',usage); -} - - -// --------------------------------------------------------------------------- -// MZSCHEME::usage_returns(char *iname, SwigType *t, ParmList *l, String &usage) -// -// Produces a usage string for a function in MzScheme -// --------------------------------------------------------------------------- - -void -MZSCHEME::usage_returns (char *iname, SwigType *d, ParmList *l, DOHString *usage) -{ - Parm *p; - DOHString *param; - int have_param = 0, j; - - param = NewString(""); - - Clear(usage); - Printf(usage,"returns "); - - // go through and see if any are output. - - for (p = l; p != 0; p = Getnext(p)) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - - if (strcmp (Char(pn),"BOTH") && strcmp (Char(pn),"OUTPUT")) - continue; - // Print the type. If the parameter has been named, use that as well. - - if (SwigType_type(pt) != T_VOID) { - ++have_param; - - // Print the type. - Printv(param," $", Getname(pt), 0); - if (SwigType_ispointer(pt)) { - for (j = 0; j < SwigType_ispointer(pt) - 1; j++) { - Putc('*',param); - } + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + + String *var_name = NewString(""); + String *proc_name = NewString(""); + String *rvalue = NewString(""); + String *temp = NewString(""); + String *tm; + + // Make a static variable; + + Printf (var_name, "_wrap_const_%s", Swig_name_mangle(iname)); + + // Build the name for scheme. + Printv(proc_name, iname,NIL); + Replaceall(proc_name, "_", "-"); + + if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value.\n"); + return SWIG_NOWRAP; + } + + // See if there's a typemap + + Printv(rvalue, value,NIL); + if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 1)) { + temp = Copy(rvalue); + Clear(rvalue); + Printv(rvalue, "\"", temp, "\"",NIL); + } + if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) { + Delete(temp); + temp = Copy(rvalue); + Clear(rvalue); + Printv(rvalue, "'", temp, "'",NIL); + } + if ((tm = Swig_typemap_lookup_new("constant",n,name,0))) { + Replaceall(tm,"$source",rvalue); + Replaceall(tm,"$value",rvalue); + Replaceall(tm,"$target",name); + Printf (f_init, "%s\n", tm); + } else { + // Create variable and assign it a value + + Printf (f_header, "static %s = ", SwigType_lstr(type,var_name)); + if ((SwigType_type(type) == T_STRING)) { + Printf (f_header, "\"%s\";\n", value); + } else if (SwigType_type(type) == T_CHAR) { + Printf (f_header, "\'%s\';\n", value); + } else { + Printf (f_header, "%s;\n", value); + } + + // Now create a variable declaration + + { + /* Hack alert: will cleanup later -- Dave */ + Node *n = NewHash(); + Setattr(n,"name",var_name); + Setattr(n,"sym:name",iname); + Setattr(n,"type", type); + variableWrapper(n); + Delete(n); } - Printf(param,"# "); } - Delete(pn); + Delete(proc_name); + Delete(rvalue); + Delete(temp); + return SWIG_OK; } - // See if we stick on the function return type. - if (SwigType_type(d) != T_VOID || have_param == 0) { - ++have_param; - if (SwigType_type(d) == T_VOID) - Insert(param,0," unspecified"); - else { - Insert(param,0,"# "); - Insert(param,0,SwigType_str(d,0)); - Insert(param,0," $"); + /* ------------------------------------------------------------ + * validIdentifer() + * ------------------------------------------------------------ */ + + virtual int validIdentifier(String *s) { + char *c = Char(s); + /* Check whether we have an R5RS identifier.*/ + /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */ + /* <initial> --> <letter> | <special initial> */ + if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~'))) { + /* <peculiar identifier> --> + | - | ... */ + if ((strcmp(c, "+") == 0) + || strcmp(c, "-") == 0 + || strcmp(c, "...") == 0) return 1; + else return 0; } + /* <subsequent> --> <initial> | <digit> | <special subsequent> */ + while (*c) { + if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+') + || (*c == '-') || (*c == '.') || (*c == '@'))) return 0; + c++; + } + return 1; } - - // Kill extra white space. - // Sorry. Not implemented: param.strip(); - Replace(param,"$", "<", DOH_REPLACE_ANY); - Replace(param,"#", ">", DOH_REPLACE_ANY); - Replace(param,"><", "> <", DOH_REPLACE_ANY); - - // If there are multiple return values put them in a list. - if (have_param > 1) { - Insert(param,0,"("); - Append(param,")"); - } - Printv(usage,param,0); - Delete(param); +}; + +/* ----------------------------------------------------------------------------- + * swig_mzscheme() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_mzscheme(void) { + return new MZSCHEME(); } -// ---------------------------------------------------------------------- -// MZSCHEME::usage_const(char *iname, SwigType *type, char *value, String &usage) -// -// Produces a usage string for a MzScheme constant -// ---------------------------------------------------------------------- - -void -MZSCHEME::usage_const (char *iname, SwigType *, char *value, DOHString *usage) -{ - Printv(usage,"(", iname, " ", value, ")", 0); -} diff --git a/Source/Modules1.1/mzscheme.h b/Source/Modules1.1/mzscheme.h deleted file mode 100644 index 8aa38ebcb..000000000 --- a/Source/Modules1.1/mzscheme.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Simplified Wrapper and Interface Generator (SWIG) - * - * Author : David Beazley - * - * Department of Computer Science - * University of Chicago - * 1100 E 58th Street - * Chicago, IL 60637 - * beazley@cs.uchicago.edu - * - * Please read the file LICENSE for the copyright and terms by which SWIG - * can be used and distributed. - *******************************************************************************/ - -/************************************************************************** - * $Header$ - * - * class MZSCHEME - * - * Mzscheme implementation - * (Caution : This is *somewhat* experimental) - * - **************************************************************************/ - -class MZSCHEME : public Language -{ -private: - void get_pointer(DOHString_or_char *name, int parm, SwigType *t, Wrapper *f); - void usage_var(char *, SwigType *, DOHString *usage); - void usage_func(char *, SwigType *, ParmList *, DOHString *usage); - void usage_returns(char *, SwigType *, ParmList *, DOHString *usage); - void usage_const(char *, SwigType *, char *, DOHString *usage); - -public : - void parse_args (int, char *argv[]); - void initialize(String *module); - void function (DOH *node); - void variable (DOH *node); - void constant (DOH *node); - void close (void); - void create_command (String *, String *) { }; -}; diff --git a/Source/Modules1.1/ocaml.cxx b/Source/Modules1.1/ocaml.cxx new file mode 100755 index 000000000..786fee5dd --- /dev/null +++ b/Source/Modules1.1/ocaml.cxx @@ -0,0 +1,1072 @@ +/* -*- c-indentation-style: gnu -*- */ +/****************************************************************************** + * Simplified Wrapper and Interface Generator (SWIG) + * + * Author : Art Yerkes + * Modified from mzscheme.cxx : David Beazley + * + * Please read the file LICENSE for the copyright and terms by which SWIG + * can be used and distributed. + *****************************************************************************/ + +char cvsroot_ocaml_cxx[] = "$Header$"; + +/*********************************************************************** + * $Header$ + * + * ocaml.cxx + * + * Definitions for adding functions to Ocaml 101 + ***********************************************************************/ + +#include "swigmod.h" + +#include <ctype.h> + +static const char *ocaml_usage = (char*)"\ +\n\ +Ocaml Options (available with -ocaml)\n\ +-help - Print this help\n\ +-prefix name - Set a prefix to be appended to all names\n\ +\n"; + +static int classmode = 0; +static int in_constructor = 0, in_destructor = 0, in_copyconst = 0; +static int const_enum = 0; +static int static_member_function = 0; +static char *prefix=0; +static String *classname=0; +static String *module=0; +static char *ocaml_path=(char*)"ocaml"; +static String *init_func_def = 0; + +static Hash *seen_enums = 0; +static Hash *seen_enumvalues = 0; +static Hash *seen_constructors = 0; + +static File *f_header = 0; +static File *f_runtime = 0; +static File *f_wrappers = 0; +static File *f_init = 0; +static File *f_mlout = 0; +static File *f_mliout = 0; +static File *f_mlbody = 0; +static File *f_mlibody = 0; +static File *f_enumtypes_type = 0; +static File *f_enumtypes_value = 0; +static File *f_class_ctors = 0; +static File *f_class_ctors_end = 0; +static File *f_enum_to_int = 0; +static File *f_int_to_enum = 0; + +class OCAML : public Language { +public: + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main (int argc, char *argv[]) { + + int i; + + SWIG_library_directory(ocaml_path); + + // Look for certain command line options + for (i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp (argv[i], "-help") == 0) { + fputs (ocaml_usage, stderr); + SWIG_exit (0); + } + else if (strcmp (argv[i], "-prefix") == 0) { + if (argv[i + 1]) { + prefix = new char[strlen(argv[i + 1]) + 2]; + strcpy(prefix, argv[i + 1]); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + } + } + + // If a prefix has been specified make sure it ends in a '_' + + if (prefix) { + if (prefix[strlen (prefix)] != '_') { + prefix[strlen (prefix) + 1] = 0; + prefix[strlen (prefix)] = '_'; + } + } else + prefix = (char*)"swig_"; + + // Add a symbol for this module + + Preprocessor_define ("SWIGOCAML 1",0); + + // Set name of typemaps + + SWIG_typemap_lang("ocaml"); + + // Read in default typemaps */ + SWIG_config_file("ocaml.i"); + allow_overloading(); + + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + f_enumtypes_type = NewString(""); + f_enumtypes_value = NewString(""); + f_mlbody = NewString(""); + f_mlibody = NewString(""); + f_class_ctors = NewString(""); + f_class_ctors_end = NewString(""); + f_enum_to_int = NewString(""); + f_int_to_enum = NewString(""); + + module = Getattr(n,"name"); + + seen_constructors = NewHash(); + seen_enums = NewHash(); + seen_enumvalues = NewHash(); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("mli",f_mlibody); + Swig_register_filebyname("ml",f_mlbody); + + init_func_def = NewString(""); + Swig_register_filebyname("init",init_func_def); + + Swig_name_register("set","%v__set__"); + Swig_name_register("get","%v__get__"); + + Printf(f_runtime, + "/* -*- buffer-read-only: t -*- vi: set ro: */\n"); + Printf( f_runtime, "#define SWIG_MODULE \"%s\"\n", module ); + /* Module name */ + Printf( f_mlbody, "let module_name = \"%s\"\n", module ); + Printf( f_mlibody, "val module_name : string\n" ); + Printf( f_enum_to_int, + "let enum_to_int x v =\n" + " match v with C_enum y -> (\n" + " match (x : c_enum_type) with\n" + " `unknown -> (match (y : c_enum_tag) with\n" + " `int (x : int) -> C_int x\n" + " | _ -> (raise (LabelNotFromThisEnum v)))\n" + ); + + Printf( f_int_to_enum, + "let int_to_enum x y =\n" + " match (x : c_enum_type) with\n" + " `unknown -> C_enum (`int y)\n" ); + + Swig_banner (f_runtime); + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } + + /* Produce the enum_to_int and int_to_enum functions */ + + Printf(f_enumtypes_type,"type c_enum_type = [ \n `unknown\n" ); + Printf(f_enumtypes_value,"type c_enum_tag = [ \n `int of int\n" ); + + String *mlfile = NewString(""); + String *mlifile = NewString(""); + + Printv(mlfile,module,".ml",NIL); + Printv(mlifile,module,".mli",NIL); + + f_mlout = NewFile(mlfile,"w"); + f_mliout = NewFile(mlifile,"w"); + + Language::top(n); + + Printf( f_enum_to_int, + ") | _ -> (C_int (get_int v))\n" + "let _ = Callback.register \"%s_enum_to_int\" enum_to_int\n", + module ); + Printf( f_mlibody, + "val enum_to_int : c_enum_type -> c_obj -> c_obj\n" ); + + Printf( f_int_to_enum, + "let _ = Callback.register \"%s_int_to_enum\" int_to_enum\n", + module ); + Printf( f_mlibody, + "val int_to_enum : c_enum_type -> int -> c_obj\n" ); + Printf( f_enumtypes_type, "]\n" ); + Printf( f_enumtypes_value, "]\n" ); + + SwigType_emit_type_table (f_runtime, f_wrappers); + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + + Dump(f_enumtypes_type,f_mlout); + Dump(f_enumtypes_value,f_mlout); + Dump(f_mlbody,f_mlout); + Dump(f_enum_to_int,f_mlout); + Dump(f_int_to_enum,f_mlout); + Delete(f_int_to_enum); + Delete(f_enum_to_int); + Dump(f_class_ctors,f_mlout); + Dump(f_class_ctors_end,f_mlout); + Close(f_mlout); + Delete(f_mlout); + + Dump(f_enumtypes_type,f_mliout); + Dump(f_enumtypes_value,f_mliout); + Dump(f_mlibody,f_mliout); + Close(f_mliout); + Delete(f_mliout); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * functionWrapper() + * Create a function declaration and register it with the interpreter. + * ------------------------------------------------------------ */ + + void throw_unhandled_ocaml_type_error (SwigType *d) + { + Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, + "Unable to handle type %s.\n", SwigType_str(d,0)); + } + + /* Return true iff T is a pointer type */ + + int + is_a_pointer (SwigType *t) + { + return SwigType_ispointer(SwigType_typedef_resolve_all(t)); + } + + virtual int functionWrapper(Node *n) { + char *iname = GetChar(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + Parm *p; + + Wrapper *f = NewWrapper(); + String *proc_name = NewString(""); + String *source = NewString(""); + String *target = NewString(""); + String *arg = NewString(""); + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *build = NewString(""); + String *tm; + int argout_set = 0; + int i = 0; + int numargs; + int numreq; + int newobj = Getattr(n,"feature:new") ? 1 : 0; + String *overname = 0; + + // Make a wrapper name for this + String *wname = Swig_name_wrapper(iname); + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; + } + if (overname) { + Append(wname, overname); + } + Setattr(n,"wrap:name",wname); + + // Build the name for Scheme. + Printv(proc_name,"_",iname,NIL); + String *mangled_name = mangleNameForCaml(proc_name); + + if( classmode && in_constructor ) { // Emit constructor for object + String *mangled_name_nounder = + NewString((char *)(Char(mangled_name))+1); + Printf( f_class_ctors_end, + "let %s clst = _%s clst\n", + mangled_name_nounder, mangled_name_nounder ); + Printf(f_mlibody, + "val %s : c_obj -> c_obj\n", + mangled_name_nounder ); + Delete(mangled_name_nounder); + } else if( classmode && in_destructor ) { + Printf(f_class_ctors, + " \"~\", %s ;\n", mangled_name ); + } else if( classmode && !in_constructor && !in_destructor && + !static_member_function ) { + String *opname = Copy(Getattr(n,"name")); + + Replaceall(opname,"operator ",""); + + if( strstr( Char(mangled_name), "__get__" ) ) { + String *set_name = Copy(mangled_name); + if( !Getattr(n,"feature:immutable") ) { + Replaceall(set_name,"__get__","__set__"); + Printf(f_class_ctors, + " \"%s\", (fun args -> " + "if args = (C_list [ raw_ptr ]) then %s args else %s args) ;\n", + opname, mangled_name, set_name ); + Delete(set_name); + } else { + Printf(f_class_ctors, + " \"%s\", (fun args -> " + "if args = (C_list [ raw_ptr ]) then %s args else C_void) ;\n", + opname, mangled_name ); + } + } else if( strstr( Char(mangled_name), "__set__" ) ) { + ; /* Nothing ... handled by the case above */ + } else { + Printf(f_class_ctors, + " \"%s\", %s ;\n", + opname, mangled_name); + } + + Delete(opname); + } + + if( classmode && in_constructor ) { + Setattr(seen_constructors,mangled_name,"true"); + } + + // writing the function wrapper function + Printv(f->def, + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "#endif\n" + "value ", wname, " (", NIL); + Printv(f->def, "value args", NIL); + Printv(f->def, ")\n{", NIL); + + /* Define the scheme name in C. This define is used by several + macros. */ + Printv(f->def, "#define FUNC_NAME \"", mangled_name, "\"", NIL); + + // adds local variables + Wrapper_add_local(f, "args", "CAMLparam1(args)"); + Wrapper_add_local(f, "ret", "CAMLlocal2(swig_result,rv)"); + Wrapper_add_local(f, "_len", "int _len"); + Wrapper_add_local(f, "lenv", "int lenv = 1"); + Wrapper_add_local(f, "argc", "int argc = caml_list_length(args)"); + Wrapper_add_local(f, "argv", "value *argv"); + Wrapper_add_local(f, "i", "int i"); + + Printv( f->code, + "argv = (value *)malloc( argc * sizeof( value ) );\n" + "for( i = 0; i < argc; i++ ) {\n" + " argv[i] = caml_list_nth(args,i);\n" + "}\n", NIL ); + + // Declare return variable and arguments + // number of parameters + // they are called arg0, arg1, ... + // the return value is called result + + emit_args(d, l, f); + + /* Attach the standard typemaps */ + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + + numargs = emit_num_arguments(l); + numreq = emit_num_required(l); + + Printf(f->code,"swig_result = Val_unit;\n" ); + + // Now write code to extract the parameters (this is super ugly) + + for (i = 0, p = l; i < numargs; i++) { + /* Skip ignored arguments */ + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); + + // Produce names of source and target + Clear(source); + Clear(target); + Clear(arg); + Printf(source, "caml_list_nth(args,%d)", i); + Printf(target, "%s",ln); + Printv(arg, Getattr(p,"name"),NIL); + + if (i >= numreq) { + Printf(f->code,"if (caml_list_length(args) > %d) {\n",i); + } + // Handle parameter types. + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$source",source); + Replaceall(tm,"$target",target); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",source); + Printv(f->code, tm, "\n", NIL); + p = Getattr(p,"tmap:in:next"); + } else { + // no typemap found + // check if typedef and resolve + throw_unhandled_ocaml_type_error (pt); + p = nextSibling(p); + } + if (i >= numreq) { + Printf(f->code,"}\n"); + } + } + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + // Pass output arguments back to the caller. + + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"emit:input")); /* Deprecated */ + Replaceall(tm,"$target",Getattr(p,"lname")); /* Deprecated */ + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + argout_set = 1; + } else { + p = nextSibling(p); + } + } + + // Free up any memory allocated for the arguments. + + /* Insert cleanup code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } + + // Now write code to make the function call + + emit_action(n,f); + + // Now have return value, figure out what to do with it. + + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","rv"); + Replaceall(tm,"$result","rv"); + Printv(f->code, tm, "\n",NIL); + } else { + throw_unhandled_ocaml_type_error (d); + } + + // Dump the argument output code + Printv(f->code, Char(outarg),NIL); + + // Dump the argument cleanup code + Printv(f->code, Char(cleanup),NIL); + + // Look for any remaining cleanup + + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printv(f->code, tm, "\n",NIL); + } + } + + // Free any memory allocated by the function being wrapped.. + + if ((tm = Swig_typemap_lookup_new("swig_result",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printv(f->code, tm, "\n",NIL); + } + + // Wrap things up (in a manner of speaking) + + Printv(f->code, + tab4, "swig_result = caml_list_append(swig_result,rv);\n" + tab4, "free( argv );\n" + tab4, "if( lenv == 0 )\n" + tab4, "{\n" + tab4, tab4, "CAMLreturn(Val_unit);\n", + tab4, "}\n" + tab4, "else\n" + tab4, "{\n", + tab4, tab4, "CAMLreturn(swig_result);\n", + tab4, "}\n", NIL); + Printf(f->code, "#undef FUNC_NAME\n"); + Printv(f->code, "}\n",NIL); + + Wrapper_print(f, f_wrappers); + + if( Getattr(n,"sym:overloaded") ) { + if( !Getattr(n,"sym:nextSibling") ) { + int maxargs; + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + String *dispatch = + Swig_overload_dispatch(n, + "free(argv);\nCAMLreturn(%s(args));\n", + &maxargs); + + Wrapper_add_local(df, "argv", "value *argv"); + + Printv(df->def, + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "#endif\n" + "value ",dname,"(value args) {\n" + " CAMLparam1(args);\n" + " int i;\n" + " int argc = caml_list_length(args);\n",NIL); + Printv( df->code, + "argv = (value *)malloc( argc * sizeof( value ) );\n" + "for( i = 0; i < argc; i++ ) {\n" + " argv[i] = caml_list_nth(args,i);\n" + "}\n", NIL ); + Printv(df->code,dispatch,"\n",NIL); + Printf(df->code,"failwith(\"No matching function for overloaded '%s'\");\n", iname); + Printv(df->code,"}\n",NIL); + Wrapper_print(df,f_wrappers); + + Printf(f_mlbody, + "external %s_f : c_obj list -> c_obj list = \"%s\"\n" + "let %s = fnhelper %s %s_f\n", + mangled_name, dname, mangled_name, + newobj ? "true" : "false", + mangled_name ); + if( !classmode || in_constructor || in_destructor || + static_member_function ) + Printf(f_mlibody, + "(* overload *)\n" + "val %s : c_obj -> c_obj\n", mangled_name ); + + DelWrapper(df); + Delete(dispatch); + Delete(dname); + } + } else { + Printf(f_mlbody, + "external %s_f : c_obj list -> c_obj list = \"%s\"\n" + "let %s = fnhelper %s %s_f\n", + mangled_name, wname, mangled_name, newobj ? "true" : "false", + mangled_name ); + if( !classmode || in_constructor || in_destructor || + static_member_function ) + Printf(f_mlibody, + "(* Non-overload *)\n" + "val %s : c_obj -> c_obj\n", mangled_name ); + } + + Delete(proc_name); + Delete(source); + Delete(target); + Delete(arg); + Delete(outarg); + Delete(cleanup); + Delete(build); + DelWrapper(f); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * variableWrapper() + * + * Create a link to a C variable. + * This creates a single function _wrap_swig_var_varname(). + * This function takes a single optional argument. If supplied, it means + * we are setting this variable to some value. If omitted, it means we are + * simply evaluating this variable. Either way, we return the variables + * value. + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + char *name = GetChar(n,"name"); + String *iname = Getattr(n,"sym:name"); + String *mname = mangleNameForCaml(iname); + SwigType *t = Getattr(n,"type"); + + String *proc_name = NewString(""); + char var_name[256]; + String *tm; + String *tm2 = NewString("");; + String *argnum = NewString("0"); + String *arg = NewString("Field(args,0)"); + Wrapper *f; + + if (!iname || !addSymbol(iname,n)) return SWIG_ERROR; + + f = NewWrapper(); + + // evaluation function names + + strcpy(var_name, Char(Swig_name_wrapper(iname))); + + // Build the name for scheme. + Printv(proc_name, iname,NIL); + //Replaceall(proc_name, "_", "-"); + + if ((SwigType_type(t) != T_USER) || (is_a_pointer(t))) { + + Printf (f->def, + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "#endif\n" + "value %s(value args) {\n", var_name); + Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); + + Wrapper_add_local (f, "swig_result", "value swig_result"); + + if (!Getattr(n,"feature:immutable")) { + /* Check for a setting of the variable value */ + Printf (f->code, "if (args != Val_int(0)) {\n"); + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","args"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","args"); + Printv(f->code, tm, "\n",NIL); + } else { + throw_unhandled_ocaml_type_error (t); + } + Printf (f->code, "}\n"); + } + + // Now return the value of the variable (regardless + // of evaluating or setting) + + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","swig_result"); + Replaceall(tm,"$result","swig_result"); + Printf (f->code, "%s\n", tm); + } else { + throw_unhandled_ocaml_type_error (t); + } + + Printf (f->code, "\nreturn swig_result;\n"); + Printf (f->code, "#undef FUNC_NAME\n"); + Printf (f->code, "}\n"); + + Wrapper_print (f, f_wrappers); + + // Now add symbol to the Ocaml interpreter + + if( Getattr( n, "feature:immutable" ) ) { + Printf( f_mlbody, + "external __%s : c_obj -> c_obj = \"%s\"\n" + "let _%s = __%s C_void\n", + mname, var_name, mname, mname ); + Printf( f_mlibody, "val _%s : c_obj\n", iname ); + if( const_enum ) { + Printf( f_enum_to_int, + " | `%s -> _%s\n", + mname, mname ); + Printf( f_int_to_enum, + " if y = (get_int _%s) then `%s else\n", + mname, mname ); + } + } else { + Printf( f_mlbody, "external _%s : c_obj -> c_obj = \"%s\"\n", + mname, var_name ); + Printf( f_mlibody, "external _%s : c_obj -> c_obj = \"%s\"\n", + mname, var_name ); + } + } else { + Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, + "Unsupported variable type %s (ignored).\n", SwigType_str(t,0)); + } + + Delete(proc_name); + Delete(argnum); + Delete(arg); + Delete(tm2); + DelWrapper(f); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmemberfunctionHandler -- + * Overridden to set static_member_function + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler( Node *n ) { + int rv; + static_member_function = 1; + rv = Language::staticmemberfunctionHandler( n ); + static_member_function = 0; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + + String *var_name = NewString(""); + String *proc_name = NewString(""); + String *rvalue = NewString(""); + String *temp = NewString(""); + String *tm; + + // Make a static variable; + + Printf (var_name, "_wrap_const_%s", Swig_name_mangle(iname)); + + // Build the name for scheme. + Printv(proc_name, iname,NIL); + //Replaceall(proc_name, "_", "-"); + + if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value.\n"); + return SWIG_NOWRAP; + } + + // See if there's a typemap + + Printv(rvalue, value,NIL); + if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 1)) { + temp = Copy(rvalue); + Clear(rvalue); + Printv(rvalue, "\"", temp, "\"",NIL); + } + if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) { + Delete(temp); + temp = Copy(rvalue); + Clear(rvalue); + Printv(rvalue, "'", temp, "'",NIL); + } + if ((tm = Swig_typemap_lookup_new("constant",n,name,0))) { + Replaceall(tm,"$source",rvalue); + Replaceall(tm,"$value",rvalue); + Replaceall(tm,"$target",name); + Printf (f_init, "%s\n", tm); + } else { + // Create variable and assign it a value + + Printf (f_header, "static %s = ", SwigType_lstr(type,var_name)); + if ((SwigType_type(type) == T_STRING)) { + Printf (f_header, "\"%s\";\n", value); + } else if (SwigType_type(type) == T_CHAR) { + Printf (f_header, "\'%s\';\n", value); + } else { + Printf (f_header, "%s;\n", value); + } + + { + /* Hack alert: will cleanup later -- Dave */ + Node *n = NewHash(); + Setattr(n,"name",var_name); + Setattr(n,"sym:name",iname); + Setattr(n,"type", type); + Setattr(n,"feature:immutable","1"); + variableWrapper(n); + Delete(n); + } + } + Delete(proc_name); + Delete(rvalue); + Delete(temp); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * validIdentifer() + * ------------------------------------------------------------ */ + + virtual int validIdentifier(String *s) { +#if 0 + char *c = Char(s); + /* Check whether we have an R5RS identifier.*/ + /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */ + /* <initial> --> <letter> | <special initial> */ + if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~'))) { + /* <peculiar identifier> --> + | - | ... */ + if ((strcmp(c, "+") == 0) + || strcmp(c, "-") == 0 + || strcmp(c, "...") == 0) return 1; + else return 0; + } + /* <subsequent> --> <initial> | <digit> | <special subsequent> */ + while (*c) { + if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+') + || (*c == '-') || (*c == '.') || (*c == '@'))) return 0; + c++; + } +#endif + return 1; + } + + int constructorHandler(Node *n) { + int ret; + + in_constructor = 1; + ret = Language::constructorHandler(n); + in_constructor = 0; + + return ret; + } + + int destructorHandler(Node *n) { + int ret; + + in_destructor = 1; + ret = Language::destructorHandler(n); + in_destructor = 0; + + return ret; + } + + int copyconstructorHandler(Node *n) { + int ret; + + in_copyconst = 1; + in_constructor = 1; + ret = Language::copyconstructorHandler(n); + in_constructor = 0; + in_copyconst = 0; + + return ret; + } + + int classHandler( Node *n ) { + String *name = Getattr(n,"name"); + String *mangled_sym_name = mangleNameForCaml(name); + + if( !name ) return SWIG_OK; + + classname = mangled_sym_name; + + Printf( f_class_ctors, + "let create_%s_from_ptr raw_ptr =\n" + " C_obj (let rec method_table = [\n" + " \"nop\", (fun args -> C_void) ;\n", + classname ); + + Printf( f_mlibody, + "val create_%s_from_ptr : c_obj -> c_obj\n", + classname ); + + classmode = 1; + int rv = Language::classHandler(n); + classmode = 0; + +#if 0 + Printf(f_mlibody, + "val delete_%s : c_obj -> unit\n", + mangled_sym_name ); +#endif + + /* Handle up-casts in a nice way */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "ocaml:ctor"); + if (bname) + Printv(f_class_ctors, + " \"::",bname,"\", (fun args -> " + "create_",bname,"_from_ptr raw_ptr) ;\n",NIL); + + base = Nextitem(baselist); + } + } + + Printf(f_class_ctors, + " \"&\", (fun args -> raw_ptr) ;\n" + " \":parents\",\n" + " (fun args -> \n" + " C_list \n" + " (List.map \n" + " (fun (x,y) -> \n" + " C_string (String.sub x 2 ((String.length x) - 2)))\n" + " (List.filter \n" + " (fun (x,y) -> \n" + " ((String.length x) > 2) && \n" + " x.[0] == ':' && \n" + " x.[1] == ':') method_table))) ;\n" + " \":classof\", (fun args -> (C_string \"%s\")) ;\n" + " \":methods\", " + "(fun args -> C_list (List.map (fun (x,y) -> C_string x) " + "method_table)) ] in\n" + " (fun mth arg ->\n" + " try\n" + " let method_name,application = List.hd (List.filter (fun (x,y) -> x = mth) method_table) in\n" + " application \n" + " (match arg with C_list l -> (C_list (raw_ptr :: l)) | C_void -> (C_list [ raw_ptr ]) | v -> (C_list [ raw_ptr ; v ]))\n" + " with (Failure \"hd\") -> \n" + " (* Try parent classes *)\n" + " begin\n" + " let parent_classes = [ \n", + name ); + + /* Handle inheritance -- Mostly stolen from python code */ + baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "ocaml:ctor"); + if (bname) + Printv(f_class_ctors, + " create_",bname,"_from_ptr",NIL); + + base = Nextitem(baselist); + if (base) + Printv(f_class_ctors," ;\n",NIL); + else + Printv(f_class_ctors,"\n",NIL); + } + } + + Printv(f_class_ctors," ]\n",NIL); + + Printf(f_class_ctors, + " in let rec try_parent plist raw_ptr = \n" + " match plist with\n" + " p :: tl -> (try\n" + " (invoke (p raw_ptr)) mth arg\n" + " with (BadMethodName (p,m,s)) -> try_parent tl raw_ptr)\n" + " | [] ->\n" + " raise (BadMethodName (raw_ptr,mth,\"%s\"))\n" + " in try_parent parent_classes raw_ptr\n" + " end\n" + " | e -> raise e))\n", + name ); + + Printf( f_class_ctors, + "let _ = Callback.register \"create_%s_from_ptr\" " + "create_%s_from_ptr\n", + classname, classname ); + + Setattr(n,"ocaml:ctor",classname); + + return rv; + } + + String *mangleNameForCaml( String *s ) { + String *out = Copy(s); + Replaceall(out," ","_"); + Replaceall(out,"::","_"); + Replaceall(out,",","_x_"); + Replaceall(out,"+","__plus__"); + Replaceall(out,"-","__minus__"); + Replaceall(out,"<","__ldbrace__"); + Replaceall(out,">","__rdbrace__"); + Replaceall(out,"!","__not__"); + Replaceall(out,"%","__mod__"); + Replaceall(out,"^","__xor__"); + Replaceall(out,"*","__star__"); + Replaceall(out,"&","__amp__"); + Replaceall(out,"|","__or__"); + Replaceall(out,"(","__lparen__"); + Replaceall(out,")","__rparen__"); + Replaceall(out,"[","__lbrace__"); + Replaceall(out,"]","__rbrace__"); + Replaceall(out,"~","__bnot__"); + Replaceall(out,"=","__equals__"); + Replaceall(out,"/","__slash__"); + Replaceall(out,".","__dot__"); + return out; + } + + /* Benedikt Grundmann inspired --> Enum wrap styles */ + + int enumvalueDeclaration(Node *n) { + String *name = Getattr(n,"name"); + + if( const_enum && name && !Getattr(seen_enumvalues,name) ) { + Printf( f_enumtypes_value,"| `%s\n", name ); + Setattr(seen_enumvalues,name,"true"); + Setattr(n,"feature:immutable","1"); + + return constantWrapper(n); + } else return SWIG_OK; + } + + int enumDeclaration(Node *n) { + String *name = Getattr(n,"name"); + + if( name && !Getattr(seen_enums,name) ) { + const_enum = 1; + Printf( f_enum_to_int, "| `%s -> (match (y : c_enum_tag) with\n", name ); + Printf( f_int_to_enum, "| `%s -> C_enum (\n", name ); + Printf( f_mlbody, + "let _ = Callback.register \"%s_marker\" (`%s)\n", + name, name ); + Printf( f_enumtypes_type,"| `%s\n", name ); + Setattr(seen_enumvalues,name,"true"); + } + + int ret = Language::enumDeclaration(n); + + if( const_enum ) { + Printf( f_int_to_enum, "`int y)\n", name ); + Printf( f_enum_to_int, + "| `int (x : int) -> C_int x\n" + "| _ -> raise (Failure \"Unknown enum tag\"))\n" ); + } + + const_enum = 0; + + return ret; + } +}; + +/* ------------------------------------------------------------------------- + * swig_ocaml() - Instantiate module + * ------------------------------------------------------------------------- */ + +extern "C" Language * +swig_ocaml(void) { + return new OCAML(); +} + diff --git a/Source/Modules1.1/overload.cxx b/Source/Modules1.1/overload.cxx new file mode 100644 index 000000000..f62e63f93 --- /dev/null +++ b/Source/Modules1.1/overload.cxx @@ -0,0 +1,338 @@ +/* ----------------------------------------------------------------------------- + * overload.cxx + * + * This file is used to analyze overloaded functions and methods. + * It looks at signatures and tries to gather information for + * building a dispatch function. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_overload_cxx[] = "$Header$"; + +#include "swigmod.h" + +#define MAX_OVERLOAD 256 + +extern int emit_num_required(ParmList *); + +/* ----------------------------------------------------------------------------- + * Swig_overload_rank() + * + * This function takes an overloaded declaration and creates a list that ranks + * all overloaded methods in an order that can be used to generate a dispatch + * function. + * ----------------------------------------------------------------------------- */ + +struct Overloaded { + Node *n; /* Node */ + int argc; /* Argument count */ + ParmList *parms; /* Parameters used for overload check */ + int error; /* Ambiguity error */ +}; + +List * +Swig_overload_rank(Node *n) { + Overloaded nodes[MAX_OVERLOAD]; + int nnodes = 0; + Node *o = Getattr(n,"sym:overloaded"); + Node *c; + + if (!o) return 0; + + c = o; + while (c) { + if (!Getattr(c,"error")) { + if (Getattr(c,"wrap:name")) { + nodes[nnodes].n = c; + nodes[nnodes].parms = Getattr(c,"wrap:parms"); + nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms); + nodes[nnodes].error = 0; + nnodes++; + } + } + c = Getattr(c,"sym:nextSibling"); + } + + /* Sort the declarations by required argument count */ + { + int i,j; + for (i = 0; i < nnodes; i++) { + for (j = i+1; j < nnodes; j++) { + if (nodes[i].argc > nodes[j].argc) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } + } + } + } + + /* Sort the declarations by argument types */ + { + int i,j; + for (i = 0; i < nnodes-1; i++) { + if (nodes[i].argc == nodes[i+1].argc) { + for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { + Parm *p1 = nodes[i].parms; + Parm *p2 = nodes[j].parms; + int differ = 0; + int num_checked = 0; + while (p1 && p2 && (num_checked < nodes[i].argc)) { + // Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); + if (checkAttribute(p1,"tmap:in:numinputs","0")) { + p1 = Getattr(p1,"tmap:in:next"); + continue; + } + if (checkAttribute(p2,"tmap:in:numinputs","0")) { + p2 = Getattr(p2,"tmap:in:next"); + continue; + } + String *t1 = Getattr(p1,"tmap:typecheck:precedence"); + String *t2 = Getattr(p2,"tmap:typecheck:precedence"); + if ((!t1) && (!nodes[i].error)) { + Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), + "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", + Getattr(nodes[i].n,"name"),ParmList_str(Getattr(nodes[i].n,"parms")), + SwigType_str(Getattr(p1,"type"),0)); + nodes[i].error = 1; + } else if ((!t2) && (!nodes[j].error)) { + Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", + Getattr(nodes[j].n,"name"),ParmList_str(Getattr(nodes[j].n,"parms")), + SwigType_str(Getattr(p2,"type"),0)); + nodes[j].error = 1; + } + if (t1 && t2) { + int t1v, t2v; + t1v = atoi(Char(t1)); + t2v = atoi(Char(t2)); + differ = t1v-t2v; + } + else if (!t1 && t2) differ = 1; + else if (t2 && !t1) differ = -1; + else if (!t1 && !t2) differ = -1; + num_checked++; + if (differ > 0) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + break; + } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) { + t1 = Getattr(p1,"ltype"); + if (!t1) { + t1 = SwigType_ltype(Getattr(p1,"type")); + if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) { + SwigType_add_pointer(t1); + } + Setattr(p1,"ltype",t1); + } + t2 = Getattr(p2,"ltype"); + if (!t2) { + t2 = SwigType_ltype(Getattr(p2,"type")); + if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) { + SwigType_add_pointer(t2); + } + Setattr(p2,"ltype",t2); + } + + /* Need subtype check here. If t2 is a subtype of t1, then we need to change the + order */ + + if (SwigType_issubtype(t2,t1)) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } + + if (Strcmp(t1,t2) != 0) { + differ = 1; + break; + } + } else if (differ) { + break; + } + if (Getattr(p1,"tmap:in:next")) { + p1 = Getattr(p1,"tmap:in:next"); + } else { + p1 = nextSibling(p1); + } + if (Getattr(p2,"tmap:in:next")) { + p2 = Getattr(p2,"tmap:in:next"); + } else { + p2 = nextSibling(p2); + } + } + if (!differ) { + /* See if declarations differ by const only */ + String *d1 = Getattr(nodes[i].n,"decl"); + String *d2 = Getattr(nodes[j].n,"decl"); + if (d1 && d2) { + String *dq1 = Copy(d1); + String *dq2 = Copy(d2); + if (SwigType_isconst(d1)) { + SwigType_pop(dq1); + } + if (SwigType_isconst(d2)) { + SwigType_pop(dq2); + } + if (Strcmp(dq1,dq2) == 0) { + + if (SwigType_isconst(d1) && !SwigType_isconst(d2)) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + differ = 1; + if (!nodes[j].error) { + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n", + Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms), + Getfile(nodes[i].n), Getline(nodes[i].n)); + } + nodes[j].error = 1; + } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) { + differ = 1; + if (!nodes[j].error) { + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n", + Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms), + Getfile(nodes[i].n), Getline(nodes[i].n)); + } + nodes[j].error = 1; + } + } + Delete(dq1); + Delete(dq2); + } + } + if (!differ) { + if (!nodes[j].error) { + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded %s(%s) is shadowed by %s(%s) at %s:%d.\n", + Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms), + Getattr(nodes[i].n,"name"), ParmList_protostr(nodes[i].parms), + Getfile(nodes[i].n),Getline(nodes[i].n)); + nodes[j].error = 1; + } + } + } + } + } + } + List *result = NewList(); + { + int i; + for (i = 0; i < nnodes; i++) { + Append(result,nodes[i].n); + // Printf(stdout,"[ %d ] %s\n", i, ParmList_protostr(nodes[i].parms)); + // Swig_print_node(nodes[i].n); + } + } + return result; +} + +/* ----------------------------------------------------------------------------- + * Swig_overload_dispatch() + * + * Generate a dispatch function. argc is assumed to hold the argument count. + * argv is the argument vector. + * + * Note that for C++ class member functions, Swig_overload_dispatch() assumes + * that argc includes the "self" argument and that the first element of argv[] + * is the "self" argument. So for a member function: + * + * Foo::bar(int x, int y, int z); + * + * the argc should be 4 (not 3!) and the first element of argv[] would be + * the appropriate scripting language reference to "self". For regular + * functions (and static class functions) the argc and argv only include + * the regular function arguments. + * ----------------------------------------------------------------------------- */ + +static bool print_typecheck(String *f, int j, Parm *pj) +{ + char tmp[256]; + sprintf(tmp,"argv[%d]",j); + String *tm = Getattr(pj,"tmap:typecheck"); + if (tm) { + Replaceid(tm,Getattr(pj,"lname"),"_v"); + Replaceall(tm,"$input", tmp); + Printv(f,tm,"\n",NIL); + return true; + } + else + return false; +} + +String * +Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *maxargs) { + int i,j; + + *maxargs = 1; + + String *f = NewString(""); + + /* Get a list of methods ranked by precedence values and argument count */ + List *dispatch = Swig_overload_rank(n); + int nfunc = Len(dispatch); + + /* Loop over the functions */ + + for (i = 0; i < nfunc; i++) { + Node *ni = Getitem(dispatch,i); + Parm *pi = Getattr(ni,"wrap:parms"); + int num_required = emit_num_required(pi); + int num_arguments = emit_num_arguments(pi); + if (num_arguments > *maxargs) *maxargs = num_arguments; + int varargs = emit_isvarargs(pi); + + if (!varargs) { + if (num_required == num_arguments) { + Printf(f,"if (argc == %d) {\n", num_required); + } else { + Printf(f,"if ((argc >= %d) && (argc <= %d)) {\n", num_required, num_arguments); + } + } else { + Printf(f,"if (argc >= %d) {\n", num_required); + } + + if (num_arguments) { + Printf(f,"int _v;\n"); + } + + int num_braces = 0; + j = 0; + Parm *pj = pi; + while (pj) { + if (checkAttribute(pj,"tmap:in:numinputs","0")) { + pj = Getattr(pj,"tmap:in:next"); + continue; + } + if (j >= num_required) { + Printf(f, "if (argc <= %d) {\n", j); + Printf(f, Char(fmt),Getattr(ni,"wrap:name")); + Printf(f, "}\n"); + } + if (print_typecheck(f, j, pj)) { + Printf(f, "if (_v) {\n"); + num_braces++; + } + Parm *pk = Getattr(pj,"tmap:in:next"); + if (pk) pj = pk; + else pj = nextSibling(pj); + j++; + } + Printf(f, Char(fmt),Getattr(ni,"wrap:name")); + /* close braces */ + for (/* empty */; num_braces > 0; num_braces--) + Printf(f, "}\n"); + Printf(f,"}\n"); /* braces closes "if" for this method */ + } + Delete(dispatch); + return f; +} + + diff --git a/Source/Modules1.1/perl5.cxx b/Source/Modules1.1/perl5.cxx index fb04cafdd..94191080d 100644 --- a/Source/Modules1.1/perl5.cxx +++ b/Source/Modules1.1/perl5.cxx @@ -1,4 +1,4 @@ -/* ----------------------------------------------------------------------------- +/* ---------------------------------------------------------------------------- * perl5.cxx * * Generate Perl5 wrappers @@ -7,1950 +7,1588 @@ * Loic Dachary (loic@ceic.com) * David Fletcher * Gary Holt + * Jason Stewart (jason@openinformatics.com) * * Copyright (C) 1999-2000. The University of Chicago * See the file LICENSE for information on usage and redistribution. - * ----------------------------------------------------------------------------- */ + * ------------------------------------------------------------------------- */ -/* DB: I had to take some features related to package naming out of this to - get the new type system to work. These need to be put back in at some point. */ +char cvsroot_perl5_cxx[] = "$Header$"; -static char cvsroot[] = "$Header$"; +#include "swigmod.h" -#include "swig11.h" -#include "perl5.h" +#ifndef MACSWIG +#include "swigconfig.h" +#endif -static char *usage = (char*)"\ +static const char *usage = (char*)"\ Perl5 Options (available with -perl5)\n\ - -module name - Set module name\n\ - -interface name - Set interface name\n\ - -package name - Set package prefix\n\ + -ldflags - Print runtime libraries to link with\n\ -static - Omit code related to dynamic loading.\n\ - -shadow - Create shadow classes.\n\ + -nopm - Do not generate the .pm file.\n\ + -proxy - Create proxy classes.\n\ + -const - Wrap constants as constants and not variables (implies -shadow).\n\ -compat - Compatibility mode.\n\n"; -static String *smodule = 0; static int compat = 0; -static int export_all = 0; -static String *package = 0; +static int no_pmfile = 0; + +static int export_all = 0; + +/* + * pmfile + * set by the -pm flag, overrides the name of the .pm file + */ +static String *pmfile = 0; + +/* + * module + * set by the %module directive, e.g. "Xerces". It will determine + * the name of the .pm file, and the dynamic library. + */ static String *module = 0; -static String *interface = 0; -static String *cmodule = 0; -static String *vinit = 0; -static FILE *f_pm = 0; -static String *pm; /* Package initialization code */ -static String *magic; /* Magic variable wrappers */ + +/* + * fullmodule + * the fully namespace qualified name of the module, e.g. "XML::Xerces" + * it will be used to set the package namespace in the .pm file, as + * well as the name of the initialization methods in the glue library + */ +static String *fullmodule = 0; +/* + * cmodule + * the namespace of the internal glue code, set to the value of + * module with a 'c' appended + */ +static String *cmodule = 0; + +static String *command_tab = 0; +static String *constant_tab = 0; +static String *variable_tab = 0; + +static File *f_runtime = 0; +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; +static File *f_pm = 0; +static String *pm; /* Package initialization code */ +static String *magic; /* Magic variable wrappers */ static int is_static = 0; /* The following variables are used to manage Perl5 classes */ -static int blessed = 0; /* Enable object oriented features */ -static Hash *classes = 0; /* A hash table for storing the classes we've seen so far */ -static Hash *symbols = 0; -static int have_constructor = 0; -static int have_destructor= 0; -static int have_data_members = 0; -static String *class_name = 0; /* Name of the class (what Perl thinks it is) */ -static String *class_type = 0; /* Type of class "struct", "class", "union" */ -static String *real_classname = 0; /* Real name of C/C++ class */ -static String *base_class = 0; /* Base class (if using inheritance) */ -static int class_renamed = 0; +static int blessed = 0; /* Enable object oriented features */ +static int do_constants = 0; /* Constant wrapping */ +static List *classlist = 0; /* List of classes */ +static int have_constructor = 0; +static int have_destructor= 0; +static int have_data_members = 0; +static String *class_name = 0; /* Name of the class (what Perl thinks it is) */ +static String *real_classname = 0; /* Real name of C/C++ class */ static String *fullclassname = 0; static String *pcode = 0; /* Perl code associated with each class */ static String *blessedmembers = 0; /* Member data associated with each class */ static int member_func = 0; /* Set to 1 when wrapping a member function */ -static String *realpackage = 0; /* Name of real module */ -static String *func_stubs = 0; /* Function stubs */ -static String *var_stubs = 0; /* Variable stubs */ -static String *member_keys = 0; /* Keys for all member data */ -static String *exported = 0; /* Exported symbols */ +static String *func_stubs = 0; /* Function stubs */ +static String *const_stubs = 0; /* Constant stubs */ +static int num_consts = 0; /* Number of constants */ +static String *var_stubs = 0; /* Variable stubs */ +static String *exported = 0; /* Exported symbols */ static String *pragma_include = 0; +static Hash *operators = 0; +static int have_operators = 0; + +class PERL5 : public Language { +public: + + /* Test to see if a type corresponds to something wrapped with a shadow class */ + Node *is_shadow(SwigType *t) { + Node *n; + n = classLookup(t); + /* Printf(stdout,"'%s' --> '%x'\n", t, n); */ + if (n) { + if (!Getattr(n,"perl5:proxy")) { + setclassname(n); + } + return Getattr(n,"perl5:proxy"); + } + return 0; + } + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ -/* Test to see if a type corresponds to something wrapped with a shadow class */ -static DOH *is_shadow(SwigType *t) { - DOH *r; - SwigType *lt = Swig_clocal_type(t); - r = Getattr(classes,lt); - Delete(lt); - return r; -} - -/* ----------------------------------------------------------------------------- - * PERL5::parse_args() - * ----------------------------------------------------------------------------- */ -void -PERL5::parse_args(int argc, char *argv[]) { - int i = 1; + virtual void main(int argc, char *argv[]) { + int i = 1; - cmodule = NewString(""); - Swig_swiglib_set("perl5"); - for (i = 1; i < argc; i++) { + SWIG_library_directory("perl5"); + for (i = 1; i < argc; i++) { if (argv[i]) { - if(strcmp(argv[i],"-package") == 0) { - if (argv[i+1]) { - package = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if(strcmp(argv[i],"-interface") == 0) { - if (argv[i+1]) { - interface = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if (strcmp(argv[i],"-exportall") == 0) { - export_all = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-static") == 0) { - is_static = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-shadow") == 0) { - blessed = 1; + if(strcmp(argv[i],"-package") == 0) { + Printf(stderr,"*** -package is no longer supported\n*** use the directive '%module A::B::C' in your interface file instead\n*** see the Perl section in the manual for details.\n"); + SWIG_exit(EXIT_FAILURE); + } else if(strcmp(argv[i],"-interface") == 0) { + Printf(stderr,"*** -interface is no longer supported\n*** use the directive '%module A::B::C' in your interface file instead\n*** see the Perl section in the manual for details.\n"); + SWIG_exit(EXIT_FAILURE); + } else if (strcmp(argv[i],"-exportall") == 0) { + export_all = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-static") == 0) { + is_static = 1; + Swig_mark_arg(i); + } else if ((strcmp(argv[i],"-shadow") == 0) || ((strcmp(argv[i],"-proxy") == 0))) { + blessed = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-const") == 0) { + do_constants = 1; + blessed = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-nopm") == 0) { + no_pmfile = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i],"-compat") == 0) { - compat = 1; + } else if (strcmp(argv[i],"-pm") == 0) { Swig_mark_arg(i); - } else if (strcmp(argv[i],"-help") == 0) { - fputs(usage,stderr); - } + i++; + pmfile = NewString(argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-compat") == 0) { + compat = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_PERL_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } } - } - - Preprocessor_define((void *) "SWIGPERL 1", 0); - Preprocessor_define((void *) "SWIGPERL5 1", 0); -} + } -/* ----------------------------------------------------------------------------- - * PERL5::initialize() - * ----------------------------------------------------------------------------- */ -void -PERL5::initialize(String *modname) -{ - char filen[256]; - - classes = NewHash(); - symbols = NewHash(); - - vinit = NewString(""); - pm = NewString(""); - func_stubs = NewString(""); - var_stubs = NewString(""); - exported = NewString(""); - magic = NewString(""); - pragma_include = NewString(""); - - Swig_banner(f_runtime); - - if (NoInclude) { - Printf(f_header,"#define SWIG_NOINCLUDE\n"); + Preprocessor_define("SWIGPERL 1", 0); + Preprocessor_define("SWIGPERL5 1", 0); + SWIG_typemap_lang("perl5"); + SWIG_config_file("perl5.swg"); + allow_overloading(); } - if (Swig_insert_file("common.swg", f_runtime) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate 'common.swg' in SWIG library.\n"); - Swig_exit (EXIT_FAILURE); - } + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ - if (Swig_insert_file("perl5.swg", f_runtime) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate 'perl5.swg' in SWIG library.\n"); - Swig_exit (EXIT_FAILURE); - } + virtual int top(Node *n) { - if (!module) module = NewString(modname); + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); - /* Create a C module name and put it in 'cmodule' */ - Clear(cmodule); - Append(cmodule,module); - Replace(cmodule,":","_",DOH_REPLACE_ANY); + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + classlist = NewList(); + + pm = NewString(""); + func_stubs = NewString(""); + var_stubs = NewString(""); + const_stubs = NewString(""); + exported = NewString(""); + magic = NewString(""); + pragma_include = NewString(""); + + command_tab = NewString("static swig_command_info swig_commands[] = {\n"); + constant_tab = NewString("static swig_constant_info swig_constants[] = {\n"); + variable_tab = NewString("static swig_variable_info swig_variables[] = {\n"); + + Swig_banner(f_runtime); + + if (NoInclude) { + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); + } - if (!package) { - package = NewString(module); - } + module = Copy(Getattr(n,"name")); /* If we're in blessed mode, change the package name to "packagec" */ - if (blessed) { - realpackage = package; - package = interface ? interface : NewStringf("%sc",package); - } else { - realpackage = NewString(package); - } + + if (blessed) { + cmodule = NewStringf("%sc",module); + } else { + cmodule = NewString(module); + } + fullmodule = NewString(module); /* Create a .pm file * Need to strip off any prefixes that might be found in * the module name */ - { - char *m = Char(module) + Len(module); - while (m != Char(module)) { - if (*m == ':') { - m++; - break; + if (no_pmfile) { + f_pm = NewString(0); + } else { + if (pmfile == NULL) { + char *m = Char(module) + Len(module); + while (m != Char(module)) { + if (*m == ':') { + m++; + break; + } + m--; + } + pmfile = NewStringf("%s.pm", m); + } + String *filen = NewStringf("%s%s", Swig_file_dirname(outfile),pmfile); + if ((f_pm = NewFile(filen,"w")) == 0) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit (EXIT_FAILURE); } - m--; + Swig_register_filebyname("pm",f_pm); } - sprintf(filen,"%s%s.pm", output_dir,m); - if ((f_pm = fopen(filen,"w")) == 0) { - Printf(stderr,"Unable to open %s\n", filen); - Swig_exit (EXIT_FAILURE); + { + String *tmp = NewString(fullmodule); + Replaceall(tmp,":","_"); + Printf(f_header,"#define SWIG_init boot_%s\n\n", tmp); + Printf(f_header,"#define SWIG_name \"%s::boot_%s\"\n", cmodule, tmp); + Printf(f_header,"#define SWIG_prefix \"%s::\"\n", cmodule); + Delete(tmp); } - } - if (!blessed) { - smodule = NewString(module); - } else if (is_static) { - smodule = NewStringf("%sc",module); - Append(cmodule,"c"); - Append(cmodule,"c"); - } else { - smodule = NewString(module); - } - { - String *tmp = NewString(realpackage); - Replace(tmp,":","_", DOH_REPLACE_ANY); - Printf(f_header,"#define SWIG_init boot_%s\n\n", tmp); - Printf(f_header,"#define SWIG_name \"%s::boot_%s\"\n", package, tmp); - Delete(tmp); - } - Printf(f_header,"#define SWIG_varinit \"%s::var_%s_init();\"\n", package, cmodule); - Printf(f_header,"#ifdef __cplusplus\n"); - Printf(f_header,"extern \"C\"\n"); - Printf(f_header,"#endif\n"); - Printf(f_header,"#ifndef PERL_OBJECT\n"); - Printf(f_header,"SWIGEXPORT(void) SWIG_init (CV* cv);\n"); - Printf(f_header,"#else\n"); - Printf(f_header,"SWIGEXPORT(void) SWIG_init (CV *cv, CPerlObj *);\n"); - Printf(f_header,"#endif\n"); - Printf(f_init,"#ifdef __cplusplus\n"); - Printf(f_init,"extern \"C\"\n"); - Printf(f_init,"#endif\n"); - Printf(f_init,"XS(SWIG_init) {\n"); - Printf(f_init,"\t dXSARGS;\n"); - Printf(f_init,"\t int i;\n"); - Printf(f_init,"\t char *file = __FILE__;\n"); - Printv(f_init, - "for (i = 0; swig_types_initial[i]; i++) {\n", - "swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n", - "}\n", 0); - Printf(f_init,"\t newXS(\"%s::var_%s_init\", _wrap_perl5_%s_var_init, file);\n",package,cmodule, cmodule); - - Printv(vinit, - "XS(_wrap_perl5_", cmodule, "_var_init) {\n", - tab4, "dXSARGS;\n", - tab4, "SV *sv;\n", - 0); - - Printf(f_pm,"# This file was automatically generated by SWIG\n"); - Printf(f_pm,"package %s;\n",realpackage); - Printf(f_pm,"require Exporter;\n"); - if (!is_static) { - Printf(f_pm,"require DynaLoader;\n"); - Printf(f_pm,"@ISA = qw(Exporter DynaLoader);\n"); - } else { - Printf(f_pm,"@ISA = qw(Exporter);\n"); - } + Printf(f_pm,"# This file was automatically generated by SWIG\n"); + Printf(f_pm,"package %s;\n",fullmodule); - /* Start creating magic code */ - - Printv(magic, - "#ifdef PERL_OBJECT\n", - "#define MAGIC_CLASS _wrap_", module, "_var::\n", - "class _wrap_", module, "_var : public CPerlObj {\n", - "public:\n", - "#else\n", - "#define MAGIC_CLASS\n", - "#endif\n", - "SWIGCLASS_STATIC int swig_magic_readonly(SV *sv, MAGIC *mg) {\n", - tab4, "MAGIC_PPERL\n", - tab4, "sv = sv; mg = mg;\n", - tab4, "croak(\"Value is read-only.\");\n", - tab4, "return 0;\n", - "}\n", - 0); -} + Printf(f_pm,"require Exporter;\n"); + if (!is_static) { + Printf(f_pm,"require DynaLoader;\n"); + Printf(f_pm,"@ISA = qw(Exporter DynaLoader);\n"); + } else { + Printf(f_pm,"@ISA = qw(Exporter);\n"); + } -/* ----------------------------------------------------------------------------- - * PERL5::import() - * ----------------------------------------------------------------------------- */ -void -PERL5::import(String *modname) { - if (blessed) { - Printf(f_pm,"require %s;\n", modname); - } -} + /* Start creating magic code */ + + Printv(magic, + "#ifdef PERL_OBJECT\n", + "#define MAGIC_CLASS _wrap_", module, "_var::\n", + "class _wrap_", module, "_var : public CPerlObj {\n", + "public:\n", + "#else\n", + "#define MAGIC_CLASS\n", + "#endif\n", + "SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *sv, MAGIC *mg) {\n", + tab4, "MAGIC_PPERL\n", + tab4, "sv = sv; mg = mg;\n", + tab4, "croak(\"Value is read-only.\");\n", + tab4, "return 0;\n", + "}\n", + NIL); -/* ----------------------------------------------------------------------------- - * PERL5::close() - * ----------------------------------------------------------------------------- */ -void -PERL5::close(void) { - String *base = NewString(""); + Printf(f_wrappers,"#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); + + /* emit wrappers */ + Language::top(n); + String *base = NewString(""); + /* Dump out variable wrappers */ - Printv(magic, - "\n\n#ifdef PERL_OBJECT\n", - "};\n", - "#endif\n", - 0); + Printv(magic, + "\n\n#ifdef PERL_OBJECT\n", + "};\n", + "#endif\n", + NIL); - Printf(f_header,"%s\n", magic); + Printf(f_header,"%s\n", magic); - String *type_table = NewString(""); - SwigType_emit_type_table(f_runtime,type_table); + String *type_table = NewString(""); + SwigType_emit_type_table(f_runtime,type_table); /* Patch the type table to reflect the names used by shadow classes */ - if (blessed) { - SwigType *type; - for (type = Firstkey(classes); type; type = Nextkey(classes)) { - String *mangle = NewStringf("\"%s\"", SwigType_manglestr(type)); - String *rep = NewStringf("\"%s\"", Getattr(classes,type)); - Replace(type_table,mangle,rep,DOH_REPLACE_ANY); - Delete(mangle); - Delete(rep); + if (blessed) { + Node *cls; + for (cls = Firstitem(classlist); cls; cls = Nextitem(classlist)) { + if (Getattr(cls,"perl5:proxy")) { + SwigType *type = Copy(Getattr(cls,"classtype")); + SwigType_add_pointer(type); + String *mangle = NewStringf("\"%s\"", SwigType_manglestr(type)); + String *rep = NewStringf("\"%s\"", Getattr(cls,"perl5:proxy")); + Replaceall(type_table,mangle,rep); + Delete(mangle); + Delete(rep); + Delete(type); + } + } } - } - - Printf(f_wrappers,"%s",type_table); - Delete(type_table); - - /* Printf(stdout,"::: Perl shadow :::\n\n%s",classes); */ - Printf(f_init,"\t ST(0) = &PL_sv_yes;\n"); - Printf(f_init,"\t XSRETURN(1);\n"); - Printf(f_init,"}\n"); + Printf(f_wrappers,"%s",type_table); + Delete(type_table); - Printv(vinit,tab4, "XSRETURN(1);\n", "}\n", 0); - Printf(f_wrappers,"%s", vinit); - - Printf(f_pm,"package %s;\n", package); - - if (!is_static) { - Printf(f_pm,"bootstrap %s;\n", realpackage); - } else { - String *tmp = NewString(realpackage); - Replace(tmp,":","_",DOH_REPLACE_ANY); - Printf(f_pm,"boot_%s();\n", tmp); - Delete(tmp); - } - Printf(f_pm,"var_%s_init();\n", cmodule); - Printf(f_pm,"%s",pragma_include); - Printf(f_pm,"package %s;\n", realpackage); - Printf(f_pm,"@EXPORT = qw(%s );\n",exported); + Printf(constant_tab,"{0}\n};\n"); + Printv(f_wrappers,constant_tab,NIL); - if (blessed) { + Printf(f_wrappers,"#ifdef __cplusplus\n}\n#endif\n"); - Printv(base, - "\n# ---------- BASE METHODS -------------\n\n", - "package ", realpackage, ";\n\n", - 0); + Printf(f_init,"\t ST(0) = &PL_sv_yes;\n"); + Printf(f_init,"\t XSRETURN(1);\n"); + Printf(f_init,"}\n"); - /* Write out the TIE method */ + /* Finish off tables */ + Printf(variable_tab, "{0}\n};\n"); + Printv(f_wrappers,variable_tab,NIL); - Printv(base, - "sub TIEHASH {\n", - tab4, "my ($classname,$obj) = @_;\n", - tab4, "return bless $obj, $classname;\n", - "}\n\n", - 0); + Printf(command_tab,"{0,0}\n};\n"); + Printv(f_wrappers,command_tab,NIL); - /* Output a CLEAR method. This is just a place-holder, but by providing it we - * can make declarations such as - * %$u = ( x => 2, y=>3, z =>4 ); - * - * Where x,y,z are the members of some C/C++ object. */ - Printf(base,"sub CLEAR { }\n\n"); + Printf(f_pm,"package %s;\n", cmodule); - /* Output default firstkey/nextkey methods */ - - Printf(base, "sub FIRSTKEY { }\n\n"); - Printf(base, "sub NEXTKEY { }\n\n"); - - /* Output a 'this' method */ - - Printv(base, - "sub this {\n", - tab4, "my $ptr = shift;\n", - tab4, "return tied(%$ptr);\n", - "}\n\n", - 0); + if (!is_static) { + Printf(f_pm,"bootstrap %s;\n", fullmodule); + } else { + String *tmp = NewString(fullmodule); + Replaceall(tmp,":","_"); + Printf(f_pm,"boot_%s();\n", tmp); + Delete(tmp); + } + Printf(f_pm,"%s",pragma_include); + Printf(f_pm,"package %s;\n", fullmodule); + Printf(f_pm,"@EXPORT = qw( %s);\n",exported); - Printf(f_pm,"%s",base); + if (blessed) { - /* Emit function stubs for stand-alone functions */ + Printv(base, + "\n# ---------- BASE METHODS -------------\n\n", + "package ", fullmodule, ";\n\n", + NIL); - Printf(f_pm,"\n# ------- FUNCTION WRAPPERS --------\n\n"); - Printf(f_pm,"package %s;\n\n",realpackage); - Printf(f_pm,"%s",func_stubs); + /* Write out the TIE method */ - /* Emit package code for different classes */ + Printv(base, + "sub TIEHASH {\n", + tab4, "my ($classname,$obj) = @_;\n", + tab4, "return bless $obj, $classname;\n", + "}\n\n", + NIL); - Printf(f_pm,"%s",pm); + /* Output a CLEAR method. This is just a place-holder, but by providing it we + * can make declarations such as + * %$u = ( x => 2, y=>3, z =>4 ); + * + * Where x,y,z are the members of some C/C++ object. */ - /* Emit variable stubs */ + Printf(base,"sub CLEAR { }\n\n"); - Printf(f_pm,"\n# ------- VARIABLE STUBS --------\n\n"); - Printf(f_pm,"package %s;\n\n",realpackage); - Printf(f_pm,"%s",var_stubs); - } + /* Output default firstkey/nextkey methods */ - Printf(f_pm,"1;\n"); - fclose(f_pm); - Delete(base); -} + Printf(base, "sub FIRSTKEY { }\n\n"); + Printf(base, "sub NEXTKEY { }\n\n"); -/* ----------------------------------------------------------------------------- - * get_pointer() - * ----------------------------------------------------------------------------- */ -static void -get_pointer(char *iname, char *srcname, char *src, char *dest, - SwigType *t, String *f, char *ret) { + /* Output a 'this' method */ - SwigType_remember(t); - SwigType *lt = Swig_clocal_type(t); - Printv(f, "if (SWIG_ConvertPtr(", src, ",(void **) &", dest, ",", 0); + Printv(base, + "sub this {\n", + tab4, "my $ptr = shift;\n", + tab4, "return tied(%$ptr);\n", + "}\n\n", + NIL); - /* If we're passing a void pointer, we give the pointer conversion a NULL - pointer, otherwise pass in the expected type. */ + Printf(f_pm,"%s",base); - if (Cmp(lt,"p.void") == 0) { - Printf(f, " 0 ) < 0) {\n"); - } else { - Printv(f, "SWIGTYPE", SwigType_manglestr(t), ") < 0) {\n",0); - } + /* Emit function stubs for stand-alone functions */ - Printv(f, - "croak(\"Type error in ", srcname, " of ", iname,". Expected %s\", SWIGTYPE", - SwigType_manglestr(t), "->name);\n", - ret, ";\n", - "}\n", - 0); - Delete(lt); -} + Printf(f_pm,"\n# ------- FUNCTION WRAPPERS --------\n\n"); + Printf(f_pm,"package %s;\n\n",fullmodule); + Printf(f_pm,"%s",func_stubs); -/* ----------------------------------------------------------------------------- - * PERL5::create_command() - * ----------------------------------------------------------------------------- */ -void -PERL5::create_command(String *cname, String *iname) { - Printf(f_init,"\t newXS(\"%s::%s\", %s, file);\n", package, iname, Swig_name_wrapper(cname)); - if (export_all) { - Printf(exported,"%s ",iname); - } -} + /* Emit package code for different classes */ + Printf(f_pm,"%s",pm); -/* ----------------------------------------------------------------------------- - * PERL5::create_function() - * ----------------------------------------------------------------------------- */ -void -PERL5::function(DOH *node) -{ - char *name, *iname; - SwigType *d; - ParmList *l; - Parm *p; - int pcount,i,j; - Wrapper *f; - char source[256],target[256],temp[256], argnum[32]; - char *tm; - String *cleanup, *outarg; - int numopt = 0; - int need_save, num_saved = 0; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - d = Getattr(node,"type"); - l = Getattr(node,"parms"); - - f = NewWrapper(); - cleanup = NewString(""); - outarg = NewString(""); - - Printv(f, "XS(", Swig_name_wrapper(iname), ") {\n", 0); - - pcount = emit_args(node, f); - numopt = check_numopt(l); - - Wrapper_add_local(f,"argvi","int argvi = 0"); - - /* Check the number of arguments */ - - Printf(f," if ((items < %d) || (items > %d)) \n", pcount-numopt, ParmList_numarg(l)); - Printf(f," croak(\"Usage: %s\");\n", usage_func(iname,d,l)); - - /* Write code to extract parameters. */ - i = 0; - j = 0; - for (p = l; p; p = Getnext(p)) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - - /* Produce string representation of source and target arguments */ - sprintf(source,"ST(%d)",j); - sprintf(target,"%s", Char(Getlname(p))); - sprintf(argnum,"%d",j+1); - - /* Check to see if this argument is being ignored */ - if (!Getignore(p)) { - /* Check for optional argument */ - if (j>= (pcount-numopt)) - Printf(f," if (items > %d) {\n", j); - - if ((tm = Swig_typemap_lookup((char*)"in",pt,pn,source,target,f))) { - Printf(f,"%s\n",tm); - Replace(f,"$argnum",argnum,DOH_REPLACE_ANY); - Replace(f,"$arg",source,DOH_REPLACE_ANY); - } else { - switch(SwigType_type(pt)) { - case T_BOOL: - case T_INT : - case T_SHORT : - case T_LONG : - case T_SCHAR: - case T_UINT: - case T_USHORT: - case T_ULONG: - case T_UCHAR: - Printf(f," %s = (%s)SvIV(ST(%d));\n", target, SwigType_lstr(pt,0),j); - break; - case T_CHAR : - - Printf(f," %s = (char) *SvPV(ST(%d),PL_na);\n", target, j); - break; - - case T_DOUBLE : - case T_FLOAT : - Printf(f," %s = (%s)SvNV(ST(%d));\n", target, SwigType_lstr(pt,0), j); - break; - - case T_VOID : - break; - - case T_USER: - SwigType_add_pointer(pt); - sprintf(temp,"argument %d", i+1); - get_pointer(iname, temp, source, target, pt, f, (char *)"XSRETURN(1)"); - SwigType_del_pointer(pt); - break; - - case T_STRING: - Printf(f," if (! SvOK((SV*) ST(%d))) { %s = 0; }\n", j, target); - Printf(f," else { %s = (char *) SvPV(ST(%d),PL_na); }\n", target,j); - break; - - case T_POINTER: case T_ARRAY: case T_REFERENCE: - sprintf(temp,"argument %d", i+1); - get_pointer(iname,temp,source,target, pt, f, (char*)"XSRETURN(1)"); - break; - - default : - Printf(stderr,"%s:%d. Unable to use type %s as a function argument.\n",Getfile(node), Getline(node), SwigType_str(pt,0)); - break; - } + if (num_consts > 0) { + /* Emit constant stubs */ + Printf(f_pm,"\n# ------- CONSTANT STUBS -------\n\n"); + Printf(f_pm,"package %s;\n\n",fullmodule); + Printf(f_pm,"%s",const_stubs); } - /* The source is going to be an array of saved values. */ - sprintf(temp,"_saved[%d]",num_saved); - if (j>= (pcount-numopt)) - Printf(f," } \n"); - j++; - } else { - temp[0] = 0; - } - /* Check if there is any constraint code */ - if ((tm = Swig_typemap_lookup((char*)"check",pt,pn,source,target,0))) { - Printf(f,"%s\n", tm); - Replace(f,"$argnum",argnum, DOH_REPLACE_ANY); - } - need_save = 0; + /* Emit variable stubs */ - if ((tm = Swig_typemap_lookup((char*)"freearg",pt,pn,target,temp,0))) { - Printf(cleanup,"%s\n", tm); - Replace(cleanup,"$argnum",argnum,DOH_REPLACE_ANY); - Replace(cleanup,"$arg",temp,DOH_REPLACE_ANY); - need_save = 1; + Printf(f_pm,"\n# ------- VARIABLE STUBS --------\n\n"); + Printf(f_pm,"package %s;\n\n",fullmodule); + Printf(f_pm,"%s",var_stubs); } - if ((tm = Swig_typemap_lookup((char*)"argout",pt,pn,target,(char*)"ST(argvi)",0))) { - String *tempstr = NewString(tm); - Replace(tempstr,"$argnum",argnum, DOH_REPLACE_ANY); - Replace(tempstr,"$arg",temp, DOH_REPLACE_ANY); - Printf(outarg,"%s\n", tempstr); - Delete(tempstr); - need_save = 1; - } - /* If we need a saved variable, we need to emit to emit some code for that - This only applies if the argument actually existed (not ignore) */ - if ((need_save) && (!Getignore(p))) { - Printv(f, tab4, temp, " = ", source, ";\n", 0); - num_saved++; - } - i++; - } - /* If there were any saved arguments, emit a local variable for them */ - if (num_saved) { - sprintf(temp,"_saved[%d]",num_saved); - Wrapper_add_localv(f,"_saved","SV *",temp,0); + Printf(f_pm,"1;\n"); + Close(f_pm); + Delete(f_pm); + Delete(base); + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; } - /* Now write code to make the function call */ - - emit_func_call(node,f); - - if ((tm = Swig_typemap_lookup((char*)"out",d,iname,(char*)"result",(char*)"ST(argvi)",0))) { - Printf(f, "%s\n", tm); - } else { - if (SwigType_type(d) != T_VOID) { - Printf(f," ST(argvi) = sv_newmortal();\n"); - switch (SwigType_type(d)) { - case T_INT: case T_BOOL: case T_UINT: - case T_SHORT: case T_USHORT: - case T_LONG : case T_ULONG: - case T_SCHAR: case T_UCHAR : - Printf(f," sv_setiv(ST(argvi++),(IV) result);\n"); - break; - case T_DOUBLE : - case T_FLOAT : - Printf(f," sv_setnv(ST(argvi++), (double) result);\n"); - break; - case T_CHAR : - Wrapper_add_local(f,"_ctemp", "char ctemp[2]"); - Printv(f, - tab4, "ctemp[0] = result;\n", - tab4, "ctemp[1] = 0;\n", - tab4, "sv_setpv((SV*)ST(argvi++),ctemp);\n", - 0); - break; - - case T_USER: - SwigType_add_pointer(d); - SwigType_remember(d); - Printv(f, - tab4, "SWIG_MakePtr(ST(argvi++), (void *) result, SWIGTYPE", SwigType_manglestr(d),");\n", 0); - SwigType_del_pointer(d); - break; - - case T_STRING: - Printf(f," sv_setpv((SV*)ST(argvi++),(char *) result);\n"); - break; - - case T_POINTER: case T_ARRAY: case T_REFERENCE: - SwigType_remember(d); - Printv(f, tab4, "SWIG_MakePtr(ST(argvi++), (void *) result, SWIGTYPE", SwigType_manglestr(d), ");\n", 0); - break; - - default : - Printf(stderr,"%s:%d. Unable to use return type %s in function %s.\n", Getfile(node), Getline(node), SwigType_str(d,0), name); - break; + /* ------------------------------------------------------------ + * importDirective(Node *n) + * ------------------------------------------------------------ */ + + virtual int importDirective(Node *n) { + if (blessed) { + String *modname = Getattr(n,"module"); + if (modname) { + Printf(f_pm,"require %s;\n", modname); } } + return Language::importDirective(n); } - /* If there were any output args, take care of them. */ - - Printv(f,outarg,0); - - /* If there was any cleanup, do that. */ + /* ------------------------------------------------------------ + * functionWrapper() + * ------------------------------------------------------------ */ + + virtual int functionWrapper(Node *n) { + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *overname = 0; + + Parm *p; + int i; + Wrapper *f; + char source[256],target[256],temp[256]; + String *tm; + String *cleanup, *outarg; + int num_saved = 0; + int num_arguments, num_required; + int varargs = 0; + + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; + } - Printv(f,cleanup,0); + f = NewWrapper(); + cleanup = NewString(""); + outarg = NewString(""); - if (NewObject) { - if ((tm = Swig_typemap_lookup((char*)"newfree",d,iname,(char*)"result",(char*)"",0))) { - Printf(f,"%s\n",tm); + String *wname = Swig_name_wrapper(iname); + if (overname) { + Append(wname,overname); } - } + Setattr(n,"wrap:name",wname); + Printv(f->def, "XS(", wname, ") {\n", NIL); + Printv(f->def, "char _swigmsg[SWIG_MAX_ERRMSG] = \"\";\n", NIL); + Printv(f->def, "const char *_swigerr = _swigmsg;\n","{\n",NIL); - if ((tm = Swig_typemap_lookup((char*)"ret",d,iname,(char*)"result",(char*)"",0))) { - Printf(f,"%s\n", tm); - } - - Printf(f," XSRETURN(argvi);\n}\n"); + emit_args(d, l, f); + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); - /* Add the dXSARGS last */ + num_arguments = emit_num_arguments(l); + num_required = emit_num_required(l); + varargs = emit_isvarargs(l); - Wrapper_add_local(f,"dXSARGS","dXSARGS"); + Wrapper_add_local(f,"argvi","int argvi = 0"); - /* Substitute the cleanup code */ - Replace(f,"$cleanup",cleanup,DOH_REPLACE_ANY); - Replace(f,"$name",iname,DOH_REPLACE_ANY); + /* Check the number of arguments */ + if (!varargs) { + Printf(f->code," if ((items < %d) || (items > %d)) {\n", num_required, num_arguments); + } else { + Printf(f->code," if (items < %d) {\n", num_required); + } + Printf(f->code," SWIG_croak(\"Usage: %s\");\n", usage_func(Char(iname),d,l)); + Printf(f->code,"}\n"); - /* Dump the wrapper function */ + /* Write code to extract parameters. */ + i = 0; + for (i = 0, p = l; i < num_arguments; i++) { + + /* Skip ignored arguments */ + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } - Printf(f_wrappers,"%s", f); + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); - /* Now register the function */ + /* Produce string representation of source and target arguments */ + sprintf(source,"ST(%d)",i); + sprintf(target,"%s", Char(ln)); - Printf(f_init,"\t newXS(\"%s::%s\", %s, file);\n", package, iname, Swig_name_wrapper(iname)); + if (i >= num_required) { + Printf(f->code," if (items > %d) {\n", i); + } + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$target",target); + Replaceall(tm,"$source",source); + Replaceall(tm,"$input", source); + Setattr(p,"emit:input",source); /* Save input location */ + Printf(f->code,"%s\n",tm); + p = Getattr(p,"tmap:in:next"); + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument.\n",SwigType_str(pt,0)); + p = nextSibling(p); + } + if (i >= num_required) { + Printf(f->code," }\n"); + } + } - if (export_all) { - Printf(exported,"%s ", iname); - } + if (varargs) { + if (p && (tm = Getattr(p,"tmap:in"))) { + sprintf(source,"ST(%d)",i); + Replaceall(tm,"$input", source); + Setattr(p,"emit:input", source); + Printf(f->code,"if (items >= %d) {\n", i); + Printv(f->code, tm, "\n", NIL); + Printf(f->code,"}\n"); + } + } + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert cleanup code */ + for (i = 0, p = l; p; i++) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } - /* -------------------------------------------------------------------- - * Create a stub for this function, provided it's not a member function - * - * Really we only need to create a stub if this function involves - * complex datatypes. If it does, we'll make a small wrapper to - * process the arguments. If it doesn't, we'll just make a symbol - * table entry. - * -------------------------------------------------------------------- */ - - if ((blessed) && (!member_func)) { - int need_stub = 0; - String *func = NewString(""); - - /* We'll make a stub since we may need it anyways */ - - Printv(func, "sub ", iname, " {\n", - tab4, "my @args = @_;\n", - 0); - - /* Now we have to go through and patch up the argument list. If any - * arguments to our function correspond to other Perl objects, we - * need to extract them from a tied-hash table object.*/ - - Parm *p = l; - int i = 0; - while(p) { - SwigType *pt = Gettype(p); - - if (!Getignore(p)) { - /* Look up the datatype name here */ - char sourceNtarget[256]; - sprintf(sourceNtarget,"$args[%d]",i); - - if ((tm = Swig_typemap_lookup((char*)"perl5in",pt,(char*)"",sourceNtarget,sourceNtarget,0))) { - Printf(func,"%s\n", tm); - } else if (is_shadow(pt)) { - /* - if (i >= (pcount - numopt)) - Printf(func," if (scalar(@args) >= %d) {\n ", i); - Printf(func," $args[%d] = tied(%%{$args[%d]});\n", i, i); - if (i >= (pcount - numopt)) - Printf(func," }\n"); - need_stub = 1; - */ + /* Insert argument output code */ + num_saved = 0; + for (i=0,p = l; p;i++) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","ST(argvi)"); + Replaceall(tm,"$result","ST(argvi)"); + String *in = Getattr(p,"emit:input"); + if (in) { + sprintf(temp,"_saved[%d]", num_saved); + Replaceall(tm,"$arg",temp); + Replaceall(tm,"$input",temp); + Printf(f->code,"_saved[%d] = %s;\n", num_saved, in); + num_saved++; } - i++; + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); } - p = Getnext(p); } - Printv(func, tab4, "my $result = ", package, "::", iname, "(@args);\n", 0); + /* If there were any saved arguments, emit a local variable for them */ + if (num_saved) { + sprintf(temp,"_saved[%d]",num_saved); + Wrapper_add_localv(f,"_saved","SV *",temp,NIL); + } - /* Now check to see what kind of return result was found. - * If this function is returning a result by 'value', SWIG did an - * implicit malloc/new. We'll mark the object like it was created - * in Perl so we can garbage collect it. */ + /* Now write code to make the function call */ - if ((tm = Swig_typemap_lookup((char*)"perl5out",d,(char*)"",name,(char*)"sv",0))) { - Printv(func, - tm, "\n", - tab4, "return $result;\n", - "}\n", - 0); - need_stub = 1; - } else if (is_shadow(d)) { - Printv(func, tab4, "return undef if (!defined($result));\n", 0); - - /* If we're returning an object by value, put it's reference - into our local hash table */ - - if ((!SwigType_ispointer(d)) || NewObject) { - Printv(func, tab4, "$", is_shadow(d), "::OWNER{$result} = 1;\n", 0); - } + emit_action(n,f); - /* We're returning a Perl "object" of some kind. Turn it into a tied hash */ + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","ST(argvi)"); + Replaceall(tm,"$result", "ST(argvi)"); + Printf(f->code, "%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s in function %s.\n", SwigType_str(d,0), name); + } - Printv(func, - tab4, "my %resulthash;\n", - tab4, "tie %resulthash, ref($result), $result;\n", - tab4, "return bless \\%resulthash, ref($result);\n", - "}\n", - 0); + /* If there were any output args, take care of them. */ - need_stub = 1; - } else { + Printv(f->code,outarg,NIL); - /* Hmmm. This doesn't appear to be anything I know about */ - Printv(func, tab4, "return $result;\n", "}\n", 0); - } + /* If there was any cleanup, do that. */ - /* Now check if we needed the stub. If so, emit it, otherwise - * Emit code to hack Perl's symbol table instead */ + Printv(f->code,cleanup,NIL); - if (need_stub) { - Printf(func_stubs,"%s",func); - } else { - Printv(func_stubs,"*", iname, " = *", package, "::", iname, ";\n", 0); + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } } - Delete(func); - } - Delete(cleanup); - Delete(outarg); - Delete(f); -} -/* ----------------------------------------------------------------------------- - * PERL5::link_variable() - * ----------------------------------------------------------------------------- */ + if ((tm = Swig_typemap_lookup_new("ret",n,"result", 0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n", tm); + } -void PERL5::variable(DOH *node) { - char *name, *iname; - SwigType *t; + Printf(f->code," XSRETURN(argvi);\n"); + Printf(f->code,"fail:\n"); + Printv(f->code,cleanup,NIL); + Printv(f->code,"(void) _swigerr;\n", NIL); + Printv(f->code,"}\n",NIL); + Printv(f->code,"croak(_swigerr);\n", NIL); + Printv(f->code,"}\n",NIL); - char set_name[256]; - char val_name[256]; - Wrapper *getf, *setf; - char *tm; - int setable = 1; + /* Add the dXSARGS last */ - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); + Wrapper_add_local(f,"dXSARGS","dXSARGS"); - sprintf(set_name,"_wrap_set_%s",iname); - sprintf(val_name,"_wrap_val_%s",iname); + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); + Replaceall(f->code,"$symname",iname); - getf = NewWrapper(); - setf = NewWrapper(); + /* Dump the wrapper function */ - /* Create a new scalar that we will attach magic to */ + Wrapper_print(f,f_wrappers); + + /* Now register the function */ + + if (!Getattr(n,"sym:overloaded")) { + Printf(command_tab,"{\"%s::%s\", %s},\n", cmodule, iname, wname); + } else if (!Getattr(n,"sym:nextSibling")) { + /* Generate overloaded dispatch function */ + int maxargs, ii; + String *dispatch = Swig_overload_dispatch(n,"(*PL_markstack_ptr++);SWIG_CALLXS(%s); return;",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + + Printv(df->def, + "XS(", dname, ") {\n", NIL); + + Wrapper_add_local(df,"dXSARGS", "dXSARGS"); + Replaceid(dispatch,"argc","items"); + for (ii = 0; ii < maxargs; ii++) { + char pat[128]; + char rep[128]; + sprintf(pat,"argv[%d]",ii); + sprintf(rep,"ST(%d)",ii); + Replaceall(dispatch,pat,rep); + } + Printv(df->code,dispatch,"\n",NIL); + Printf(df->code,"croak(\"No matching function for overloaded '%s'\");\n", iname); + Printf(df->code,"XSRETURN(0);\n"); + Printv(df->code,"}\n",NIL); + Wrapper_print(df,f_wrappers); + Printf(command_tab,"{\"%s::%s\", %s},\n", cmodule, iname, dname); + DelWrapper(df); + Delete(dispatch); + Delete(dname); + } + if (!Getattr(n,"sym:nextSibling")) { + if (export_all) { + Printf(exported,"%s ", iname); + } + + /* -------------------------------------------------------------------- + * Create a stub for this function, provided it's not a member function + * -------------------------------------------------------------------- */ + + if ((blessed) && (!member_func)) { + int need_stub = 0; + String *func = NewString(""); + + /* We'll make a stub since we may need it anyways */ + + Printv(func, "sub ", iname, " {\n", + tab4, "my @args = @_;\n", + NIL); + + Printv(func, tab4, "my $result = ", cmodule, "::", iname, "(@args);\n", NIL); + + /* Now check to see what kind of return result was found. + * If this function is returning a result by 'value', SWIG did an + * implicit malloc/new. We'll mark the object like it was created + * in Perl so we can garbage collect it. */ + + if (is_shadow(d)) { + Printv(func, tab4, "return undef if (!defined($result));\n", NIL); + + /* If we're returning an object by value, put it's reference + into our local hash table */ + + if ((!SwigType_ispointer(d) && !SwigType_isreference(d)) || Getattr(n,"feature:new")) { + Printv(func, tab4, "$", is_shadow(d), "::OWNER{$result} = 1;\n", NIL); + } + + /* We're returning a Perl "object" of some kind. Turn it into a tied hash */ + Printv(func, + tab4, "my %resulthash;\n", + tab4, "tie %resulthash, ref($result), $result;\n", + tab4, "return bless \\%resulthash, ref($result);\n", + "}\n", + NIL); + + need_stub = 1; + } else { + /* Hmmm. This doesn't appear to be anything I know about */ + Printv(func, tab4, "return $result;\n", "}\n", NIL); + } + + /* Now check if we needed the stub. If so, emit it, otherwise + * Emit code to hack Perl's symbol table instead */ + + if (need_stub) { + Printf(func_stubs,"%s",func); + } else { + Printv(func_stubs,"*", iname, " = *", cmodule, "::", iname, ";\n", NIL); + } + Delete(func); + } + } + Delete(cleanup); + Delete(outarg); + DelWrapper(f); + return SWIG_OK; + } - Printv(vinit, tab4, "sv = perl_get_sv(\"", package, "::", iname, "\",TRUE | 0x2);\n", 0); + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + Wrapper *getf, *setf; + String *tm; + + String *set_name = NewStringf("_wrap_set_%s", iname); + String *val_name = NewStringf("_wrap_val_%s", iname); + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + getf = NewWrapper(); + setf = NewWrapper(); + + /* Create a Perl function for setting the variable value */ + + if (!Getattr(n,"feature:immutable")) { + Printf(setf->def,"SWIGCLASS_STATIC int %s(pTHX_ SV* sv, MAGIC *mg) {\n", set_name); + Printv(setf->code, + tab4, "MAGIC_PPERL\n", + tab4, "mg = mg;\n", + NIL); + + /* Check for a few typemaps */ + tm = Swig_typemap_lookup_new("varin",n,name,0); + if (tm) { + Replaceall(tm,"$source","sv"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","sv"); + Printf(setf->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, + "Unable to link with datatype %s (ignored).\n", SwigType_str(t,0)); + return SWIG_NOWRAP; + } + Printf(setf->code," return 1;\n}\n"); + Replaceall(setf->code,"$symname",iname); + Wrapper_print(setf,magic); + } - /* Create a Perl function for setting the variable value */ + /* Now write a function to evaluate the variable */ - if (!ReadOnly) { - Printf(setf,"SWIGCLASS_STATIC int %s(SV* sv, MAGIC *mg) {\n", set_name); - Printv(setf, + Printf(getf->def,"SWIGCLASS_STATIC int %s(pTHX_ SV *sv, MAGIC *mg) {\n", val_name); + Printv(getf->code, tab4, "MAGIC_PPERL\n", tab4, "mg = mg;\n", - 0); + NIL); - /* Check for a few typemaps */ - if ((tm = Swig_typemap_lookup((char*)"varin",t,(char*)"",(char*)"sv",name,0))) { - Printf(setf,"%s\n", tm); - } else if ((tm = Swig_typemap_lookup((char*)"in",t,(char*)"",(char*)"sv",name,0))) { - Printf(setf,"%s\n", tm); + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$target","sv"); + Replaceall(tm,"$result","sv"); + Replaceall(tm,"$source",name); + Printf(getf->code,"%s\n", tm); } else { - switch(SwigType_type(t)) { - case T_INT : case T_BOOL: case T_UINT: - case T_SHORT : case T_USHORT: - case T_LONG : case T_ULONG: - case T_UCHAR: case T_SCHAR: - Printv(setf,tab4, name, " = (", SwigType_str(t,0), ") SvIV(sv);\n", 0); - break; - case T_DOUBLE : - case T_FLOAT : - Printv(setf, tab4, name, " = (", SwigType_str(t,0), ") SvNV(sv);\n", 0); - break; - case T_CHAR : - Printv(setf, tab4, name, " = (char) *SvPV(sv,PL_na);\n", 0); - break; - - case T_USER: - - SwigType_add_pointer(t); - Wrapper_add_local(setf,"_temp", "void *_temp"); - get_pointer(iname,(char*)"value",(char*)"sv",(char*)"_temp", t, setf, (char*)"return(1)"); - Printv(setf, tab4, name, " = *((", SwigType_str(t,0), ") _temp);\n", 0); - SwigType_del_pointer(t); - break; - - case T_STRING: - Wrapper_add_local(setf,"_a","char *_a"); - Printf(setf," _a = (char *) SvPV(sv,PL_na);\n"); - - if (CPlusPlus) - Printv(setf, - tab4, "if (", name, ") delete [] ", name, ";\n", - tab4, name, " = new char[strlen(_a)+1];\n", - 0); - else - Printv(setf, - tab4, "if (", name, ") free((char*)", name, ");\n", - tab4, name, " = (char *) malloc(strlen(_a)+1);\n", - 0); - Printv(setf,"strcpy((char*)", name, ",_a);\n", 0); - break; - - case T_ARRAY: - { - SwigType *aop; - SwigType *ta = Copy(t); - aop = SwigType_pop(ta); - if (SwigType_type(ta) == T_CHAR) { - String *dim = SwigType_array_getdim(aop,0); - if (dim && Len(dim)) { - Printf(setf, "strncpy(%s,(char*) SvPV(sv,PL_na), %s);\n", name,dim); - setable = 1; - } else { - setable = 0; - } - } else { - setable = 0; - } - Delete(ta); - Delete(aop); - } - break; + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to link with datatype %s (ignored).\n", SwigType_str(t,0)); + return SWIG_NOWRAP; + } + Printf(getf->code," return 1;\n}\n"); - case T_POINTER: case T_REFERENCE: - Wrapper_add_local(setf,"_temp","void *_temp"); - get_pointer(iname,(char*)"value",(char*)"sv",(char*)"_temp", t, setf, (char*)"return(1)"); - Printv(setf,tab4, name, " = (", SwigType_str(t,0), ") _temp;\n", 0); - break; + Replaceall(getf->code,"$symname",iname); + Wrapper_print(getf,magic); - default : - Printf(stderr,"%s:%d. Unable to link with datatype %s (ignored).\n", Getfile(node), Getline(node), SwigType_str(t,0)); - return; + String *tt = Getattr(n,"tmap:varout:type"); + if (tt) { + String *tm = NewStringf("&SWIGTYPE%s", SwigType_manglestr(t)); + if (Replaceall(tt,"$1_descriptor", tm)) { + SwigType_remember(t); + } + Delete(tm); + SwigType *st = Copy(t); + SwigType_add_pointer(st); + tm = NewStringf("&SWIGTYPE%s", SwigType_manglestr(st)); + if (Replaceall(tt,"$&1_descriptor", tm)) { + SwigType_remember(st); } + Delete(tm); + Delete(st); + } else { + tt = (String *) "0"; } - Printf(setf," return 1;\n}\n"); - Replace(setf,"$name",iname, DOH_REPLACE_ANY); - Printf(magic,"%s", setf); + /* Now add symbol to the PERL interpreter */ + if (Getattr(n,"feature:immutable")) { + Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS swig_magic_readonly, MAGIC_CLASS ", val_name,",", tt, " },\n",NIL); - } - - /* Now write a function to evaluate the variable */ - - Printf(getf,"SWIGCLASS_STATIC int %s(SV *sv, MAGIC *mg) {\n", val_name); - Printv(getf, - tab4, "MAGIC_PPERL\n", - tab4, "mg = mg;\n", - 0); - - if ((tm = Swig_typemap_lookup((char*)"varout",t,(char*)"",name, (char*)"sv",0))) { - Printf(getf,"%s\n", tm); - } else if ((tm = Swig_typemap_lookup((char*)"out",t,(char*)"",name,(char*)"sv",0))) { - Printf(getf,"%s\n", tm); - } else { - switch(SwigType_type(t)) { - - case T_INT : case T_BOOL: case T_UINT: - case T_SHORT : case T_USHORT: - case T_LONG : case T_ULONG: - case T_UCHAR: case T_SCHAR: - Printv(getf,tab4, "sv_setiv(sv, (IV) ", name, ");\n", 0); - Printv(vinit, tab4, "sv_setiv(sv,(IV)", name, ");\n",0); - break; - case T_DOUBLE : - case T_FLOAT : - Printv(getf, tab4,"sv_setnv(sv, (double) ", name, ");\n", 0); - Printv(vinit, tab4, "sv_setnv(sv,(double)", name, ");\n",0); - break; - case T_CHAR : - Wrapper_add_local(getf,"_ptemp","char _ptemp[2]"); - Printv(getf, - tab4, "_ptemp[0] = ", name, ";\n", - tab4, "_ptemp[1] = 0;\n", - tab4, "sv_setpv((SV*) sv, _ptemp);\n", - 0); - break; - case T_USER: - SwigType_add_pointer(t); - Printv(getf, - tab4, "rsv = SvRV(sv);\n", - tab4, "sv_setiv(rsv,(IV) &", name, ");\n", - 0); - - Wrapper_add_local(getf,"rsv","SV *rsv"); - Printv(vinit, tab4, "SWIG_MakePtr(sv, (void *) &", name, ",SWIGTYPE", SwigType_manglestr(t), ");\n",0); - SwigType_del_pointer(t); - - break; - - case T_STRING: - Printv(getf, tab4, "sv_setpv((SV*) sv, ", name, ");\n", 0); - break; - - case T_ARRAY: - { - SwigType *aop; - SwigType *ta = Copy(t); - aop = SwigType_pop(ta); - if (SwigType_type(ta) == T_CHAR) { - Printv(getf, "sv_setpv((SV*)sv, ", name, ");\n", 0); - Delete(ta); - Delete(aop); - break; - } - Delete(ta); - Delete(aop); - } - /* No break here is intentional */ - case T_POINTER: case T_REFERENCE: - Printv(getf, - tab4, "rsv = SvRV(sv);\n", - tab4, "sv_setiv(rsv,(IV) ", name, ");\n", - 0); - - Wrapper_add_local(getf,"rsv","SV *rsv"); - Printv(vinit, tab4, "SWIG_MakePtr(sv,(void *) 1, SWIGTYPE", SwigType_manglestr(t), ");\n",0); - break; - - default : - break; + } else { + Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS ", set_name, ", MAGIC_CLASS ", val_name, ",", tt, " },\n",NIL); } - } - Printf(getf," return 1;\n}\n"); - Replace(getf,"$name",iname, DOH_REPLACE_ANY); - Printf(magic,"%s", getf); - - /* Now add symbol to the PERL interpreter */ - if ((ReadOnly) || (!setable)) { - Printv(vinit, tab4, "swig_create_magic(sv,\"", package, "::", iname, "\",MAGIC_CAST MAGIC_CLASS swig_magic_readonly, MAGIC_CAST MAGIC_CLASS ", val_name, ");\n",0); - } else { - Printv(vinit, tab4, "swig_create_magic(sv,\"", package, "::", iname, "\", MAGIC_CAST MAGIC_CLASS ", set_name, ", MAGIC_CAST MAGIC_CLASS ", val_name, ");\n",0); - } - - /* If we're blessed, try to figure out what to do with the variable + /* If we're blessed, try to figure out what to do with the variable 1. If it's a Perl object of some sort, create a tied-hash around it. 2. Otherwise, just hack Perl's symbol table */ - if (blessed) { - if (is_shadow(t)) { - Printv(var_stubs, - "\nmy %__", iname, "_hash;\n", - "tie %__", iname, "_hash,\"", is_shadow(t), "\", $", - package, "::", iname, ";\n", - "$", iname, "= \\%__", iname, "_hash;\n", - "bless $", iname, ", ", is_shadow(t), ";\n", - 0); - } else { - Printv(var_stubs, "*", iname, " = *", package, "::", iname, ";\n", 0); + if (blessed) { + if (is_shadow(t)) { + Printv(var_stubs, + "\nmy %__", iname, "_hash;\n", + "tie %__", iname, "_hash,\"", is_shadow(t), "\", $", + cmodule, "::", iname, ";\n", + "$", iname, "= \\%__", iname, "_hash;\n", + "bless $", iname, ", ", is_shadow(t), ";\n", + NIL); + } else { + Printv(var_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL); + } } if (export_all) - Printf(exported,"$%s ", name); + Printf(exported,"$%s ", iname); + + DelWrapper(setf); + DelWrapper(getf); + Delete(set_name); + Delete(val_name); + return SWIG_OK; } - Delete(setf); - Delete(getf); -} -/* ----------------------------------------------------------------------------- - * PERL5::constant() - * ----------------------------------------------------------------------------- */ + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ -/* Functions used to create constants */ - -static const char *setiv = "#ifndef PERL_OBJECT\ -\n#define swig_setiv(a,b) _swig_setiv(a,b)\ -\nstatic void _swig_setiv(char *name, long value) { \ -\n#else\ -\n#define swig_setiv(a,b) _swig_setiv(pPerl,a,b)\ -\nstatic void _swig_setiv(CPerlObj *pPerl, char *name, long value) { \ -\n#endif\ -\n SV *sv; \ -\n sv = perl_get_sv(name,TRUE | 0x2);\ -\n sv_setiv(sv, (IV) value);\ -\n SvREADONLY_on(sv);\ -\n}\n"; - -static const char *setnv = "#ifndef PERL_OBJECT\ -\n#define swig_setnv(a,b) _swig_setnv(a,b)\ -\nstatic void _swig_setnv(char *name, double value) { \ -\n#else\ -\n#define swig_setnv(a,b) _swig_setnv(pPerl,a,b)\ -\nstatic void _swig_setnv(CPerlObj *pPerl, char *name, double value) { \ -\n#endif\ -\n SV *sv; \ -\n sv = perl_get_sv(name,TRUE | 0x2);\ -\n sv_setnv(sv, value);\ -\n SvREADONLY_on(sv);\ -\n}\n"; - -static const char *setpv = "#ifndef PERL_OBJECT\ -\n#define swig_setpv(a,b) _swig_setpv(a,b)\ -\nstatic void _swig_setpv(char *name, char *value) { \ -\n#else\ -\n#define swig_setpv(a,b) _swig_setpv(pPerl,a,b)\ -\nstatic void _swig_setpv(CPerlObj *pPerl, char *name, char *value) { \ -\n#endif\ -\n SV *sv; \ -\n sv = perl_get_sv(name,TRUE | 0x2);\ -\n sv_setpv(sv, value);\ -\n SvREADONLY_on(sv);\ -\n}\n"; - -static const char *setrv = "#ifndef PERL_OBJECT\ -\n#define swig_setrv(a,b,c) _swig_setrv(a,b,c)\ -\nstatic void _swig_setrv(char *name, void *value, char *type) { \ -\n#else\ -\n#define swig_setrv(a,b,c) _swig_setrv(pPerl,a,b,c)\ -\nstatic void _swig_setrv(CPerlObj *pPerl, char *name, void *value, char *type) { \ -\n#endif\ -\n SV *sv; \ -\n sv = perl_get_sv(name,TRUE | 0x2);\ -\n sv_setref_pv(sv, type, value);\ -\n SvREADONLY_on(sv);\ -\n}\n"; - -void -PERL5::constant(DOH *node) - { - char *name; - SwigType *type; - char *value; - char *tm; - static int have_int_func = 0; - static int have_double_func = 0; - static int have_char_func = 0; - static int have_ref_func = 0; - - name = GetChar(node,"name"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - - if ((tm = Swig_typemap_lookup((char*)"const",type,name,value,name,0))) { - Printf(f_init,"%s\n",tm); - } else { - switch(SwigType_type(type)) { - case T_INT: case T_UINT: case T_BOOL: - case T_SHORT: case T_USHORT: - case T_LONG: case T_ULONG: - case T_SCHAR: case T_UCHAR: - if (!have_int_func) { - Printf(f_header,"%s\n",setiv); - have_int_func = 1; - } - Printv(vinit, tab4, "swig_setiv(\"", package, "::", name, "\", (long) ", value, ");\n",0); - break; - case T_DOUBLE: - case T_FLOAT: - if (!have_double_func) { - Printf(f_header,"%s\n",setnv); - have_double_func = 1; - } - Printv(vinit, tab4, "swig_setnv(\"", package, "::", name, "\", (double) (", value, "));\n",0); - break; - case T_CHAR : - if (!have_char_func) { - Printf(f_header,"%s\n",setpv); - have_char_func = 1; - } - Printf(vinit," swig_setpv(\"%s::%s\",\"%s\");\n", package, name, value); + virtual int constantWrapper(Node *n) { + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + String *tm; - break; - case T_STRING: - if (!have_char_func) { - Printf(f_header,"%s\n",setpv); - have_char_func = 1; - } - Printf(vinit," swig_setpv(\"%s::%s\",\"%s\");\n", package, name, value); - break; - - case T_POINTER: case T_ARRAY: case T_REFERENCE: - if (!have_ref_func) { - Printf(f_header,"%s\n",setrv); - have_ref_func = 1; - } - Printv(vinit, tab4, "swig_setrv(\"", package, "::", name, "\", (void *) ", value, ", \"", - SwigType_manglestr(type), "\");\n", 0); - break; + if (!addSymbol(iname,n)) return SWIG_ERROR; - default: - Printf(stderr,"%s:%d. Unsupported constant value.\n", Getfile(node), Getline(node)); - break; + /* Special hook for member pointer */ + if (SwigType_type(type) == T_MPOINTER) { + String *wname = Swig_name_wrapper(iname); + Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type,wname), value); + value = Char(wname); } - } - if (blessed) { - if (is_shadow(type)) { - Printv(var_stubs, - "\nmy %__", name, "_hash;\n", - "tie %__", name, "_hash,\"", is_shadow(type), "\", $", - package, "::", name, ";\n", - "$", name, "= \\%__", name, "_hash;\n", - "bless $", name, ", ", is_shadow(type), ";\n", - 0); + if ((tm = Swig_typemap_lookup_new("consttab",n,name,0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value",value); + Printf(constant_tab,"%s,\n", tm); + } else if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) { + Replaceall(tm,"$source", value); + Replaceall(tm,"$target", name); + Replaceall(tm,"$value",value); + Printf(f_init, "%s\n", tm); } else { - Printv(var_stubs, "*",name," = *", package, "::", name, ";\n", 0); + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value.\n"); + return SWIG_NOWRAP; } + + if (blessed) { + if (is_shadow(type)) { + Printv(var_stubs, + "\nmy %__", iname, "_hash;\n", + "tie %__", iname, "_hash,\"", is_shadow(type), "\", $", + cmodule, "::", iname, ";\n", + "$", iname, "= \\%__", iname, "_hash;\n", + "bless $", iname, ", ", is_shadow(type), ";\n", + NIL); + } else if (do_constants) { + Printv(const_stubs,"sub ", name, " () { $", + cmodule, "::", name, " }\n", NIL); + num_consts++; + } else { + Printv(var_stubs, "*",iname," = *", cmodule, "::", iname, ";\n", NIL); + } + } + if (export_all) { + if (do_constants && !is_shadow(type)) { + Printf(exported,"%s ",name); + } else { + Printf(exported,"$%s ",iname); + } + } + return SWIG_OK; } - if (export_all) - Printf(exported,"$%s ",name); -} -/* ----------------------------------------------------------------------------- - * PERL5::usage_func() - * ----------------------------------------------------------------------------- */ -char * -PERL5::usage_func(char *iname, SwigType *, ParmList *l) { - static String *temp = 0; - Parm *p; - int i; - - if (!temp) temp = NewString(""); - Clear(temp); - Printf(temp,"%s(",iname); - - /* Now go through and print parameters */ - p = l; - i = 0; - while (p != 0) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - if (!Getignore(p)) { - /* If parameter has been named, use that. Otherwise, just print a type */ - if (SwigType_type(pt) != T_VOID) { - if (Len(pn) > 0) { - Printf(temp,"%s",pn); - } else { - Printf(temp,"%s",SwigType_str(pt,0)); + /* ------------------------------------------------------------ + * usage_func() + * ------------------------------------------------------------ */ + char *usage_func(char *iname, SwigType *, ParmList *l) { + static String *temp = 0; + Parm *p; + int i; + + if (!temp) temp = NewString(""); + Clear(temp); + Printf(temp,"%s(",iname); + + /* Now go through and print parameters */ + p = l; + i = 0; + while (p != 0) { + SwigType *pt = Getattr(p,"type"); + String *pn = Getattr(p,"name"); + if (!Getattr(p,"ignore")) { + /* If parameter has been named, use that. Otherwise, just print a type */ + if (SwigType_type(pt) != T_VOID) { + if (Len(pn) > 0) { + Printf(temp,"%s",pn); + } else { + Printf(temp,"%s",SwigType_str(pt,0)); + } } + i++; + p = nextSibling(p); + if (p) + if (!Getattr(p,"ignore")) + Putc(',',temp); + } else { + p = nextSibling(p); + if (p) + if ((i>0) && (!Getattr(p,"ignore"))) + Putc(',',temp); } - i++; - p = Getnext(p); - if (p) - if (!Getignore(p)) - Putc(',',temp); - } else { - p = Getnext(p); - if (p) - if ((i>0) && (!Getignore(p))) - Putc(',',temp); } + Printf(temp,");"); + return Char(temp); } - Printf(temp,");"); - return Char(temp); -} -/* ----------------------------------------------------------------------------- - * PERL5::nativefunction() - * ----------------------------------------------------------------------------- */ -void -PERL5::nativefunction(DOH *node) { - char *name, *funcname; - name = GetChar(node,"scriptname"); - funcname = GetChar(node,"name"); - Printf(f_init,"\t newXS(\"%s::%s\", %s, file);\n", package,name, funcname); - if (export_all) - Printf(exported,"%s ",name); - if (blessed) { - Printv(func_stubs,"*", name, " = *", package, "::", name, ";\n", 0); - } -} + /* ------------------------------------------------------------ + * nativeWrapper() + * ------------------------------------------------------------ */ + + virtual int nativeWrapper(Node *n) { + String *name = Getattr(n,"sym:name"); + String *funcname = Getattr(n,"wrap:name"); -/**************************************************************************** - *** OBJECT-ORIENTED FEATURES - **************************************************************************** - *** These extensions provide a more object-oriented interface to C++ - *** classes and structures. The code here is based on extensions - *** provided by David Fletcher and Gary Holt. - *** - *** I have generalized these extensions to make them more general purpose - *** and to resolve object-ownership problems. - *** - *** The approach here is very similar to the Python module : - *** 1. All of the original methods are placed into a single - *** package like before except that a 'c' is appended to the - *** package name. - *** - *** 2. All methods and function calls are wrapped with a new - *** perl function. While possibly inefficient this allows - *** us to catch complex function arguments (which are hard to - *** track otherwise). - *** - *** 3. Classes are represented as tied-hashes in a manner similar - *** to Gary Holt's extension. This allows us to access - *** member data. - *** - *** 4. Stand-alone (global) C functions are modified to take - *** tied hashes as arguments for complex datatypes (if - *** appropriate). - *** - *** 5. Global variables involving a class/struct is encapsulated - *** in a tied hash. - *** - *** 6. Object ownership is maintained by having a hash table - *** within in each package called "this". It is unlikely - *** that C++ program will use this so it's a somewhat - *** safe variable name. - *** - ****************************************************************************/ + if (!addSymbol(funcname,n)) return SWIG_ERROR; -/* ----------------------------------------------------------------------------- - * PERL5::cpp_open_class() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_open_class(DOH *node) { + Printf(command_tab,"{\"%s::%s\", %s},\n", cmodule,name,funcname); + if (export_all) + Printf(exported,"%s ",name); + if (blessed) { + Printv(func_stubs,"*", name, " = *", cmodule, "::", name, ";\n", NIL); + } + return SWIG_OK; + } - this->Language::cpp_open_class(node); + /**************************************************************************** + *** OBJECT-ORIENTED FEATURES + **************************************************************************** + *** These extensions provide a more object-oriented interface to C++ + *** classes and structures. The code here is based on extensions + *** provided by David Fletcher and Gary Holt. + *** + *** I have generalized these extensions to make them more general purpose + *** and to resolve object-ownership problems. + *** + *** The approach here is very similar to the Python module : + *** 1. All of the original methods are placed into a single + *** package like before except that a 'c' is appended to the + *** package name. + *** + *** 2. All methods and function calls are wrapped with a new + *** perl function. While possibly inefficient this allows + *** us to catch complex function arguments (which are hard to + *** track otherwise). + *** + *** 3. Classes are represented as tied-hashes in a manner similar + *** to Gary Holt's extension. This allows us to access + *** member data. + *** + *** 4. Stand-alone (global) C functions are modified to take + *** tied hashes as arguments for complex datatypes (if + *** appropriate). + *** + *** 5. Global variables involving a class/struct is encapsulated + *** in a tied hash. + *** + ****************************************************************************/ - char *classname = GetChar(node,"name"); - char *rname = GetChar(node,"scriptname"); - char *ctype = GetChar(node,"classtype"); - - if (blessed) { - have_constructor = 0; - have_destructor = 0; - have_data_members = 0; - - Delete(class_name); class_name = 0; - Delete(class_type); class_type =0; - Delete(real_classname); real_classname = 0; - Delete(base_class); base_class = 0; - Delete(fullclassname); fullclassname = 0; - - /* If the class is being renamed to something else, use the renaming */ - if (rname) { - class_name = NewString(rname); - class_renamed = 1; - } else { - class_name = NewString(classname); - class_renamed = 0; + + void setclassname(Node *n) { + String *symname = Getattr(n,"sym:name"); + String *fullname; + String *actualpackage; + Node *clsmodule = Getattr(n,"module"); + + if (!clsmodule) { + /* imported module does not define a module name. Oh well */ + return; } - /* Use the fully qualified name of the Perl class */ - if (!compat) { - fullclassname = NewStringf("%s::%s",realpackage,class_name); + /* Do some work on the class name */ + actualpackage = Getattr(clsmodule,"name"); + if ((!compat) && (!Strchr(symname,':'))) { + fullname = NewStringf("%s::%s",actualpackage,symname); } else { - fullclassname = NewString(class_name); + fullname = NewString(symname); } - real_classname = NewString(classname); - if (base_class) Delete(base_class); - base_class = 0; - class_type = NewString(ctype); - pcode = NewString(""); - blessedmembers = NewString(""); - member_keys = NewString(""); - - /* Add some symbols to the hash tables */ - Hash *nnode = NewHash(); - Setattr(nnode,"name", classname); - Setattr(nnode,"scriptname", fullclassname); - Setattr(nnode,"classtype", ctype); - cpp_class_decl(nnode); + Setattr(n,"perl5:proxy", fullname); } -} - -/* ----------------------------------------------------------------------------- - * PERL5::cpp_close_class() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_close_class() { - - if (blessed) { - Printv(pm, - "\n############# Class : ", fullclassname, " ##############\n", - "\npackage ", fullclassname, ";\n", - 0); - - /* If we are inheriting from a base class, set that up */ - - if (Cmp(class_name,realpackage)) - Printv(pm, "@ISA = qw( ",realpackage, 0); - else - Printv(pm, "@ISA = qw( ", 0); - - if (base_class) { - Printv(pm, " ", base_class, 0); + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + virtual int classDeclaration(Node *n) { + /* Do some work on the class name */ + if (blessed) { + setclassname(n); + Append(classlist,n); } - Printf(pm, " );\n"); + return Language::classDeclaration(n); + } + + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ - /* Dump out a hash table containing the pointers that we own */ + virtual int classHandler(Node *n) { - Printf(pm, "%%OWNER = ();\n"); - if (have_data_members) { - Printv(pm, - "%BLESSEDMEMBERS = (\n", blessedmembers, ");\n\n", - 0); - } - if (have_data_members || have_destructor) - Printf(pm, "%%ITERATORS = ();\n"); + if (blessed) { + have_constructor = 0; + have_operators = 0; + have_destructor = 0; + have_data_members = 0; + operators = NewHash(); + class_name = Getattr(n,"sym:name"); - /* Dump out the package methods */ + if (!addSymbol(class_name,n)) return SWIG_ERROR; - Printv(pm,pcode,0); - Delete(pcode); - - /* Output methods for managing ownership */ + /* Use the fully qualified name of the Perl class */ + if (!compat) { + fullclassname = NewStringf("%s::%s",fullmodule,class_name); + } else { + fullclassname = NewString(class_name); + } + real_classname = Getattr(n,"name"); + pcode = NewString(""); + blessedmembers = NewString(""); + } - Printv(pm, - "sub DISOWN {\n", - tab4, "my $self = shift;\n", - tab4, "my $ptr = tied(%$self);\n", - tab4, "delete $OWNER{$ptr};\n", - tab4, "};\n\n", - "sub ACQUIRE {\n", - tab4, "my $self = shift;\n", - tab4, "my $ptr = tied(%$self);\n", - tab4, "$OWNER{$ptr} = 1;\n", - tab4, "};\n\n", - 0); + /* Emit all of the members */ + Language::classHandler(n); - /* Only output the following methods if a class has member data */ - if (have_data_members) { + /* Finish the rest of the class */ + if (blessed) { + /* Generate a client-data entry */ + SwigType *ct = NewStringf("p.%s", real_classname); + Printv(f_init,"SWIG_TypeClientData(SWIGTYPE", SwigType_manglestr(ct),", (void*) \"", + fullclassname, "\");\n", NIL); + SwigType_remember(ct); + Delete(ct); - /* Output a FETCH method. This is actually common to all classes */ Printv(pm, - "sub FETCH {\n", - tab4, "my ($self,$field) = @_;\n", - tab4, "my $member_func = \"", package, "::", Swig_name_get(Swig_name_member(class_name,(char*)"${field}")), "\";\n", - tab4, "my $val = &$member_func($self);\n", - tab4, "if (exists $BLESSEDMEMBERS{$field}) {\n", - tab8, "return undef if (!defined($val));\n", - tab8, "my %retval;\n", - tab8, "tie %retval,$BLESSEDMEMBERS{$field},$val;\n", - tab8, "return bless \\%retval, $BLESSEDMEMBERS{$field};\n", - tab4, "}\n", - tab4, "return $val;\n", - "}\n\n", - 0); + "\n############# Class : ", fullclassname, " ##############\n", + "\npackage ", fullclassname, ";\n", + NIL); + + if (have_operators) { + Printf(pm, "use overload\n"); + DOH *key; + for (key = Firstkey(operators); key; key = Nextkey(operators)) { + char *name = Char(key); + // fprintf(stderr,"found name: <%s>\n", name); + if (strstr(name, "operator_equal_to")) { + Printv(pm, tab4, "\"==\" => sub { $_[0]->operator_equal_to($_[1])},\n",NIL); + } else if (strstr(name, "operator_not_equal_to")) { + Printv(pm, tab4, "\"!=\" => sub { $_[0]->operator_not_equal_to($_[1])},\n",NIL); + } else if (strstr(name, "operator_assignment")) { + Printv(pm, tab4, "\"=\" => sub { $_[0]->operator_assignment($_[1])},\n",NIL); + } else { + fprintf(stderr,"Unknown operator: %s\n", name); + } + } + Printv(pm, tab4, "\"fallback\" => 1;\n",NIL); + } + /* If we are inheriting from a base class, set that up */ + + Printv(pm, "@ISA = qw( ",fullmodule, NIL); + + /* Handle inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "perl5:proxy"); + if (!bname) { + base = Nextitem(baselist); + continue; + } + Printv(pm," ", bname, NIL); + base = Nextitem(baselist); + } + } + Printf(pm, " );\n"); + + /* Dump out a hash table containing the pointers that we own */ + Printf(pm, "%%OWNER = ();\n"); + if (have_data_members) { + Printv(pm, + "%BLESSEDMEMBERS = (\n", blessedmembers, ");\n\n", + NIL); + } + if (have_data_members || have_destructor) + Printf(pm, "%%ITERATORS = ();\n"); - /* Output a STORE method. This is also common to all classes (might move to base class) */ + /* Dump out the package methods */ - Printv(pm, - "sub STORE {\n", - tab4, "my ($self,$field,$newval) = @_;\n", - tab4, "my $member_func = \"", package, "::", Swig_name_set(Swig_name_member(class_name,(char*)"${field}")), "\";\n", - tab4, "if (exists $BLESSEDMEMBERS{$field}) {\n", - tab8, "&$member_func($self,tied(%{$newval}));\n", - tab4, "} else {\n", - tab8, "&$member_func($self,$newval);\n", - tab4, "}\n", - "}\n\n", - 0); + Printv(pm,pcode,NIL); + Delete(pcode); - /* Output a FIRSTKEY method. This is to allow iteration over a structure's keys. */ + /* Output methods for managing ownership */ Printv(pm, - "sub FIRSTKEY {\n", + "sub DISOWN {\n", tab4, "my $self = shift;\n", - tab4, "$ITERATORS{$self} = [", member_keys, "];\n", - tab4, "my $first = shift @{$ITERATORS{$self}};\n", - tab4, "return $first;\n", - "}\n\n", - 0); - - /* Output a NEXTKEY method. This is the iterator so that each and keys works */ - - Printv(pm, - "sub NEXTKEY {\n", + tab4, "my $ptr = tied(%$self);\n", + tab4, "delete $OWNER{$ptr};\n", + tab4, "};\n\n", + "sub ACQUIRE {\n", tab4, "my $self = shift;\n", - tab4, "$nelem = scalar @{$ITERATORS{$self}};\n", - tab4, "if ($nelem > 0) {\n", - tab8, "my $member = shift @{$ITERATORS{$self}};\n", - tab8, "return $member;\n", - tab4, "} else {\n", - tab8, "$ITERATORS{$self} = [", member_keys, "];\n", - tab8, "return ();\n", - tab4, "}\n", - "}\n\n", - 0); - } - } -} - -/* ----------------------------------------------------------------------------- - * PERL5::cpp_member_func() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_memberfunction(DOH *node) { - char *name, *iname; - SwigType *t; - ParmList *l; - String *func; - char *realname; - Parm *p; - int i; - String *cname; - int pcount, numopt; - char *tm; - int need_wrapper = 0; - - member_func = 1; - this->Language::cpp_memberfunction(node); - member_func = 0; - - if (!blessed) return; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - l = Getattr(node,"parms"); - - func = NewString(""); - cname = NewString("perl5:"); - - /* Now emit a Perl wrapper function around our member function, we might need - to patch up some arguments along the way */ - - if (!iname) - realname = name; - else - realname = iname; - - Printf(cname,"%s::%s",class_name,realname); - if (Getattr(symbols,cname)) { - return; /* Forget it, we saw this already */ - } - Setattr(symbols,cname,cname); - - Printv(func, - "sub ", realname, " {\n", - tab4, "my @args = @_;\n", - 0); - - /* Now we have to go through and patch up the argument list. If any - arguments to our function correspond to other Perl objects, we - need to extract them from a tied-hash table object. */ - - p = l; - pcount = ParmList_len(l); - numopt = check_numopt(l); - i = 1; - while(p) { - SwigType *pt = Gettype(p); - if (!Getignore(p)) { - char sourceNtarget[512]; - sprintf(sourceNtarget, "$args[%d]", i); - - if ((tm = Swig_typemap_lookup((char*)"perl5in",pt,(char*)"",sourceNtarget,sourceNtarget,0))) { - Printf(func,"%s\n",tm); - need_wrapper = 1; + tab4, "my $ptr = tied(%$self);\n", + tab4, "$OWNER{$ptr} = 1;\n", + tab4, "};\n\n", + NIL); + + /* Only output the following methods if a class has member data */ + + if (have_data_members) { + + /* Output a FETCH method. This is actually common to all classes */ + Printv(pm, + "sub FETCH {\n", + tab4, "my ($self,$field) = @_;\n", + tab4, "my $member_func = \"swig_${field}_get\";\n", + tab4, "my $val = $self->$member_func();\n", + tab4, "if (exists $BLESSEDMEMBERS{$field}) {\n", + tab8, "return undef if (!defined($val));\n", + tab8, "my %retval;\n", + tab8, "tie %retval,$BLESSEDMEMBERS{$field},$val;\n", + tab8, "return bless \\%retval, $BLESSEDMEMBERS{$field};\n", + tab4, "}\n", + tab4, "return $val;\n", + "}\n\n", + NIL); + + /* Output a STORE method. This is also common to all classes (might move to base class) */ + + Printv(pm, + "sub STORE {\n", + tab4, "my ($self,$field,$newval) = @_;\n", + tab4, "my $member_func = \"swig_${field}_set\";\n", + tab4, "if (exists $BLESSEDMEMBERS{$field}) {\n", + tab8, "$self->$member_func(tied(%{$newval}));\n", + tab4, "} else {\n", + tab8, "$self->$member_func($newval);\n", + tab4, "}\n", + "}\n\n", + NIL); } - i++; - } - p = Getnext(p); - } - - /* Okay. We've made argument adjustments, now call into the package */ - - Printv(func, - tab4, "my $result = ", package, "::", Swig_name_member(class_name,realname), - "(@args);\n", - 0); - - /* Now check to see what kind of return result was found. - * If this function is returning a result by 'value', SWIG did an - * implicit malloc/new. We'll mark the object like it was created - * in Perl so we can garbage collect it. */ - - if ((tm = Swig_typemap_lookup((char*)"perl5out",t,(char*)"",name,(char*)"sv",0))) { - Printv(func, - tm, "\n", - tab4,"return $result;\n", - "}\n", - 0); - need_wrapper = 1; - - } else if (is_shadow(t)) { - - Printv(func,tab4, "return undef if (!defined($result));\n", 0); - - /* If we're returning an object by value, put it's reference - into our local hash table */ - - if (!SwigType_ispointer(t) || NewObject) { - Printv(func, tab4, "$", is_shadow(t), "::OWNER{$result} = 1; \n", 0); + Delete(operators); operators = 0; } - - /* We're returning a Perl "object" of some kind. Turn it into - a tied hash */ - - Printv(func, - tab4, "my %resulthash;\n", - tab4, "tie %resulthash, ref($result), $result;\n", - tab4, "return bless \\%resulthash, ref($result);\n", - "}\n", - 0); - - need_wrapper = 1; - } else { - - /* Hmmm. This doesn't appear to be anything I know about so just - return it unmodified */ - - Printv(func, tab4,"return $result;\n", "}\n", 0); + return SWIG_OK; } - if (need_wrapper) { - Printv(pcode,func,0); - } else { - Printv(pcode,"*",realname," = *", package, "::", Swig_name_member(class_name,realname), ";\n", 0); - } - Delete(func); - Delete(cname); -} + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ -/* ----------------------------------------------------------------------------- - * PERL5::cpp_variable() - * - * Adds an instance member. This is a little hairy because data members are - * really added with a tied-hash table that is attached to the object. - * - * On the low level, we will emit a pair of get/set functions to retrieve - * values just like before. These will then be encapsulated in a FETCH/STORE - * method associated with the tied-hash. - * - * In the event that a member is an object that we have already wrapped, then - * we need to retrieve the data a tied-hash as opposed to what SWIG normally - * returns. To determine this, we build an internal hash called 'BLESSEDMEMBERS' - * that contains the names and types of tied data members. If a member name - * is in the list, we tie it, otherwise, we just return the normal SWIG value. - * ----------------------------------------------------------------------------- */ + virtual int memberfunctionHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); -void PERL5::cpp_variable(DOH *node) { - char *name, *iname; - SwigType *t; - char *realname; - String *cname; + String *func; + int need_wrapper = 0; - cname = NewString("perl5:"); - - /* Emit a pair of get/set functions for the variable */ - - member_func = 1; - this->Language::cpp_variable(node); - member_func = 0; + member_func = 1; + Language::memberfunctionHandler(n); + member_func = 0; + if ((blessed) && (!Getattr(n,"sym:nextSibling"))) { + func = NewString(""); + + /* Now emit a Perl wrapper function around our member function, we might need + to patch up some arguments along the way */ + + if (Strstr(symname, "operator") == symname) { + if (Strstr(symname, "operator_equal_to")) { + DohSetInt(operators,"operator_equal_to",1); + have_operators = 1; + } else if (Strstr(symname, "operator_not_equal_to")) { + DohSetInt(operators,"operator_not_equal_to",1); + have_operators = 1; + } else if (Strstr(symname, "operator_assignment")) { + DohSetInt(operators,"operator_assignment",1); + have_operators = 1; + } else { + Printf(stderr,"Unknown operator: %s\n", symname); + } + // fprintf(stderr,"Found member_func operator: %s\n", symname); + } - if (blessed) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); + Printv(func, + "sub ", symname, " {\n", + tab4, "my @args = @_;\n", + NIL); + + /* Okay. We've made argument adjustments, now call into the package */ + + Printv(func, + tab4, "my $result = ", cmodule, "::", Swig_name_member(class_name,symname), + "(@args);\n", + NIL); + + /* Now check to see what kind of return result was found. + * If this function is returning a result by 'value', SWIG did an + * implicit malloc/new. We'll mark the object like it was created + * in Perl so we can garbage collect it. */ - if (iname) realname = iname; - else realname = name; + if (is_shadow(t)) { + Printv(func,tab4, "return undef if (!defined($result));\n", NIL); - Printf(cname,"%s::%s", class_name, realname); - if (Getattr(symbols,cname)) { - Delete(cname); - return; + /* If we're returning an object by value, put it's reference + into our local hash table */ + + if ((!SwigType_ispointer(t) && !SwigType_isreference(t)) || Getattr(n,"feature:new")) { + Printv(func, tab4, "$", is_shadow(t), "::OWNER{$result} = 1; \n", NIL); + } + + /* We're returning a Perl "object" of some kind. Turn it into + a tied hash */ + + Printv(func, + tab4, "my %resulthash;\n", + tab4, "tie %resulthash, ref($result), $result;\n", + tab4, "return bless \\%resulthash, ref($result);\n", + "}\n", + NIL); + + need_wrapper = 1; + } else { + + /* Hmmm. This doesn't appear to be anything I know about so just + return it unmodified */ + + Printv(func, tab4,"return $result;\n", "}\n", NIL); + } + + if (need_wrapper) { + Printv(pcode,func,NIL); + } else { + Printv(pcode,"*",symname," = *", cmodule, "::", Swig_name_member(class_name,symname), ";\n", NIL); + } + Delete(func); } - Setattr(symbols,cname,cname); - - /* Store name of key for future reference */ - Printf(member_keys,"'%s', ", realname); - - /* Now we need to generate a little Perl code for this */ - - if (is_shadow(t)) { - - /* This is a Perl object that we have already seen. Add an - entry to the members list*/ - Printv(blessedmembers, - tab4, realname, " => '", is_shadow(t), "',\n", - 0); - - } + return SWIG_OK; } - have_data_members++; - Delete(cname); -} - -/* ----------------------------------------------------------------------------- - * PERL5::cpp_constructor() - * - * Emits a blessed constructor for our class. In addition to our construct - * we manage a Perl hash table containing all of the pointers created by - * the constructor. This prevents us from accidentally trying to free - * something that wasn't necessarily allocated by malloc or new - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_constructor(DOH *node) { - char *name, *iname; - ParmList *l; - Parm *p; - int i; - String *realname; - String *cname; - - cname = NewString("perl5:constructor:"); - - /* Emit an old-style constructor for this class */ - - member_func = 1; - this->Language::cpp_constructor(node); - - if (blessed) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - l = Getattr(node,"parms"); - if (iname) - realname = iname; - else { - if (class_renamed) realname = class_name; - else realname = class_name; - } - Printf(cname,"%s::%s", class_name, realname); - if (Getattr(symbols,cname)) { - Delete(cname); - return; - } - Setattr(symbols,cname, cname); - if ((Cmp(realname,class_name) == 0)) { + /* ------------------------------------------------------------ + * membervariableHandler() + * + * Adds an instance member. This is a little hairy because data members are + * really added with a tied-hash table that is attached to the object. + * + * On the low level, we will emit a pair of get/set functions to retrieve + * values just like before. These will then be encapsulated in a FETCH/STORE + * method associated with the tied-hash. + * + * In the event that a member is an object that we have already wrapped, then + * we need to retrieve the data a tied-hash as opposed to what SWIG normally + * returns. To determine this, we build an internal hash called 'BLESSEDMEMBERS' + * that contains the names and types of tied data members. If a member name + * is in the list, we tie it, otherwise, we just return the normal SWIG value. + * ----------------------------------------------------------------------------- */ - /* Emit a blessed constructor */ + virtual int membervariableHandler(Node *n) { - Printf(pcode, "sub new {\n"); + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); - } else { + /* Emit a pair of get/set functions for the variable */ - /* Constructor doesn't match classname so we'll just use the normal name */ + member_func = 1; + Language::membervariableHandler(n); + member_func = 0; - Printv(pcode, "sub ", Swig_name_construct(realname), " () {\n", 0); + if (blessed) { - } + Printv(pcode,"*swig_", symname, "_get = *", cmodule, "::", Swig_name_get(Swig_name_member(class_name,symname)), ";\n", NIL); + Printv(pcode,"*swig_", symname, "_set = *", cmodule, "::", Swig_name_set(Swig_name_member(class_name,symname)), ";\n", NIL); - Printv(pcode, tab4, "my $self = shift;\n", - tab4, "my @args = @_;\n", 0); + /* Now we need to generate a little Perl code for this */ - /* We are going to need to patch up arguments here if necessary - * Now we have to go through and patch up the argument list. If any - * arguments to our function correspond to other Perl objects, we - * need to extract them from a tied-hash table object. */ + if (is_shadow(t)) { - p = l; - i = 0; - while(p) { - SwigType *pt = Gettype(p); + /* This is a Perl object that we have already seen. Add an + entry to the members list*/ + Printv(blessedmembers, + tab4, symname, " => '", is_shadow(t), "',\n", + NIL); - if (is_shadow(pt)) { - /* Yep. This smells alot like an object, patch up the arguments */ - Printf(pcode, " $args[%d] = tied(%%{$args[%d]});\n", i, i); } - p = Getnext(p); - i++; } - - Printv(pcode, - tab4, "$self = ", package, "::", Swig_name_construct(realname), "(@args);\n", - tab4, "return undef if (!defined($self));\n", - tab4, "bless $self, \"", fullclassname, "\";\n", - tab4, "$OWNER{$self} = 1;\n", - tab4, "my %retval;\n", - tab4, "tie %retval, \"", fullclassname, "\", $self;\n", - tab4, "return bless \\%retval,\"", fullclassname, "\";\n", - "}\n\n", - 0); - - have_constructor = 1; - + have_data_members++; + return SWIG_OK; } - Delete(cname); - member_func = 0; -} -/* ----------------------------------------------------------------------------- - * PERL5::cpp_destructor() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_destructor(DOH *node) { - String *realname; - char *name, *newname; - member_func = 1; - this->Language::cpp_destructor(node); - - if (blessed) { - name = GetChar(node,"name"); - newname = GetChar(node,"scriptname"); - - if (newname) realname = newname; - else { - if (class_renamed) realname = class_name; - else realname = name; - } + /* ------------------------------------------------------------ + * constructorDeclaration() + * + * Emits a blessed constructor for our class. In addition to our construct + * we manage a Perl hash table containing all of the pointers created by + * the constructor. This prevents us from accidentally trying to free + * something that wasn't necessarily allocated by malloc or new + * ------------------------------------------------------------ */ - /* Emit a destructor for this object*/ + virtual int constructorHandler(Node *n) { - Printv(pcode, - "sub DESTROY {\n", - tab4, "return unless $_[0]->isa('HASH');\n", - tab4, "my $self = tied(%{$_[0]});\n", - tab4, "delete $ITERATORS{$self};\n", - tab4, "if (exists $OWNER{$self}) {\n", - tab8, package, "::", Swig_name_destroy(realname), "($self);\n", - tab8, "delete $OWNER{$self};\n", - tab4, "}\n}\n\n", - 0); + String *symname = Getattr(n,"sym:name"); - have_destructor = 1; + member_func = 1; + Language::constructorHandler(n); - } - member_func = 0; -} + if ((blessed) && (!Getattr(n,"sym:nextSibling"))) { + if ((Cmp(symname,class_name) == 0)) { + /* Emit a blessed constructor */ + Printf(pcode, "sub new {\n"); + } else { + /* Constructor doesn't match classname so we'll just use the normal name */ + Printv(pcode, "sub ", Swig_name_construct(symname), " () {\n", NIL); + } -/* ----------------------------------------------------------------------------- - * PERL5::cpp_staticfunction() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_staticfunction(DOH *node) { - char *name, *iname; - this->Language::cpp_staticfunction(node); - char *realname; - - if (blessed) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - if (iname) realname = name; - else realname = iname; - - Printv(pcode, "*", realname, " = *", realpackage, "::", Swig_name_member(class_name,realname), ";\n", 0); - } -} + Printv(pcode, tab4, "my $pkg = shift;\n", + tab4, "my @args = @_;\n", NIL); + + Printv(pcode, + tab4, "my $self = ", cmodule, "::", Swig_name_construct(symname), "(@args);\n", + tab4, "return undef if (!defined($self));\n", + /* tab4, "bless $self, \"", fullclassname, "\";\n", */ + tab4, "$OWNER{$self} = 1;\n", + tab4, "my %retval;\n", + tab4, "tie %retval, \"", fullclassname, "\", $self;\n", + tab4, "return bless \\%retval, $pkg;\n", + "}\n\n", + NIL); -/* ----------------------------------------------------------------------------- - * PERL5::cpp_inherit() - * ------------------------------------------------------------------------------ */ -void -PERL5::cpp_inherit(List *bases) { - String *base; - char *bc; - int have_first = 0; - if (!blessed) { - this->Language::cpp_inherit(bases); - return; + have_constructor = 1; + } + member_func = 0; + return SWIG_OK; } - /* Inherit variables and constants from base classes, but not - functions (since Perl can handle that okay). */ - - this->Language::cpp_inherit(bases); - - /* Now tell the Perl5 module that we're inheriting from base classes */ - - base_class = NewString(""); - for (base = Firstitem(bases); base; base = Nextitem(bases)) { - /* See if this is a class we know about */ - String *b = NewString(base); - bc = Char(is_shadow(b)); - Delete(b); - if (bc) { - if (have_first) Putc(' ', base_class); - Printf(base_class,bc); - have_first = 1; + /* ------------------------------------------------------------ + * destructorHandler() + * ------------------------------------------------------------ */ + + virtual int destructorHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + member_func = 1; + Language::destructorHandler(n); + if (blessed) { + Printv(pcode, + "sub DESTROY {\n", + tab4, "return unless $_[0]->isa('HASH');\n", + tab4, "my $self = tied(%{$_[0]});\n", + tab4, "return unless defined $self;\n", + tab4, "delete $ITERATORS{$self};\n", + tab4, "if (exists $OWNER{$self}) {\n", + tab8, cmodule, "::", Swig_name_destroy(symname), "($self);\n", + tab8, "delete $OWNER{$self};\n", + tab4, "}\n}\n\n", + NIL); + have_destructor = 1; } + member_func = 0; + return SWIG_OK; } - if (!have_first) { - Delete(base_class); - base_class = 0; - } -} -/* ----------------------------------------------------------------------------- - * PERL5::cpp_constant() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_constant(DOH *node) { - char *name, *iname; - String *realname; - int oldblessed = blessed; - char cname[256]; - - /* Create a normal constant */ - blessed = 0; - this->Language::cpp_constant(node); - blessed = oldblessed; - - if (blessed) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - if (!iname) - realname = name; - else - realname = iname; - - sprintf(cname,"%s::%s",Char(class_name),Char(realname)); - if (Getattr(symbols, cname)) { - return; + /* ------------------------------------------------------------ + * staticmemberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler(Node *n) { + member_func = 1; + Language::staticmemberfunctionHandler(n); + member_func = 0; + if ((blessed) && (!Getattr(n,"sym:nextSibling"))) { + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + if (is_shadow(t)) { + Printv(pcode, + "sub ", symname, " {\n", + tab4, "my @args = @_;\n", + NIL); + + /* Okay. We've made argument adjustments, now call into the package */ + + Printv(pcode, + tab4, "my $result = ", cmodule, "::", Swig_name_member(class_name,symname), + "(@args);\n", + NIL); + + /* Now check to see what kind of return result was found. + * If this function is returning a result by 'value', SWIG did an + * implicit malloc/new. We'll mark the object like it was created + * in Perl so we can garbage collect it. */ + + Printv(pcode,tab4, "return undef if (!defined($result));\n", NIL); + + /* If we're returning an object by value, put it's reference + into our local hash table */ + + if ((!SwigType_ispointer(t) && !SwigType_isreference(t)) || Getattr(n,"feature:new")) { + Printv(pcode, tab4, "$", is_shadow(t), "::OWNER{$result} = 1; \n", NIL); + } + + /* We're returning a Perl "object" of some kind. Turn it into + a tied hash */ + + Printv(pcode, + tab4, "my %resulthash;\n", + tab4, "tie %resulthash, ref($result), $result;\n", + tab4, "return bless \\%resulthash, ref($result);\n", + "}\n", + NIL); + } else { + Printv(pcode,"*",symname," = *", cmodule, "::", Swig_name_member(class_name,symname), ";\n", NIL); + } } - Setattr(symbols, cname,cname); - - /* Create a symbol table entry for it */ - Printv(pcode, "*", realname, " = *", package, "::", Swig_name_member(class_name,realname), ";\n", 0); + return SWIG_OK; } -} -/* ----------------------------------------------------------------------------- - * PERL5::cpp_class_decl() - * ----------------------------------------------------------------------------- */ -void -PERL5::cpp_class_decl(DOH *node) { - String *name = Getname(node); - String *rename = Getattr(node,"scriptname"); - String *ctype = Getattr(node,"classtype"); - String *stype; - if (blessed) { - stype = NewString(name); - SwigType_add_pointer(stype); - Setattr(classes,stype,rename); - Delete(stype); - if (Len(ctype) > 0) { - stype = NewStringf("%s %s",ctype,name); - SwigType_add_pointer(stype); - Setattr(classes,stype,rename); - Delete(stype); + /* ------------------------------------------------------------ + * staticmembervariableHandler() + * ------------------------------------------------------------ */ + + virtual int staticmembervariableHandler(Node *n) { + Language::staticmembervariableHandler(n); + if (blessed) { + String *symname = Getattr(n,"sym:name"); + Printv(pcode,"*",symname," = *", cmodule, "::", Swig_name_member(class_name,symname), ";\n", NIL); } + return SWIG_OK; } -} - -/* ----------------------------------------------------------------------------- - * PERL5::add_typedef() - * ----------------------------------------------------------------------------- */ -void -PERL5::add_typedef(SwigType *t, String *name) { - - if (!blessed) return; - if (is_shadow(t)) { - DOH *node = NewHash(); - Setattr(node,"name",name); - Setattr(node,"scriptname", is_shadow(t)); - Setattr(node,"classtype",""); - cpp_class_decl(node); + + /* ------------------------------------------------------------ + * memberconstantHandler() + * ------------------------------------------------------------ */ + + virtual int memberconstantHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + int oldblessed = blessed; + + /* Create a normal constant */ + blessed = 0; + Language::memberconstantHandler(n); + blessed = oldblessed; + + if (blessed) { + Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(class_name,symname), ";\n", NIL); + } + return SWIG_OK; } -} - -/* ----------------------------------------------------------------------------- - * PERL5::pragma() - * - * Pragma directive. - * - * %pragma(perl5) code="String" # Includes a string in the .pm file - * %pragma(perl5) include="file.pl" # Includes a file in the .pm file - * ----------------------------------------------------------------------------- */ - -void PERL5::pragma(DOH *node) { - String *name = Getattr(node,"name"); - String *value = Getattr(node,"value"); - if (Cmp(name,"code") == 0) { - /* Dump the value string into the .pm file */ - if (value) { - Printf(pragma_include, "%s\n", value); - } - } else if (Cmp(name,"include") == 0) { - /* Include a file into the .pm file */ - if (value) { - FILE *f = Swig_open(value); - if (!f) { - Printf(stderr,"%s:%d. Unable to locate file %s\n", Getfile(node), Getline(node),value); - } else { - char buffer[4096]; - while (fgets(buffer,4095,f)) { - Printf(pragma_include,"%s",buffer); + /* ------------------------------------------------------------ + * pragma() + * + * Pragma directive. + * + * %pragma(perl5) code="String" # Includes a string in the .pm file + * %pragma(perl5) include="file.pl" # Includes a file in the .pm file + * ------------------------------------------------------------ */ + + virtual int pragmaDirective(Node *n) { + String *lang; + String *code; + String *value; + if (!ImportMode) { + lang = Getattr(n,"lang"); + code = Getattr(n,"name"); + value = Getattr(n,"value"); + if (Strcmp(lang,"perl5") == 0) { + if (Strcmp(code,"code") == 0) { + /* Dump the value string into the .pm file */ + if (value) { + Printf(pragma_include, "%s\n", value); + } + } else if (Strcmp(code,"include") == 0) { + /* Include a file into the .pm file */ + if (value) { + FILE *f = Swig_open(value); + if (!f) { + Printf(stderr,"%s : Line %d. Unable to locate file %s\n", input_file, line_number,value); + } else { + char buffer[4096]; + while (fgets(buffer,4095,f)) { + Printf(pragma_include,"%s",buffer); + } + } + } + } else { + Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file,line_number); } } } + return Language::pragmaDirective(n); } -} - - +}; + +/* ----------------------------------------------------------------------------- + * swig_perl5() - Instantiate module + * ----------------------------------------------------------------------------- */ +extern "C" Language * +swig_perl5(void) { + return new PERL5(); +} diff --git a/Source/Modules1.1/perl5.h b/Source/Modules1.1/perl5.h deleted file mode 100644 index 90b35f8e6..000000000 --- a/Source/Modules1.1/perl5.h +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** - * Simplified Wrapper and Interface Generator (SWIG) - * - * Author : David Beazley - * - * Department of Computer Science - * University of Chicago - * 1100 E 58th Street - * Chicago, IL 60637 - * beazley@cs.uchicago.edu - * - * Please read the file LICENSE for the copyright and terms by which SWIG - * can be used and distributed. - ****************************************************************************/ - -/************************************************************************** - * class PERL5 - * - * A Perl 5 implementation - **************************************************************************/ - -class PERL5 : public Language { -private: - char *usage_func(char *, SwigType *, ParmList *); -public : - virtual void parse_args(int, char *argv[]); - virtual void initialize(String *modname); - virtual void function(DOH *node); - virtual void variable(DOH *node); - virtual void constant(DOH *node); - virtual void close(void); - virtual void nativefunction(DOH *); - virtual void create_command(String *, String *); - - // Support for blessed perl thingies.... - - virtual void cpp_open_class(DOH *); - virtual void cpp_close_class(); - virtual void cpp_memberfunction(DOH *); - virtual void cpp_staticfunction(DOH *); - virtual void cpp_variable(DOH *); - virtual void cpp_constructor(DOH *); - virtual void cpp_destructor(DOH *); - virtual void cpp_inherit(List *bases); - virtual void cpp_constant(DOH *); - virtual void cpp_class_decl(DOH *); - virtual void add_typedef(SwigType *t, String *name); - virtual void pragma(DOH *node); - virtual void import(String *filename); -}; - - - diff --git a/Source/Modules1.1/php4.cxx b/Source/Modules1.1/php4.cxx new file mode 100644 index 000000000..051e24601 --- /dev/null +++ b/Source/Modules1.1/php4.cxx @@ -0,0 +1,2113 @@ +/* + * PHP4 Support + * + * Richard Palmer + * richard@magicality.org + * Nov 2001 + * + * Portions copyright Sun Microsystems (c) 2001 + * Tim Hockin <thockin@sun.com> + * + * Portions copyright Ananova Ltd (c) 2002 + * Sam Liddicott <sam@ananova.com> + * + */ + +char cvsroot_php4_cxx[] = "$Header$"; + +#include <ctype.h> + +#include "swigmod.h" +#include "swigconfig.h" + +static const char *usage = (char*)"\ +PHP4 Options (available with -php4)\n\ + -cppext - cpp file extension (default to .cpp)\n\ + -proxy - Create proxy classes.\n\ + -dlname name - Set module prefix.\n\ + -make - Create simple makefile.\n\ + -phpfull - Create full make files.\n\ + -withincs libs - With -phpfull writes needed incs in config.m4\n\ + -withlibs libs - With -phpfull writes needed libs in config.m4\n\n\ + -withc libs - With -phpfull makes extra c files in Makefile.in\n\ + -withcxx libs - With -phpfull makes extra c++ files in Makefile.in\n\n"; + +static int constructors=0; +static String *NOTCLASS=NewString("Not a class"); +static Node *classnode=0; +static String *module = 0; +static String *cap_module = 0; +static String *dlname = 0; +static String *withlibs = 0; +static String *withincs = 0; +static String *withc = 0; +static String *withcxx = 0; +static String *outfile = 0; + +//static char *package = 0; // Name of the package +static char *shadow_classname; + +static Wrapper *f_php; +static int gen_extra = 0; +static int gen_make = 0; + +static File *f_runtime = 0; +static File *f_h = 0; +static File *f_phpcode = 0; +static String *phpfilename =0; + +static String *s_header; +static String *s_wrappers; +static String *s_init; +static String *s_vinit; +static String *s_vdecl; +static String *s_cinit; +static String *s_oinit; +static String *s_entry; +static String *cs_entry; +static String *all_cs_entry; +static String *pragma_incl; +static String *pragma_code; +static String *pragma_phpinfo; + +/* Variables for using PHP classes */ +static String *class_name = 0; +static String *realpackage = 0; +static String *package = 0; + +static Hash *shadow_get_vars; +static Hash *shadow_set_vars; +static String *shadow_classdef; +static String *shadow_code; +static int have_default_constructor = 0; +#define NATIVE_CONSTRUCTOR 1 +#define ALTERNATIVE_CONSTRUCTOR 2 +static int native_constructor=0; +static int destructor=0; +static int enum_flag = 0; // Set to 1 when wrapping an enum +static int static_flag = 0; // Set to 1 when wrapping a static functions or member variables +static int const_flag = 0; // Set to 1 when wrapping a const member variables +static int variable_wrapper_flag = 0; // Set to 1 when wrapping a member variable/enum/const +static int wrapping_member = 0; +static Hash *zend_types = 0; + +static String *shadow_enum_code = 0; +static String *php_enum_code = 0; +static String *all_shadow_extra_code = 0; + //Extra code for all shadow classes from %pragma +static String *this_shadow_extra_code = 0; + //Extra Code for current single shadow class freom %pragma +static String *all_shadow_import = 0; + //import for all shadow classes from %pragma +static String *this_shadow_import = 0; + //import for current shadow classes from %pragma +static String *module_baseclass = 0; + //inheritance for module class from %pragma +static String *all_shadow_baseclass = 0; + //inheritence for all shadow classes from %pragma +static String *this_shadow_baseclass = 0; + //inheritance for shadow class from %pragma and cpp_inherit +static String *this_shadow_multinherit = 0; +static int shadow = 1; + + +extern "C" { +static void (*r_prevtracefunc)(SwigType *t, String *mangled, String *clientdata) = 0; +} + +static const char *php_header = +"/*" +"\n +----------------------------------------------------------------------+" +"\n | PHP version 4.0 |" +"\n +----------------------------------------------------------------------+" +"\n | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |" +"\n +----------------------------------------------------------------------+" +"\n | This source file is subject to version 2.02 of the PHP license, |" +"\n | that is bundled with this package in the file LICENSE, and is |" +"\n | available at through the world-wide-web at |" +"\n | http://www.php.net/license/2_02.txt. |" +"\n | If you did not receive a copy of the PHP license and are unable to |" +"\n | obtain it through the world-wide-web, please send a note to |" +"\n | license@php.net so we can mail you a copy immediately. |" +"\n +----------------------------------------------------------------------+" +"\n | Authors: |" +"\n | |" +"\n +----------------------------------------------------------------------+" +"\n */\n"; + +void +SwigPHP_emit_resource_registrations() { + DOH *key; + String *destructor=0; + String *classname=0; + String *shadow_classname=0; + + if (!zend_types) return; + key = Firstkey(zend_types); + + if (key) Printf(s_oinit,"\n/* Register resource destructors for pointer types */\n"); + while (key) if (1 /* is pointer type*/) { + Node *class_node; + if ((class_node=Getattr(zend_types,key))) { + // Write out destructor function header + Printf(s_wrappers,"/* NEW Destructor style */\nstatic ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n",key); + + // write out body + if ((class_node!=NOTCLASS)) { + classname = Getattr(class_node,"name"); + if (! (shadow_classname = Getattr(class_node,"sym:name"))) shadow_classname=classname; + // Do we have a known destructor for this type? + if ((destructor = Getattr(class_node,"destructor"))) { + Printf(s_wrappers,"/* has destructor: %s */\n",destructor); + Printf(s_wrappers,"%s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n",destructor,key); + } else { + Printf(s_wrappers,"/* bah! No destructor for this wrapped class!! */\n"); + } + } else { + Printf(s_wrappers,"/* bah! No destructor for this simple type!! */\n"); + } + + // close function + Printf(s_wrappers,"}\n"); + + // declare le_swig_<mangled> to store php registration + Printf(s_vdecl,"static int le_swig_%s=0; /* handle for %s */\n", key, shadow_classname); + + // register with php + Printf(s_oinit,"le_swig_%s=zend_register_list_destructors_ex" + "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", + key,key,key); + + // store php type in class struct + Printf(s_oinit,"SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", + key,key); + } + key = Nextkey(zend_types); + } +} + +class PHP4 : public Language { +public: + + /* Test to see if a type corresponds to something wrapped with a shadow class. */ + + String *is_shadow(SwigType *t) { + String *r = 0; + Node *n = classLookup(t); + if (n) { + r = Getattr(n,"php:proxy"); // Set by classDeclaration() + if (!r) { + r = Getattr(n,"sym:name"); // Not seen by classDeclaration yet, but this is the name + } + } + return r; + } + + /* ----------------------------------------------------------------------------- + * get_pointer() + * ----------------------------------------------------------------------------- */ + void + get_pointer(char *iname, char *srcname, char *src, char *dest, + SwigType *t, String *f, char *ret) { + + SwigType_remember(t); + SwigType *lt = SwigType_ltype(t); + Printv(f, "if (SWIG_ConvertPtr(", src, ",(void **) ", dest, ",", NIL); + + /* If we're passing a void pointer, we give the pointer conversion a NULL + pointer, otherwise pass in the expected type. */ + + if (Cmp(lt,"p.void") == 0) { + Printf(f, " 0 ) < 0) {\n"); + } else { + Printv(f, "SWIGTYPE", SwigType_manglestr(t), ") < 0) {\n",NIL); + } + + Printv(f, + "zend_error(E_ERROR, \"Type error in ", srcname, " of ", iname, + " Expected %s\", SWIGTYPE", SwigType_manglestr(t), "->name);\n", ret, + ";\n", + "}\n", + NIL); + Delete(lt); + } + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { + int i; + SWIG_library_directory("php4"); + SWIG_config_cppext("cpp"); + + for(i = 1; i < argc; i++) { + if (argv[i]) { + if(strcmp(argv[i], "-phpfull") == 0) { + gen_extra = 1; + Swig_mark_arg(i); + } else if(strcmp(argv[i], "-dlname") == 0) { + if (argv[i+1]) { + dlname = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withlibs") == 0) { + if (argv[i+1]) { + withlibs = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withincs") == 0) { + if (argv[i+1]) { + withincs = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withc") == 0) { + if (argv[i+1]) { + withc = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withcxx") == 0) { + if (argv[i+1]) { + withcxx = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-cppext") == 0) { + if (argv[i+1]) { + SWIG_config_cppext(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i],"-noproxy") == 0)) { + shadow = 0; + Swig_mark_arg(i); + } else if(strcmp(argv[i], "-make") == 0) { + gen_make = 1; + Swig_mark_arg(i); + } else if(strcmp(argv[i], "-help") == 0) { + fputs(usage, stderr); + } + } + } + + Preprocessor_define((void *) "SWIGPHP 1", 0); + Preprocessor_define((void *) "SWIGPHP4 1", 0); + Preprocessor_define ("SWIG_NO_OVERLOAD 1", 0); + SWIG_typemap_lang("php4"); + /* DB: Suggest using a language configuration file */ + SWIG_config_file("php4.swg"); + } + + void create_simple_make(void) { + File *f_make; + + f_make = NewFile((void *)"makefile", "w"); + if(CPlusPlus) + Printf(f_make, "CC=g++\n"); + else + Printf(f_make, "CC=gcc\n"); + + Printf(f_make, + "OBJS=%s_wrap.o\n" + "PROG=lib%s.so\n" + "CFLAGS=-fpic\n" + "LDFLAGS=-shared\n" + "PHP_INC=`php-config --includes`\n" + "EXTRA_INC=\n" + "EXTRA_LIB=\n\n", + module, module); + + Printf(f_make, + "$(PROG): $(OBJS)\n" + "\t$(CC) $(LDFLAGS) $(OBJS) -o $(PROG) $(EXTRA_LIB)\n\n" + "%%.o: %%.%s\n" + "\t$(CC) $(EXTRA_INC) $(PHP_INC) $(CFLAGS) -c $<\n", + (CPlusPlus?"cpp":"c")); + + Close(f_make); + } + + void create_extra_files(void) { + File *f_extra; + + static String *configm4=0; + static String *makefilein=0; + static String *credits=0; + + configm4=NewString(""); + Printv(configm4, Swig_file_dirname(outfile), "config.m4", NIL); + + makefilein=NewString(""); + Printv(makefilein, Swig_file_dirname(outfile), "Makefile.in", NIL); + + credits=NewString(""); + Printv(credits, Swig_file_dirname(outfile), "CREDITS", NIL); + + // are we a --with- or --enable- + int with=(withincs || withlibs)?1:0; + + // Note makefile.in only copes with one source file + // also withincs and withlibs only take one name each now + // the code they generate should be adapted to take multiple lines + + if(gen_extra) { + /* Write out Makefile.in */ + f_extra = NewFile(makefilein, "w"); + if (!f_extra) { + Printf(stderr,"Unable to open %s\n",makefilein); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_extra, + "# $Id$\n\n" + "LTLIBRARY_NAME = php_%s.la\n", + module); + + // CPP has more and different entires to C in Makefile.in + if (! CPlusPlus) Printf(f_extra,"LTLIBRARY_SOURCES = %s %s\n" + "LTLIBRARY_SOURCES_CPP = %s\n",Swig_file_filename(outfile),withc,withcxx); + else Printf(f_extra,"LTLIBRARY_SOURCES = %s\n" + "LTLIBRARY_SOURCES_CPP = %s %s\n" + "LTLIBRARY_OBJECTS_X = $(LTLIBRARY_SOURCES_CPP:.cpp=.lo) $(LTLIBRARY_SOURCES_CPP:.cxx=.lo)\n" + ,withc,Swig_file_filename(outfile),withcxx); + + Printf(f_extra,"LTLIBRARY_SHARED_NAME = php_%s.la\n" + "LTLIBRARY_SHARED_LIBADD = $(%(upper)s_SHARED_LIBADD)\n\n" + "include $(top_srcdir)/build/dynlib.mk\n", + module,module); + + Printf(f_extra,"\n# patch in .cxx support to php build system to work like .cpp\n" + ".SUFFIXES: .cxx\n\n" + ".cxx.o:\n" + " $(CXX_COMPILE) -c $<\n\n" + ".cxx.lo:\n" + " $(CXX_PHP_COMPILE)\n\n" + ".cxx.slo:\n" + " $(CXX_SHARED_COMPILE)\n\n"); + + Printf(f_extra,"\n# make it easy to test module\n" + "testmodule:\n" + " php -q -d extension_dir=modules %s\n\n",Swig_file_filename(phpfilename)); + Close(f_extra); + + /* Now config.m4 */ + // Note: # comments are OK in config.m4 if you don't mind them + // appearing in the final ./configure file + // (which can help with ./configure debugging) + + // NOTE2: phpize really ought to be able to write out a sample + // config.m4 based on some simple data, I'll take this up with + // the php folk! + f_extra = NewFile(configm4, "w"); + if (!f_extra) { + Printf(stderr, "Unable to open %s\n",configm4); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_extra, + "dnl $Id$\n" + "dnl ***********************************************************************\n" + "dnl ** THIS config.m4 is provided for PHPIZE and PHP's consumption NOT\n" + "dnl ** for any part of the rest of the %s build system\n" + "dnl ***********************************************************************\n\n" + ,module); + + if (! with) { // must be enable then + Printf(f_extra, + "PHP_ARG_ENABLE(%s, whether to enable %s support,\n" + "[ --enable-%s Enable %s support])\n\n", + module,module,module,module); + } else { + Printf(f_extra, + "PHP_ARG_WITH(%s, for %s support,\n" + "[ --with-%s[=DIR] Include %s support.])\n\n", + module,module,module,module); + // These tests try and file the library we need + Printf(f_extra,"dnl THESE TESTS try and find the library and header files\n" + "dnl your new php module needs. YOU MAY NEED TO EDIT THEM\n" + "dnl as written they assume your header files are all in the same place\n\n"); + + Printf(f_extra,"dnl ** are we looking for %s_lib.h or something else?\n",module); + if (withincs) Printf(f_extra,"HNAMES=\"%s\"\n\n",withincs); + else Printf(f_extra,"HNAMES=\"\"; # %s_lib.h ?\n\n",module); + + Printf(f_extra,"dnl ** Are we looking for lib%s.a or lib%s.so or something else?\n",module,module); + if (withlibs) Printf(f_extra,"LIBNAMES=\"%s\"\n\n",withlibs); + else Printf(f_extra,"LIBNAMES=\"\"; # lib_%s.so ?\n\n",withlibs); + Printf(f_extra,"dnl IF YOU KNOW one of the symbols in the library and you\n" + "dnl specify it below then we can have a link test to see if it works\n" + "LIBSYMBOL=\"\"\n\n"); + } + + // Now write out tests to find thing.. they may need to extend tests + Printf(f_extra,"if test \"$PHP_%(upper)s\" != \"no\"; then\n\n",module); + + // Ready for when we add libraries as we find them + Printf(f_extra," PHP_SUBST(%(upper)s_SHARED_LIBADD)\n\n",module); + + if (withlibs) { // find more than one library + Printf(f_extra," for LIBNAME in $LIBNAMES ; do\n"); + Printf(f_extra," LIBDIR=\"\"\n"); + // For each path element to try... + Printf(f_extra," for i in $PHP_%(upper)s $PHP_%(upper)s/lib /usr/lib /usr/local/lib ; do\n",module,module); + Printf(f_extra," if test -r $i/lib$LIBNAME.a -o -r $i/lib$LIBNAME.so ; then\n" + " LIBDIR=\"$i\"\n" + " break\n" + " fi\n" + " done\n\n"); + Printf(f_extra," dnl ** and $LIBDIR should be the library path\n" + " if test \"$LIBNAME\" != \"\" -a -z \"$LIBDIR\" ; then\n" + " AC_MSG_RESULT(Library files $LIBNAME not found)\n" + " AC_MSG_ERROR(Is the %s distribution installed properly?)\n" + " else\n" + " AC_MSG_RESULT(Library files $LIBNAME found in $LIBDIR)\n" + " PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $LIBDIR, %(upper)s_SHARED_LIBADD)\n" + " fi\n",module,module); + Printf(f_extra," done\n\n"); + } + + if (withincs) { // Find more than once include + Printf(f_extra," for HNAME in $HNAMES ; do\n"); + Printf(f_extra," INCDIR=\"\"\n"); + // For each path element to try... + Printf(f_extra," for i in $PHP_%(upper)s $PHP_%(upper)s/include $PHP_%(upper)s/includes $PHP_%(upper)s/inc $PHP_%(upper)s/incs /usr/local/include /usr/include; do\n",module,module,module,module,module); + // Try and find header files + Printf(f_extra," if test \"$HNAME\" != \"\" -a -r $i/$HNAME ; then\n" + " INCDIR=\"$i\"\n" + " break\n" + " fi\n" + " done\n\n"); + + Printf(f_extra, + " dnl ** Now $INCDIR should be the include file path\n" + " if test \"$HNAME\" != \"\" -a -z \"$INCDIR\" ; then\n" + " AC_MSG_RESULT(Include files $HNAME not found)\n" + " AC_MSG_ERROR(Is the %s distribution installed properly?)\n" + " else\n" + " AC_MSG_RESULT(Include files $HNAME found in $INCDIR)\n" + " PHP_ADD_INCLUDE($INCDIR)\n" + " fi\n\n",module); + Printf(f_extra," done\n\n"); + } + + if (CPlusPlus) Printf(f_extra, + " # As this is a C++ module..\n" + " PHP_REQUIRE_CXX\n" + " AC_CHECK_LIB(stdc++, cin)\n"); + + if (with) { + Printf(f_extra," if test \"$LIBSYMBOL\" != \"\" ; then\n" + " old_LIBS=\"$LIBS\"\n" + " LIBS=\"$LIBS -L$TEST_DIR/lib -lm -ldl\"\n" + " AC_CHECK_LIB($LIBNAME, $LIBSYMBOL, [AC_DEFINE(HAVE_TESTLIB,1, [ ])],\n" + " [AC_MSG_ERROR(wrong test lib version or lib not found)])\n" + " LIBS=\"$old_LIBS\"\n" + " fi\n\n"); + } + + Printf(f_extra," AC_DEFINE(HAVE_%(upper)s, 1, [ ])\n",module); + Printf(f_extra,"dnl AC_DEFINE_UNQUOTED(PHP_%(upper)s_DIR, \"$%(upper)s_DIR\", [ ])\n",module,module); + Printf(f_extra," PHP_EXTENSION(%s, $ext_shared)\n",module); + + // and thats all! + Printf(f_extra,"fi\n"); + + Close(f_extra); + + /* CREDITS */ + f_extra = NewFile(credits, "w"); + if (!f_extra) { + Printf(stderr,"Unable to open %s\n",credits); + SWIG_exit(EXIT_FAILURE); + } + Printf(f_extra, "%s\n", module); + Close(f_extra); + } + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + + String *filen; + String *s_type; + + /* Initialize all of the output files */ + outfile = Getattr(n,"outfile"); + + /* main output file */ + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + + Swig_banner(f_runtime); + + /* sections of the output file */ + s_init = NewString("/* init section */\n"); + s_header = NewString("/* header section */\n"); + s_wrappers = NewString("/* wrapper section */\n"); + s_type = NewString(""); + /* subsections of the init section */ + s_vinit = NewString("/* vinit subsection */\n"); + s_vdecl = NewString("/* vdecl subsection */\n"); + s_cinit = NewString("/* cinit subsection */\n"); + s_oinit = NewString("/* oinit subsection */\n"); + pragma_phpinfo = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",s_init); + Swig_register_filebyname("header",s_header); + Swig_register_filebyname("wrapper",s_wrappers); + + shadow_classdef = NewString(""); + shadow_code = NewString(""); + php_enum_code = NewString(""); + module_baseclass = NewString(""); + all_shadow_extra_code = NewString(""); + all_shadow_import = NewString(""); + all_shadow_baseclass = NewString(""); + + /* Set the module name */ + module = Copy(Getattr(n,"name")); + cap_module = NewStringf("%(upper)s",module); + + if(shadow) { + realpackage = module; + package = NewStringf("%sc", module); + } + + /* Set the dlname */ + if (!dlname) { +#if defined(_WIN32) || defined(__WIN32__) + dlname = NewStringf("%s.dll", module); +#else + dlname = NewStringf("%s.so", module); +#endif + } + + /* PHP module file */ + filen = NewString(""); + Printv(filen, Swig_file_dirname(outfile), module, ".php", NIL); + phpfilename = NewString(filen); + + f_phpcode = NewFile(filen, "w"); + if (!f_phpcode) { + Printf(stderr, "*** Can't open '%s'\n", filen); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_phpcode, "<?php\n\n"); + + Swig_banner(f_phpcode); + + Printf(f_phpcode, + "global $%s_LOADED__;\n" + "if ($%s_LOADED__) return;\n" + "$%s_LOADED__ = true;\n\n" + "/* if our extension has not been loaded, do what we can */\n" + "if (!extension_loaded(\"php_%s\")) {\n" + " if (!dl(\"php_%s\")) return;\n" + "}\n\n", cap_module, cap_module, cap_module, module, dlname); + + + /* sub-sections of the php file */ + pragma_code = NewString(""); + pragma_incl = NewString(""); + + /* Initialize the rest of the module */ + + f_php = NewWrapper();// wots this used for now? + + /* start the header section */ + Printf(s_header, php_header); + Printf(s_header, + "#define SWIG_init init%s\n\n" + "#define SWIG_name \"%s\"\n" + "#ifdef HAVE_CONFIG_H\n" + "#include \"config.h\"\n" + "#endif\n\n" + "#ifdef __cplusplus\n" + "extern \"C\" {\n" + "#endif\n" + "#include \"php.h\"\n" + "#include \"php_ini.h\"\n" + "#include \"ext/standard/info.h\"\n" + "#include \"php_%s.h\"\n" + "#ifdef __cplusplus\n" + "}\n" + "#endif\n\n", + module, module, module); + + /* Create the .h file too */ + filen = NewString(""); + Printv(filen, Swig_file_dirname(outfile), "php_", module, ".h", NIL); + f_h = NewFile(filen, "w"); + if (!f_h) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit(EXIT_FAILURE); + } + + Swig_banner(f_h); + Printf(f_h, php_header); + + Printf(f_h, "\n\n" + "#ifndef PHP_%s_H\n" + "#define PHP_%s_H\n\n" + "extern zend_module_entry %s_module_entry;\n" + "#define phpext_%s_ptr &%s_module_entry\n\n" + "#ifdef PHP_WIN32\n" + "# define PHP_%s_API __declspec(dllexport)\n" + "#else\n" + "# define PHP_%s_API\n" + "#endif\n\n" + "PHP_MINIT_FUNCTION(%s);\n" + "PHP_MSHUTDOWN_FUNCTION(%s);\n" + "PHP_RINIT_FUNCTION(%s);\n" + "PHP_RSHUTDOWN_FUNCTION(%s);\n" + "PHP_MINFO_FUNCTION(%s);\n\n", + cap_module, cap_module, module, module, module, cap_module, cap_module, + module, module, module, module, module); + + /* start the function entry section */ + s_entry = NewString("/* entry subsection */\n"); + /* holds all the per-class function entry sections */ + all_cs_entry = NewString("/* class entry subsection */\n"); + cs_entry = NULL; + + Printf(s_entry,"/* Every non-class user visible function must have an entry here */\n"); + Printf(s_entry,"function_entry %s_functions[] = {\n", module); + + /* start the init section */ + if (gen_extra) + Printf(s_init,"#ifdef COMPILE_DL_%s\n", cap_module); + Printf(s_init, + "#ifdef __cplusplus\n" + "extern \"C\" {\n" + "#endif\n" + "ZEND_GET_MODULE(%s)\n" + "#ifdef __cplusplus\n" + "}\n" + "#endif\n\n", + module); + if (gen_extra) + Printf(s_init,"#endif\n\n"); + + Printf(s_init, + "PHP_MSHUTDOWN_FUNCTION(%s)\n{\n" + " return SUCCESS;\n" + "}\n", + module); + + /* We have to register the constants before they are (possibly) used + * by the pointer typemaps. This all needs re-arranging really as + * things are being called in the wrong order + */ + + Printf(s_init,"PHP_MINIT_FUNCTION(%s)\n{\n", module); + Printf(s_init, + " int i;\n" + " for (i = 0; swig_types_initial[i]; i++) {\n" + " swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n" + " }\n"); + /* Emit all of the code */ + Language::top(n); + + SwigPHP_emit_resource_registrations(); +// Printv(s_init,s_resourcetypes,NIL); + /* We need this after all classes written out by ::top */ + Printf(s_oinit, "CG(active_class_entry) = NULL;\n"); + Printf(s_oinit, "/* end oinit subsection */\n"); + Printf(s_init, "%s\n", s_oinit); + + /* Constants generated during top call */ + // But save them for RINIT + Printf(s_cinit, "/* end cinit subsection */\n"); + + /* finish our init section which will have been used by class wrappers */ + Printf(s_vinit, "/* end vinit subsection */\n"); + + Printf(s_init, " return SUCCESS;\n"); + Printf(s_init,"}\n"); + + // Now do REQUEST init which holds cinit and vinit + Printf(s_init, + "PHP_RINIT_FUNCTION(%s)\n{\n", + module); + + Printf(s_init, "%s\n", s_cinit); + Clear(s_cinit); + + Printf(s_init, "%s\n", s_vinit); + Clear(s_vinit); + + Printf(s_init, + " return SUCCESS;\n" + "}\n"); + + Delete(s_cinit); + Delete(s_vinit); + + Printf(s_init, + "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n" + " return SUCCESS;\n" + "}\n", + module); + + Printf(s_init, + "PHP_MINFO_FUNCTION(%s)\n{\n" + "%s" + "}\n" + "/* end init section */\n", + module, pragma_phpinfo); + + /* Complete header file */ + + Printf(f_h, + "/*If you declare any globals in php_%s.h uncomment this:\n" + "ZEND_BEGIN_MODULE_GLOBALS(%s)\n" + "ZEND_END_MODULE_GLOBALS(%s)\n" + "*/\n", + module, module, module); + + Printf(f_h, + "#ifdef ZTS\n" + "#define %s_D zend_%s_globals *%s_globals\n" + "#define %s_DC , %s_D\n" + "#define %s_C %s_globals\n" + "#define %s_CC , %s_C\n" + "#define %s_SG(v) (%s_globals->v)\n" + "#define %s_FETCH() zend_%s_globals *%s_globals " + "= ts_resource(%s_globals_id)\n" + "#else\n" + "#define %s_D\n" + "#define %s_DC\n" + "#define %s_C\n" + "#define %s_CC\n" + "#define %s_SG(v) (%s_globals.v)\n" + "#define %s_FETCH()\n" + "#endif\n\n" + "#endif /* PHP_%s_H */\n", + cap_module, module, module, cap_module, cap_module, cap_module, module, + cap_module, cap_module, cap_module, module, cap_module, module, module, + module, cap_module, cap_module, cap_module, cap_module, cap_module, module, + cap_module, cap_module); + + Close(f_h); + + Printf(s_header, "%s\n\n",all_cs_entry); + Printf(s_header, + "%s" + " {NULL, NULL, NULL}\n};\n\n" + "zend_module_entry %s_module_entry = {\n" + "#if ZEND_MODULE_API_NO > 20010900\n" + " STANDARD_MODULE_HEADER,\n" + "#endif\n" + " \"%s\",\n" + " %s_functions,\n" + " PHP_MINIT(%s),\n" + " PHP_MSHUTDOWN(%s),\n" + " PHP_RINIT(%s),\n" + " PHP_RSHUTDOWN(%s),\n" + " PHP_MINFO(%s),\n" + "#if ZEND_MODULE_API_NO > 20010900\n" + " NO_VERSION_YET,\n" + "#endif\n" + " STANDARD_MODULE_PROPERTIES\n" + "};\nzend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", + s_entry, module, module, module, module, module, module, module,module,module); + + String *type_table = NewString(""); + SwigType_emit_type_table(f_runtime,type_table); + Printf(s_header,"%s",type_table); + Delete(type_table); + + /* Oh dear, more things being called in the wrong order. This whole + * function really needs totally redoing. + */ + + Printv(f_runtime, s_header, NIL); + + // Wrapper_print(f_c, s_wrappers); + Wrapper_print(f_php, s_wrappers); + + Printf(s_header, "/* end header section */\n"); + Printf(s_wrappers, "/* end wrapper section */\n"); + Printf(s_vdecl, "/* end vdecl subsection */\n"); + + Printv(f_runtime, s_vdecl, s_wrappers, s_init, NIL); + Delete(s_header); + Delete(s_wrappers); + Delete(s_init); + Delete(s_vdecl); + Close(f_runtime); + Printf(f_phpcode, "%s\n%s\n?>\n", pragma_incl, pragma_code); + Close(f_phpcode); + + create_extra_files(); + + if(!gen_extra && gen_make) + create_simple_make(); + + return SWIG_OK; + } + +/* Just need to append function names to function table to register with + PHP +*/ + + void create_command(char *cname, char *iname) { +// char *lower_cname = strdup(cname); +// char *c; + +// for(c = lower_cname; *c != '\0'; c++) { +// if(*c >= 'A' && *c <= 'Z') +// *c = *c + 32; +// } + + Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname); + + // This is for the single main function_entry record + if (! cs_entry) Printf(s_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " %s, NULL)\n", cname,iname); + +// free(lower_cname); + } + + /* ------------------------------------------------------------ + * functionWrapper() + * ------------------------------------------------------------ */ + + virtual int functionWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + int newobject = (Getattr(n,"feature:new"))?1:0; + Parm *p; + char source[256],target[256],temp[256],argnum[32],args[32]; + int i,numopt; + String *tm; + Wrapper *f; + int num_saved = (Getattr(n,"feature:new"))?1:0; + String *cleanup, *outarg; + bool mvr=(shadow && variable_wrapper_flag && !enum_flag); + bool mvrset=0; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + mvrset=(mvr && (strcmp(iname, Char(Swig_name_set(Swig_name_member(shadow_classname, name)))) == 0)); + + // if shadow and variable wrapper we want to snag the main contents + // of this function to stick in to the property handler.... + if (mvr) { //shadow && variable_wrapper_flag && !enum_flag) { + String *member_function_name = NewString(""); + String *php_function_name = NewString(iname); + if(strcmp(iname, Char(Swig_name_set(Swig_name_member(shadow_classname, name)))) == 0) { + Setattr(shadow_set_vars, php_function_name, name); + } + if(strcmp(iname, Char(Swig_name_get(Swig_name_member(shadow_classname, name)))) == 0) { + Setattr(shadow_get_vars, php_function_name, name); + } + Putc(toupper((int )*iname), member_function_name); + Printf(member_function_name, "%s", iname+1); + + cpp_func(Char(member_function_name), d, l, php_function_name); + + Delete(php_function_name); + Delete(member_function_name); + } + + outarg = cleanup = NULL; + f = NewWrapper(); + numopt = 0; + + outarg = NewString(""); + cleanup = NewString(""); + + // Special action for shadowing destructors under php. + // The real destructor is the resource list destructor, this is + // merely the thing that actually knows how to destroy... + + if (destructor) { + String *destructorname=NewString(""); + Printf(destructorname,"_%s",Swig_name_wrapper(iname)); + Setattr(classnode,"destructor",destructorname); + + Wrapper *df = NewWrapper(); + Printf(df->def,"/* This function is designed to be called by the zend list destructors to typecast and do the actual destruction */\n" + "void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n",destructorname); + + Wrapper_add_localv(df, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); + Wrapper_add_localv(df, "ptr", "void *ptr=value->ptr", NIL); + Wrapper_add_localv(df, "newobject", "int newobject=value->newobject", NIL); + // Magic spell nicked from further down. + emit_args(d, l, df); + emit_attach_parmmaps(l,f); + + // Get type of first arg, thing to be destructed + // Skip ignored arguments + { + p=l; + //while (Getattr(p,"tmap:ignore")) {p = Getattr(p,"tmap:ignore:next");} + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + + Printf(df->code, + " efree(value);\n" + " if (! newobject) return; /* can't delete it! */\n" + " SWIG_ZTS_ConvertResourceData(ptr,rsrc->type,type_name,(void **) &arg1,SWIGTYPE%s TSRMLS_CC);\n" + " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n" + ,SwigType_manglestr(pt), shadow_classname); + } + emit_action(n,df); + + Printf(df->code,"}\n"); + + Wrapper_print(df,s_wrappers); + } + + if (mvr) { // do prop[gs]et header + if (mvrset) Printf(f->def, "static int _wrap_%s(zend_property_reference *property_reference, pval *value) {\n",iname); + else Printf(f->def, "static pval _wrap_%s(zend_property_reference *property_reference) {\n",iname); + } else { // regular header + create_command(iname, Char(Swig_name_wrapper(iname))); + Printv(f->def, "ZEND_NAMED_FUNCTION(" , Swig_name_wrapper(iname), ") {\n", NIL); + } + + emit_args(d, l, f); + /* Attach standard typemaps */ + + emit_attach_parmmaps(l,f); + + int num_arguments = emit_num_arguments(l); + int num_required = emit_num_required(l); + numopt = num_arguments - num_required; + + // we do +1 because we are going to push in this_ptr as arg0 if present + // or do we need to? + + sprintf(args, "%s[%d]", "zval **args", num_arguments+1); + + Wrapper_add_local(f, "args",args); + Wrapper_add_localv(f, "argbase", "int argbase=0", NIL); + // This generated code may be called + // 1) as an object method, or + // 2) as a class-method/function (without a "this_ptr") + // Option (1) has "this_ptr" for "this", option (2) needs it as + // first parameter + // NOTE: possible we ignore this_ptr as a param for native constructor + + if (native_constructor) { + if (native_constructor==NATIVE_CONSTRUCTOR) Printf(f->code, "/* NATIVE Constructor */\nint self_constructor=1;\n"); + else Printf(f->code, "/* ALTERNATIVE Constructor */\n"); + } + + if (mvr && ! mvrset) { + Wrapper_add_local(f, "_return_value", "zval _return_value"); + Wrapper_add_local(f, "return_value", "zval *return_value=&_return_value"); + }; + + // only let this_ptr count as arg[-1] if we are not a constructor + // if we are a constructor and this_ptr is null we are called as a class + // method and can make one of us + if (! mvr && native_constructor==0) Printf(f->code, + "if (this_ptr && this_ptr->type==IS_OBJECT) {\n" + " /* fake this_ptr as first arg (till we can work out how to do it better */\n" + " argbase++;\n" + "}\n"); + + // I'd like to write out: + //" //args[argbase++]=&this_ptr;\n" + // but zend_get_parameters_array_ex can't then be told to leave + // the first slot alone, so we have to check whether or not to access + // this_ptr explicitly in each case where we normally just read args[] + + if(numopt > 0) { // membervariable wrappers do not have optional args + Wrapper_add_local(f, "arg_count", "int arg_count"); + Printf(f->code, + "arg_count = ZEND_NUM_ARGS();\n" + "if(arg_count<(%d-argbase) || arg_count>(%d-argbase))\n" + "\tWRONG_PARAM_COUNT;\n\n", + num_required, num_arguments); + + /* Verified args, retrieve them... */ + Printf(f->code, + "if(zend_get_parameters_array_ex(arg_count-argbase,args)!=SUCCESS)" + "\n\t\tWRONG_PARAM_COUNT;\n\n"); + + } else if (!mvr) { + Printf(f->code, + "if(((ZEND_NUM_ARGS() + argbase )!= %d) || (zend_get_parameters_array_ex(%d-argbase, args)" + "!= SUCCESS)) {\n" + "WRONG_PARAM_COUNT;\n}\n\n", + num_arguments, num_arguments); + } + + /* Now convert from php to C variables */ + // At this point, argcount if used is the number of deliberatly passed args + // not including this_ptr even if it is used. + // It means error messages may be out by argbase with error + // reports. We can either take argbase into account when raising + // errors, or find a better way of dealing with _thisptr + // I would like, if objects are wrapped, to assume _thisptr is always + // _this and the and not the first argument + // This may mean looking at Lang::memberfunctionhandler + + for (i = 0, p = l; i < num_arguments; i++) { + /* Skip ignored arguments */ + //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");} + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + + + if (mvr) { // do we assert that numargs=2, that i<2 + if (i==0) sprintf(source,"&(property_reference->object)"); + else sprintf(source,"&value"); + } else { + // Do we fake this_ptr as arg0, or just possibly shift other args by 1 if we did fake? + if (i==0) sprintf(source, "((%d<argbase)?(&this_ptr):(args[%d-argbase]))", i, i); + else sprintf(source, "args[%d-argbase]", i); } + sprintf(target, "%s", Char(Getattr(p,"lname"))); + sprintf(argnum, "%d", i+1); + + /* Check if optional */ + + if(i>= (num_required)) + Printf(f->code,"\tif(arg_count > %d) {\n", i); + + Setattr(p,"emit:input", source); + + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$target",target); + Replaceall(tm,"$source",source); + Replaceall(tm,"$input", source); + Printf(f->code,"%s\n",tm); + p = Getattr(p,"tmap:in:next"); + if (i >= num_required) { + Printf(f->code,"}\n"); + } + continue; + } else { + Printf(stderr,"%s : Line %d, Unable to use type %s as a function argument.\n", input_file, line_number, SwigType_str(pt,0)); + } + if (i>= num_required) + Printf(f->code,"\t}\n"); + } + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert cleanup code */ + for (i = 0, p = l; p; i++) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert argument output code */ + num_saved = 0; + for (i=0,p = l; p;i++) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$input",Getattr(p,"lname")); + Replaceall(tm,"$target","return_value"); + Replaceall(tm,"$result","return_value"); + + String *in = Getattr(p,"emit:input"); + if (in) { + sprintf(temp,"_saved[%d]", num_saved); + Replaceall(tm,"$arg",temp); + Printf(f->code,"_saved[%d] = %s;\n", num_saved, in); + num_saved++; + } + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); + } + } + + // These are saved for argout again... + if(num_saved) { + sprintf(temp, "_saved[%d]",num_saved); + // Used to be zval *, perhaps above we should use * %s + Wrapper_add_localv(f,"_saved","zval **",temp,NIL); + } + + /* emit function call*/ + if (destructor) { + // If it is a registered resource (and it always should be) + // then destroy it the resource way + + Printf(f->code, + "/*if ((*args[0])->type==IS_RESOURCE) { */\n" + "/* Get zend list destructor to free it */\n" + "/* zend_list_delete(Z_LVAL_PP(args[0])); */\n" + "/* } else {*/ \n",name,name + ); + // but leave the old way in for as long as we accept strings as swig objects + emit_action(n,f); + Printf(f->code,"/*}*/\n"); + } else { + emit_action(n,f); + } + + if((tm = Swig_typemap_lookup((char*)"out",d,iname,(char*)"result",(char*)"result",(char*)"return_value",0))) { + Replaceall(tm, "$input", "result"); + Replaceall(tm, "$source", "result"); + Replaceall(tm, "$target", "return_value"); + Replaceall(tm, "$result", "return_value"); + Replaceall(tm,"$owner", newobject ? "1" : "0"); + Printf(f->code, "%s\n", tm); + // are we returning a wrapable object? + // I don't know if this test is comlete, I nicked it + if(is_shadow(d) && (SwigType_type(d) != T_ARRAY)) { + Printf(f->code,"/* Wrap this return value */\n"); + if (native_constructor==NATIVE_CONSTRUCTOR) { + Printf(f->code, "if (this_ptr) {\n/* NATIVE Constructor, use this_ptr */\n"); + Printf(f->code,"zval *_cPtr; MAKE_STD_ZVAL(_cPtr);\n" + "*_cPtr = *return_value;\n" + "INIT_ZVAL(*return_value);\n" + "add_property_zval(this_ptr,\"_cPtr\",_cPtr);\n" + "} else if (! this_ptr) ",shadow_classname); + } + { // THIS CODE only really needs writing out if the object to be returned + // Is being shadow-wrap-thingied + Printf(f->code, "{\n/* ALTERNATIVE Constructor, make an object wrapper */\n"); + // Make object + String *shadowrettype = NewString(""); + SwigToPhpType(d, iname, shadowrettype, shadow); + + Printf(f->code, + "zval *obj, *_cPtr;\n" + "MAKE_STD_ZVAL(obj);\n" + "MAKE_STD_ZVAL(_cPtr);\n" + "*_cPtr = *return_value;\n" + "INIT_ZVAL(*return_value);\n"); + + if (! shadow) { + Printf(f->code, + "*return_value=*_cPtr;\n"); + } else { + Printf(f->code, + "object_init_ex(obj,ptr_ce_swig_%s);\n" + "add_property_zval(obj,\"_cPtr\",_cPtr);\n" + "*return_value=*obj;\n", + shadowrettype); + } + Printf(f->code, "}\n"); + } + } // end of if-shadow lark + } else { + Printf(stderr,"%s: Line %d, Unable to use return type %s in function %s.\n", input_file, line_number, SwigType_str(d,0), name); + } + + if(outarg) + Printv(f->code,outarg,NIL); + + if(cleanup) + Printv(f->code,cleanup,NIL); + + // Whats this bit for? + if((tm = Swig_typemap_lookup((char*)"ret",d,iname,(char *)"result", (char*)"result",(char*)"",0))) { + Printf(f->code,"%s\n", tm); + } + + Replaceall(f->code,"$cleanup",cleanup); + Replaceall(f->code,"$symname",iname); + + if (mvr) { + if (! mvrset) Printf(f->code,"return _return_value;\n"); + else Printf(f->code,"return SUCCESS;\n"); + } + + Printf(f->code, "}\n"); + Wrapper_print(f,s_wrappers); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int OLDvariableWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + String *tm; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + SwigType_remember(t); + + /* First link C variables to PHP */ + + tm = Swig_typemap_lookup_new("varinit", n, name, 0); + if(tm) { + Replaceall(tm, "$target", name); + Printf(s_vinit, "%s\n", tm); + } else { + Printf(stderr,"%s: Line %d, Unable to link with type %s\n", + input_file, line_number, SwigType_str(t,0), name); + } + + /* Now generate PHP -> C sync blocks */ + tm = Swig_typemap_lookup_new("varin", n, name, 0); + /* + if(tm) { + Replaceall(tm, "$symname", iname); + Printf(f_c->code, "%s\n", tm); + } else { + Printf(stderr,"%s: Line %d, Unable to link with type %s\n", + input_file, line_number, SwigType_str(t, 0), name); + } +*/ + /* Now generate C -> PHP sync blocks */ +/* + if(!Getattr(n,"feature:immutable")) { + + tm = Swig_typemap_lookup_new("varout", n, name, 0); + if(tm) { + Replaceall(tm, "$symname", iname); + Printf(f_php->code, "%s\n", tm); + } else { + Printf(stderr,"%s: Line %d, Unable to link with type %s\n", + input_file, line_number, SwigType_str(t, 0), name); + } + } +*/ + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + char *value = GetChar(n,"value"); + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + String *rval; + String *tm; + + SwigType_remember(type); + + switch(SwigType_type(type)) { + case T_STRING: + rval = NewStringf("\"%s\"", value); + break; + case T_CHAR: + rval = NewStringf("\'%s\'", value); + break; + default: + rval = NewString(value); + } + + if((tm = Swig_typemap_lookup_new("consttab", n, name, 0))) { + Replaceall(tm, "$source", value); + Replaceall(tm, "$target", name); + Replaceall(tm, "$value", value); + Printf(s_cinit, "%s\n", tm); + } + return SWIG_OK; + } + + /* + * PHP4::pragma() + * + * Pragma directive. + * + * %pragma(php4) code="String" # Includes a string in the .php file + * %pragma(php4) include="file.pl" # Includes a file in the .php file + */ + + virtual int pragmaDirective(Node *n) { + if (!ImportMode) { + String *lang = Getattr(n,"lang"); + String *type = Getattr(n,"name"); + String *value = Getattr(n,"value"); + + if (Strcmp(lang,"php4") == 0) { + + if (Strcmp(type, "code") == 0) { + if (value) + Printf(pragma_code, "%s\n", value); + } else if (Strcmp(type, "include") == 0) { + if (value) + Printf(pragma_incl, "include \"%s\";\n", value); + } else if (Strcmp(type, "phpinfo") == 0) { + if (value) + Printf(pragma_phpinfo, "%s\n", value); + } else { + Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", + input_file, line_number); + } + } + } + return Language::pragmaDirective(n); + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + String *symname = Getattr(n,"sym:name"); + Setattr(n,"php:proxy",symname); + return Language::classDeclaration(n); + } + + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ + + virtual int classHandler(Node *n) { + constructors=0; + //SwigType *t = Getattr(n, "classtype"); + if(class_name) free(class_name); + class_name = Swig_copy_string(GetChar(n, "name")); + // String *use_class_name=SwigType_manglestr(SwigType_ltype(t)); + + if(shadow) { + char *rename = GetChar(n, "sym:name"); + if (!addSymbol(rename,n)) return SWIG_ERROR; + shadow_classname = Swig_copy_string(rename); + cs_entry = NewString(""); + Printf(cs_entry,"/* Function entries for %s */\n" + "static zend_function_entry %s_functions[] = {\n" + ,shadow_classname, shadow_classname); + + if(Strcmp(shadow_classname, module) == 0) { + Printf(stderr, "class name cannot be equal to module name: %s\n", shadow_classname); + SWIG_exit(1); + } + + Clear(shadow_classdef); + Clear(shadow_code); + + have_default_constructor = 0; + shadow_enum_code = NewString(""); + this_shadow_baseclass = NewString(""); + this_shadow_multinherit = NewString(""); + this_shadow_extra_code = NewString(""); + this_shadow_import = NewString(""); + + shadow_get_vars = NewHash(); + shadow_set_vars = NewHash(); + + /* Deal with inheritance */ + List *baselist = Getattr(n, "bases"); + + if(baselist) { + int class_count = 0; + Node *base = Firstitem(baselist); + + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + + if (base && is_shadow(Getattr(base, "name"))) { + class_count++; + Printf(this_shadow_baseclass, "%s", Getattr(base, "name")); + } + + if (base) for(base = Nextitem(baselist); base; base = Nextitem(baselist)) { + if (Getattr(base,"feature:ignore")) continue; + if(is_shadow(Getattr(base, "name"))) { + class_count++; + Printf(this_shadow_multinherit, "%s ", Getattr(base, "name")); + } + } + + if(class_count > 1) Printf(stderr, "Error: %s inherits from multiple base classes(%s %s). Multiple inheritance is not directly supported by PHP4, SWIG may support it at some point in the future.\n", shadow_classname, base, this_shadow_multinherit); + } + + /* Write out class init code */ + Printf(s_vdecl,"static zend_class_entry ce_swig_%s;\n",shadow_classname); + Printf(s_vdecl,"static zend_class_entry* ptr_ce_swig_%s=NULL;\n",shadow_classname); + } + + classnode=n; + Language::classHandler(n); + classnode=0; + + if(shadow) { + DOH *key; + int gcount, scount; + String *s_propget=NewString(""); + String *s_propset=NewString(""); + List *baselist = Getattr(n, "bases"); + Node *base = NULL; + + // If no constructor was generated (abstract class) we had better + // generate a constructor that raises an error about instantiating + // abstract classes + if (! constructors || Getattr(n,"abstract")) { + // have to write out fake constructor which raises an error when called + abstractConstructorHandler(n); + } + + Printf(s_oinit,"/* Define class %s */\n" + "INIT_OVERLOADED_CLASS_ENTRY(ce_swig_%s,\"%(lower)s\",%s_functions," + "NULL,_wrap_propget_%s,_wrap_propset_%s);\n", + shadow_classname,shadow_classname,shadow_classname, + shadow_classname,shadow_classname,shadow_classname); + + // ******** Write property SET handlers + Printf(s_header,"static int _wrap_propset_%s(zend_property_reference *property_reference, pval *value);\n", shadow_classname); + Printf(s_propset,"static int _wrap_propset_%s(zend_property_reference *property_reference, pval *value) { \n" + " zval * _value;\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " if (_propset_%s(property_reference, value)==SUCCESS) return SUCCESS;\n" + " /* set it ourselves as it is %s */\n" + " MAKE_STD_ZVAL(_value);\n" + " *_value=*value;\n" + " INIT_PZVAL(_value);\n" + " zval_copy_ctor(_value);\n" + " return add_property_zval_ex(property_reference->object,Z_STRVAL_P(&(property->element)),1+Z_STRLEN_P(&(property->element)),_value);\n" + "}\n", shadow_classname, shadow_classname,shadow_classname); + Printf(s_header,"static int _propset_%s(zend_property_reference *property_reference, pval *value);\n", shadow_classname); + Printf(s_propset,"static int _propset_%s(zend_property_reference *property_reference, pval *value) {\n", shadow_classname); + + if (baselist) base=Firstitem(baselist); + else base=NULL; + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + key = Firstkey(shadow_set_vars); + + // Print function header; we only need to find property name if there + // are properties for this class to look up... + if (key || ! base) { // or if we are base class and set it ourselves + Printf(s_propset," /* get the property name */\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " char *propname=Z_STRVAL_P(&(property->element));\n"); + } else { + if (base) { + Printf(s_propset," /* No extra properties for subclass %s */\n",shadow_classname); + } else { + Printf(s_propset," /* No properties for base class %s */\n",shadow_classname); + } + } + + scount=0; + while (key) { + if (scount++) Printf(s_propset," else"); + Printf(s_propset," if (strcmp(propname,\"%s\")==0) {\n" + " return _wrap_%s(property_reference, value);\n" + " }",Getattr(shadow_set_vars,key),key); + + key=Nextkey(shadow_set_vars); + } + + if (scount) Printf(s_propset," else"); + + // If there is a base class then chain it's handler else set directly + // try each base class handler, else set directly... + if (base) { + Printf(s_propset, " {\n /* chain to base class */\n"); + while(base) { + Printf(s_propset," if (_propset_%s(property_reference, value)==SUCCESS) return SUCCESS;\n", + GetChar(base, "sym:name")); + + base=Nextitem(baselist); + while (base && Getattr(base,"feature:ignore")) base=Nextitem(baselist); + } + Printf(s_propset," }\n"); + } + Printf(s_propset," return FAILURE;\n}\n\n"); + + // ******** Write property GET handlers + Printf(s_header,"static pval _wrap_propget_%s(zend_property_reference *property_reference);\n", shadow_classname); + Printf(s_propget,"static pval _wrap_propget_%s(zend_property_reference *property_reference) {\n" + " pval result;\n" + " pval **_result;\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " result.type = IS_NULL;\n" + " if (_propget_%s(property_reference, &result)==SUCCESS) return result;\n" + " /* return it ourselves */\n" + " if (zend_hash_find(Z_OBJPROP_P(property_reference->object),Z_STRVAL_P(&(property->element)),1+Z_STRLEN_P(&(property->element)),(void**)&_result)==SUCCESS) {\n" + " zval *_value;\n" + " MAKE_STD_ZVAL(_value);" + " *_value=**_result;\n" + " INIT_PZVAL(_value);\n" + " zval_copy_ctor(_value);\n" + " return *_value;\n" + " }\n" + " result.type = IS_NULL;\n" + " return result;\n" + "}\n", shadow_classname, shadow_classname); + Printf(s_header,"static int _propget_%s(zend_property_reference *property_reference, pval *value);\n", shadow_classname); + Printf(s_propget,"static int _propget_%s(zend_property_reference *property_reference, pval *value) {\n", shadow_classname); + + if (baselist) base=Firstitem(baselist); + else base=NULL; + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + key = Firstkey(shadow_get_vars); + + // Print function header; we only need to find property name if there + // are properties for this class to look up... + if (key || !base ) { // or if we are base class... + Printf(s_propget," /* get the property name */\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " char *propname=Z_STRVAL_P(&(property->element));\n"); + } else { + if (base) { + Printf(s_propget," /* No extra properties for subclass %s */\n",shadow_classname); + } else { + Printf(s_propget," /* No properties for base class %s */\n",shadow_classname); + } + } + + gcount=0; + while (key) { + if (gcount++) Printf(s_propget," else"); + Printf(s_propget," if (strcmp(propname,\"%s\")==0) {\n" + " *value=_wrap_%s(property_reference);\n" + " return SUCCESS;\n" + " }",Getattr(shadow_get_vars,key),key); + + key=Nextkey(shadow_get_vars); + } + + if (gcount) Printf(s_propget," else"); + + // If there is a base class then chain it's handler else return null + if (base) { + Printf(s_propget, " {\n /* chain to base class */\n"); + while(base) { + Printf(s_propget," if (_propget_%s(property_reference, value)==SUCCESS) return SUCCESS;\n", + GetChar(base, "sym:name")); + + base=Nextitem(baselist); + while (base && Getattr(base,"feature:ignore")) base=Nextitem(baselist); + } + Printf(s_propget," }\n"); + } + Printf(s_propget," return FAILURE;\n}\n\n"); + + // wrappers generated now... + + // add wrappers to output code + Printf(s_wrappers,"/* property handler for class %s */\n",shadow_classname); + Printv(s_wrappers,s_propget,s_propset,NIL); + + // Save class in class table + if (baselist) base=Firstitem(baselist); + else base=NULL; + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + + if (base) { + Printf(s_oinit,"if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,&ce_swig_%s,NULL))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n", + shadow_classname,shadow_classname,GetChar(base, "sym:name"), shadow_classname); + } else { + Printf(s_oinit,"if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,NULL,NULL))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n", + shadow_classname,shadow_classname, shadow_classname); + } + Printf(s_oinit,"\n"); + + + Printv(f_phpcode, shadow_classdef, shadow_code, NIL); + + // Write the enum initialisation code in a static block + // These are all the enums defined withing the c++ class. + + // PHP Needs to handle shadow enums properly still + if(strlen(Char(shadow_enum_code)) != 0 ) Printv(f_phpcode, "{\n /* enum */\n", shadow_enum_code, " }\n", NIL); + + free(shadow_classname); + shadow_classname = NULL; + + Delete(shadow_enum_code); shadow_enum_code = NULL; + Delete(this_shadow_baseclass); this_shadow_baseclass = NULL; + Delete(this_shadow_extra_code); this_shadow_extra_code = NULL; + Delete(this_shadow_import); this_shadow_import = NULL; + Delete(shadow_set_vars); shadow_set_vars = NULL; + Delete(shadow_get_vars); shadow_get_vars = NULL; + Delete(this_shadow_multinherit); this_shadow_multinherit = NULL; + + Printf(all_cs_entry,"%s { NULL, NULL, NULL}\n};\n",cs_entry); + //??delete cs_entry; + cs_entry=NULL; + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int memberfunctionHandler(Node *n) { + char *name = GetChar(n, "name"); + char *iname = GetChar(n, "sym:name"); + SwigType *t = Getattr(n, "type"); + ParmList *l = Getattr(n, "parms"); + + this->Language::memberfunctionHandler(n); + + if(shadow) { + char *realname = iname ? iname : name; + String *php_function_name = Swig_name_member(shadow_classname, realname); + + cpp_func(iname, t, l, realname, php_function_name); + + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ + + virtual int membervariableHandler(Node *n) { + + wrapping_member = 1; + variable_wrapper_flag = 1; + Language::membervariableHandler(n); + wrapping_member = 0; + variable_wrapper_flag = 0; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmemberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler(Node *n) { + char *name = GetChar(n, "name"); + char *iname = GetChar(n, "sym:name"); + + Language::staticmemberfunctionHandler(n); + + if(shadow) { + String *symname = Getattr(n, "sym:name"); + static_flag = 1; + char *realname = iname ? iname : name; + String *php_function_name = Swig_name_member(shadow_classname, realname); + cpp_func(Char(symname), Getattr(n, "type"), Getattr(n, "parms"), symname, php_function_name); + static_flag = 0; + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmembervariableHandler() + * ------------------------------------------------------------ */ + + virtual int staticmembervariableHandler(Node *n) { + SwigType *d = Getattr(n, "type"); + char *iname = GetChar(n, "sym:name"); + char *name = GetChar(n, "name"); + String *static_name = NewStringf("%s::%s", class_name, name); +// String *use_class_name=SwigType_manglestr(SwigType_ltype(t)); + Wrapper *f; + + /* A temporary(!) hack for static member variables. + * Php currently supports class functions, but not class variables. + * Until it does, we convert a class variable to a class function + * that returns the current value of the variable. E.g. + * + * class Example { + * public: + * static int ncount; + * }; + * + * would be available in php as Example::ncount() + */ + static_flag = 1; + if(Getattr(n,"feature:immutable")) { + const_flag = 1; + } + cpp_func(iname, d, 0, iname); + static_flag = 0; + + create_command(iname, Char(Swig_name_wrapper(iname))); + + f = NewWrapper(); + + Printv(f->def, "ZEND_NAMED_FUNCTION(", Swig_name_wrapper(iname), ") {\n", NIL); + + /* If a argument is given we set the variable. Then we return + * the current value + */ + + Printf(f->code, + "zval **args[1];\n" + "int argcount;\n\n" + "argcount = ZEND_NUM_ARGS();\n" + "if(argcount > %d) WRONG_PARAM_COUNT;\n\n", (const_flag? 0 : 1)); + + if(!const_flag) { + Printf(f->code, "if(argcount) {\n"); + + Printf(f->code, "if(zend_get_parameters_array_ex(argcount, args) != SUCCESS) WRONG_PARAM_COUNT;\n"); + + switch(SwigType_type(d)) { + case T_BOOL: + case T_INT: + case T_SHORT: + case T_LONG: + case T_SCHAR: + case T_UINT: + case T_USHORT: + case T_ULONG: + case T_UCHAR: + Printf(f->code, + "convert_to_long_ex(args[0]);\n" + "%s = Z_LVAL_PP(args[0]);\n", static_name); + break; + case T_CHAR: + Printf(f->code, + "convert_to_string_ex(args[0]);\n" + "%s = estrdup(Z_STRVAL(args[0]));\n", static_name); + break; + case T_DOUBLE: + case T_FLOAT: + Printf(f->code, + "convert_to_double_ex(args[0]);\n" + "%s = Z_DVAL_PP(args[0]);\n", + static_name); + break; + case T_VOID: + break; + case T_USER: + Printf(f->code, "convert_to_string_ex(args[0]);\n"); + get_pointer(Char(iname), (char*)"variable", (char*)"args[0]", Char(static_name), d, f->code, (char *)"RETURN_FALSE"); + break; + case T_POINTER: + case T_ARRAY: + case T_REFERENCE: + Printf(f->code, "convert_to_string_ex(args[0]);\n"); + get_pointer(Char(iname), (char*)"variable", (char*)"args[0]", Char(static_name), d, f->code, (char*)"RETURN_FALSE"); + break; + default: + Printf(stderr,"%s : Line %d, Unable to use type %s as a class variable.\n", input_file, line_number, SwigType_str(d,0)); + break; + } + + Printf(f->code, "}\n\n"); + + } /* end of const_flag */ + + switch(SwigType_type(d)) { + case T_BOOL: + case T_INT: + case T_SHORT: + case T_LONG: + case T_SCHAR: + case T_UINT: + case T_USHORT: + case T_ULONG: + case T_UCHAR: + Printf(f->code, + "RETURN_LONG(%s);\n", static_name); + break; + case T_DOUBLE: + case T_FLOAT: + Printf(f->code, + "RETURN_DOUBLE(%s);\n", static_name); + break; + case T_CHAR: + Printf(f->code, + "{\nchar ctemp[2];\n" + "ctemp[0] = %s;\n" + "ctemp[1] = 0;\n" + "RETURN_STRING(ctemp, 1);\n}\n", + static_name); + break; + + case T_USER: + case T_POINTER: + Printf(f->code, + "SWIG_SetPointerZval(return_value, (void *)%s, " + "SWIGTYPE%s);\n", static_name, SwigType_manglestr(d)); + break; + case T_STRING: + Printf(f->code, "RETURN_STRING(%s, 1);\n", static_name); + break; + } + + + Printf(f->code, "}\n"); + + const_flag = 0; + + Wrapper_print(f, s_wrappers); + + return SWIG_OK; + } + + + void SwigToPhpType(SwigType *t, String_or_char *pname, String* php_type, int shadow_flag) { + char *ptype = 0; + + if(shadow_flag) + ptype = PhpTypeFromTypemap((char*)"pstype", t, pname,(char*)""); + if(!ptype) + ptype = PhpTypeFromTypemap((char*)"ptype",t,pname,(char*)""); + + + if(ptype) { + Printf(php_type, ptype); + free(ptype); + } + else { + /* Map type here */ + switch(SwigType_type(t)) { + case T_CHAR: + case T_SCHAR: + case T_UCHAR: + case T_SHORT: + case T_USHORT: + case T_INT: + case T_UINT: + case T_LONG: + case T_ULONG: + case T_FLOAT: + case T_DOUBLE: + case T_BOOL: + case T_STRING: + case T_VOID: + Printf(php_type, ""); + break; + case T_POINTER: + case T_REFERENCE: + case T_USER: + if(shadow_flag && is_shadow(t)) + Printf(php_type, Char(is_shadow(t))); + else + Printf(php_type, ""); + break; + case T_ARRAY: + /* TODO */ + break; + default: + Printf(stderr, "SwigToPhpType: unhandled data type: %s\n", SwigType_str(t,0)); + break; + } + } + } + + + char *PhpTypeFromTypemap(char *op, SwigType *t, String_or_char *pname, String_or_char *lname) { + String *tms; + char bigbuf[1024]; + char *tm; + char *c = bigbuf; + if(!(tms = Swig_typemap_lookup(op, t, pname, lname, (char*)"", (char*)"", NULL))) return NULL; + + tm = Char(tms); + while(*tm && (isspace(*tm) || *tm == '{')) tm++; + while(*tm && *tm != '}') *c++ = *tm++; + *c='\0'; + return Swig_copy_string(bigbuf); + } + + int abstractConstructorHandler(Node *n) { + char *iname = GetChar(n, "sym:name"); + if (shadow) { + Wrapper *f; + f = NewWrapper(); + + // constructor header + if (cs_entry) Printf(cs_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " _wrap_new_%s, NULL)\n", iname,iname); + // now constructor body + Printf(f_h, "ZEND_NAMED_FUNCTION(_wrap_new_%s);\n",iname); + Printf(f->def, "ZEND_NAMED_FUNCTION(_wrap_new_%s) {\n" + "zend_error(E_ERROR,\"Cannot create swig object type: %s as the underlying object is abstract\");\n" + "}\n\n", iname, iname); + Wrapper_print(f,s_wrappers); + DelWrapper(f); + } + return SWIG_OK; + } + /* ------------------------------------------------------------ + * constructorHandler() + * ------------------------------------------------------------ */ + + virtual int constructorHandler(Node *n) { + char *iname = GetChar(n, "sym:name"); + + if (shadow) native_constructor = (strcmp(iname, shadow_classname) == 0)?\ + NATIVE_CONSTRUCTOR:ALTERNATIVE_CONSTRUCTOR; + else native_constructor=0; + constructors++; + Language::constructorHandler(n); + + if(shadow) { + // But we also need one per wrapped-class + if (cs_entry) Printf(cs_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " _wrap_new_%s, NULL)\n", iname,iname); + } + + native_constructor = 0; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * destructorHandler() + * ------------------------------------------------------------ */ + + virtual int destructorHandler(Node *n) { + char *iname = GetChar(n, "sym:name"); + + destructor=1; + Language::destructorHandler(n); + destructor=0; + + // we don't give user access to destructors, they have to unset var + // and let php dispose instead + if(0 && shadow) { + // But we also need one per wrapped-class + if (cs_entry) Printf(cs_entry, + " ZEND_NAMED_FE(_destroy_%(lower)s,\n" + " _wrap_delete_%s, NULL)\n", iname,iname); + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberconstantHandler() + * ------------------------------------------------------------ */ + + virtual int memberconstantHandler(Node *n) { + wrapping_member = 1; + Language::memberconstantHandler(n); + wrapping_member = 0; + return SWIG_OK; + } + + // This method is quite stale and ought to be factored out + void cpp_func(char *iname, SwigType *t, ParmList *l, String *php_function_name, String *handler_name = NULL) { + if(!shadow) return; + + // if they didn't provide a handler name, use the realname + if (! handler_name) handler_name=php_function_name; + + if(l) { + if(SwigType_type(Getattr(l, "type")) == T_VOID) { + l = nextSibling(l); + } + } + + // But we also need one per wrapped-class + // Printf(f_h, "x ZEND_NAMED_FUNCTION(%s);\n", Swig_name_wrapper(handler_name)); + if (cs_entry && !(variable_wrapper_flag && shadow)) Printf(cs_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " %s, NULL)\n", php_function_name,Swig_name_wrapper(handler_name)); + + if(variable_wrapper_flag) { return; } + + /* Workaround to overcome Getignore(p) not working - p does not always + * have the Getignore attribute set. Noticeable when cpp_func is called + * from cpp_member_func() + */ + + Wrapper *f = NewWrapper(); + emit_args(NULL, l, f); + DelWrapper(f); + + /*Workaround end */ + + } + +}; /* class PHP4 */ + +/* ----------------------------------------------------------------------------- + * swig_php() - Instantiate module + * ----------------------------------------------------------------------------- */ + +static PHP4 *maininstance=0; + +// We use this function to be able to write out zend_register_list_destructor_ex +// lines for most things in the type table +// NOTE: it's a function NOT A PHP4::METHOD +extern "C" +void typetrace(SwigType *ty, String *mangled, String *clientdata) { + Node *class_node; + if (!zend_types) { + zend_types=NewHash(); + } + // we want to know if the type which reduced to this has a constructor + if ((class_node=maininstance->classLookup(ty))) { + if (! Getattr(zend_types,mangled)) { + // OK it may have been set before by a different SwigType but it would + // have had the same underlying class node I think + // - it is certainly required not to have different originating class + // nodes for the same SwigType + Setattr(zend_types,mangled,class_node); + } + } else { // a non-class pointer + Setattr(zend_types,mangled,NOTCLASS); + } + if (r_prevtracefunc) (*r_prevtracefunc)(ty, mangled, (String *) clientdata); +} + +extern "C" Language * +swig_php(void) { + maininstance=new PHP4(); + if (! r_prevtracefunc) { + r_prevtracefunc=SwigType_remember_trace(typetrace); + } else { + Printf(stderr,"php4 Typetrace vector already saved!\n"); + assert(0); + } + return maininstance; +} + diff --git a/Source/Modules1.1/pike.cxx b/Source/Modules1.1/pike.cxx new file mode 100644 index 000000000..bcd51763e --- /dev/null +++ b/Source/Modules1.1/pike.cxx @@ -0,0 +1,881 @@ +/*********************************************************************** + * Pike language module for SWIG + ***********************************************************************/ + +char cvsroot_pike_cxx[] = "$Header$"; + +#include "swigmod.h" +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +class PIKE : public Language { +private: + + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + String *PrefixPlusUnderscore; + int current; + + // Wrap modes + enum { + NO_CPP, + MEMBER_FUNC, + CONSTRUCTOR, + DESTRUCTOR, + MEMBER_VAR, + CLASS_CONST, + STATIC_FUNC, + STATIC_VAR + }; + +public: + + /* --------------------------------------------------------------------- + * PIKE() + * + * Initialize member data + * --------------------------------------------------------------------- */ + + PIKE() { + f_runtime = 0; + f_header = 0; + f_wrappers = 0; + f_init = 0; + PrefixPlusUnderscore = 0; + current = NO_CPP; + } + + /* --------------------------------------------------------------------- + * main() + * + * Parse command line options and initializes variables. + * --------------------------------------------------------------------- */ + + virtual void main(int argc, char *argv[]) { + + /* Set location of SWIG library */ + SWIG_library_directory("pike"); + + /* Look for certain command line options */ + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_PIKE_RUNTIME); + SWIG_exit(EXIT_SUCCESS); + } + } + } + + /* Add a symbol to the parser for conditional compilation */ + Preprocessor_define("SWIGPIKE 1", 0); + + /* Set language-specific configuration file */ + SWIG_config_file("pike.swg"); + + /* Set typemap language */ + SWIG_typemap_lang("pike"); + + /* Enable overloaded methods support */ + allow_overloading(); + } + + /* --------------------------------------------------------------------- + * top() + * --------------------------------------------------------------------- */ + + virtual int top(Node *n) { + /* Get the module name */ + String *module = Getattr(n, "name"); + + /* Get the output file name */ + String *outfile = Getattr(n, "outfile"); + + /* Open the output file */ + f_runtime = NewFile(outfile, "w"); + if (!f_runtime) { + Printf(stderr, "*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header", f_header); + Swig_register_filebyname("wrapper", f_wrappers); + Swig_register_filebyname("runtime", f_runtime); + Swig_register_filebyname("init", f_init); + + /* Standard stuff for the SWIG runtime section */ + Swig_banner(f_runtime); + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } + + Printf(f_header, "#define SWIG_init pike_module_init\n"); + Printf(f_header, "#define SWIG_name \"%s\"\n\n", module); + + /* Change naming scheme for constructors and destructors */ + Swig_name_register("construct","%c_create"); + Swig_name_register("destroy","%c_destroy"); + + /* Current wrap type */ + current = NO_CPP; + + /* Emit code for children */ + Language::top(n); + + /* Close the initialization function */ + Printf(f_init, "}\n"); + SwigType_emit_type_table(f_runtime, f_wrappers); + + /* Close all of the files */ + Dump(f_header, f_runtime); + Dump(f_wrappers, f_runtime); + Wrapper_pretty_print(f_init, f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + + /* Done */ + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * importDirective() + * ------------------------------------------------------------ */ + + virtual int importDirective(Node *n) { + String *modname = Getattr(n,"module"); + if (modname) { + Printf(f_init,"pike_require(\"%s\");\n", modname); + } + return Language::importDirective(n); + } + + /* ------------------------------------------------------------ + * strip() + * + * For names that begin with the current class prefix plus an + * underscore (e.g. "Foo_enum_test"), return the base function + * name (i.e. "enum_test"). + * ------------------------------------------------------------ */ + + String *strip(const DOHString_or_char *name) { + String *s = Copy(name); + if (Strncmp(name, PrefixPlusUnderscore, Len(PrefixPlusUnderscore)) != 0) { + return s; + } + Replaceall(s, PrefixPlusUnderscore, ""); + return s; + } + + /* ------------------------------------------------------------ + * add_method() + * ------------------------------------------------------------ */ + + void add_method(Node *n, const DOHString_or_char *name, const DOHString_or_char *function, const DOHString_or_char *description) { + String *rename; + if (current != NO_CPP) { + rename = strip(name); + } else { + rename = NewString(name); + } + Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description); + Delete(rename); + } + + /* --------------------------------------------------------------------- + * functionWrapper() + * + * Create a function declaration and register it with the interpreter. + * --------------------------------------------------------------------- */ + + virtual int functionWrapper(Node *n) { + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + + Parm *p; + String *tm; + int i; + + String *overname = 0; + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; + } + + Wrapper *f = NewWrapper(); + + /* Write code to extract function parameters. */ + emit_args(d, l, f); + + /* Attach the standard typemaps */ + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + + /* Get number of required and total arguments */ + int num_arguments = emit_num_arguments(l); + int varargs = emit_isvarargs(l); + + /* Which input argument to start with? */ + int start = (current == MEMBER_FUNC || current == MEMBER_VAR || current == DESTRUCTOR) ? 1 : 0; + + /* Offset to skip over the attribute name */ + // int offset = (current == MEMBER_VAR) ? 1 : 0; + int offset = 0; + + String *wname = Swig_name_wrapper(iname); + if (overname) { + Append(wname,overname); + } + + Printv(f->def, "static void ", wname, "(INT32 args) {", NIL); + + /* Generate code for argument marshalling */ + String *description = NewString(""); + char source[64]; + for (i = 0, p = l; i < num_arguments; i++) { + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); + + if (i < start) { + String *lstr = SwigType_lstr(pt,0); + Printf(f->code, "%s = (%s) THIS;\n", ln, lstr); + Delete(lstr); + } else { + /* Look for an input typemap */ + sprintf(source, "sp[%d-args]", i-start+offset); + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm, "$source", source); + Replaceall(tm, "$target", ln); + Replaceall(tm, "$input", source); + Setattr(p, "emit:input", source); + Printf(f->code, "%s\n", tm); + String *pikedesc = Getattr(p, "tmap:in:pikedesc"); + if (pikedesc) { + Printv(description, pikedesc, " ", NIL); + } + p = Getattr(p,"tmap:in:next"); + continue; + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument.\n",SwigType_str(pt,0)); + break; + } + } + p = nextSibling(p); + } + + /* Check for trailing varargs */ + if (varargs) { + if (p && (tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$input", "varargs"); + Printv(f->code,tm,"\n",NIL); + } + } + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert cleanup code */ + String *cleanup = NewString(""); + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert argument output code */ + String *outarg = NewString(""); + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","resultobj"); + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); + } + } + + /* Emit the function call */ + emit_action(n,f); + + /* Clear the return stack */ + Printf(f->code, "pop_n_elems(args);\n"); + + /* Return the function value */ + if (current == CONSTRUCTOR) { + Printv(f->code, "THIS = (void *) result;\n", NIL); + Printv(description, ", tVoid", NIL); + } else if (current == DESTRUCTOR) { + Printv(description, ", tVoid", NIL); + } else { + Wrapper_add_local(f, "resultobj", "struct object *resultobj"); + Printv(description, ", ", NIL); + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source", "result"); + Replaceall(tm,"$target", "resultobj"); + Replaceall(tm,"$result", "resultobj"); + if (Getattr(n,"feature:new")) { + Replaceall(tm,"$owner","1"); + } else { + Replaceall(tm,"$owner","0"); + } + String *pikedesc = Getattr(n, "tmap:out:pikedesc"); + if (pikedesc) { + Printv(description, pikedesc, NIL); + } + Printf(f->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s in function %s.\n", SwigType_str(d,0), name); + } + } + + /* Output argument output code */ + Printv(f->code,outarg,NIL); + + /* Output cleanup code */ + Printv(f->code,cleanup,NIL); + + /* Look to see if there is any newfree cleanup code */ + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } + } + + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } + + /* Close the function */ + Printf(f->code, "}\n"); + + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); + + /* Substitute the function name */ + Replaceall(f->code,"$symname",iname); + Replaceall(f->code,"$result","resultobj"); + + /* Dump the function out */ + Wrapper_print(f,f_wrappers); + + /* Now register the function with the interpreter. */ + if (!Getattr(n,"sym:overloaded")) { + add_method(n, iname, wname, description); + } else { + Setattr(n,"wrap:name", wname); + if (!Getattr(n,"sym:nextSibling")) { + dispatchFunction(n); + } + } + + Delete(cleanup); + Delete(outarg); + Delete(description); + Delete(wname); + DelWrapper(f); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * dispatchFunction() + * + * Emit overloading dispatch function + * ------------------------------------------------------------ */ + + void dispatchFunction(Node *n) { + /* Last node in overloaded chain */ + + int maxargs; + String *tmp = NewString(""); + String *dispatch = Swig_overload_dispatch(n,"return %s(self,args);",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *f = NewWrapper(); + String *symname = Getattr(n,"sym:name"); + String *wname = Swig_name_wrapper(symname); + + Printv(f->def, + "struct object *", wname, + "(struct object *self, struct object *args) {", + NULL); + + + Wrapper_add_local(f,"argc","INT32 argc"); + Printf(tmp,"struct object *argv[%d]", maxargs+1); + Wrapper_add_local(f,"argv",tmp); + Wrapper_add_local(f,"ii","INT32 ii"); + Printf(f->code,"argc = sizeof(args);\n"); + Printf(f->code,"for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n",maxargs); + Printf(f->code,"argv[ii] = array_index(args,&argv[ii],ii);\n"); + Printf(f->code,"}\n"); + + Replaceall(dispatch,"$args","self,args"); + Printv(f->code,dispatch,"\n",NIL); + Printf(f->code,"No matching function for overloaded '%s'\n", symname); + Printf(f->code,"return NULL;\n"); + Printv(f->code,"}\n",NIL); + Wrapper_print(f,f_wrappers); + add_method(n,symname,wname,0); + + DelWrapper(f); + Delete(dispatch); + Delete(tmp); + Delete(wname); + } + + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + // return Language::variableWrapper(n); + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *wname; + // static int have_globals = 0; + String *tm; + Wrapper *getf, *setf; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + getf = NewWrapper(); + setf = NewWrapper(); + + wname = Swig_name_wrapper(iname); + + /* Create a function for setting the value of the variable */ + + Printf(setf->def,"static int %s_set(object *_val) {", wname); + if (!Getattr(n,"feature:immutable")) { + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","_val"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","_val"); + Printf(setf->code,"%s\n",tm); + Delete(tm); + } else { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, + "Unable to set variable of type %s.\n", SwigType_str(t,0)); + } + Printf(setf->code," return 0;\n"); + } else { + /* Is a readonly variable. Issue an error */ + + Printv(setf->code, + tab4, "Variable $iname is read-only.\n", + tab4, "return 1;\n", + NIL); + + } + + Printf(setf->code,"}\n"); + Wrapper_print(setf,f_wrappers); + + /* Create a function for getting the value of a variable */ + Printf(getf->def,"static object *%s_get() {", wname); + Wrapper_add_local(getf,"pikeobj", "object *pyobj"); + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","pikeobj"); + Replaceall(tm,"$result","pikeobj"); + Printf(getf->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to link with type %s\n", SwigType_str(t,0)); + } + + Printf(getf->code," return pikeobj;\n}\n"); + Wrapper_print(getf,f_wrappers); + + /* Now add this to the variable linking mechanism */ + Printf(f_init,"\t SWIG_addvarlink(SWIG_globals,(char*)\"%s\",%s_get, %s_set);\n", iname, wname, wname); + + DelWrapper(setf); + DelWrapper(getf); + return SWIG_OK; + + } + + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + + Swig_require(&n, "*sym:name", "type", "value", NIL); + + String *symname = Getattr(n, "sym:name"); + SwigType *type = Getattr(n, "type"); + String *value = Getattr(n, "value"); + + /* Special hook for member pointer */ + if (SwigType_type(type) == T_MPOINTER) { + String *wname = Swig_name_wrapper(symname); + Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value); + value = wname; + } + + /* Perform constant typemap substitution */ + String *tm = Swig_typemap_lookup_new("constant", n, value, 0); + if (tm) { + Replaceall(tm, "$source", value); + Replaceall(tm, "$target", symname); + Replaceall(tm, "$symname", symname); + Replaceall(tm, "$value", value); + Printf(f_init, "%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value); + } + + Swig_restore(&n); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * nativeWrapper() + * ------------------------------------------------------------ */ + + virtual int nativeWrapper(Node *n) { + // return Language::nativeWrapper(n); + String *name = Getattr(n,"sym:name"); + String *wrapname = Getattr(n,"wrap:name"); + + if (!addSymbol(wrapname,n)) return SWIG_ERROR; + + add_method(n, name, wrapname,0); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * enumDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumDeclaration(Node *n) { + return Language::enumDeclaration(n); + } + + /* ------------------------------------------------------------ + * enumvalueDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumvalueDeclaration(Node *n) { + return Language::enumvalueDeclaration(n); + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + return Language::classDeclaration(n); + } + + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ + + virtual int classHandler(Node *n) { + + String *symname = Getattr(n, "sym:name"); + if (!addSymbol(symname, n)) + return SWIG_ERROR; + + PrefixPlusUnderscore = NewStringf("%s_", getClassPrefix()); + + Printf(f_init, "start_new_program();\n"); + + /* Handle inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist) > 0) { + Node *base = Firstitem(baselist); + while (base) { + char *basename = Char(Getattr(base,"name")); + if (SwigType_istemplate(basename)) { + basename = Char(SwigType_namestr(basename)); + } + SwigType *basetype = NewString(basename); + SwigType_add_pointer(basetype); + SwigType_remember(basetype); + String *basemangle = SwigType_manglestr(basetype); + Printf(f_init, "low_inherit((struct program *) SWIGTYPE%s->clientdata, 0, 0, 0, 0, 0);\n", basemangle); + Delete(basemangle); + Delete(basetype); + base = Nextitem(baselist); + } + } else { + Printf(f_init, "ADD_STORAGE(swig_object_wrapper);\n"); + } + + Language::classHandler(n); + + /* Accessors for member variables */ + /* + List *membervariables = Getattr(n,"membervariables"); + if (membervariables && Len(membervariables) > 0) { + membervariableAccessors(membervariables); + } + */ + + /* Done, close the class */ + Printf(f_init, "add_program_constant(\"%s\", pr = end_program(), 0);\n", symname); + + SwigType *tt = NewString(symname); + SwigType_add_pointer(tt); + SwigType_remember(tt); + String *tm = SwigType_manglestr(tt); + Printf(f_init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) pr);\n", tm); + Delete(tm); + Delete(tt); + + Delete(PrefixPlusUnderscore); PrefixPlusUnderscore = 0; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberfunctionHandler() + * + * Method for adding C++ member function + * ------------------------------------------------------------ */ + + virtual int memberfunctionHandler(Node *n) { + current = MEMBER_FUNC; + Language::memberfunctionHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constructorHandler() + * + * Method for adding C++ member constructor + * ------------------------------------------------------------ */ + + virtual int constructorHandler(Node *n) { + current = CONSTRUCTOR; + Language::constructorHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * destructorHandler() + * ------------------------------------------------------------ */ + + virtual int destructorHandler(Node *n) { + current = DESTRUCTOR; + Language::destructorHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * membervariableAccessors() + * ------------------------------------------------------------ */ + + void membervariableAccessors(List *membervariables) { + String *name; + Node *n; + bool need_setter; + String *funcname; + + /* If at least one of them is mutable, we need a setter */ + need_setter = false; + n = Firstitem(membervariables); + while (n) { + if (!Getattr(n, "feature:immutable")) { + need_setter = true; + break; + } + n = Nextitem(membervariables); + } + + /* Create a function to set the values of the (mutable) variables */ + if (need_setter) { + Wrapper *wrapper = NewWrapper(); + String *setter = Swig_name_member(getClassPrefix(), (char *) "`->="); + String *wname = Swig_name_wrapper(setter); + Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL); + Printf(wrapper->locals, "char *name = (char *) STR0(sp[0-args].u.string);\n"); + + n = Firstitem(membervariables); + while (n) { + if (!Getattr(n, "feature:immutable")) { + name = Getattr(n, "name"); + funcname = Swig_name_wrapper(Swig_name_set(Swig_name_member(getClassPrefix(), name))); + Printf(wrapper->code, "if (!strcmp(name, \"%s\")) {\n", name); + Printf(wrapper->code, "%s(args);\n", funcname); + Printf(wrapper->code, "return;\n"); + Printf(wrapper->code, "}\n"); + Delete(funcname); + } + n = Nextitem(membervariables); + } + + /* Close the function */ + Printf(wrapper->code, "pop_n_elems(args);\n"); + Printf(wrapper->code, "}\n"); + + /* Dump wrapper code to the output file */ + Wrapper_print(wrapper, f_wrappers); + + /* Register it with Pike */ + String *description = NewString("tStr tFloat, tVoid"); + add_method(Firstitem(membervariables), "`->=", wname, description); + Delete(description); + + /* Clean up */ + Delete(wname); + Delete(setter); + DelWrapper(wrapper); + } + + /* Create a function to get the values of the (mutable) variables */ + Wrapper *wrapper = NewWrapper(); + String *getter = Swig_name_member(getClassPrefix(), (char *) "`->"); + String *wname = Swig_name_wrapper(getter); + Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL); + Printf(wrapper->locals, "char *name = (char *) STR0(sp[0-args].u.string);\n"); + + n = Firstitem(membervariables); + while (n) { + name = Getattr(n, "name"); + funcname = Swig_name_wrapper(Swig_name_get(Swig_name_member(getClassPrefix(), name))); + Printf(wrapper->code, "if (!strcmp(name, \"%s\")) {\n", name); + Printf(wrapper->code, "%s(args);\n", funcname); + Printf(wrapper->code, "return;\n"); + Printf(wrapper->code, "}\n"); + Delete(funcname); + n = Nextitem(membervariables); + } + + /* Close the function */ + Printf(wrapper->code, "pop_n_elems(args);\n"); + Printf(wrapper->code, "}\n"); + + /* Dump wrapper code to the output file */ + Wrapper_print(wrapper, f_wrappers); + + /* Register it with Pike */ + String *description = NewString("tStr, tMix"); + add_method(Firstitem(membervariables), "`->", wname, description); + Delete(description); + + /* Clean up */ + Delete(wname); + Delete(getter); + DelWrapper(wrapper); + } + + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ + + virtual int membervariableHandler(Node *n) { + List *membervariables = Getattr(getCurrentClass(),"membervariables"); + if (!membervariables) { + membervariables = NewList(); + Setattr(getCurrentClass(),"membervariables",membervariables); + } + Append(membervariables,n); + current = MEMBER_VAR; + Language::membervariableHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* ----------------------------------------------------------------------- + * staticmemberfunctionHandler() + * + * Wrap a static C++ function + * ---------------------------------------------------------------------- */ + + virtual int staticmemberfunctionHandler(Node *n) { + current = STATIC_FUNC; + Language::staticmemberfunctionHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberconstantHandler() + * + * Create a C++ constant + * ------------------------------------------------------------ */ + + virtual int memberconstantHandler(Node *n) { + current = CLASS_CONST; + constantWrapper(n); + current = NO_CPP; + return SWIG_OK; + } + + /* --------------------------------------------------------------------- + * staticmembervariableHandler() + * --------------------------------------------------------------------- */ + + virtual int staticmembervariableHandler(Node *n) { + current = STATIC_VAR; + Language::staticmembervariableHandler(n); + current = NO_CPP; + return SWIG_OK; + } +}; + +/* ----------------------------------------------------------------------------- + * swig_pike() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_pike(void) { + return new PIKE(); +} + + + + + diff --git a/Source/Modules1.1/python.cxx b/Source/Modules1.1/python.cxx index c58fae78a..6651ace92 100644 --- a/Source/Modules1.1/python.cxx +++ b/Source/Modules1.1/python.cxx @@ -9,1562 +9,1260 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_python_cxx[] = "$Header$"; -#include "swig11.h" -#include "python.h" +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +#include <ctype.h> + +#define PYSHADOW_MEMBER 0x2 static String *const_code = 0; static String *shadow_methods = 0; static String *module = 0; +static String *mainmodule = 0; static String *interface = 0; static String *global_name = 0; -static int shadow = 0; -static int have_defarg = 0; -static int have_output; +static int shadow = 1; static int use_kw = 0; -static int noopt = 1; -static FILE *f_shadow; -static Hash *hash; -static Hash *symbols; -static String *classes; -static String *func; -static String *vars; -static String *pragma_include = 0; + +static File *f_runtime = 0; +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; +static File *f_shadow = 0; +static File *f_shadow_stubs = 0; + static String *methods; -static char *class_name; +static String *class_name; +static String *shadow_indent = 0; +static int in_class = 0; +static int classic = 0; -static char *usage = (char *)"\ +/* C++ Support + Shadow Classes */ + +static int have_constructor; +static int have_repr; +static String *real_classname; + +static const char *usage = (char *)"\ Python Options (available with -python)\n\ + -ldflags - Print runtime libraries to link with\n\ -globals name - Set name used to access C global variable ('cvar' by default).\n\ - -module name - Set module name\n\ -interface name - Set the lib name\n\ -keyword - Use keyword arguments\n\ - -noopt - No optimized shadows (pre 1.5.2)\n\ - -opt - Optimized shadow classes (1.5.2 or later)\n\ - -shadow - Generate shadow classes. \n\n"; - -/* Test to see if a type corresponds to something wrapped with a shadow class */ -static DOH *is_shadow(SwigType *t) { - DOH *r; - SwigType *lt = Swig_clocal_type(t); - r = Getattr(hash,lt); - Delete(lt); - return r; -} + -classic - Use classic classes only\n\ + -noexcept - No automatic exception handling.\n\ + -noproxy - Don't generate proxy classes. \n\n"; -/* ----------------------------------------------------------------------------- - * PYTHON::parse_args() - * ----------------------------------------------------------------------------- */ -void -PYTHON::parse_args(int argc, char *argv[]) { - int i; - Swig_swiglib_set("python"); +class PYTHON : public Language { +public: + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { - for (i = 1; i < argc; i++) { + SWIG_library_directory("python"); + + for (int i = 1; i < argc; i++) { if (argv[i]) { - /* Added edz@bsn.com */ if(strcmp(argv[i],"-interface") == 0) { - if (argv[i+1]) { - interface = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - /* end added */ - } else if (strcmp(argv[i],"-globals") == 0) { - if (argv[i+1]) { - global_name = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if (strcmp(argv[i],"-shadow") == 0) { - shadow = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-noopt") == 0) { - noopt = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-opt") == 0) { - noopt = 0; + if (argv[i+1]) { + interface = NewString(argv[i+1]); Swig_mark_arg(i); - } else if (strcmp(argv[i],"-keyword") == 0) { - use_kw = 1; + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + /* end added */ + } else if (strcmp(argv[i],"-globals") == 0) { + if (argv[i+1]) { + global_name = NewString(argv[i+1]); Swig_mark_arg(i); - } else if (strcmp(argv[i],"-help") == 0) { - fputs(usage,stderr); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); } + } else if ((strcmp(argv[i],"-shadow") == 0) || ((strcmp(argv[i],"-proxy") == 0))) { + shadow = 1; + Swig_mark_arg(i); + } else if ((strcmp(argv[i],"-noproxy") == 0)) { + shadow = 0; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-keyword") == 0) { + use_kw = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-classic") == 0) { + classic = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_PYTHON_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } } + } + if (!global_name) global_name = NewString("cvar"); + Preprocessor_define("SWIGPYTHON 1", 0); + SWIG_typemap_lang("python"); + SWIG_config_file("python.swg"); + allow_overloading(); } - if (!global_name) global_name = NewString("cvar"); - Preprocessor_define((void *) "SWIGPYTHON", 0); -} -/* ----------------------------------------------------------------------------- - * PYTHON::import() - * ----------------------------------------------------------------------------- */ -void -PYTHON::import(String *modname) { - if (shadow) { - Printf(f_shadow,"\nfrom %s import *\n", modname); - } -} -/* ----------------------------------------------------------------------------- - * PYTHON::add_method() - * ----------------------------------------------------------------------------- */ -void -PYTHON::add_method(String *name, String *function, int kw) { - if (!kw) - Printf(methods,"\t { \"%s\", %s, METH_VARARGS },\n", name, function); - else - Printf(methods,"\t { \"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS },\n", name, function); -} + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ -/* ----------------------------------------------------------------------------- - * PYTHON::initialize() - * ----------------------------------------------------------------------------- */ -void -PYTHON::initialize(String *modname) { - char filen[256]; - - hash = NewHash(); - symbols = NewHash(); - const_code = NewString(""); - shadow_methods = NewString(""); - classes = NewString(""); - func = NewString(""); - vars = NewString(""); - pragma_include = NewString(""); - methods = NewString(""); - - Swig_banner(f_runtime); - - Printf(f_runtime,"#define SWIGPYTHON\n"); - if (NoInclude) - Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); - - if (Swig_insert_file("common.swg", f_runtime) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate common.swg. (Possible installation problem).\n"); - Swig_exit (EXIT_FAILURE); - } - if (Swig_insert_file("python.swg", f_runtime) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate python.swg. (Possible installation problem).\n"); - Swig_exit (EXIT_FAILURE); - } - - if (!module) module = NewString(modname); - - /* If shadow classing is enabled, we're going to change the module name to "modulec" */ - if (shadow) { - - sprintf(filen,"%s%s.py", output_dir, Char(module)); - // If we don't have an interface then change the module name X to Xc - if (! interface) - Append(module,"c"); - if ((f_shadow = fopen(filen,"w")) == 0) { - Printf(stderr,"Unable to open %s\n", filen); - Swig_exit (EXIT_FAILURE); + virtual int top(Node *n) { + + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); } - Printf(f_shadow,"# This file was created automatically by SWIG.\n"); - Printf(f_shadow,"import %s\n", interface ? interface : module); + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); - // Include some information in the code - Printf(f_header,"\n/*-----------------------------------------------\n @(target):= %s.so\n\ - ------------------------------------------------*/\n", interface ? interface : module); + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",f_init); - if (!noopt) - Printf(f_shadow,"import new\n"); - } + const_code = NewString(""); + shadow_methods = NewString(""); + methods = NewString(""); - Printf(f_header,"#define SWIG_init init%s\n\n", module); - Printf(f_header,"#define SWIG_name \"%s\"\n", module); - - /* Output the start of the init function. */ - Printf(f_init,"static PyObject *SWIG_globals;\n"); - Printf(f_init,"#ifdef __cplusplus\n"); - Printf(f_init,"extern \"C\" \n"); - Printf(f_init,"#endif\n"); - Printf(f_init,"SWIGEXPORT(void) init%s(void) {\n",module); - Printf(f_init,"PyObject *m, *d;\n"); - Printf(f_init,"int i;\n"); - Printf(f_init,"SWIG_globals = SWIG_newvarlink();\n"); - Printf(f_init,"m = Py_InitModule(\"%s\", %sMethods);\n", module, module); - Printf(f_init,"d = PyModule_GetDict(m);\n"); - Printv(f_init, - "for (i = 0; swig_types_initial[i]; i++) {\n", - "swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n", - "}\n", - 0); - - Printf(f_wrappers,"#ifdef __cplusplus\n"); - Printf(f_wrappers,"extern \"C\" {\n"); - Printf(f_wrappers,"#endif\n"); - Printf(const_code,"static swig_const_info swig_const_table[] = {\n"); - Printf(methods,"static PyMethodDef %sMethods[] = {\n", module); -} + Swig_banner(f_runtime); -/* ----------------------------------------------------------------------------- - * PYTHON::close() - * ----------------------------------------------------------------------------- */ -void -PYTHON::close(void) { - Printf(methods,"\t { NULL, NULL }\n"); - Printf(methods,"};\n"); - Printf(f_wrappers,"%s\n",methods); - Printf(f_wrappers,"#ifdef __cplusplus\n"); - Printf(f_wrappers,"}\n"); - Printf(f_wrappers,"#endif\n"); - - SwigType_emit_type_table(f_runtime,f_wrappers); - - Printf(const_code, "{0}};\n"); - Printf(f_wrappers,"%s\n",const_code); - - Printv(f_init, "SWIG_InstallConstants(d,swig_const_table);\n", 0); - Printf(f_init,"}\n"); - - if (shadow) { - Printv(f_shadow, - classes, - "\n\n#-------------- FUNCTION WRAPPERS ------------------\n\n", - func, - "\n\n#-------------- VARIABLE WRAPPERS ------------------\n\n", - vars, - 0); - - if (Len(pragma_include) > 0) { - Printv(f_shadow, - "\n\n#-------------- USER INCLUDE -----------------------\n\n", - pragma_include, - 0); - } - fclose(f_shadow); - } -} + Printf(f_runtime,"#define SWIGPYTHON\n"); + if (NoInclude) + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); -/* ----------------------------------------------------------------------------- - * PYTHON::get_pointer() - * ----------------------------------------------------------------------------- */ -void -PYTHON::get_pointer(char *src, char *dest, SwigType *t, String *f, char *ret) { - SwigType *lt; - SwigType_remember(t); - Printv(f,tab4, "if ((SWIG_ConvertPtr(", src, ",(void **) &", dest, ",", 0); - - lt = Swig_clocal_type(t); - if (Cmp(lt,"p.void") == 0) { - Printv(f, "0,1)) == -1) return ", ret, ";\n", 0); - } - /* if (SwigType_type(t) == T_VOID) Printv(f, "0,1)) == -1) return ", ret, ";\n", 0);*/ - else { - Printv(f,"SWIGTYPE", SwigType_manglestr(t), ",1)) == -1) return ", ret, ";\n", 0); - } - Delete(lt); -} + /* Set module name */ + module = Copy(Getattr(n,"name")); + mainmodule = Getattr(n,"name"); -/* ----------------------------------------------------------------------------- - * PYTHON::create_command() - * ----------------------------------------------------------------------------- */ -void -PYTHON::create_command(String *cname, String *iname) { - add_method(iname, Swig_name_wrapper(cname), use_kw); -} + char filen[256]; -/* ----------------------------------------------------------------------------- - * PYTHON::create_function() - * ----------------------------------------------------------------------------- */ -void -PYTHON::function(DOH *node) { - char *name; - char *iname; - SwigType *d; - ParmList *l; - Parm *p; - int pcount,i,j; - char wname[256]; - char source[64], target[64], argnum[20]; - char *usage = 0; - Wrapper *f; - String *parse_args; - String *arglist; - String *get_pointers; - String *cleanup; - String *outarg; - String *check; - String *kwargs; - char *tm; - int numopt = 0; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - d = Getattr(node,"type"); - l = Getattr(node,"parms"); - f = NewWrapper(); - parse_args = NewString(""); - arglist = NewString(""); - get_pointers = NewString(""); - cleanup = NewString(""); - outarg = NewString(""); - check = NewString(""); - kwargs = NewString(""); - - have_output = 0; - - strcpy(wname,Char(Swig_name_wrapper(iname))); - - if (!use_kw) { - Printv(f, - "static PyObject *", wname, - "(PyObject *self, PyObject *args) {", - 0); - } else { - Printv(f, - "static PyObject *", wname, - "(PyObject *self, PyObject *args, PyObject *kwargs) {", - 0); - } - Wrapper_add_local(f,"resultobj", "PyObject *resultobj"); + /* If shadow classing is enabled, we're going to change the module name to "_module" */ + if (shadow) { + sprintf(filen,"%s%s.py", Swig_file_dirname(outfile), Char(module)); + // If we don't have an interface then change the module name X to _X + if (interface) module = interface; + else Insert(module,0,"_"); + if ((f_shadow = NewFile(filen,"w")) == 0) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit (EXIT_FAILURE); + } + f_shadow_stubs = NewString(""); - /* Get the function usage string for later use */ + Swig_register_filebyname("shadow",f_shadow); + Swig_register_filebyname("python",f_shadow); - usage = usage_func(iname,d,l); + Printv(f_shadow, + "# This file was created automatically by SWIG.\n", + "# Don't modify this file, modify the SWIG interface instead.\n", + "# This file is compatible with both classic and new-style classes.\n", + NIL); - /* Write code to extract function parameters. */ - pcount = emit_args(node, f); - if (!use_kw) { - Printf(parse_args," if(!PyArg_ParseTuple(args,\""); - } else { - Printf(parse_args," if(!PyArg_ParseTupleAndKeywords(args,kwargs,\""); - Printf(arglist,",kwnames"); - } + Printf(f_shadow,"import %s\n", module); - i = 0; - j = 0; - numopt = check_numopt(l); - if (numopt) have_defarg = 1; - p = l; - Printf(kwargs,"{ "); - while (p != 0) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - String *pv = Getvalue(p); - - sprintf(source,"obj%d",i); - sprintf(target,Char(Getlname(p))); - sprintf(argnum,"%d",j+1); - - if (!Getignore(p)) { - Putc(',',arglist); - if (j == pcount-numopt) Putc('|',parse_args); /* Optional argument separator */ - if (Len(pn)) { - Printf(kwargs,"\"%s\",", pn); - } else { - Printf(kwargs,"\"arg%d\",", j+1); + // Python-2.2 object hack + + + Printv(f_shadow, + "def _swig_setattr(self,class_type,name,value):\n", + tab4, "if (name == \"this\"):\n", + tab4, tab4, "if isinstance(value, class_type):\n", + tab4, tab8, "self.__dict__[name] = value.this\n", + tab4, tab8, "if hasattr(value,\"thisown\"): self.__dict__[\"thisown\"] = value.thisown\n", + tab4, tab8, "del value.thisown\n", + tab4, tab8, "return\n", + // tab8, "if (name == \"this\") or (name == \"thisown\"): self.__dict__[name] = value; return\n", + tab4, "method = class_type.__swig_setmethods__.get(name,None)\n", + tab4, "if method: return method(self,value)\n", + tab4, "self.__dict__[name] = value\n\n", + NIL); + + Printv(f_shadow, + "def _swig_getattr(self,class_type,name):\n", + tab4, "method = class_type.__swig_getmethods__.get(name,None)\n", + tab4, "if method: return method(self)\n", + tab4, "raise AttributeError,name\n\n", + NIL); + + if (!classic) { + Printv(f_shadow, + "import types\n", + "try:\n", + " _object = types.ObjectType\n", + " _newclass = 1\n", + "except AttributeError:\n", + " class _object : pass\n", + " _newclass = 0\n", + "\n\n", + NIL); } - if ((tm = Swig_typemap_lookup((char*)"in",pt,pn,source,target,f))) { - Putc('O',parse_args); - Wrapper_add_localv(f, source, "PyObject *",source, " = 0", 0); - Printf(arglist,"&%s",source); - if (i >= (pcount-numopt)) - Printv(get_pointers, tab4, "if (", source, ")\n", 0); - Printv(get_pointers,tm,"\n", 0); - Replace(get_pointers,"$argnum", argnum, DOH_REPLACE_ANY); - Replace(get_pointers,"$arg",source, DOH_REPLACE_ANY); - } else { - int noarg = 0; - - switch(SwigType_type(pt)) { - case T_INT : case T_UINT: - Putc('i',parse_args); - break; - case T_SHORT: case T_USHORT: - Putc('h',parse_args); - break; - case T_LONG : case T_ULONG: - Putc('l',parse_args); - break; - case T_SCHAR : case T_UCHAR : - Putc('b',parse_args); - break; - case T_CHAR: - Putc('c',parse_args); - break; - case T_FLOAT : - Putc('f',parse_args); - break; - case T_DOUBLE: - Putc('d',parse_args); - break; - - case T_BOOL: - { - char tempb[128]; - char tempval[128]; - if (pv) { - sprintf(tempval, "(int) %s", Char(pv)); - } - sprintf(tempb,"tempbool%d",i); - Putc('i',parse_args); - if (!pv) - Wrapper_add_localv(f,tempb,"int",tempb,0); - else - Wrapper_add_localv(f,tempb,"int",tempb, "=",tempval,0); - Printv(get_pointers, tab4, target, " = ( ", tempb, " != 0);\n", 0); - Printf(arglist,"&%s",tempb); - noarg = 1; - } - break; + // Include some information in the code + Printf(f_header,"\n/*-----------------------------------------------\n @(target):= %s.so\n\ + ------------------------------------------------*/\n", module); - case T_VOID : - noarg = 1; - break; + } - case T_USER: + Printf(f_header,"#define SWIG_init init%s\n\n", module); + Printf(f_header,"#define SWIG_name \"%s\"\n", module); - Putc('O',parse_args); - sprintf(source,"argo%d", i); - sprintf(target,Char(Getlname(p))); + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"extern \"C\" {\n"); + Printf(f_wrappers,"#endif\n"); + Printf(const_code,"static swig_const_info swig_const_table[] = {\n"); + Printf(methods,"static PyMethodDef SwigMethods[] = {\n"); - Wrapper_add_localv(f,source,"PyObject *",source,"=0",0); - Printf(arglist,"&%s",source); - SwigType_add_pointer(pt); - get_pointer(source, target, pt, get_pointers, (char*)"NULL"); - SwigType_del_pointer(pt); - noarg = 1; - break; + /* emit code */ + Language::top(n); - case T_STRING: - Putc('s',parse_args); - Printf(arglist,"&%s", Getlname(p)); - noarg = 1; - break; + /* Close language module */ + Printf(methods,"\t { NULL, NULL }\n"); + Printf(methods,"};\n"); + Printf(f_wrappers,"%s\n",methods); - case T_POINTER: case T_ARRAY: case T_REFERENCE: + SwigType_emit_type_table(f_runtime,f_wrappers); - /* Have some sort of pointer variable. Create a temporary local - variable for the string and read the pointer value into it. */ + Printf(const_code, "{0}};\n"); + Printf(f_wrappers,"%s\n",const_code); + Printf(f_init,"}\n"); - Putc('O',parse_args); - sprintf(source,"argo%d", i); - sprintf(target,"%s",Char(Getlname(p))); + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"}\n"); + Printf(f_wrappers,"#endif\n"); - Wrapper_add_localv(f,source,"PyObject *",source,"=0",0); - Printf(arglist,"&%s",source); - get_pointer(source, target, pt, get_pointers, (char*)"NULL"); - noarg = 1; - break; + if (shadow) { + Printv(f_shadow, f_shadow_stubs, "\n",NIL); + Close(f_shadow); + Delete(f_shadow); + } - default : - Printf(stderr,"%s:%d. Unable to use type %s as a function argument.\n",Getfile(node), Getline(node), SwigType_str(pt,0)); - break; - } + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * importDirective() + * ------------------------------------------------------------ */ - if (!noarg) - Printf(arglist,"&%s",Getlname(p)); + virtual int importDirective(Node *n) { + if (shadow) { + String *modname = Getattr(n,"module"); + if (modname) { + Printf(f_shadow,"import %s\n", modname); } - j++; - } - /* Check if there was any constraint code */ - if ((tm = Swig_typemap_lookup((char*)"check",pt,pn,source,target,0))) { - Printf(check,"%s\n",tm); - Replace(check,"$argnum", argnum, DOH_REPLACE_ANY); - } - /* Check if there was any cleanup code */ - if ((tm = Swig_typemap_lookup((char*)"freearg",pt,pn,target,source,0))) { - Printf(cleanup,"%s\n",tm); - Replace(cleanup,"$argnum", argnum, DOH_REPLACE_ANY); - Replace(cleanup,"$arg",source, DOH_REPLACE_ANY); } - /* Check for output arguments */ - if ((tm = Swig_typemap_lookup((char*)"argout",pt,pn,target,(char*)"resultobj",0))) { - Printf(outarg,"%s\n", tm); - Replace(outarg,"$argnum",argnum,DOH_REPLACE_ANY); - Replace(outarg,"$arg",source, DOH_REPLACE_ANY); - have_output++; - } - p = Getnext(p); - i++; + return Language::importDirective(n); } - Printf(kwargs," NULL }"); - if (use_kw) { - Wrapper_add_localv(f,"kwnames","char *kwnames[] = ", kwargs, ";\n", 0); - /* Printv(f->locals,tab4, "char *kwnames[] = ", kwargs, ";\n", 0); */ + /* ------------------------------------------------------------ + * add_method() + * ------------------------------------------------------------ */ + + void add_method(String *name, String *function, int kw) { + if (!kw) + Printf(methods,"\t { (char *)\"%s\", %s, METH_VARARGS },\n", name, function); + else + Printf(methods,"\t { (char *)\"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS },\n", name, function); } + + /* ------------------------------------------------------------ + * functionWrapper() + * ------------------------------------------------------------ */ - Printf(parse_args,":%s\"", iname); - Printv(parse_args, - arglist, ")) return NULL;\n", - 0); + virtual int functionWrapper(Node *n) { + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + + Parm *p; + int i; + char wname[256]; + char source[64]; + Wrapper *f; + String *parse_args; + String *arglist; + String *get_pointers; + String *cleanup; + String *outarg; + String *kwargs; + String *tm; + String *overname = 0; + + int num_required; + int num_arguments; + int varargs = 0; + int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0; + + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; + } - /* Now slap the whole first part of the wrapper function together */ - Printv(f, parse_args, get_pointers, check, 0); + f = NewWrapper(); + parse_args = NewString(""); + arglist = NewString(""); + get_pointers = NewString(""); + cleanup = NewString(""); + outarg = NewString(""); + kwargs = NewString(""); + + Wrapper_add_local(f,"resultobj", "PyObject *resultobj"); - /* Emit the function call */ - emit_func_call(node,f); + /* Write code to extract function parameters. */ + emit_args(d, l, f); + + /* Attach the standard typemaps */ + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + /* Get number of required and total arguments */ + num_arguments = emit_num_arguments(l); + num_required = emit_num_required(l); + varargs = emit_isvarargs(l); + + strcpy(wname,Char(Swig_name_wrapper(iname))); + if (overname) { + strcat(wname,Char(overname)); + } - /* Return the function value */ - if ((tm = Swig_typemap_lookup((char*)"out",d,iname,(char*)"result",(char*)"resultobj",0))) { - Printf(f,"%s\n", tm); - } else { - switch(SwigType_type(d)) { - case T_INT: case T_UINT: case T_BOOL: - case T_SHORT: case T_USHORT: - case T_LONG : case T_ULONG: - case T_SCHAR: case T_UCHAR : - Printf(f," resultobj = PyInt_FromLong((long)result);\n"); - break; - case T_DOUBLE : - case T_FLOAT : - Printf(f," resultobj = PyFloat_FromDouble(result);\n"); - break; - case T_CHAR : - Printf(f," resultobj = Py_BuildValue(\"c\",result);\n"); - break; - case T_USER : - SwigType_add_pointer(d); - SwigType_remember(d); - Printv(f,tab4, "resultobj = SWIG_NewPointerObj((void *)result, SWIGTYPE", SwigType_manglestr(d), ");\n",0); - SwigType_del_pointer(d); - break; - case T_STRING: - Printf(f," resultobj = Py_BuildValue(\"s\",result);\n"); - break; - case T_POINTER: case T_ARRAY: case T_REFERENCE: - SwigType_remember(d); - Printv(f, tab4, "resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE", SwigType_manglestr(d), ");\n", 0); - break; - case T_VOID: - Printf(f," Py_INCREF(Py_None);\n"); - Printf(f," resultobj = Py_None;\n"); - break; - default : - Printf(stderr,"%s:%d. Unable to use return type %s in function %s.\n", Getfile(node), Getline(node), SwigType_str(d,0), name); - break; + if (!allow_kwargs || Getattr(n,"sym:overloaded")) { + if (!varargs) { + Printv(f->def, + "static PyObject *", wname, + "(PyObject *self, PyObject *args) {", + NIL); + } else { + Printv(f->def, + "static PyObject *", wname, "__varargs__", + "(PyObject *self, PyObject *args, PyObject *varargs) {", + NIL); + } + if (allow_kwargs) { + Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, + "Can't use keyword arguments with overloaded functions.\n"); + allow_kwargs = 0; + } + } else { + if (varargs) { + Swig_warning(WARN_LANG_VARARGS_KEYWORD, input_file, line_number, + "Can't wrap varargs with keyword arguments enabled\n"); + varargs = 0; + } + Printv(f->def, + "static PyObject *", wname, + "(PyObject *self, PyObject *args, PyObject *kwargs) {", + NIL); + } + if (!allow_kwargs) { + Printf(parse_args," if(!PyArg_ParseTuple(args,(char *)\""); + } else { + Printf(parse_args," if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\""); + Printf(arglist,",kwnames"); } - } - /* Output argument output code */ - Printv(f,outarg,0); + /* Generate code for argument marshalling */ - /* Output cleanup code */ - Printv(f,cleanup,0); + Printf(kwargs,"{ "); + for (i = 0, p=l; i < num_arguments; i++) { + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } - /* Look to see if there is any newfree cleanup code */ - if (NewObject) { - if ((tm = Swig_typemap_lookup((char*)"newfree",d,iname,(char*)"result",(char*)"",0))) { - Printf(f,"%s\n",tm); - } - } + SwigType *pt = Getattr(p,"type"); + String *pn = Getattr(p,"name"); + String *ln = Getattr(p,"lname"); - /* See if there is any return cleanup code */ - if ((tm = Swig_typemap_lookup((char*)"ret",d,iname,(char*)"result",(char*)"",0))) { - Printf(f,"%s\n",tm); - } + sprintf(source,"obj%d",i); - Printf(f," return resultobj;\n}\n"); + Putc(',',arglist); + if (i == num_required) Putc('|', parse_args); /* Optional argument separator */ - /* Substitute the cleanup code */ - Replace(f,"$cleanup",cleanup, DOH_REPLACE_ANY); + /* Keyword argument handling */ + if (Len(pn)) { + Printf(kwargs,"\"%s\",", pn); + } else { + Printf(kwargs,"\"arg%d\",", i+1); + } - /* Substitute the function name */ - Replace(f,"$name",iname, DOH_REPLACE_ANY); + /* Look for an input typemap */ + if ((tm = Getattr(p,"tmap:in"))) { + String *parse = Getattr(p,"tmap:in:parse"); + if (!parse) { + Replaceall(tm,"$source",source); + Replaceall(tm,"$target",ln); + Replaceall(tm,"$input", source); + Setattr(p,"emit:input", source); /* Save the location of the object */ + + if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) { + Replaceall(tm,"$disown","SWIG_POINTER_DISOWN"); + } else { + Replaceall(tm,"$disown","0"); + } - /* Dump the function out */ - Printf(f_wrappers,"%s",f); + Putc('O',parse_args); + Wrapper_add_localv(f, source, "PyObject *",source, " = 0", NIL); + Printf(arglist,"&%s",source); + if (i >= num_required) + Printv(get_pointers, "if (", source, ") {\n", NIL); + Printv(get_pointers,tm,"\n", NIL); + if (i >= num_required) + Printv(get_pointers, "}\n", NIL); - /* Now register the function with the interpreter. */ - add_method(iname, wname, use_kw); + } else { + Printf(parse_args,"%s",parse); + Printf(arglist,"&%s", ln); + } + p = Getattr(p,"tmap:in:next"); + continue; + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument.\n",SwigType_str(pt,0)); + break; + } + p = nextSibling(p); + } + + /* finish argument marshalling */ + Printf(kwargs," NULL }"); + if (allow_kwargs) { + Printv(f->locals,tab4, "char *kwnames[] = ", kwargs, ";\n", NIL); + } - /* Create a shadow for this function (if enabled and not in a member function) */ + Printf(parse_args,":%s\"", iname); + Printv(parse_args, + arglist, ")) goto fail;\n", + NIL); - if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { - int need_wrapper = 0; - int munge_return = 0; + /* Now piece together the first part of the wrapper function */ + Printv(f->code, parse_args, get_pointers, NIL); + + /* Check for trailing varargs */ + if (varargs) { + if (p && (tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$input", "varargs"); + Printv(f->code,tm,"\n",NIL); + } + } + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert cleanup code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } - /* Check return code for modification */ - if (is_shadow(d)) { - need_wrapper = 1; - munge_return = 1; + /* Insert argument output code */ + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","resultobj"); + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); + } } + + /* Emit the function call */ + emit_action(n,f); - /* If no modification is needed. We're just going to play some - symbol table games instead */ + /* This part below still needs cleanup */ - if (!need_wrapper) { - Printv(func,iname, " = ", module, ".", iname, "\n\n", 0); + /* Return the function value */ + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source", "result"); + Replaceall(tm,"$target", "resultobj"); + Replaceall(tm,"$result", "resultobj"); + if (Getattr(n,"feature:new")) { + Replaceall(tm,"$owner","1"); + } else { + Replaceall(tm,"$owner","0"); + } + Printf(f->code,"%s\n", tm); } else { - Printv(func,"def ", iname, "(*args, **kwargs):\n", 0); - Printv(func, tab4, "val = apply(", module, ".", iname, ",args,kwargs)\n",0); + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s in function %s.\n", SwigType_str(d,0), name); + } - if (munge_return) { - /* If the output of this object has been remapped in any way, we're - going to return it as a bare object */ + /* Output argument output code */ + Printv(f->code,outarg,NIL); - if (!Swig_typemap_search((char*)"out",d,iname)) { + /* Output cleanup code */ + Printv(f->code,cleanup,NIL); - /* If there are output arguments, we are going to return the value - unchanged. Otherwise, emit some shadow class conversion code. */ + /* Look to see if there is any newfree cleanup code */ + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } + } - if (!have_output) { - Printv(func, tab4, "if val: val = ", is_shadow(d), "Ptr(val)", 0); - if ((!SwigType_ispointer(d)) || NewObject) - Printf(func, "; val.thisown = 1\n"); - else - Printf(func,"\n"); - } + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } + + Printf(f->code," return resultobj;\n"); + + /* Error handling code */ + + Printf(f->code,"fail:\n"); + Printv(f->code,cleanup,NIL); + Printf(f->code,"return NULL;\n"); + Printf(f->code,"}\n"); + + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); + + /* Substitute the function name */ + Replaceall(f->code,"$symname",iname); + Replaceall(f->code,"$result","resultobj"); + + /* Dump the function out */ + Wrapper_print(f,f_wrappers); + + /* If varargs. Need to emit a varargs stub */ + if (varargs) { + DelWrapper(f); + f = NewWrapper(); + Printv(f->def, + "static PyObject *", wname, + "(PyObject *self, PyObject *args) {", + NIL); + Wrapper_add_local(f,"resultobj", "PyObject *resultobj"); + Wrapper_add_local(f,"varargs", "PyObject *varargs"); + Wrapper_add_local(f,"newargs", "PyObject *newargs"); + Printf(f->code,"newargs = PyTuple_GetSlice(args,0,%d);\n", num_arguments); + Printf(f->code,"varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args)+1);\n", num_arguments); + Printf(f->code,"resultobj = %s__varargs__(self,newargs,varargs);\n", wname); + Printf(f->code,"Py_XDECREF(newargs);\n"); + Printf(f->code,"Py_XDECREF(varargs);\n"); + Printf(f->code,"return resultobj;\n"); + Printf(f->code,"}\n"); + Wrapper_print(f,f_wrappers); + } + + Setattr(n,"wrap:name", wname); + + /* Now register the function with the interpreter. */ + if (!Getattr(n,"sym:overloaded")) { + add_method(iname, wname, allow_kwargs); + + /* Create a shadow for this function (if enabled and not in a member function) */ + if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (in_class) { + Printv(f_shadow_stubs,iname, " = ", module, ".", iname, "\n\n", NIL); + } else { + Printv(f_shadow,iname, " = ", module, ".", iname, "\n\n", NIL); } } - Printv(func, tab4, "return val\n\n", 0); + } else { + if (!Getattr(n,"sym:nextSibling")) { + dispatchFunction(n); + } } + Delete(parse_args); + Delete(arglist); + Delete(get_pointers); + Delete(cleanup); + Delete(outarg); + Delete(kwargs); + DelWrapper(f); + return SWIG_OK; } - Delete(parse_args); - Delete(arglist); - Delete(get_pointers); - Delete(cleanup); - Delete(outarg); - Delete(check); - Delete(kwargs); - Delete(f); -} -/* ----------------------------------------------------------------------------- - * PYTHON::variable() - * ----------------------------------------------------------------------------- */ -void -PYTHON::variable(DOH *node) { - char *name, *iname; - SwigType *t; - char *wname; + /* ------------------------------------------------------------ + * dispatchFunction() + * ------------------------------------------------------------ */ + void dispatchFunction(Node *n) { + /* Last node in overloaded chain */ + + int maxargs; + String *tmp = NewString(""); + String *dispatch = Swig_overload_dispatch(n,"return %s(self,args);",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *f = NewWrapper(); + String *symname = Getattr(n,"sym:name"); + String *wname = Swig_name_wrapper(symname); + + Printv(f->def, + "static PyObject *", wname, + "(PyObject *self, PyObject *args) {", + NIL); + + Wrapper_add_local(f,"argc","int argc"); + Printf(tmp,"PyObject *argv[%d]", maxargs+1); + Wrapper_add_local(f,"argv",tmp); + Wrapper_add_local(f,"ii","int ii"); + Printf(f->code,"argc = PyObject_Length(args);\n"); + Printf(f->code,"for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n",maxargs); + Printf(f->code,"argv[ii] = PyTuple_GetItem(args,ii);\n"); + Printf(f->code,"}\n"); + + Replaceall(dispatch,"$args","self,args"); + Printv(f->code,dispatch,"\n",NIL); + Printf(f->code,"PyErr_SetString(PyExc_TypeError,\"No matching function for overloaded '%s'\");\n", symname); + Printf(f->code,"return NULL;\n"); + Printv(f->code,"}\n",NIL); + Wrapper_print(f,f_wrappers); + add_method(symname,wname,0); + + /* Create a shadow for this function (if enabled and not in a member function) */ + if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + Printv(f_shadow_stubs,symname, " = ", module, ".", symname, "\n\n", NIL); + } + DelWrapper(f); + Delete(dispatch); + Delete(tmp); + Delete(wname); + } + + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *wname; static int have_globals = 0; - char *tm; + String *tm; Wrapper *getf, *setf; - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); + if (!addSymbol(iname,n)) return SWIG_ERROR; getf = NewWrapper(); setf = NewWrapper(); - /* If this is our first call, add the globals variable to the - Python dictionary. */ + /* If this is our first call, add the globals variable to the + Python dictionary. */ if (!have_globals) { - Printf(f_init,"\t PyDict_SetItemString(d,\"%s\", SWIG_globals);\n",global_name); + Printf(f_init,"\t PyDict_SetItemString(d,(char*)\"%s\", SWIG_globals);\n",global_name); have_globals=1; if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { - Printv(vars, global_name, " = ", module, ".", global_name, "\n", 0); + Printf(f_shadow_stubs,"%s = %s.%s\n", global_name, module, global_name); } } - wname = Char(Swig_name_wrapper(name)); + if ((shadow) && (SwigType_isconst(t))) { + if (!in_class) { + Printf(f_shadow_stubs,"%s = %s.%s\n", iname, global_name, iname); + } + } + + wname = Swig_name_wrapper(iname); /* Create a function for setting the value of the variable */ - Printf(setf,"static int %s_set(PyObject *val) {\n", wname); - if (!ReadOnly) { - if ((tm = Swig_typemap_lookup((char*)"varin",t,name,(char*)"val",name,0))) { - Printf(setf,"%s\n",tm); - Replace(setf,"$name",iname, DOH_REPLACE_ANY); + Printf(setf->def,"static int %s_set(PyObject *_val) {", wname); + if (!Getattr(n,"feature:immutable")) { + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","_val"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","_val"); + Printf(setf->code,"%s\n",tm); + Delete(tm); } else { - switch(SwigType_type(t)) { - - case T_INT: case T_SHORT: case T_LONG : - case T_UINT: case T_USHORT: case T_ULONG: - case T_SCHAR: case T_UCHAR: case T_BOOL: - Wrapper_add_localv(setf,"tval",SwigType_lstr(t,0),"tval",0); - Printv(setf, - "tval = (", SwigType_lstr(t,0), ") PyInt_AsLong(val);\n", - "if (PyErr_Occurred()) {\n", - "PyErr_SetString(PyExc_TypeError,\"C variable '", - iname, "'(", SwigType_str(t,0), ")\");\n", - "return 1; \n", - "}\n", - name, " = tval;\n", - 0); - break; - - case T_FLOAT: case T_DOUBLE: - Wrapper_add_localv(setf,"tval",SwigType_lstr(t,0), "tval",0); - Printv(setf, - "tval = (", SwigType_lstr(t,0), ") PyFloat_AsDouble(val);\n", - "if (PyErr_Occurred()) {\n", - "PyErr_SetString(PyExc_TypeError,\"C variable '", - iname, "'(", SwigType_str(t,0), ")\");\n", - "return 1; \n", - "}\n", - name, " = tval;\n", - 0); - break; - - case T_CHAR: - Wrapper_add_local(setf,"tval","char * tval"); - Printv(setf, - "tval = (char *) PyString_AsString(val);\n", - "if (PyErr_Occurred()) {\n", - "PyErr_SetString(PyExc_TypeError,\"C variable '", - iname, "'(", SwigType_str(t,0), ")\");\n", - "return 1; \n", - "}\n", - name, " = *tval;\n", - 0); - break; - - case T_USER: - SwigType_add_pointer(t); - Wrapper_add_localv(setf,"temp",SwigType_lstr(t,0),"temp",0); - get_pointer((char*)"val",(char*)"temp",t,setf,(char*)"1"); - Printv(setf, name, " = *temp;\n", 0); - SwigType_del_pointer(t); - break; - - case T_STRING: - Wrapper_add_local(setf,"tval","char * tval"); - Printv(setf, - "tval = (char *) PyString_AsString(val);\n", - "if (PyErr_Occurred()) {\n", - "PyErr_SetString(PyExc_TypeError,\"C variable '", - iname, "'(", SwigType_str(t,0), ")\");\n", - "return 1; \n", - "}\n", - 0); - - if (CPlusPlus) { - Printv(setf, - "if (", name, ") delete [] ", name, ";\n", - name, " = new char[strlen(tval)+1];\n", - "strcpy((char *)", name, ",tval);\n", - 0); - } else { - Printv(setf, - "if (", name, ") free((char*)", name, ");\n", - name, " = (char *) malloc(strlen(tval)+1);\n", - "strcpy((char *)", name, ",tval);\n", - 0); - } - break; - - case T_ARRAY: - { - int setable = 0; - SwigType *aop; - SwigType *ta = Copy(t); - aop = SwigType_pop(ta); - if (SwigType_type(ta) == T_CHAR) { - String *dim = SwigType_array_getdim(aop,0); - if (dim && Len(dim)) { - Printf(setf, "strncpy(%s,PyString_AsString(val), %s);\n", name,dim); - setable = 1; - } - } - if (!setable) { - Printv(setf, - "PyErr_SetString(PyExc_TypeError,\"Variable ", iname, - " is read-only.\");\n", - "return 1;\n", - 0); - } - Delete(ta); - Delete(aop); - } - break; - - case T_POINTER: case T_REFERENCE: - Wrapper_add_localv(setf,"temp", SwigType_lstr(t,0), "temp",0); - get_pointer((char*)"val",(char*)"temp",t,setf,(char*)"1"); - Printv(setf, name, " = temp;\n", 0); - break; - - default: - Printf(stderr,"%s:%d. Unable to link with type %s.\n", Getfile(node), Getline(node), SwigType_str(t,0)); - } + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, + "Unable to set variable of type %s.\n", SwigType_str(t,0)); } - Printf(setf," return 0;\n"); + Printf(setf->code," return 0;\n"); } else { /* Is a readonly variable. Issue an error */ - Printv(setf, - "PyErr_SetString(PyExc_TypeError,\"Variable ", iname, + Printv(setf->code, + tab4, "PyErr_SetString(PyExc_TypeError,\"Variable ", iname, " is read-only.\");\n", - "return 1;\n", - 0); + tab4, "return 1;\n", + NIL); } - Printf(setf,"}\n"); - Printf(f_wrappers,"%s", setf); + Printf(setf->code,"}\n"); + Wrapper_print(setf,f_wrappers); /* Create a function for getting the value of a variable */ - Printf(getf,"static PyObject *%s_get() {\n", wname); + Printf(getf->def,"static PyObject *%s_get() {", wname); Wrapper_add_local(getf,"pyobj", "PyObject *pyobj"); - if ((tm = Swig_typemap_lookup((char*)"varout",t,name,name,(char*)"pyobj",0))) { - Printf(getf,"%s\n",tm); - Replace(getf,"$name",iname, DOH_REPLACE_ANY); - } else if ((tm = Swig_typemap_lookup((char*)"out",t,name,name,(char*)"pyobj",0))) { - Printf(getf,"%s\n",tm); - Replace(getf,"$name",iname, DOH_REPLACE_ANY); + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","pyobj"); + Replaceall(tm,"$result","pyobj"); + Printf(getf->code,"%s\n", tm); } else { - switch(SwigType_type(t)) { - case T_INT: case T_UINT: - case T_SHORT: case T_USHORT: - case T_LONG: case T_ULONG: - case T_SCHAR: case T_UCHAR: case T_BOOL: - Printv(getf, "pyobj = PyInt_FromLong((long) ", name, ");\n", 0); - break; - case T_FLOAT: case T_DOUBLE: - Printv(getf, "pyobj = PyFloat_FromDouble((double) ", name, ");\n", 0); - break; - case T_CHAR: - Wrapper_add_local(getf,"ptemp","char ptemp[2]"); - Printv(getf, - "ptemp[0] = ", name, ";\n", - "ptemp[1] = 0;\n", - "pyobj = PyString_FromString(ptemp);\n", - 0); - break; - case T_USER: - SwigType_add_pointer(t); - SwigType_remember(t); - Printv(getf, - "pyobj = SWIG_NewPointerObj((void *) &", name , - ", SWIGTYPE", SwigType_manglestr(t), ");\n", - 0); - SwigType_del_pointer(t); - break; - case T_STRING: - Printv(getf, - "if (", name, ")\n", - "pyobj = PyString_FromString(", name, ");\n", - "else pyobj = PyString_FromString(\"(NULL)\");\n", - 0); - break; - - case T_POINTER: case T_ARRAY: case T_REFERENCE: - { - SwigType *ta = Copy(t); - SwigType_pop(ta); - if (SwigType_type(ta) == T_CHAR) { - Printv(getf,"pyobj = PyString_FromString(", name, ");\n", 0); - } else { - SwigType_remember(t); - Printv(getf, - "pyobj = SWIG_NewPointerObj((void *)", name, - ", SWIGTYPE", SwigType_manglestr(t), ");\n", - 0); - } - Delete(ta); - } - break; - - default: - Printf(stderr,"Unable to link with type %s\n", SwigType_str(t,0)); - break; - } + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to link with type %s\n", SwigType_str(t,0)); } - - Printf(getf," return pyobj;\n}\n"); - Printf(f_wrappers,"%s", getf); + + Printf(getf->code," return pyobj;\n}\n"); + Wrapper_print(getf,f_wrappers); /* Now add this to the variable linking mechanism */ + Printf(f_init,"\t SWIG_addvarlink(SWIG_globals,(char*)\"%s\",%s_get, %s_set);\n", iname, wname, wname); - Printf(f_init,"\t SWIG_addvarlink(SWIG_globals,\"%s\",%s_get, %s_set);\n", iname, wname, wname); + DelWrapper(setf); + DelWrapper(getf); + return SWIG_OK; + } - /* Output a shadow variable. (If applicable and possible) */ + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + String *tm; + int have_tm = 0; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + /* Special hook for member pointer */ + if (SwigType_type(type) == T_MPOINTER) { + String *wname = Swig_name_wrapper(iname); + Printf(f_header, "static %s = %s;\n", SwigType_str(type,wname), value); + value = wname; + } + if ((tm = Swig_typemap_lookup_new("consttab",n,name,0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value", value); + Printf(const_code,"%s,\n", tm); + have_tm = 1; + } + if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value",value); + Printf(f_init, "%s\n", tm); + have_tm = 1; + } + if (!have_tm) { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value.\n"); + return SWIG_NOWRAP; + } if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { - if (is_shadow(t)) { - Printv(vars, - iname, " = ", is_shadow(t), "Ptr(", module, ".", global_name, - ".", iname, ")\n", - 0); + if (!in_class) { + Printv(f_shadow,iname, " = ", module, ".", iname, "\n", NIL); + } else { + Printv(f_shadow_stubs,iname, " = ", module, ".", iname, "\n", NIL); } } - Delete(setf); - Delete(getf); -} + return SWIG_OK; + } -/* ----------------------------------------------------------------------------- - * PYTHON::constant() - * ----------------------------------------------------------------------------- */ -void -PYTHON::constant(DOH *node) { - char *name; - SwigType *type; - char *value; - char *tm; - - name = GetChar(node,"name"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - - if ((tm = Swig_typemap_lookup((char*)"const",type,name,value,name,0))) { - Printf(const_code,"%s\n", tm); - } else { - switch(SwigType_type(type)) { - case T_INT: case T_UINT: case T_BOOL: - case T_SHORT: case T_USHORT: - case T_LONG: case T_ULONG: - case T_SCHAR: case T_UCHAR: - Printv(const_code, "{ SWIG_PY_INT, \"", name, "\", (long) ", value, ", 0, 0, 0},\n", 0); - break; - case T_DOUBLE: - case T_FLOAT: - Printv(const_code, "{ SWIG_PY_FLOAT, \"", name, "\", 0, (double) ", value, ", 0,0},\n", 0); - break; - case T_CHAR : - Printf(const_code, "{ SWIG_PY_STRING, \"%s\", 0, 0, (void *) \"%s\", 0 }, \n", name, value); - break; - case T_STRING: - Printf(const_code,"{ SWIG_PY_STRING, \"%s\", 0, 0, (void *) \"%s\", 0 }, \n", name, value); - break; - case T_POINTER: case T_ARRAY: case T_REFERENCE: - SwigType_remember(type); - Printv(const_code, "{ SWIG_PY_POINTER, \"", name, "\", 0, 0, (void *) ", value, ", &SWIGTYPE", SwigType_manglestr(type), "}, \n", 0); - break; - default: - Printf(stderr,"%s:%d. Unsupported constant value. %s, %d\n", Getfile(node), Getline(node), name, SwigType_type(type)); - return; - break; + /* ------------------------------------------------------------ + * nativeWrapper() + * ------------------------------------------------------------ */ + + virtual int nativeWrapper(Node *n) { + String *name = Getattr(n,"sym:name"); + String *wrapname = Getattr(n,"wrap:name"); + + if (!addSymbol(wrapname,n)) return SWIG_ERROR; + + add_method(name, wrapname,0); + if (shadow) { + Printv(f_shadow_stubs, name, " = ", module, ".", name, "\n\n", NIL); } + return SWIG_OK; } - if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { - Printv(vars,name, " = ", module, ".", name, "\n", 0); - } -} -/* ----------------------------------------------------------------------------- - * PYTHON::usage_func() - Make string showing how to call a function - * ----------------------------------------------------------------------------- */ -char * -PYTHON::usage_func(char *iname, SwigType *, ParmList *l) { - static String *temp = 0; - Parm *p; - int i; - if (!temp) temp = NewString(""); - - Clear(temp); - Printf(temp,"%s(", iname); - - i = 0; - p = l; - while (p != 0) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - if (!Getignore(p)) { - i++; - /* If parameter has been named, use that. Otherwise, just print a type */ - - if (SwigType_type(pt) != T_VOID) { - if (Len(pn) > 0) { - Printf(temp,"%s",pn); + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + String *importname; + Node *mod; + if (shadow) { + mod = Getattr(n,"module"); + if (mod) { + String *modname = Getattr(mod,"name"); + if (Strcmp(modname,mainmodule) != 0) { + importname = NewStringf("%s.%s", modname, Getattr(n,"sym:name")); } else { - Printf(temp,"%s", SwigType_str(pt,0)); + importname = NewString(Getattr(n,"sym:name")); } - } - p = Getnext(p); - if (p != 0) { - if (!Getignore(p)) - Putc(',',temp); - } - } else { - p = Getnext(p); - if (p) { - if ((!Getignore(p)) && (i > 0)) - Putc(',',temp); + Setattr(n,"python:proxy",importname); } } + return Language::classDeclaration(n); } - Putc(')',temp); - return Char(temp); -} -/* ----------------------------------------------------------------------------- - * PYTHON::nativefunctin() - * ----------------------------------------------------------------------------- */ -void -PYTHON::nativefunction(DOH *node) { - char *name; - char *funcname; - name = GetChar(node,"scriptname"); - funcname = GetChar(node,"name"); - - /* Figure out what kind of function this is */ - if (Swig_proto_cmp("f(p.PyObject,p.PyObject).p.PyObject",node) == 0) { - /* Not with keyword arguments */ - add_method(name,funcname,0); - } - if (Swig_proto_cmp("f(p.PyObject,p.PyObject,p.PyObject).p.PyObject",node) == 0) { - add_method(name,funcname,1); - } - if (shadow) { - Printv(func, name, " = ", module, ".", name, "\n\n", 0); - } -} + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_class_decl() - Register a class definition - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_class_decl(DOH *node) { - String *name = Getname(node); - String *rename = Getattr(node,"scriptname"); - String *ctype = Getattr(node,"classtype"); - String *stype; - if (shadow) { - stype = NewString(name); - SwigType_add_pointer(stype); - Setattr(hash,stype,rename); - Delete(stype); - /* Add full name of datatype to the hash table */ - if (Len(ctype) > 0) { - stype = NewStringf("%s %s", ctype, name); - SwigType_add_pointer(stype); - Setattr(hash,stype,rename); - Delete(stype); - } - } -} + virtual int classHandler(Node *n) { + int oldclassic = classic; -/* ----------------------------------------------------------------------------- - * PYTHON::pragma() - * ----------------------------------------------------------------------------- */ -void -PYTHON::pragma(DOH *node) { - String *name; - String *value; - name = Getattr(node,"name"); - value = Getattr(node,"value"); - - if (Cmp(name,"code") == 0) { if (shadow) { - Printf(f_shadow,"%s\n",value); - } - } else if (Cmp(name,"include") == 0) { - if (shadow) { - if (value) { - FILE *f = Swig_open(value); - if (!f) { - Printf(stderr,"%s:%d. Unable to locate file %s\n", Getfile(node), Getline(node),value); - } else { - char buffer[4096]; - while (fgets(buffer,4095,f)) { - Printv(pragma_include,buffer,0); + + /* Create new strings for building up a wrapper function */ + have_constructor = 0; + have_repr = 0; + + if (Getattr(n,"cplus:exceptionclass")) { + classic = 1; + } + if (Getattr(n,"feature:classic")) classic = 1; + + shadow_indent = (String *) tab4; + + class_name = Getattr(n,"sym:name"); + real_classname = Getattr(n,"name"); + + if (!addSymbol(class_name,n)) return SWIG_ERROR; + + /* Handle inheritance */ + String *base_class = NewString(""); + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "python:proxy"); + if (!bname) { + base = Nextitem(baselist); + continue; + } + Printv(base_class,bname,NIL); + base = Nextitem(baselist); + if (base) { + Putc(',',base_class); } } } + Printv(f_shadow,"class ", class_name, NIL); + + if (Len(base_class)) { + Printf(f_shadow,"(%s)", base_class); + } else { + if (!classic) { + Printf(f_shadow,"(_object)"); + } + } + Printf(f_shadow,":\n"); + + Printv(f_shadow,tab4,"__swig_setmethods__ = {}\n",NIL); + if (Len(base_class)) { + Printf(f_shadow,"%sfor _s in [%s]: __swig_setmethods__.update(_s.__swig_setmethods__)\n",tab4,base_class); + } + + Printv(f_shadow, + tab4, "__setattr__ = lambda self, name, value: _swig_setattr(self, ", class_name, ", name, value)\n", + NIL); + + Printv(f_shadow,tab4,"__swig_getmethods__ = {}\n",NIL); + if (Len(base_class)) { + Printf(f_shadow,"%sfor _s in [%s]: __swig_getmethods__.update(_s.__swig_getmethods__)\n",tab4,base_class); + } + + Printv(f_shadow, + tab4, "__getattr__ = lambda self, name: _swig_getattr(self, ", class_name, ", name)\n", + NIL); } - } -} -#ifdef OLD -/* C++ pragmas are no longer handled as a special case. The generic %pragma - directive may used in or outside of a class. Therefore, this functionality - should be moved into the pragma method, not handled here. -- Dave. (12/14/00). -*/ - -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_pragma() - Handle C++ pragmas - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_pragma(Pragma *plist) { - PyPragma *pyp1 = 0, *pyp2 = 0; - if (pragmas) { - delete pragmas; - pragmas = 0; + /* Emit all of the members */ + + in_class = 1; + Language::classHandler(n); + in_class = 0; + + /* Complete the class */ + if (shadow) { + /* Generate a class registration function */ + { + SwigType *ct = NewStringf("p.%s", real_classname); + SwigType_remember(ct); + Printv(f_wrappers, + "static PyObject * ", class_name, "_swigregister(PyObject *self, PyObject *args) {\n", + tab4, "PyObject *obj;\n", + tab4, "if (!PyArg_ParseTuple(args,(char*)\"O\", &obj)) return NULL;\n", + tab4, "SWIG_TypeClientData(SWIGTYPE", SwigType_manglestr(ct),", obj);\n", + tab4, "Py_INCREF(obj);\n", + tab4, "return Py_BuildValue((char *)\"\");\n", + "}\n",NIL); + String *cname = NewStringf("%s_swigregister", class_name); + add_method(cname, cname, 0); + Delete(cname); + Delete(ct); + } + if (!have_constructor) { + Printv(f_shadow,tab4,"def __init__(self): raise RuntimeError, \"No constructor defined\"\n",NIL); + } + + if (!have_repr) { + /* Supply a repr method for this class */ + Printv(f_shadow, + tab4, "def __repr__(self):\n", + tab8, "return \"<C ", class_name," instance at %s>\" % (self.this,)\n", + NIL); + } + /* Now build the real class with a normal constructor */ + Printv(f_shadow, + "\nclass ", class_name, "Ptr(", class_name, "):\n", + tab4, "def __init__(self,this):\n", + tab8, "self.this = this\n", + tab8, "if not hasattr(self,\"thisown\"): self.thisown = 0\n", + // tab8,"try: self.this = this.this; self.thisown = getattr(this,'thisown',0); this.thisown=0\n", + // tab8,"except AttributeError: self.this = this\n" + tab8, "self.__class__ = ", class_name, "\n", + NIL); + + Printf(f_shadow,"%s.%s_swigregister(%sPtr)\n", module, class_name, class_name,0); + shadow_indent = 0; + Printf(f_shadow,"%s\n", f_shadow_stubs); + Clear(f_shadow_stubs); + } + classic = oldclassic; + return SWIG_OK; } - while (plist) { - if (strcmp(Char(plist->lang),(char*)"python") == 0) { - if (strcmp(Char(plist->name),"addtomethod") == 0) { - /* parse value, expected to be in the form "methodName:line" */ - String *temp = NewString(plist->value); - char* txtptr = strchr(Char(temp), ':'); - if (txtptr) { - /* add name and line to a list in current_class */ - *txtptr = 0; - txtptr++; - pyp1 = new PyPragma(Char(temp),txtptr); - pyp1->next = 0; - if (pyp2) { - pyp2->next = pyp1; - pyp2 = pyp1; + + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int memberfunctionHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + int oldshadow; + + /* Create the default member function */ + oldshadow = shadow; /* Disable shadowing when wrapping member functions */ + if (shadow) shadow = shadow | PYSHADOW_MEMBER; + Language::memberfunctionHandler(n); + shadow = oldshadow; + + if (!Getattr(n,"sym:nextSibling")) { + if (shadow) { + int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0; + if (Strcmp(symname,"__repr__") == 0) + have_repr = 1; + + if (Getattr(n,"feature:shadow")) { + String *pycode = pythoncode(Getattr(n,"feature:shadow"),tab4); + Printv(f_shadow,pycode,"\n",NIL); + } else { + if (allow_kwargs && !Getattr(n,"sym:overloaded")) { + Printv(f_shadow,tab4, "def ", symname, "(*args, **kwargs): ", NIL); + Printv(f_shadow, "return apply(", module, ".", Swig_name_member(class_name,symname), ",args, kwargs)\n", NIL); } else { - pragmas = pyp1; - pyp2 = pragmas; + Printv(f_shadow, tab4, "def ", symname, "(*args): ", NIL); + Printv(f_shadow, "return apply(", module, ".", Swig_name_member(class_name,symname), ",args)\n",NIL); } - } else { - Printf(stderr,"%s : Line %d. Malformed addtomethod pragma. Should be \"methodName:text\"\n", - Char(plist->filename),plist->lineno); - } - Delete(temp); - } else if (strcmp(Char(plist->name), "addtoclass") == 0) { - pyp1 = new PyPragma((char*)"__class__",Char(plist->value)); - pyp1->next = 0; - if (pyp2) { - pyp2->next = pyp1; - pyp2 = pyp1; - } else { - pragmas = pyp1; - pyp2 = pragmas; } } } - plist = plist->next; + return SWIG_OK; } -} -/* ----------------------------------------------------------------------------- - * PYTHON::emitAddPragmas() - * - * Search the current class pragma for any text belonging to name. - * Append the text properly spaced to the output string. - * ----------------------------------------------------------------------------- */ -void -PYTHON::emitAddPragmas(String *output, char* name, char* spacing) { - PyPragma *p = pragmas; - while (p) { - if (strcmp(Char(p->m_method),name) == 0) { - Printv(output,spacing,p->m_text,"\n",0); + /* ------------------------------------------------------------ + * staticmemberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + Language::staticmemberfunctionHandler(n); + if (shadow) { + Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", module, ".", Swig_name_member(class_name, symname), "\n", NIL); + if (!classic) { + Printv(f_shadow, tab4, "if _newclass:", symname, " = staticmethod(", module, ".", + Swig_name_member(class_name, symname), ")\n", NIL); + } } - p = p->next; + return SWIG_OK; } -} -#endif - -/* C++ Support + Shadow Classes */ - -static String *setattr = 0; -static String *getattr = 0; -static String *csetattr = 0; -static String *cgetattr = 0; -static String *pyclass = 0; -static String *imethod = 0; -static String *construct = 0; -static String *cinit = 0; -static String *additional = 0; -static int have_constructor; -static int have_destructor; -static int have_getattr; -static int have_setattr; -static int have_repr; -static char *class_type; -static char *real_classname; -static String *base_class = 0; -static int class_renamed = 0; + /* ------------------------------------------------------------ + * constructorDeclaration() + * ------------------------------------------------------------ */ + + virtual int constructorHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + int oldshadow = shadow; + + if (shadow) shadow = shadow | PYSHADOW_MEMBER; + Language::constructorHandler(n); + shadow = oldshadow; + + if (!Getattr(n,"sym:nextSibling")) { + if (shadow) { + int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0; + if (!have_constructor) { + if (Getattr(n,"feature:shadow")) { + String *pycode = pythoncode(Getattr(n,"feature:shadow"),tab4); + Printv(f_shadow,pycode,"\n",NIL); + } else { + if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) { + Printv(f_shadow, tab4, "def __init__(self,*args,**kwargs):\n", NIL); + Printv(f_shadow, tab8, "self.this = apply(", module, ".", Swig_name_construct(symname), ",args,kwargs)\n", NIL); + } else { + Printv(f_shadow, tab4, "def __init__(self,*args):\n",NIL); + Printv(f_shadow, tab8, "self.this = apply(", module, ".", Swig_name_construct(symname), ",args)\n", NIL); + } + Printv(f_shadow, + tab8, "self.thisown = 1\n", + NIL); + } + have_constructor = 1; + } else { + /* Hmmm. We seem to be creating a different constructor. We're just going to create a + function for it. */ -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_open_class() - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_open_class(DOH *node) { - this->Language::cpp_open_class(node); + if (Getattr(n,"feature:shadow")) { + String *pycode = pythoncode(Getattr(n,"feature:shadow"),""); + Printv(f_shadow_stubs,pycode,"\n",NIL); + } else { + if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) + Printv(f_shadow_stubs, "def ", symname, "(*args,**kwargs):\n", NIL); + else + Printv(f_shadow_stubs, "def ", symname, "(*args):\n", NIL); + + Printv(f_shadow_stubs, tab4, "val = apply(", NIL); + if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) + Printv(f_shadow_stubs, module, ".", Swig_name_construct(symname), ",args,kwargs)\n", NIL); + else + Printv(f_shadow_stubs, module, ".", Swig_name_construct(symname), ",args)\n", NIL); + Printv(f_shadow_stubs,tab4, "val.thisown = 1\n", + tab4, "return val\n\n", NIL); + } + } + } + } + return SWIG_OK; + } - char *classname = GetChar(node,"name"); - char *rname = GetChar(node,"scriptname"); - char *ctype = GetChar(node,"classtype"); - - if (shadow) { - /* Create new strings for building up a wrapper function */ - setattr = NewString(""); - getattr = NewString(""); - csetattr = NewString(""); - cgetattr = NewString(""); - pyclass = NewString(""); - imethod = NewString(""); - construct = NewString(""); - cinit = NewString(""); - additional= NewString(""); - base_class = 0; - have_constructor = 0; - have_destructor = 0; - have_getattr = 0; - have_setattr = 0; - have_repr = 0; - if (rname) { - class_name = Swig_copy_string(rname); - class_renamed = 1; - } else { - class_name = Swig_copy_string(classname); - class_renamed = 0; + /* ------------------------------------------------------------ + * destructorHandler() + * ------------------------------------------------------------ */ + + virtual int destructorHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + int oldshadow = shadow; + + if (shadow) shadow = shadow | PYSHADOW_MEMBER; + Language::destructorHandler(n); + shadow = oldshadow; + if (shadow) { + Printv(f_shadow, tab4, "def __del__(self, destroy= ", module, ".", Swig_name_destroy(symname), "):\n", NIL); + Printv(f_shadow, tab8, "try:\n", NIL); + Printv(f_shadow, tab4, tab8, "if self.thisown: destroy(self)\n", NIL); + Printv(f_shadow, tab8, "except: pass\n", NIL); } + return SWIG_OK; } - real_classname = Swig_copy_string(classname); - class_type = Swig_copy_string(ctype); + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ - cpp_class_decl(node); + virtual int membervariableHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); - if (shadow) { - Printv(setattr, - tab4, "def __setattr__(self,name,value):\n", - tab8, "if (name == \"this\") or (name == \"thisown\"): self.__dict__[name] = value; return\n", - tab8, "method = ", class_name, ".__setmethods__.get(name,None)\n", - tab8, "if method: return method(self,value)\n", - 0); + int oldshadow = shadow; + if (shadow) shadow = shadow | PYSHADOW_MEMBER; + Language::membervariableHandler(n); + shadow = oldshadow; - Printv(getattr, tab4, "def __getattr__(self,name):\n", 0); - Printv(csetattr, tab4, "__setmethods__ = {\n", 0); - Printv(cgetattr, tab4, "__getmethods__ = {\n", 0); - } -} + if (shadow) { + int immutable = 0; + if (!Getattr(n,"feature:immutable")) { + Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", Swig_name_set(Swig_name_member(class_name,symname)), "\n", NIL); + } else { + immutable = 1; + } + Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", Swig_name_get(Swig_name_member(class_name,symname)),"\n", NIL); -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_member_func() - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_memberfunction(DOH *node) { - char *realname; - char *name, *iname; - SwigType *t; - ParmList *l; - int oldshadow; - char cname[1024]; - - /* Create the default member function */ - oldshadow = shadow; /* Disable shadowing when wrapping member functions */ - if (shadow) shadow = shadow | PYSHADOW_MEMBER; - this->Language::cpp_memberfunction(node); - shadow = oldshadow; - if (shadow) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - l = Getattr(node,"parms"); - realname = iname ? iname : name; - - /* Check to see if we've already seen this */ - sprintf(cname,"python:%s::%s",class_name,realname); - if (Getattr(symbols,cname)) return; - Setattr(symbols,cname,cname); - - if (strcmp(realname,"__repr__") == 0) - have_repr = 1; - - if (!is_shadow(t) && !noopt) { - Printv(imethod, - class_name, ".", realname, " = new.instancemethod(", module, ".", Swig_name_member(class_name,realname), ", None, ", class_name, ")\n", - 0); - } else { - if (use_kw) - Printv(pyclass,tab4, "def ", realname, "(*args, **kwargs):\n", 0); - else - Printv(pyclass, tab4, "def ", realname, "(*args):\n", 0); - - if (use_kw) - Printv(pyclass, tab8, "val = apply(", module, ".", Swig_name_member(class_name,realname), ",args, kwargs)\n", 0); - else - Printv(pyclass, tab8, "val = apply(", module, ".", Swig_name_member(class_name,realname), ",args)\n",0); - - /* Check to see if the return type is an object */ - if (is_shadow(t)) { - if (!Swig_typemap_search((char*)"out",t,Swig_name_member(class_name,realname))) { - if (!have_output) { - Printv(pyclass, tab8, "if val: val = ", is_shadow(t), "Ptr(val) ", 0); - if ((!SwigType_ispointer(t) || NewObject)) { - Printf(pyclass, "; val.thisown = 1\n"); - } else { - Printf(pyclass,"\n"); - } - } + if (!classic) { + if (immutable) { + Printv(f_shadow,tab4,"if _newclass:", symname," = property(", module, ".", + Swig_name_get(Swig_name_member(class_name,symname)),")\n", NIL); + } else { + Printv(f_shadow,tab4,"if _newclass:", symname," = property(", + module, ".", Swig_name_get(Swig_name_member(class_name,symname)),",", + module, ".", Swig_name_set(Swig_name_member(class_name,symname)),")\n", NIL); } } - Printv(pyclass, tab8, "return val\n", 0); } - /* emitAddPragmas(*pyclass, realname, tab8); - *pyclass << tab8 << "return val\n"; */ + return SWIG_OK; } -} -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_constructor() - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_constructor(DOH *node) { - char *name, *iname; - ParmList *l; - char *realname; - int oldshadow = shadow; - char cname[1024]; - - if (shadow) shadow = shadow | PYSHADOW_MEMBER; - this->Language::cpp_constructor(node); - shadow = oldshadow; - - if (shadow) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - l = Getattr(node,"parms"); - realname = iname ? iname : class_name; - - /* Check to see if we've already seen this */ - sprintf(cname,":python:constructor:%s::%s",class_name,realname); - if (Getattr(symbols,cname)) return; - Setattr(symbols,cname,cname); - - if (!have_constructor) { - if (use_kw) - Printv(construct, tab4, "def __init__(self,*args,**kwargs):\n", 0); - else - Printv(construct, tab4, "def __init__(self,*args):\n",0); - - if (use_kw) - Printv(construct, tab8, "self.this = apply(", module, ".", Swig_name_construct(realname), ",args,kwargs)\n", 0); - else - Printv(construct, tab8, "self.this = apply(", module, ".", Swig_name_construct(realname), ",args)\n", 0); - Printv(construct, tab8, "self.thisown = 1\n", 0); - // emitAddPragmas(construct,(char*)"__init__",(char*)tab8); - have_constructor = 1; - } else { - /* Hmmm. We seem to be creating a different constructor. We're just going to create a - function for it. */ - - if (use_kw) - Printv(additional, "def ", realname, "(*args,**kwargs):\n", 0); - else - Printv(additional, "def ", realname, "(*args):\n", 0); - - Printv(additional, tab4, "val = ", class_name, "Ptr(apply(", 0); - if (use_kw) - Printv(additional, module, ".", Swig_name_construct(realname), ",args,kwargs))\n", 0); - else - Printv(additional, module, ".", Swig_name_construct(realname), ",args))\n", 0); - Printv(additional,tab4, "val.thisown = 1\n", - tab4, "return val\n\n", 0); + /* ------------------------------------------------------------ + * staticmembervariableHandler() + * ------------------------------------------------------------ */ + + virtual int staticmembervariableHandler(Node *n) { + String *symname; + SwigType *t; + + Language::staticmembervariableHandler(n); + if (shadow) { + t = Getattr(n,"type"); + symname = Getattr(n,"sym:name"); + if (SwigType_isconst(t) && !Getattr(n, "value")) { + Printf(f_shadow,"%s%s = %s.%s.%s\n", tab4, symname, module, global_name, Swig_name_member(class_name,symname)); + } } - } -} + return SWIG_OK; -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_destructor() - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_destructor(DOH *node) { - char *name, *newname; - char *realname; - int oldshadow = shadow; - - if (shadow) shadow = shadow | PYSHADOW_MEMBER; - this->Language::cpp_destructor(node); - shadow = oldshadow; - if (shadow) { - name = GetChar(node,"name"); - newname = GetChar(node,"scriptname"); - if (newname) realname = newname; - else realname = class_renamed ? class_name : name; - - Printv(pyclass, tab4, "def __del__(self,", module, "=", module, "):\n", 0); - // emitAddPragmas(pyclass,(char*)"__del__",(char*)tab8); - Printv(pyclass, tab8, "if self.thisown == 1 :\n", - tab8, tab4, module, ".", Swig_name_destroy(realname), "(self)\n", 0); - - have_destructor = 1; } -} -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_close_class() - Close a class and write wrappers - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_close_class() { - String *ptrclass; - String *repr; - - ptrclass = NewString(""); - repr = NewString(""); - - if (shadow) { - if (!have_constructor) { - /* Build a constructor that takes a pointer to this kind of object */ - Printv(construct, - tab4, "def __init__(self,this):\n", - tab8, "self.this = this\n", - 0); - } - /* First, build the pointer base class */ - if (base_class) { - Printv(ptrclass, "class ", class_name, "(", base_class, "):\n", 0); - } else { - Printv(ptrclass, "class ", class_name, ":\n", 0); - } - Printv(getattr, - tab8, "method = ", class_name, ".__getmethods__.get(name,None)\n", - tab8, "if method: return method(self)\n", - tab8, "raise AttributeError,name\n", - 0); - Printv(setattr, tab8, "self.__dict__[name] = value\n",0); - Printv(cgetattr, tab4, "}\n", 0); - Printv(csetattr, tab4, "}\n", 0); - Printv(ptrclass,cinit,construct,"\n",0); - Printv(classes,ptrclass,pyclass,0); - - if (have_setattr) { - Printv(classes, csetattr, setattr, 0); - } - if (have_getattr) { - Printv(classes,cgetattr,getattr,0); - } - if (!have_repr) { - /* Supply a repr method for this class */ - Printv(repr, - tab4, "def __repr__(self):\n", - tab8, "return \"<C ", class_name," instance at %s>\" % (self.this,)\n", - 0); - - Printv(classes,repr,0); - // emitAddPragmas(classes,(char*)"__class__",(char*)tab4); - } + /* ------------------------------------------------------------ + * memberconstantHandler() + * ------------------------------------------------------------ */ - /* Now build the real class with a normal constructor */ - Printv(classes, - "class ", class_name, "Ptr(", class_name, "):\n", - tab4, "def __init__(self,this):\n", - tab8, "self.this = this\n", - tab8, "self.thisown = 0\n", - tab8, "self.__class__ = ", class_name, "\n", - "\n", additional, "\n", - 0); - - Printv(classes,imethod,"\n",0); - Delete(pyclass); - Delete(imethod); - Delete(setattr); - Delete(getattr); - Delete(additional); - } - Delete(ptrclass); - Delete(repr); -} + virtual int memberconstantHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + int oldshadow = shadow; + if (shadow) shadow = shadow | PYSHADOW_MEMBER; + Language::memberconstantHandler(n); + shadow = oldshadow; -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_inherit() - Handle inheritance - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_inherit(List *bases) { - char *bc; - String *base; - int first_base = 0; - - if (!shadow) { - this->Language::cpp_inherit(bases); - return; + if (shadow) { + Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(class_name,symname), "\n", NIL); + } + return SWIG_OK; } - /* We'll inherit variables and constants, but not methods */ - this->Language::cpp_inherit(bases); + /* ------------------------------------------------------------ + * pythoncode() - Output python code into the shadow file + * ------------------------------------------------------------ */ - if (!bases) return; - base_class = NewString(""); + String *pythoncode(String *code, const String *indent) { + String *out = NewString(""); + String *temp; + char *t; + if (!indent) indent = ""; - /* Now tell the Python module that we're inheriting from a base class */ + temp = NewString(code); - for (base = Firstitem(bases); base; base = Nextitem(bases)) { - String *bs = NewString(base); - SwigType_add_pointer(bs); - bc = GetChar(hash,bs); - if (bc) { - if (first_base) Putc(',',base_class); - Printv(base_class,bc,0); - first_base = 1; + t = Char(temp); + if (*t == '{') { + Delitem(temp,0); + Delitem(temp,DOH_END); } - Delete(bs); - } - if (!first_base) { - Delete(base_class); - base_class = 0; + /* Split the input text into lines */ + List *clist = DohSplit(temp,'\n',-1); + Delete(temp); + int initial = 0; + String *s; + + /* Get the initial indentation */ + for (s = Firstitem(clist); s; s = Nextitem(clist)) { + if (Len(s)) { + char *c = Char(s); + while (*c) { + if (!isspace(*c)) break; + initial++; + c++; + } + if (*c && !isspace(*c)) break; + else { + initial = 0; + } + } + } + while (s) { + if (Len(s) > initial) { + char *c = Char(s); + c += initial; + Printv(out,indent,c,"\n",NIL); + } else { + Printv(out,"\n",NIL); + } + s = Nextitem(clist); + } + Delete(clist); + return out; } -} -/* ----------------------------------------------------------------------------- - * PYTHON::cpp_variable() - Add a member variable - * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_variable(DOH *node) { - char *name, *iname; - SwigType *t; - char *realname; - int inhash = 0; - int oldshadow = shadow; - char cname[512]; - - if (shadow) shadow = shadow | PYSHADOW_MEMBER; - this->Language::cpp_variable(node); - shadow = oldshadow; - - if (shadow) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - have_getattr = 1; - have_setattr = 1; - realname = iname ? iname : name; - - /* Check to see if we've already seen this */ - sprintf(cname,"python:%s::%s:",class_name,realname); - if (Getattr(symbols,cname)) return; - - Setattr(symbols,cname,cname); - - /* Figure out if we've seen this datatype before */ - if (is_shadow(t)) inhash = 1; - - if (ReadOnly) { - /* *setattr << tab8 << tab4 << "raise RuntimeError, \'Member is read-only\'\n"; */ - } else { - Printv(csetattr, tab8, "\"", realname, "\" : ", module, ".", Swig_name_set(Swig_name_member(class_name,realname)), ",\n", 0); - } - if (inhash) { - Printv(cgetattr, tab8, "\"", realname, "\" : lambda x : ", is_shadow(t), "Ptr(", module, ".", Swig_name_get(Swig_name_member(class_name,realname)), "(x)),\n", 0); + /* ------------------------------------------------------------ + * insertDirective() + * + * Hook for %insert directive. We're going to look for special %shadow inserts + * as a special case so we can do indenting correctly + * ------------------------------------------------------------ */ + + virtual int insertDirective(Node *n) { + String *code = Getattr(n,"code"); + String *section = Getattr(n,"section"); + + if ((!ImportMode) && ((Cmp(section,"python") == 0) || (Cmp(section,"shadow") == 0))) { + if (shadow) { + String *pycode = pythoncode(code,shadow_indent); + Printv(f_shadow, pycode, "\n", NIL); + Delete(pycode); + } } else { - Printv(cgetattr, tab8, "\"", realname, "\" : ", module, ".", Swig_name_get(Swig_name_member(class_name,realname)),",\n", 0); + Language::insertDirective(n); } + return SWIG_OK; } -} +}; /* ----------------------------------------------------------------------------- - * PYTHON::cpp_declare_const() + * swig_python() - Instantiate module * ----------------------------------------------------------------------------- */ -void -PYTHON::cpp_constant(DOH *node) { - char *name, *iname, *value; - SwigType *type; - char *realname; - int oldshadow = shadow; - char cname[512]; - - if (shadow) shadow = shadow | PYSHADOW_MEMBER; - this->Language::cpp_constant(node); - shadow = oldshadow; - - if (shadow) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - realname = iname ? iname : name; - - /* Check to see if we've already seen this */ - sprintf(cname,"python:%s::%s", class_name, realname); - if (Getattr(symbols,cname)) return; - Setattr(symbols,cname,cname); - Printv(cinit, tab4, realname, " = ", module, ".", Swig_name_member(class_name,realname), "\n", 0); - } -} -/* ----------------------------------------------------------------------------- - * PYTHON::add_typedef() - Manage typedef's for shadow classes - * ----------------------------------------------------------------------------- */ -void -PYTHON::add_typedef(SwigType *t, String *name) { - if (!shadow) return; - if (is_shadow(t)) { - DOH *node = NewHash(); - Setname(node,name); - Setattr(node,"scriptname", is_shadow(t)); - Setattr(node,"classtype",""); - cpp_class_decl(node); - } +extern "C" Language * +swig_python(void) { + return new PYTHON(); } diff --git a/Source/Modules1.1/python.h b/Source/Modules1.1/python.h deleted file mode 100644 index 16b0eef1e..000000000 --- a/Source/Modules1.1/python.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * Simplified Wrapper and Interface Generator (SWIG) - * - * Author : David Beazley - * - * Department of Computer Science - * University of Chicago - * 1100 E 58th Street - * Chicago, IL 60637 - * beazley@cs.uchicago.edu - * - * Please read the file LICENSE for the copyright and terms by which SWIG - * can be used and distributed. - *******************************************************************************/ - -/************************************************************************** - * $Header$ - * - * python.h - * - * Header file for Python module. Warning ; this is work in progress. - **************************************************************************/ - -class PYTHON : public Language { -protected: - void get_pointer(char *src, char *dest, SwigType *t, String *f, char *ret); - void add_method(String *name, String *function, int kw); - char *usage_func(char *, SwigType *, ParmList *); - -public : - - // Don't change any of this - virtual void parse_args(int, char *argv[]); - virtual void initialize(String *); - virtual void function(DOH *node); - virtual void variable(DOH *node); - virtual void constant(DOH *node); - virtual void nativefunction(DOH *); - virtual void close(void); - virtual void create_command(String *, String *); - virtual void import(String *modname); - - // C++ extensions---for creating shadow classes - - virtual void cpp_memberfunction(DOH *); - virtual void cpp_constructor(DOH *); - virtual void cpp_destructor(DOH *); - virtual void cpp_open_class(DOH *); - virtual void cpp_close_class(); - virtual void cpp_inherit(List *bases); - virtual void cpp_variable(DOH *); - virtual void cpp_constant(DOH *); - virtual void cpp_class_decl(DOH *); - virtual void pragma(DOH *node); - virtual void add_typedef(SwigType *t, String *name); -}; - -#define PYSHADOW_MEMBER 0x2 - - - - diff --git a/Source/Modules1.1/ruby.cxx b/Source/Modules1.1/ruby.cxx index ffb64a876..f5f0a796a 100644 --- a/Source/Modules1.1/ruby.cxx +++ b/Source/Modules1.1/ruby.cxx @@ -10,16 +10,17 @@ * ********************************************************************/ -static char cvsroot[] = "$Header$"; +char cvsroot_ruby_cxx[] = "$Header$"; -#include "swig11.h" -#include "ruby.h" +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif #include <ctype.h> #include <string.h> - -/* for debug */ -#define P(obj) printf("\"%s\"\n", Char(Str(obj))) +#include <limits.h> /* for INT_MAX */ class RClass { private: @@ -27,1482 +28,1413 @@ class RClass { public: String *name; /* class name (renamed) */ String *cname; /* original C class/struct name */ + String *mname; /* Mangled name */ String *vname; /* variable name */ String *type; String *prefix; String *header; String *init; - String *aliases; - String *includes; - Hash *freemethods; - Hash *predmethods; + int constructor_defined; int destructor_defined; - RClass(void) { - freemethods = NewHash(); - predmethods = NewHash(); - destructor_defined = 0; + RClass() { + temp = NewString(""); name = NewString(""); cname = NewString(""); + mname = NewString(""); vname = NewString(""); type = NewString(""); prefix = NewString(""); header = NewString(""); init = NewString(""); - aliases = NewString(""); - includes = NewString(""); - temp = NewString(""); + constructor_defined = 0; + destructor_defined = 0; } + ~RClass() { Delete(name); Delete(cname); Delete(vname); + Delete(mname); Delete(type); Delete(prefix); Delete(header); Delete(init); - Delete(aliases); - Delete(includes); - Delete(freemethods); - Delete(predmethods); Delete(temp); } - void set_name(char *cn, char *rn, char *valn) { + void set_name(const String_or_char *cn, const String_or_char *rn, const String_or_char *valn) { Clear(cname); Append(cname,cn); + Delete(mname); + mname = Swig_name_mangle(cname); Clear(name); Append(name,valn); Clear(vname); - Printf(vname,"c%s",name); - Printv(prefix,(rn ? rn : cn), "_", 0); + Printf(vname,"c%s.klass",name); + Clear(prefix); + Printv(prefix,(rn ? rn : cn), "_", NIL); } - char *strip(char *s) { - if (strncmp(s, Char(prefix), Len(prefix)) != 0) - return s; + char *strip(const String_or_char *s) { Clear(temp); - Append(temp,s); - Replace(temp,prefix,"",DOH_REPLACE_ANY); + Append(temp, s); + if (Strncmp(s, prefix, Len(prefix)) == 0) { + Replaceall(temp,prefix,""); + } return Char(temp); } }; -static char *usage = (char*)"\ +#ifdef RUBY_SUPPORTS_KEYWORD_ARGS +static const char * +usage = "\ +Ruby Options (available with -ruby)\n\ + -ldflags - Print runtime libraries to link with\n\ + -feature name - Set feature name (used by `require')\n\ + -keyword - Use keyword arguments\n"; +#else +static const char * +usage = "\ Ruby Options (available with -ruby)\n\ - -module name - Set module name\n\ + -ldflags - Print runtime libraries to link with\n\ -feature name - Set feature name (used by `require')\n"; - -static char *module = 0; -static char *modvar = 0; -static char *feature = 0; -static String *other_extern = 0; -static String *other_init = 0; -static char *import_file; - -static int current; - -enum { - NO_CPP, - MEMBER_FUNC, - CONSTRUCTOR, - DESTRUCTOR, - MEMBER_VAR, - CLASS_CONST, - STATIC_FUNC, - STATIC_VAR -}; - -static Hash *classes; /* key=cname val=RClass */ -static RClass *klass; /* Currently processing class */ -static Hash *special_methods; /* Python style special method name table */ - +#endif #define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0) #define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0)) -/* --------------------------------------------------------------------- - * RUBY::parse_args(int argc, char *argv[]) - * - * Parse command line options and initializes variables. - * --------------------------------------------------------------------- */ - -void RUBY::parse_args(int argc, char *argv[]) { - /* Look for certain command line options */ - for (int i = 1; i < argc; i++) { - if (argv[i]) { - if (strcmp(argv[i],"-feature") == 0) { - if (argv[i+1]) { - char *name = argv[i+1]; - feature = new char [strlen(name)+1]; - strcpy(feature, name); + +class RUBY : public Language { +private: + + String *module; + String *modvar; + String *feature; + int current; + Hash *classes; /* key=cname val=RClass */ + RClass *klass; /* Currently processing class */ + Hash *special_methods; /* Python style special method name table */ + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + bool use_kw; + + // Wrap modes + enum { + NO_CPP, + MEMBER_FUNC, + CONSTRUCTOR_ALLOCATE, + CONSTRUCTOR_INITIALIZE, + DESTRUCTOR, + MEMBER_VAR, + CLASS_CONST, + STATIC_FUNC, + STATIC_VAR + }; + +public: + + /* --------------------------------------------------------------------- + * RUBY() + * + * Initialize member data + * --------------------------------------------------------------------- */ + + RUBY() { + module = 0; + modvar = 0; + feature = 0; + current = NO_CPP; + classes = 0; + klass = 0; + special_methods = 0; + f_runtime = 0; + f_header = 0; + f_wrappers = 0; + f_init = 0; + use_kw = false; + } + + /* --------------------------------------------------------------------- + * main() + * + * Parse command line options and initializes variables. + * --------------------------------------------------------------------- */ + + virtual void main(int argc, char *argv[]) { + + /* Set location of SWIG library */ + SWIG_library_directory("ruby"); + + /* Look for certain command line options */ + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp(argv[i],"-feature") == 0) { + if (argv[i+1]) { + char *name = argv[i+1]; + feature = NewString(name); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i],"-help") == 0) { + Printf(stderr,"%s\n", usage); + } else if (strcmp (argv[i],"-ldflags") == 0) { + printf("%s\n", SWIG_RUBY_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } else if (strcmp(argv[i],"-keyword") == 0) { + use_kw = true; Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); } - } else if (strcmp(argv[i],"-help") == 0) { - Printf(stderr,"%s\n", usage); } } + + /* Add a symbol to the parser for conditional compilation */ + Preprocessor_define("SWIGRUBY 1", 0); + + /* Add typemap definitions */ + SWIG_typemap_lang("ruby"); + SWIG_config_file("ruby.swg"); + allow_overloading(); } - /* Set location of SWIG library */ - Swig_swiglib_set("ruby"); - /* Add a symbol to the parser for conditional compilation */ - Preprocessor_define((void *) "SWIGRUBY", 0); - Swig_set_config_file("ruby.i"); -} + /* --------------------------------------------------------------------- + * top() + * --------------------------------------------------------------------- */ + virtual int top(Node *n) { -static void insert_file(char *filename, File *file) { - if (Swig_insert_file(filename, file) == -1) { - Printf(stderr, - "SWIG : Fatal error. " - "Unable to locate %s. (Possible installation problem).\n", - filename); - Swig_exit (EXIT_FAILURE); - } -} + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); -/* --------------------------------------------------------------------- - * RUBY::initialize() - * - * Produces an initialization function. Assumes that the module - * name has already been specified. - * --------------------------------------------------------------------- */ - -void RUBY::initialize(String *modname) { - import_file = 0; - current = NO_CPP; - klass = 0; - classes = NewHash(); - special_methods = NewHash(); - other_extern = NewString(""); - other_init = NewString(""); - - /* Python style special method name. */ - /* Basic */ - Setattr(special_methods, "__repr__", "inspect"); - Setattr(special_methods, "__str__", "to_s"); - Setattr(special_methods, "__cmp__", "<=>"); - Setattr(special_methods, "__hash__", "hash"); - Setattr(special_methods, "__nonzero__", "nonzero?"); + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + modvar = 0; + current = NO_CPP; + klass = 0; + classes = NewHash(); + special_methods = NewHash(); + + /* Python style special method name. */ + /* Basic */ + Setattr(special_methods, "__repr__", "inspect"); + Setattr(special_methods, "__str__", "to_s"); + Setattr(special_methods, "__cmp__", "<=>"); + Setattr(special_methods, "__hash__", "hash"); + Setattr(special_methods, "__nonzero__", "nonzero?"); + /* Callable */ - Setattr(special_methods, "__call__", "call"); - /* Collection */ - Setattr(special_methods, "__len__", "length"); - Setattr(special_methods, "__getitem__", "[]"); - Setattr(special_methods, "__setitem__", "[]="); - /* Numeric */ - Setattr(special_methods, "__add__", "+"); - Setattr(special_methods, "__sub__", "-"); - Setattr(special_methods, "__mul__", "*"); - Setattr(special_methods, "__div__", "/"); - Setattr(special_methods, "__mod__", "%"); - Setattr(special_methods, "__divmod__", "divmod"); - Setattr(special_methods, "__pow__", "**"); - Setattr(special_methods, "__lshift__", "<<"); - Setattr(special_methods, "__rshift__", ">>"); - Setattr(special_methods, "__and__", "&"); - Setattr(special_methods, "__xor__", "^"); - Setattr(special_methods, "__or__", "|"); - Setattr(special_methods, "__neg__", "-@"); - Setattr(special_methods, "__pos__", "+@"); - Setattr(special_methods, "__abs__", "abs"); - Setattr(special_methods, "__invert__", "~"); - Setattr(special_methods, "__int__", "to_i"); - Setattr(special_methods, "__float__", "to_f"); - Setattr(special_methods, "__coerce__", "coerce"); - - Swig_banner(f_header); - - Printf(f_header,"/* Implementation : RUBY */\n\n"); - Printf(f_header,"#define SWIGRUBY\n"); - - insert_file((char*)"common.swg", f_header); - insert_file((char*)"ruby.swg", f_header); - if (NoInclude) { - insert_file((char*)"rubydec.swg", f_header); - } else { - insert_file((char*)"rubydef.swg", f_header); - } + Setattr(special_methods, "__call__", "call"); + + /* Collection */ + Setattr(special_methods, "__len__", "length"); + Setattr(special_methods, "__getitem__", "[]"); + Setattr(special_methods, "__setitem__", "[]="); + + /* Operators */ + Setattr(special_methods, "__add__", "+"); + Setattr(special_methods, "__pos__", "+@"); + Setattr(special_methods, "__sub__", "-"); + Setattr(special_methods, "__neg__", "-@"); + Setattr(special_methods, "__mul__", "*"); + Setattr(special_methods, "__div__", "/"); + Setattr(special_methods, "__mod__", "%"); + Setattr(special_methods, "__lshift__", "<<"); + Setattr(special_methods, "__rshift__", ">>"); + Setattr(special_methods, "__and__", "&"); + Setattr(special_methods, "__or__", "|"); + Setattr(special_methods, "__xor__", "^"); + Setattr(special_methods, "__invert__", "~"); + Setattr(special_methods, "__lt__", "<"); + Setattr(special_methods, "__le__", "<="); + Setattr(special_methods, "__gt__", ">"); + Setattr(special_methods, "__ge__", ">="); + Setattr(special_methods, "__eq__", "=="); + + /* Other numeric */ + Setattr(special_methods, "__divmod__", "divmod"); + Setattr(special_methods, "__pow__", "**"); + Setattr(special_methods, "__abs__", "abs"); + Setattr(special_methods, "__int__", "to_i"); + Setattr(special_methods, "__float__", "to_f"); + Setattr(special_methods, "__coerce__", "coerce"); + + Swig_banner(f_runtime); + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } - /* typedef void *VALUE */ - SwigType *value = NewSwigType(T_VOID); - SwigType_setbase(value,(char*)"void"); - SwigType_add_pointer(value); - SwigType_typedef(value,(char*)"VALUE"); - Delete(value); + /* typedef void *VALUE */ + SwigType *value = NewSwigType(T_VOID); + SwigType_add_pointer(value); + SwigType_typedef(value,(char*)"VALUE"); + Delete(value); - /* Old set_module code */ + /* Set module name */ + set_module(Char(Getattr(n,"name"))); - if (!module) { - module = new char[Len(modname)+1]; - strcpy(module, Char(modname)); + Printf(f_header,"#define SWIG_init Init_%s\n", feature); + Printf(f_header,"#define SWIG_name \"%s\"\n\n", module); + Printf(f_header,"static VALUE %s;\n", modvar); + + /* Start generating the initialization function */ + Printv(f_init, + "\n", + "#ifdef __cplusplus\n", + "extern \"C\"\n", + "#endif\n", + "void Init_", feature, "(void) {\n", + "int i;\n", + "\n", + NIL); + + Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL); + + /* Account for nested modules */ + List *modules = Split(module,':',INT_MAX); + if (modules != 0 && Len(modules) > 0) { + String *mv = 0; + String *m = Firstitem(modules); + while (m != 0) { + if (Len(m) > 0) { + if (mv != 0) { + Printv(f_init, tab4, modvar, + " = rb_define_module_under(", modvar, ", \"", m, "\");\n", NIL); + } else { + Printv(f_init, tab4, modvar, + " = rb_define_module(\"", m, "\");\n", NIL); + mv = NewString(modvar); + } + } + m = Nextitem(modules); + } + Delete(mv); + Delete(modules); + } + + Printv(f_init, + "\n", + "for (i = 0; swig_types_initial[i]; i++) {\n", + "swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n", + "SWIG_define_class(swig_types[i]);\n", + "}\n", + NIL); + Printf(f_init,"\n"); + + Language::top(n); + + /* Finish off our init function */ + Printf(f_init,"}\n"); + SwigType_emit_type_table(f_runtime,f_wrappers); + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; } - if (!feature) { - feature = new char[strlen(module)+1]; - strcpy(feature, module); + + /* ----------------------------------------------------------------------------- + * importDirective() + * ----------------------------------------------------------------------------- */ + + virtual int importDirective(Node *n) { + String *modname = Getattr(n,"module"); + if (modname) { + Printf(f_init,"rb_require(\"%s\");\n", modname); + } + return Language::importDirective(n); } - /* module name must be a constant. */ - module[0] = toupper(module[0]); - modvar = new char[1+strlen(module)+1]; - modvar[0] = 'm'; - strcpy(modvar+1, module); + /* --------------------------------------------------------------------- + * set_module(const char *mod_name) + * + * Sets the module name. Does nothing if it's already set (so it can + * be overridden as a command line option). + *---------------------------------------------------------------------- */ + + void set_module(const char *s) { + String *mod_name = NewString(s); + if (module == 0) { + /* Start with the empty string */ + module = NewString(""); + + /* Account for nested modules */ + List *modules = Split(mod_name,':',INT_MAX); + if (modules != 0 && Len(modules) > 0) { + String *last = 0; + String *m = Firstitem(modules); + while (m != 0) { + if (Len(m) > 0) { + String *cap = NewString(m); + (Char(cap))[0] = toupper((Char(cap))[0]); + if (last != 0) { + Append(module, "::"); + } + Append(module, cap); + last = m; + } + m = Nextitem(modules); + } + if (feature == 0) { + feature = Copy(last); + } + (Char(last))[0] = toupper((Char(last))[0]); + modvar = NewStringf("m%s", last); + Delete(modules); + } + } + Delete(mod_name); + } + + /* -------------------------------------------------------------------------- + * nativeWrapper() + * -------------------------------------------------------------------------- */ + virtual int nativeWrapper(Node *n) { + String *funcname = Getattr(n,"wrap:name"); + Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, + "Adding native function %s not supported (ignored).\n", funcname); + return SWIG_NOWRAP; + } - /* Old init code */ + /* --------------------------------------------------------------------- + * create_command(Node *n, char *iname) + * + * Creates a new command from a C function. + * iname = Name of function in scripting language + * --------------------------------------------------------------------- */ - Printf(f_header,"#define SWIG_init Init_%s\n", feature); - Printf(f_header,"#define SWIG_name \"%s\"\n\n", module); - Printf(f_header,"static VALUE %s;\n", modvar); - Printf(f_header,"\n%s\n", other_extern); + void create_command(Node *n, const String_or_char *iname) { - /* Start generating the initialization function */ - Printv(f_init, - "\n", - "#ifdef __cplusplus\n", - "extern \"C\"\n", - "#endif\n", - "void Init_", feature, "(void) {\n", - "int i;\n", - other_init, - "\n", - 0); - - Printv(f_init, tab4, modvar, " = rb_define_module(\"", module, "\");\n", - "_mSWIG = rb_define_module_under(", modvar, ", \"SWIG\");\n", - 0); - Printv(f_init, - "\n", - "for (i = 0; swig_types_initial[i]; i++) {\n", - "swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n", - "SWIG_define_class(swig_types[i]);\n", - "}\n", - 0); - Printf(f_init,"\n"); - klass = new RClass(); -} + String *wname = Swig_name_wrapper(iname); + if (CPlusPlus) { + Insert(wname,0,"VALUEFUNC("); + Append(wname,")"); + } + if (current != NO_CPP) + iname = klass->strip(iname); + if (Getattr(special_methods, iname)) { + iname = GetChar(special_methods, iname); + } + + String *s = NewString(""); + String *temp = NewString(""); + + switch (current) { + case MEMBER_FUNC: + Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", + iname, "\", ", wname, ", -1);\n", NIL); + break; + case CONSTRUCTOR_ALLOCATE: + Printv(s, tab4, "rb_define_singleton_method(", klass->vname, + ", \"new\", ", wname, ", -1);\n", NIL); + Replaceall(klass->init,"$allocator", s); + break; + case CONSTRUCTOR_INITIALIZE: + Printv(s, tab4, "rb_define_method(", klass->vname, + ", \"initialize\", ", wname, ", -1);\n", NIL); + Replaceall(klass->init,"$initializer", s); + break; + case MEMBER_VAR: + Append(temp,iname); + Replaceall(temp,"_set", "="); + Replaceall(temp,"_get", ""); + Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", + temp, "\", ", wname, ", -1);\n", NIL); + break; + case STATIC_FUNC: + Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, + ", \"", iname, "\", ", wname, ", -1);\n", NIL); + break; + default: + Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", + iname, "\", ", wname, ", -1);\n",NIL); + Printv(f_init,s,NIL); + break; + } + + /* Process the comma-separated list of aliases (if any) */ + String *aliasv = Getattr(n,"feature:alias"); + if (aliasv) { + List *aliases = Split(aliasv,',',INT_MAX); + if (aliases && Len(aliases) > 0) { + String *alias = Firstitem(aliases); + while (alias) { + if (Len(alias) > 0) { + Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias, "\", \"", iname, "\");\n", NIL); + } + alias = Nextitem(aliases); + } + } + Delete(aliases); + } -/* --------------------------------------------------------------------- - * RUBY::close(void) - * - * Finish the initialization function. Close any additional files and - * resources in use. - * --------------------------------------------------------------------- */ - -void RUBY::close(void) { - /* Finish off our init function */ - Printf(f_init,"}\n"); - SwigType_emit_type_table(f_header,f_wrappers); -} + Delete(temp); + Delete(s); + Delete(wname); + } + + /* --------------------------------------------------------------------- + * marshalInputArgs(int numarg, int numreq, int start, Wrapper *f) + * + * Checks each of the parameters in the parameter list for a "check" + * typemap and (if it finds one) inserts the typemapping code into + * the function wrapper. + * --------------------------------------------------------------------- */ + + void marshalInputArgs(ParmList *l, int numarg, int numreq, int start, String *kwargs, bool allow_kwargs, Wrapper *f) { + int i; + Parm *p; + String *tm; + char source[256], target[256]; + + int use_self = (current == MEMBER_FUNC || current == MEMBER_VAR) ? 1 : 0; + int varargs = emit_isvarargs(l); + + Printf(kwargs,"{ "); + for (i = 0, p = l; i < numarg; i++) { + + /* Skip ignored arguments */ + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } -/* -------------------------------------------------------------------------- - * RUBY::nativefunction() - * -------------------------------------------------------------------------- */ -void -RUBY::nativefunction(DOH *node) { - Printf(stderr,"%s:%d. Adding native function %s not supported (ignored).\n", Getfile(node), Getline(node), Getattr(node,"scriptname")); -} + SwigType *pt = Getattr(p,"type"); + String *pn = Getattr(p,"name"); + String *ln = Getattr(p,"lname"); -/* --------------------------------------------------------------------- - * RUBY::make_wrapper_name(char *cname) - * - * Creates a name for a wrapper function - * iname = Name of the function in scripting language - * --------------------------------------------------------------------- */ - -String *RUBY::make_wrapper_name(char *iname) { - String *wname = Swig_name_wrapper(iname); - Replace(wname, "?", "_p", DOH_REPLACE_ANY); - Replace(wname, "!", "_bang", DOH_REPLACE_ANY); - return wname; -} + /* Produce string representation of source and target arguments */ + int selfp = (use_self && i == 0); + if (selfp) + strcpy(source,"self"); + else + sprintf(source,"argv[%d]",i-start); -/* --------------------------------------------------------------------- - * RUBY::create_command(char *cname, char *iname) - * - * Creates a new command from a C function. - * cname = Name of the C function - * iname = Name of function in scripting language - * argc = Number of arguments - * --------------------------------------------------------------------- */ - -static int create_argc = 0; - -void RUBY::create_command(String *scname, String *siname) { - char *cname, *iname; - int argc = create_argc; - cname = Char(scname); - iname = Char(siname); - String *wname = make_wrapper_name(iname); - if (CPlusPlus) { - Insert(wname,0,"VALUEFUNC("); - Append(wname,")"); - } - if (current != NO_CPP) - iname = klass->strip(iname); - if (Getattr(special_methods, iname)) { - iname = GetChar(special_methods, iname); - } + sprintf(target,"%s", Char(ln)); - String *s = NewString(""); - String *temp = NewString(""); - char argcs[32]; - sprintf(argcs,"%d",argc); - - switch (current) { - case MEMBER_FUNC: - Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", - iname, "\", ", wname, ", ", argcs, ");\n", 0); - - break; - case CONSTRUCTOR: - Printv(s, tab4, "rb_define_singleton_method(", klass->vname, - ", \"new\", ", wname, ", ", argcs, ");\n", 0); - Replace(klass->init,"$constructor", s, DOH_REPLACE_ANY); - break; - case MEMBER_VAR: - Append(temp,iname); - Replace(temp,"_set", "=", DOH_REPLACE_ANY); - Replace(temp,"_get", "", DOH_REPLACE_ANY); - Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", - temp, "\", ", wname, ", ", argcs, ");\n", 0); - break; - case STATIC_FUNC: - Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, - ", \"", iname, "\", ", wname, ", ", argcs, ");\n", 0); - break; - default: - Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", - iname, "\", ", wname, ", ", argcs, ");\n",0); - Printv(f_init,s,0); - break; - } - Delete(s); - Delete(temp); -} + if (i >= (numreq)) { /* Check if parsing an optional argument */ + Printf(f->code," if (argc > %d) {\n", i - start); + } + + /* Record argument name for keyword argument handling */ + if (Len(pn)) { + Printf(kwargs,"\"%s\",", pn); + } else { + Printf(kwargs,"\"arg%d\",", i+1); + } -/* --------------------------------------------------------------------- - * RUBY::function() - * - * Create a function declaration and register it with the interpreter. - * --------------------------------------------------------------------- */ - -void RUBY::function(DOH *node) { - char *name, *iname; - SwigType *t; - ParmList *l; - - char source[256], target[256]; - char *tm; - String *cleanup, *outarg; - Wrapper *f; - int i; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - l = Getattr(node,"parms"); - - /* Ruby needs no destructor wrapper */ - if (current == DESTRUCTOR) { - Wrapper *dummy = NewWrapper(); - emit_func_call(node,dummy); - Delete(dummy); - return; + /* Look for an input typemap */ + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$target",ln); + Replaceall(tm,"$source",source); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",source); + Printf(f->code,"%s\n", tm); + p = Getattr(p,"tmap:in:next"); + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument.\n", SwigType_str(pt,0)); + p = nextSibling(p); + } + if (i >= numreq) { + Printf(f->code,"}\n"); + } + } + + /* Finish argument marshalling */ + Printf(kwargs," NULL }"); + if (allow_kwargs) { + Printv(f->locals, tab4, "char *kwnames[] = ", kwargs, ";\n", NIL); + } + + /* Trailing varargs */ + if (varargs) { + if (p && (tm = Getattr(p,"tmap:in"))) { + sprintf(source,"argv[%d]",i-start); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",source); + Printf(f->code,"if (argc > %d) {\n", i-start); + Printv(f->code,tm,"\n",NIL); + Printf(f->code,"}\n"); + } + } } - char mname[256], inamebuf[256]; - int predicate = 0, need_result = 0; - - cleanup = NewString(""); - outarg = NewString(""); - f = NewWrapper(); - - switch (current) { - case MEMBER_FUNC: - case MEMBER_VAR: - case STATIC_FUNC: - strcpy(mname, klass->strip(iname)); - if (Getattr(klass->predmethods, mname)) { - predicate = 1; - sprintf(inamebuf,"%s?",iname); - iname = inamebuf; + /* --------------------------------------------------------------------- + * insertConstraintCheckingCode(ParmList *l, Wrapper *f) + * + * Checks each of the parameters in the parameter list for a "check" + * typemap and (if it finds one) inserts the typemapping code into + * the function wrapper. + * --------------------------------------------------------------------- */ + + void insertConstraintCheckingCode(ParmList *l, Wrapper *f) { + Parm *p; + String *tm; + for (p = l; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } } - break; - } - String *wname = make_wrapper_name(iname); - - /* Get number of arguments */ - int numarg = ParmList_numarg(l); - int numopt = check_numopt(l); - - int start = 0; - int use_self = 0; - switch (current) { - case MEMBER_FUNC: - case MEMBER_VAR: - numarg--; - start++; - use_self = 1; - break; } - int numreq = 0; - int numoptreal = 0; - Parm *p = l; - for (i = 0; i < start; i++) p = Getnext(p); - for (i = start; p; i++, p = Getnext(p)) { - if (!Getignore(p)) { - if (i >= ParmList_len(l) - numopt) numoptreal++; - else numreq++; + /* --------------------------------------------------------------------- + * insertCleanupCode(ParmList *l, String *cleanup) + * + * Checks each of the parameters in the parameter list for a "freearg" + * typemap and (if it finds one) inserts the typemapping code into + * the function wrapper. + * --------------------------------------------------------------------- */ + + void insertCleanupCode(ParmList *l, String *cleanup) { + String *tm; + for (Parm *p = l; p; ) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } } } - int vararg = (numoptreal != 0); - - /* Now write the wrapper function itself */ - Printv(f, "static VALUE\n", wname, "(", 0); - if (vararg) { - Printv(f, "int argc, VALUE *argv, VALUE self",0); - } else { - Printv(f, "VALUE self", 0); - p = l; - for (i = 0; i < start; i++) p = Getnext(p); - for (i = start; p; i++, p = Getnext(p)) { - if (!Getignore(p)) { - Printf(f,", VALUE varg%d", i); + + /* --------------------------------------------------------------------- + * insertCleanupCode(ParmList *l, String *cleanup) + * + * Checks each of the parameters in the parameter list for a "argout" + * typemap and (if it finds one) inserts the typemapping code into + * the function wrapper. + * --------------------------------------------------------------------- */ + + void insertArgOutputCode(ParmList *l, String *outarg, int& need_result) { + String *tm; + for (Parm *p = l; p; ) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","vresult"); + Replaceall(tm,"$result","vresult"); + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + need_result = 1; + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); } } } - Printf(f,") {\n"); - - /* Emit all of the local variables for holding arguments. */ - if (vararg) { - p = l; - for (i = 0; i < start; i++) p = Getnext(p); - for (i = start; p; i++, p = Getnext(p)) { - if (!Getignore(p)) { - char s[256]; - sprintf(s,"varg%d",i); - Wrapper_add_localv(f,s,"VALUE",s,0); - } + + /* --------------------------------------------------------------------- + * validIdentifier() + * + * Is this a valid identifier in the scripting language? + * Ruby method names can include any combination of letters, numbers + * and underscores. A Ruby method name may optionally end with + * a question mark ("?"), exclamation point ("!") or equals sign ("="). + * + * Methods whose names end with question marks are, by convention, + * predicate methods that return true or false (e.g. Array#empty?). + * + * Methods whose names end with exclamation points are, by convention, + * "mutators" that modify the instance in place (e.g. Array#sort!). + * + * Methods whose names end with an equals sign are attribute setters + * (e.g. Thread#critical=). + * --------------------------------------------------------------------- */ + + virtual int validIdentifier(String *s) { + char *c = Char(s); + while (*c) { + if ( !( isalnum(*c) || (*c == '_') || (*c == '?') || (*c == '!') || (*c == '=') ) ) return 0; + c++; } + return 1; } - int pcount = emit_args(node,f); - - /* Emit count to check the number of arguments */ - if (vararg) { - int numscan = 0; - for (p = l, i = 0; i < start; i++) p = Getnext(p); - for (i = start; p; i++, p = Getnext(p)) { - if (!Getignore(p)) numscan++; + + /* --------------------------------------------------------------------- + * functionWrapper() + * + * Create a function declaration and register it with the interpreter. + * --------------------------------------------------------------------- */ + + virtual int functionWrapper(Node *n) { + String *symname = Copy(Getattr(n,"sym:name")); + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *tm; + + int need_result = 0; + + /* Ruby needs no destructor wrapper */ + if (current == DESTRUCTOR) + return SWIG_NOWRAP; + + /* If the C++ class constructor is overloaded, we only want to + * write out the "new" singleton method once since it is always + * the same. (It's the "initialize" method that will handle the + * overloading). */ + + if (current == CONSTRUCTOR_ALLOCATE && + Swig_symbol_isoverloaded(n) && + Getattr(n, "sym:nextSibling") != 0) return SWIG_OK; + + String *overname = 0; + if (Getattr(n, "sym:overloaded")) { + overname = Getattr(n, "sym:overname"); + } else { + if (!addSymbol(symname, n)) + return SWIG_ERROR; } - Printf(f,"rb_scan_args(argc, argv, \"%d%d\"", (numarg-numoptreal), numscan - (numarg-numoptreal)); - for (p = l, i = 0; i < start; i++) p = Getnext(p); - for (i = start; p; i++, p = Getnext(p)) { - if (!Getignore(p)) { - Printf(f,", &varg%d", i); - } + + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *kwargs = NewString(""); + Wrapper *f = NewWrapper(); + + /* Rename predicate methods */ + if (Getattr(n, "feature:predicate")) { + Append(symname, "?"); } - Printf(f,");\n"); - } - /* Now walk the function parameter list and generate code */ - /* to get arguments */ - int j = 0; /* Total number of non-optional arguments */ - - p = l; - for (i = 0; i < pcount ; i++, p = Getnext(p)) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - - /* Produce string representation of source and target arguments */ - int selfp = (use_self && i == 0); - if (selfp) - strcpy(source,"self"); - else - sprintf(source,"varg%d",i); - - sprintf(target,"%s", Char(Getlname(p))); - - if (!Getignore(p)) { - char *tab = (char*)tab4; - if (j >= (pcount-numopt)) { /* Check if parsing an optional argument */ - Printf(f," if (argc > %d) {\n", j - start); - tab = (char*)tab8; - } + /* Determine the name of the SWIG wrapper function */ + String *wname = Swig_name_wrapper(symname); + if (overname && current != CONSTRUCTOR_ALLOCATE) { + Append(wname,overname); + } + + /* Emit arguments */ + if (current != CONSTRUCTOR_ALLOCATE) { + emit_args(t,l,f); + } - /* Get typemap for this argument */ - tm = ruby_typemap_lookup((char*)"in",pt,pn,source,target,f); - if (tm) { - String *s = NewString(tm); - Printv(f, s, 0); - Replace(f, "$arg", source, DOH_REPLACE_ANY); - Delete(s); + /* Attach standard typemaps */ + if (current != CONSTRUCTOR_ALLOCATE) { + emit_attach_parmmaps(l, f); + } + Setattr(n, "wrap:parms", l); + + /* Get number of arguments */ + int numarg = emit_num_arguments(l); + int numreq = emit_num_required(l); + int varargs = emit_isvarargs(l); + bool allow_kwargs = use_kw || Getattr(n,"feature:kwargs"); + + int start = (current == MEMBER_FUNC || current == MEMBER_VAR) ? 1 : 0; + + /* Now write the wrapper function itself */ + Printv(f->def, "static VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL); + + if (current != CONSTRUCTOR_ALLOCATE) { + if (!varargs) { + Printf(f->code,"if ((argc < %d) || (argc > %d))\n", numreq-start, numarg-start); } else { - Printf(stderr,"%s:%d. No typemapping for datatype %s\n", - Getfile(node), Getline(node), SwigType_str(pt,0)); + Printf(f->code,"if (argc < %d)\n", numreq-start); } - if (j >= (pcount-numopt)) - Printv(f, tab4, "} \n", 0); - j++; + Printf(f->code,"rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc);\n",numreq-start); } - /* Check to see if there was any sort of a constaint typemap */ - tm = ruby_typemap_lookup((char*)"check",pt,pn,source,target); - if (tm) { - String *s = NewString(tm); - Printv(f, s, 0); - Replace(f, "$arg", source, DOH_REPLACE_ANY); - Delete(s); + /* Now walk the function parameter list and generate code */ + /* to get arguments */ + if (current != CONSTRUCTOR_ALLOCATE) { + marshalInputArgs(l, numarg, numreq, start, kwargs, allow_kwargs, f); } - /* Check if there was any cleanup code (save it for later) */ - tm = ruby_typemap_lookup((char*)"freearg",pt,pn,target,source); - if (tm) { - String *s = NewString(tm); - Printv(cleanup,s,0); - Replace(cleanup,"$arg",source, DOH_REPLACE_ANY); - Delete(s); + /* Insert constraint checking code */ + insertConstraintCheckingCode(l, f); + + /* Insert cleanup code */ + insertCleanupCode(l, cleanup); + + /* Insert argument output code */ + insertArgOutputCode(l, outarg, need_result); + + /* Now write code to make the function call */ + if (current != CONSTRUCTOR_ALLOCATE) { + if (current == CONSTRUCTOR_INITIALIZE) { + String *action = Getattr(n,"wrap:action"); + if (action) { + Append(action,"DATA_PTR(self) = result;"); + } + } + emit_action(n,f); } - tm = ruby_typemap_lookup((char*)"argout",pt,pn,target,(char*)"vresult"); - if (tm) { - String *s = NewString(tm); + int newobj = 0; + if (Getattr(n,"feature:new")) newobj = 1; + + /* Return value if necessary */ + if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_ALLOCATE && current != CONSTRUCTOR_INITIALIZE) { need_result = 1; - Printv(outarg, s, 0); - Replace(outarg, "$arg", source, DOH_REPLACE_ANY); - Delete(s); + if (Getattr(n, "feature:predicate")) { + Printv(f->code, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL); + } else { + tm = Swig_typemap_lookup_new("out",n,"result",0); + if (tm) { + Replaceall(tm,"$result","vresult"); + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","vresult"); + Replaceall(tm,"$owner", newobj ? "1" : "0"); + Printv(f->code, tm, "\n", NIL); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s.\n", SwigType_str(t,0)); + } + } } - } - /* Now write code to make the function call */ - emit_func_call(node,f); + /* Extra code needed for new and initialize methods */ + if (current == CONSTRUCTOR_ALLOCATE) { + need_result = 1; + Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(t))); + Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n"); + } else if (current == CONSTRUCTOR_INITIALIZE) { + need_result = 1; + // Printf(f->code, "DATA_PTR(self) = result;\n"); + } + /* Dump argument output code; */ + Printv(f->code,outarg,NIL); - /* Return value if necessary */ - if (SwigType_type(t) != T_VOID) { - need_result = 1; - if (predicate) { - Printv(f, tab4, "vresult = (result ? Qtrue : Qfalse);\n", 0); - } else { - tm = ruby_typemap_lookup((char*)"out",t,name,(char*)"result",(char*)"vresult"); + /* Dump the argument cleanup code */ + if (current != CONSTRUCTOR_ALLOCATE) + Printv(f->code,cleanup,NIL); + + /* Look for any remaining cleanup. This processes the %new directive */ + if (newobj) { + tm = Swig_typemap_lookup_new("newfree",n,"result",0); if (tm) { - String *s = NewString(tm); - Printv(f, s, 0); - Delete(s); - } else { - Printf(stderr,"%s:%d. No return typemap for datatype %s\n", - Getfile(node), Getline(node),SwigType_str(t,0)); + Replaceall(tm,"$source","result"); + Printv(f->code,tm, "\n",NIL); } } - } - - /* Dump argument output code; */ - Printv(f,outarg,0); - /* Dump the argument cleanup code */ - Printv(f,cleanup,0); - - /* Look for any remaining cleanup. This processes the %new directive */ - if (NewObject) { - tm = ruby_typemap_lookup((char*)"newfree",t,name,(char*)"result",(char*)""); + /* Special processing on return value. */ + tm = Swig_typemap_lookup_new("ret",n,"result",0); if (tm) { - String *s = NewString(tm); - Printv(f,s, 0); - Delete(s); + Replaceall(tm,"$source","result"); + Printv(f->code,tm, NIL); } - } - - /* free pragma */ - if (current == MEMBER_FUNC && Getattr(klass->freemethods, mname)) { - Printv(f, tab4, "DATA_PTR(self) = 0;\n", 0); - } - - /* Special processing on return value. */ - tm = ruby_typemap_lookup((char*)"ret",t,name,(char*)"result",(char*)""); - if (tm) { - String *s = NewString(tm); - Printv(f,s, 0); - } - /* Wrap things up (in a manner of speaking) */ - if (need_result) { - Wrapper_add_local(f,"vresult","VALUE vresult = Qnil"); - Printv(f, tab4, "return vresult;\n}\n", 0); - } else { - Printv(f, tab4, "return Qnil;\n}\n", 0); - } - - /* Substitute the cleanup code */ - Replace(f,"$cleanup",cleanup, DOH_REPLACE_ANY); + /* Wrap things up (in a manner of speaking) */ + if (need_result) { + if (current == CONSTRUCTOR_ALLOCATE) { + Printv(f->code, tab4, "return vresult;\n}\n", NIL); + } else if (current == CONSTRUCTOR_INITIALIZE) { + Printv(f->code, tab4, "return self;\n}\n", NIL); + } else { + Wrapper_add_local(f,"vresult","VALUE vresult = Qnil"); + Printv(f->code, tab4, "return vresult;\n}\n", NIL); + } + } else { + Printv(f->code, tab4, "return Qnil;\n}\n", NIL); + } - /* Emit the function */ - Printf(f_wrappers,"%s", f); + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); - /* Now register the function with the language */ - create_argc = vararg ? -1 : numarg; - create_command(name, iname); - Delete(cleanup); - Delete(outarg); - Delete(f); -} + /* Emit the function */ + Wrapper_print(f, f_wrappers); -/* --------------------------------------------------------------------- - * RUBY::variable() - * - * Create a link to a C variable. - * --------------------------------------------------------------------- */ - -void RUBY::variable(DOH *node) { - char *name, *iname; - SwigType *t; - - char *tm, *source; - - String *getfname, *setfname; - Wrapper *getf, *setf; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); - - getf = NewWrapper(); - setf = NewWrapper(); - - /* create getter */ - getfname = NewString(Swig_name_get(name)); - Replace(getfname,"::", "_", DOH_REPLACE_ANY); /* FIXME: Swig_name_get bug? */ - Printv(getf, "static VALUE\n", getfname, "(", 0); - Printf(getf, "VALUE self"); - Printf(getf, ") {\n"); - Wrapper_add_local(getf,"_val","VALUE _val"); - - if (SwigType_type(t) == T_USER) { - /* Hack this into a pointer */ - String *pname = NewString(""); - Printv(pname, "&", name, 0); - source = Char(pname); - } else { - source = name; + /* Now register the function with the interpreter */ + if (!Swig_symbol_isoverloaded(n)) { + create_command(n, symname); + } else { + if (current == CONSTRUCTOR_ALLOCATE) { + create_command(n, symname); + } else { + Setattr(n, "wrap:name", wname); + if (!Getattr(n, "sym:nextSibling")) + dispatchFunction(n); + } + } + + Delete(kwargs); + Delete(cleanup); + Delete(outarg); + DelWrapper(f); + Delete(symname); + + return SWIG_OK; } - tm = ruby_typemap_lookup((char*)"varout",t,name,source,(char*)"_val"); - if (!tm) - tm = ruby_typemap_lookup((char*)"out",t,name,source,(char*)"_val"); - if (tm) { - String *s = NewString(tm); - Printv(getf,s, 0); - Delete(s); - } else { - Printf(stderr,"%s:%d. Unable to link with variable type %s\n", - Getfile(node), Getline(node),SwigType_str(t,0)); - } - Printv(getf, tab4, "return _val;\n}\n", 0); - Printf(f_wrappers,"%s", getf); - - if (ReadOnly) { - setfname = NewString("NULL"); - } else { - /* create setter */ - char *target; - - setfname = NewString(Swig_name_set(name)); - Replace(setfname,"::", "_", DOH_REPLACE_ANY); /* FIXME: Swig_name_get bug? */ - Printv(setf, "static VALUE\n", setfname, "(VALUE self, ", 0); - Printf(setf, "VALUE _val) {\n"); - - if (SwigType_type(t) == T_USER) { - SwigType_add_pointer(t); - Wrapper_add_localv(setf,"temp",SwigType_lstr(t,0), "temp",0); - SwigType_del_pointer(t); - target = "temp"; + /* ------------------------------------------------------------ + * dispatchFunction() + * ------------------------------------------------------------ */ + + void dispatchFunction(Node *n) { + /* Last node in overloaded chain */ + + int maxargs; + String *tmp = NewString(""); + String *dispatch = Swig_overload_dispatch(n, "return %s(nargs, args, self);", &maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *f = NewWrapper(); + String *symname = Getattr(n, "sym:name"); + String *wname = Swig_name_wrapper(symname); + + Printv(f->def, + "static VALUE ", wname, + "(int nargs, VALUE *args, VALUE self) {", + NIL); + + Wrapper_add_local(f, "argc", "int argc"); + if (current == MEMBER_FUNC || current == MEMBER_VAR) { + Printf(tmp, "VALUE argv[%d]", maxargs+1); } else { - target = name; + Printf(tmp, "VALUE argv[%d]", maxargs); } - - tm = ruby_typemap_lookup((char*)"varin",t,name,(char*)"_val",target); - if (!tm) - tm = ruby_typemap_lookup((char*)"in",t,name,(char*)"_val",target); + Wrapper_add_local(f, "argv", tmp); + Wrapper_add_local(f, "ii", "int ii"); + if (current == MEMBER_FUNC || current == MEMBER_VAR) { + Printf(f->code, "argc = nargs + 1;\n"); + Printf(f->code, "argv[0] = self;\n"); + Printf(f->code, "for (ii = 1; (ii < argc) && (ii < %d); ii++) {\n", maxargs); + Printf(f->code, "argv[ii] = args[ii-1];\n"); + Printf(f->code, "}\n"); + } else { + Printf(f->code, "argc = nargs;\n"); + Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", maxargs); + Printf(f->code, "argv[ii] = args[ii];\n"); + Printf(f->code, "}\n"); + } + + Replaceall(dispatch, "$args", "nargs, args, self"); + Printv(f->code, dispatch, "\n", NIL); + Printf(f->code, "rb_raise(rb_eArgError, \"No matching function for overloaded '%s'\");\n", symname); + Printf(f->code,"return Qnil;\n"); + Printv(f->code, "}\n", NIL); + Wrapper_print(f, f_wrappers); + create_command(n, Char(symname)); + + DelWrapper(f); + Delete(dispatch); + Delete(tmp); + Delete(wname); + } + + /* --------------------------------------------------------------------- + * variableWrapper() + * --------------------------------------------------------------------- */ + + virtual int variableWrapper(Node *n) { + + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + String *tm; + String *getfname, *setfname; + Wrapper *getf, *setf; + + getf = NewWrapper(); + setf = NewWrapper(); + + /* create getter */ + getfname = NewString(Swig_name_get(iname)); + Printv(getf->def, "static VALUE\n", getfname, "(", NIL); + Printf(getf->def, "VALUE self"); + Printf(getf->def, ") {"); + Wrapper_add_local(getf,"_val","VALUE _val"); + + tm = Swig_typemap_lookup_new("varout",n, name, 0); if (tm) { - String *s = NewString(tm); - Printv(setf,s,0); - Delete(s); + Replaceall(tm,"$result","_val"); + Replaceall(tm,"$target","_val"); + Replaceall(tm,"$source",name); + Printv(getf->code,tm, NIL); } else { - Printf(stderr,"%s:%d. Unable to link with variable type %s\n", - Getfile(node), Getline(node),SwigType_str(t,0)); + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to read variable of type %s\n", SwigType_str(t,0)); } - if (SwigType_type(t) == T_USER) { - Printv(setf, name, " = *temp;\n",0); + Printv(getf->code, tab4, "return _val;\n}\n", NIL); + Wrapper_print(getf,f_wrappers); + + if (Getattr(n,"feature:immutable")) { + setfname = NewString("NULL"); + } else { + /* create setter */ + setfname = NewString(Swig_name_set(iname)); + Printv(setf->def, "static VALUE\n", setfname, "(VALUE self, ", NIL); + Printf(setf->def, "VALUE _val) {"); + + tm = Swig_typemap_lookup_new("varin",n,name,0); + if (tm) { + Replaceall(tm,"$input","_val"); + Replaceall(tm,"$source","_val"); + Replaceall(tm,"$target",name); + Printv(setf->code,tm,"\n",NIL); + } else { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, + "Unable to set variable of type %s\n", SwigType_str(t,0)); + } + Printv(setf->code, tab4, "return _val;\n",NIL); + Printf(setf->code,"}\n"); + Wrapper_print(setf,f_wrappers); } - Printv(setf, tab4, "return _val;\n",0); - Printf(setf,"}\n"); - Printf(f_wrappers,"%s", setf); - } - /* define accessor method */ - if (CPlusPlus) { - Insert(getfname,0,"VALUEFUNC("); - Append(getfname,")"); - Insert(setfname,0,"VALUEFUNC("); - Append(setfname,")"); - } + /* define accessor method */ + if (CPlusPlus) { + Insert(getfname,0,"VALUEFUNC("); + Append(getfname,")"); + Insert(setfname,0,"VALUEFUNC("); + Append(setfname,")"); + } - String *s = NewString(""); - switch (current) { - case STATIC_VAR: - /* C++ class variable */ - Printv(s, - tab4, "rb_define_singleton_method(", klass->vname, ", \"", - klass->strip(iname), "\", ", getfname, ", 0);\n", - 0); - if (!ReadOnly) { + String *s = NewString(""); + switch (current) { + case STATIC_VAR: + /* C++ class variable */ Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", - klass->strip(iname), "=\", ", setfname, ", 1);\n", - 0); - } - Printv(klass->init,s,0); - break; - default: - /* C global variable */ - /* wrapped in Ruby module attribute */ - Printv(s, - tab4, "rb_define_singleton_method(", modvar, ", \"", - iname, "\", ", getfname, ", 0);\n", - 0); - if (!ReadOnly) { + klass->strip(iname), "\", ", getfname, ", 0);\n", + NIL); + if (!Getattr(n,"feature:immutable")) { + Printv(s, + tab4, "rb_define_singleton_method(", klass->vname, ", \"", + klass->strip(iname), "=\", ", setfname, ", 1);\n", + NIL); + } + Printv(klass->init,s,NIL); + break; + default: + /* C global variable */ + /* wrapped in Ruby module attribute */ Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", - iname, "=\", ", setfname, ", 1);\n", - 0); + iname, "\", ", getfname, ", 0);\n", + NIL); + if (!Getattr(n,"feature:immutable")) { + Printv(s, + tab4, "rb_define_singleton_method(", modvar, ", \"", + iname, "=\", ", setfname, ", 1);\n", + NIL); + } + Printv(f_init,s,NIL); + Delete(s); + break; } - Printv(f_init,s,0); - Delete(s); - break; + Delete(getfname); + Delete(setfname); + DelWrapper(setf); + DelWrapper(getf); + return SWIG_OK; } - Delete(getfname); - Delete(setfname); - Delete(setf); - Delete(getf); -} - - -/* --------------------------------------------------------------------- - * RUBY::validate_const_name(char *name) - * - * Validate constant name. - * --------------------------------------------------------------------- */ - -char *RUBY::validate_const_name(char *name) { - if (!name || name[0] == '\0') - return name; - - if (isupper(name[0])) - return name; - if (islower(name[0])) { - name[0] = toupper(name[0]); - /* Printf(stderr,"%s:%d. Wrong constant/class/module name " - "(corrected to `%s')\n", Getfile(node), Getline(node), name); */ - Printf(stderr,"?:?. Wrong constant/class/module name (corrected to '%s')\n", name); + /* --------------------------------------------------------------------- + * validate_const_name(char *name) + * + * Validate constant name. + * --------------------------------------------------------------------- */ + + char * + validate_const_name(char *name, const char *reason) { + if (!name || name[0] == '\0') + return name; + + if (isupper(name[0])) + return name; + + if (islower(name[0])) { + name[0] = toupper(name[0]); + Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, + "Wrong %s name (corrected to `%s')\n", reason, name); + return name; + } + + Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, + "Wrong %s name\n", reason); + return name; } - - Printf(stderr,"?:?. Wrong constant/class/module name\n"); - return name; -} - -/* --------------------------------------------------------------------- - * RUBY::constant() - * - * Makes a constant. - * --------------------------------------------------------------------- */ - -void RUBY::constant(DOH *node) { - char *tm; - char *name, *iname; - SwigType *type; - char *value; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - - if (current == CLASS_CONST) - iname = klass->strip(iname); - - tm = ruby_typemap_lookup((char*)"const",type,name,value,iname); - if (tm) { - String *str = NewString(tm); - Replace(str,"$value",value, DOH_REPLACE_ANY); + + /* --------------------------------------------------------------------- + * constantWrapper() + * --------------------------------------------------------------------- */ + + virtual int constantWrapper(Node *n) { + Swig_require(&n, "*sym:name", "type", "value", NIL); + + char *iname = GetChar(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + char *value = GetChar(n,"value"); + if (current == CLASS_CONST) { - Replace(str,"$module", klass->vname, DOH_REPLACE_ANY); - Printv(klass->init, str, 0); - } else { - Replace(str,"$module", modvar, DOH_REPLACE_ANY); - Printf(f_init,"%s", str); + iname = klass->strip(iname); } - Delete(str); - } else { - Printf(stderr,"%s:%d. Unable to create constant %s = %s\n", - Getfile(node), Getline(node), SwigType_str(type,0), value); - } -} - -/* --------------------------------------------------------------------- - * RUBY::ruby_typemap_lookup(char *op, SwigType *type, char *pname, char *source, char *target, WrapperFunction *f = 0) - * - * Ruby specific typemap_lookup. - * op = string code for type of mapping - * type = the datatype - * pname = an optional parameter name - * source = a string with the source variable - * target = a string containing the target value - * f = a wrapper function object (optional) - * --------------------------------------------------------------------- */ - -char *RUBY::ruby_typemap_lookup(char *op, SwigType *type, String_or_char *pname, char *source, char *target, Wrapper *f) { - static String *s = 0; - char *tm; - String *target_replace = NewString(target); - target = Char(target_replace); - int type_code, add_pointer = 0; - - if (SwigType_type(type) == T_USER) - add_pointer = 1; - if (add_pointer) - SwigType_add_pointer(type); - type_code = SwigType_type(type); - - RClass *cls = RCLASS(classes, SwigType_base(type)); - - if (!s) s = NewString(""); - Clear(s); - - if ((strcmp("out", op) == 0 || strcmp("in", op) == 0) - && Cmp(SwigType_base(type), "VALUE") == 0) { - Printf(s,"$target = $source;\n"); - } else if (strcmp("out", op) == 0 - && (type_code == T_POINTER || type_code == T_REFERENCE) - && cls) { - const char *vname = (current == CONSTRUCTOR ? "self" : Char(cls->vname)); - Printv(s, "$target = Wrap_", cls->cname, "(", vname, ", $source);\n",0); - } else if (strcmp("in", op)==0 - && (type_code == T_POINTER || type_code == T_REFERENCE) - && cls) { - Printv(s, "Get_", cls->cname, "($source, $target);\n", 0); - } else { - if (add_pointer) { - SwigType_del_pointer(type); - add_pointer = 0; + validate_const_name(iname, "constant"); + SetChar(n, "sym:name", iname); + + /* Special hook for member pointer */ + if (SwigType_type(type) == T_MPOINTER) { + String *wname = Swig_name_wrapper(iname); + Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value); + value = Char(wname); } - - tm = Swig_typemap_lookup(op, type, pname, source, target, f); + String *tm = Swig_typemap_lookup_new("constant", n, value, 0); if (tm) { - Delete(target_replace); - Printv(s, tm, "\n", 0); - } else { - Clear(s); - if (strcmp("in", op) == 0) { - String *v = NewString(""); - if (from_VALUE(type, (char*)"$source", (char*)"$target", v)) - Printv(s, v, "\n", 0); - Delete(v); - } else if (strcmp("out", op) == 0) { - String *v = NewString(""); - if (to_VALUE(type, (char*)"$source", v)) - Printv(s, "$target = ", v, ";\n", 0); - Delete(v); - } else if (strcmp("const", op) == 0) { - String *v = NewString(""); - if (to_VALUE(type, (char*)"$value", v, 1)) { - Printv(s, "rb_define_const($module, \"$target\", ", v, ");\n", 0); - validate_const_name(target); - } - Delete(v); + Replaceall(tm, "$source", value); + Replaceall(tm, "$target", iname); + Replaceall(tm, "$symname", iname); + Replaceall(tm, "$value", value); + if (current == CLASS_CONST) { + Replaceall(tm, "$module", klass->vname); + Printv(klass->init, tm, "\n", NIL); + } else { + Replaceall(tm,"$module", modvar); + Printf(f_init, "%s\n", tm); } + } else { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, + "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value); } + Swig_restore(&n); + return SWIG_OK; } - if (source && strlen(source) > 0) - Replace(s,"$source",source, DOH_REPLACE_ANY); - if (target && strlen(target) > 0) - Replace(s,"$target",target, DOH_REPLACE_ANY); - Replace(s,"$type", SwigType_str(type,0), DOH_REPLACE_ANY); - - if (add_pointer) { - SwigType_del_pointer(type); - add_pointer = 0; - } - - if (Len(s) == 0) - return NULL; - return Char(s); -} - - -static void -convert_pointer(char *src, SwigType *t, String *f) { - SwigType_remember(t); - Printv(f, "SWIG_NewPointerObj((void *)", src, ", SWIGTYPE", SwigType_manglestr(t), ")", 0); -} - -/* --------------------------------------------------------------------- - * RUBY::to_VALUE(SwigType *type, char *value, literal) - * - * Makes a VALUE (as a string) - * type = Datatype of the C value - * value = C value (as a string) - * str = resulting code (as a string) - * raw = value is raw string (not quoted) ? - * --------------------------------------------------------------------- */ - -int RUBY::to_VALUE(SwigType *type, char *value, String *str, int raw) { - Clear(str); - switch(SwigType_type(type)) { - case T_INT: - case T_SHORT: - case T_LONG: - case T_SCHAR: - Printv(str, "INT2NUM(", value, ")", 0); - break; - case T_UINT: - case T_USHORT: - case T_ULONG: - case T_UCHAR: - Printv(str,"UINT2NUM(", value, ")", 0); - break; - case T_DOUBLE: - case T_FLOAT: - Printv(str, "rb_float_new(", value, ")", 0); - break; - case T_CHAR: - Printv(str, "rb_str_new(&", value, ", 1)", 0); - break; - case T_BOOL: - Printv(str, "(", value, " ? Qtrue : Qfalse)", 0); - break; - case T_STRING: - if (raw) - Printv(str, "rb_str_new2(\"", value, "\")", 0); - else - Printv(str, "rb_str_new2(", value, ")", 0); - break; - case T_ARRAY: - { - SwigType *aop; - SwigType *ta = Copy(type); - aop = SwigType_pop(ta); - if (SwigType_type(ta) == T_CHAR) { - Printf(str, "rb_str_new2(%s)", value); - break; - } - convert_pointer(value, type, str); - break; + + /* ----------------------------------------------------------------------------- + * classDeclaration() + * + * Records information about classes---even classes that might be defined in + * other modules referenced by %import. + * ----------------------------------------------------------------------------- */ + + virtual int classDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + String *tdname = Getattr(n,"tdname"); + + name = tdname ? tdname : name; + String *namestr = SwigType_namestr(name); + klass = RCLASS(classes, Char(namestr)); + if (!klass) { + klass = new RClass(); + String *valid_name = NewString(symname ? symname : namestr); + validate_const_name(Char(valid_name), "class"); + klass->set_name(namestr, symname, valid_name); + SET_RCLASS(classes, Char(namestr), klass); + Delete(valid_name); } - case T_POINTER: case T_REFERENCE: - convert_pointer(value, type, str); - break; - case T_USER: - SwigType_add_pointer(type); - convert_pointer(value, type, str); - SwigType_del_pointer(type); - break; - default: - break; + Delete(namestr); + return Language::classDeclaration(n); } - if (Len(str) == 0) - return 0; - return 1; -} + /* ---------------------------------------------------------------------- + * classHandler() + * ---------------------------------------------------------------------- */ -static void -get_pointer(char *src, char *dest, SwigType *t, String *f) { - SwigType *lt; + virtual int classHandler(Node *n) { - SwigType_remember(t); - Printv(f, dest, " = (", SwigType_lstr(t,0), ")SWIG_ConvertPtr(", src, ", ", 0); + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + String *namestr = SwigType_namestr(name); // does template expansion - lt = Swig_clocal_type(t); - if (Cmp(lt,"p.void") == 0) { - Printv(f, "0);", 0); - } else { - Printv(f, "SWIGTYPE", SwigType_manglestr(t), ");", 0); - } - Delete(lt); -} + klass = RCLASS(classes, Char(namestr)); + assert(klass); + Delete(namestr); + String *valid_name = NewString(symname); + validate_const_name(Char(valid_name), "class"); -/* --------------------------------------------------------------------- - * RUBY::from_VALUE(SwigType *type, char *value) - * - * extract VALUE - * type = Datatype of the C value - * value = Ruby VALUE (as a string) - * target= target C variable (as a string) - * str = resulting code (as a string) - * --------------------------------------------------------------------- */ - -int RUBY::from_VALUE(SwigType *type, char *value, char *target, String *str) { - Clear(str); - switch(SwigType_type(type)) { - case T_INT: - Printv(str, target, " = NUM2INT(", value, ");", 0); - break; - case T_LONG: - Printv(str, target, " = NUM2LONG(", value, ");", 0); - break; - case T_SHORT: - Printv(str, target, " = NUM2SHRT(", value, ");", 0); - break; - case T_UINT: - Printv(str, target, " = NUM2UINT(", value, ");", 0); - break; - case T_ULONG: - Printv(str, target, " = NUM2ULONG(", value, ");", 0); - break; - case T_USHORT: - Printv(str, target, " = NUM2USHRT(", value, ");", 0); - break; - case T_DOUBLE: - case T_FLOAT: - Printv(str, target, " = NUM2DBL(", value, ");", 0); - break; - case T_CHAR: case T_SCHAR: case T_UCHAR: - Printv(str, target, " = NUM2CHR(", value, ");", 0); - break; - case T_BOOL: - Printv(str, target, " = RTEST(", value, ");", 0); - break; - case T_STRING: - Printv(str, target, " = STR2CSTR(", value, ");", 0); - break; - case T_ARRAY: - { - SwigType *aop; - SwigType *ta = Copy(type); - aop = SwigType_pop(ta); - if (SwigType_type(ta) == T_CHAR) { - String *dim = SwigType_array_getdim(aop,0); - if (dim && Len(dim)) { - Printf(str, "strncpy(%s, STR2CSTR(%s), %s);", target, value, dim); + Clear(klass->type); + Printv(klass->type, Getattr(n,"classtype"), NIL); + Printv(klass->header, "\nswig_class c", valid_name, ";\n", NIL); + Printv(klass->init, "\n", tab4, NIL); + Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, + ", \"", klass->name, "\", $super);\n", NIL); + + SwigType *tt = NewString(name); + SwigType_add_pointer(tt); + SwigType_remember(tt); + String *tm = SwigType_manglestr(tt); + Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &c%s);\n", tm, valid_name); + Delete(tm); + Delete(tt); + Delete(valid_name); + + /* Process the comma-separated list of mixed-in module names (if any) */ + String *mixin = Getattr(n,"feature:mixin"); + if (mixin) { + List *modules = Split(mixin,',',INT_MAX); + if (modules && Len(modules) > 0) { + String *mod = Firstitem(modules); + while (mod) { + if (Len(mod) > 0) { + Printf(klass->init, "rb_include_module(%s, rb_eval_string(\"%s\"));\n", klass->vname, mod); + } + mod = Nextitem(modules); } - break; } - get_pointer(value, target, type, str); - break; + Delete(modules); } - case T_POINTER: case T_REFERENCE: - get_pointer(value, target, type, str); - break; - case T_USER: - SwigType_add_pointer(type); - get_pointer(value, target, type, str); - SwigType_del_pointer(type); - break; - default: - break; - } - if (Len(str) == 0) return 0; - return 1; -} -/* ---------------------------------------------------------------------- - * void RUBY::cpp_open_class(char *classname, char *classrename, char *ctype, int strip) - * - * Open a new C++ class. - * - * INPUTS: - * name = Real name of the C++ class - * rename = New name of the class (if %name was used) - * ctype = Class type (struct, class, union, etc...) - * strip = Flag indicating whether we should strip the - * class type off - * - * This function is in charge of creating a new class. The SWIG parser has - * already processed the entire class definition prior to calling this - * function (which should simplify things considerably). - * - * ---------------------------------------------------------------------- */ - -void RUBY::cpp_open_class(DOH *node) { - this->Language::cpp_open_class(node); - - char *cname = GetChar(node,"name"); - char *rename = GetChar(node,"scriptname"); - char *ctype = GetChar(node,"classtype"); - int strip = GetInt(node,"strip"); - - klass = RCLASS(classes, cname); - - if (strip) { - Clear(klass->type); - Append(klass->type, klass->cname); - } else { - Clear(klass->type); - Printv(klass->type, ctype, " ", klass->cname,0); - } + Printv(klass->init, "$allocator",NIL); + Printv(klass->init, "$initializer",NIL); + + Printv(klass->header, + "$freeproto", + NIL); + + Language::classHandler(n); + + /* Handle inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + String *basename = Getattr(base,"name"); + String *basenamestr = SwigType_namestr(basename); + RClass *super = RCLASS(classes, Char(basenamestr)); + Delete(basenamestr); + if (super) { + SwigType *btype = NewString(basename); + SwigType_add_pointer(btype); + SwigType_remember(btype); + String *bmangle = SwigType_manglestr(btype); + Insert(bmangle,0,"((swig_class *) SWIGTYPE"); + Append(bmangle,"->clientdata)->klass"); + Replaceall(klass->init,"$super",bmangle); + Delete(bmangle); + Delete(btype); + } + + /* Warn about multiple inheritance if additional base class(es) listed */ + base = Nextitem(baselist); + while (base) { + basename = Getattr(n,"name"); + Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s: Base %s ignored. Multiple inheritance is not supported in Ruby.\n", basename, basename); + base = Nextitem(baselist); + } + } - Printv(klass->header, "\nstatic VALUE ", klass->vname, ";\n", 0); - Printv(klass->init, "\n", tab4, 0); - Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, - ", \"", klass->name, "\", $super);\n", 0); - Replace(klass->includes,"$class", klass->vname, DOH_REPLACE_ANY); - Printv(klass->init, klass->includes,0); - Printv(klass->init, "$constructor",0); - - Printv(klass->header, - "$markproto", - "$freeproto", - "#define Wrap_", klass->cname, "(klass, ptr) (\\\n", - tab4, "(ptr) ? Data_Wrap_Struct(klass", - ", $markfunc, $freefunc, ptr) : Qnil )\n", - "#define Get_", klass->cname, "(val, ptr) {\\\n", - tab4, "if (NIL_P(val)) ptr = NULL;\\\n", - tab4, "else {\\\n", - tab8, "if (!rb_obj_is_kind_of(val, ", klass->vname, "))\\\n", - tab8, tab4, "rb_raise(rb_eTypeError, \"wrong argument type", - " (expected ", klass->name, ")\");\\\n", - tab8, "Data_Get_Struct(val, ", klass->type, ", ptr);\\\n", - tab8, "if (!ptr) rb_raise(rb_eRuntimeError, \"", - "This ", klass->name, " already released\");\\\n", - tab4, "}\\\n", - "}\n", - 0); + /* Check to see if a %markfunc was specified */ + String *markfunc = Getattr(n, "feature:markfunc"); + if (markfunc) { + Printf(klass->init, "c%s.mark = (void (*)(void *)) %s;\n", klass->name, markfunc); + } else { + Printf(klass->init, "c%s.mark = 0;\n", klass->name); + } -} + /* Check to see if a %freefunc was specified */ + String *freefunc = Getattr(n, "feature:freefunc"); + if (freefunc) { + Printf(klass->init, "c%s.destroy = (void (*)(void *)) %s;\n", klass->name, freefunc); + } else { + if (klass->destructor_defined) { + Printf(klass->init, "c%s.destroy = (void (*)(void *)) free_%s;\n", klass->name, klass->mname); + } + } + Replaceall(klass->header,"$freeproto", ""); -/* --------------------------------------------------------------------- - * void RUBY::cpp_close_class() - * - * Close the current class - * --------------------------------------------------------------------- */ + Printv(f_header, klass->header,NIL); -void RUBY::cpp_close_class() { - this->Language::cpp_close_class(); + String *s = NewString(""); + Printv(s, tab4, "rb_undef_method(CLASS_OF(", klass->vname, + "), \"new\");\n", NIL); + Replaceall(klass->init,"$allocator", s); + Replaceall(klass->init,"$initializer", ""); + Replaceall(klass->init,"$super", "rb_cObject"); + Delete(s); - Replace(klass->header,"$markfunc", "0", DOH_REPLACE_ANY); - Replace(klass->header,"$markproto", "", DOH_REPLACE_ANY); - if (!klass->destructor_defined) { - Replace(klass->header,"$freefunc", "0", DOH_REPLACE_ANY); - Replace(klass->header,"$freeproto", "", DOH_REPLACE_ANY); + Printv(f_init,klass->init,NIL); + klass = 0; + return SWIG_OK; } - Printv(f_header, klass->header,0); - - Replace(klass->aliases,"$class", klass->vname, DOH_REPLACE_ANY); - Printv(klass->init, klass->aliases,0); - - String *s = NewString(""); - Printv(s, tab4, "rb_undef_method(CLASS_OF(", klass->vname, - "), \"new\");\n", 0); - Replace(klass->init,"$constructor", s, DOH_REPLACE_ANY); - Replace(klass->init,"$super", "rb_cObject", DOH_REPLACE_ANY); - - Printv(f_init,klass->init,0); - klass = 0; -} - -/* ---------------------------------------------------------------------- - * void RUBY::cpp_inherit(char **baseclass, int mode) - * - * Inherit attributes from given baseclass. - * - * INPUT: - * baseclass = NULL terminate list of baseclasses - * - * --------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------- + * memberfunctionHandler() + * + * Method for adding C++ member function + * + * By default, we're going to create a function of the form : + * + * Foo_bar(this,args) + * + * Where Foo is the classname, bar is the member name and the this pointer + * is explicitly attached to the beginning. + * + * The renaming only applies to the member function part, not the full + * classname. + * + * --------------------------------------------------------------------- */ + + virtual int memberfunctionHandler(Node *n) { + current = MEMBER_FUNC; + Language::memberfunctionHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* --------------------------------------------------------------------- + * constructorHandler() + * + * Method for adding C++ member constructor + * -------------------------------------------------------------------- */ + + virtual int constructorHandler(Node *n) { + /* First wrap the new singleton method */ + current = CONSTRUCTOR_ALLOCATE; + Swig_name_register((String_or_char *) "construct", (String_or_char *) "%c_allocate"); + Language::constructorHandler(n); + + /* Now do the instance initialize method */ + current = CONSTRUCTOR_INITIALIZE; + Swig_name_register((String_or_char *) "construct", (String_or_char *) "new_%c"); + Language::constructorHandler(n); + + /* Done */ + Swig_name_unregister((String_or_char *) "construct"); + current = NO_CPP; + klass->constructor_defined = 1; + return SWIG_OK; + } -void RUBY::cpp_inherit(List *bases) { - if (!bases) return; - String *base; - for (base = Firstitem(bases); base; base = Nextitem(bases)) { - RClass *super = RCLASS(classes, Char(base)); - if (super) { - Replace(klass->init,"$super", super->vname, DOH_REPLACE_ANY); - break; /* ignore multiple inheritance */ + /* --------------------------------------------------------------------- + * destructorHandler() + * -------------------------------------------------------------------- */ + + virtual int destructorHandler(Node *n) { + current = DESTRUCTOR; + Language::destructorHandler(n); + + String *freefunc = NewString(""); + String *freeproto = NewString(""); + String *freebody = NewString(""); + + Printv(freefunc, "free_", klass->mname, NIL); + Printv(freeproto, "static void ", freefunc, "(", klass->type, " *);\n", NIL); + Printv(freebody, "static void\n", + freefunc, "(", klass->type, " *", Swig_cparm_name(0,0), ") {\n", + tab4, NIL); + if (Extend) { + String *wrap = Getattr(n, "wrap:code"); + if (wrap) { + File *f_code = Swig_filebyname("header"); + if (f_code) { + Printv(f_code, wrap, NIL); + } + } + /* Printv(freebody, Swig_name_destroy(name), "(", Swig_cparm_name(0,0), ")", NIL); */ + Printv(freebody,Getattr(n,"wrap:action"), NIL); + } else { + /* When no extend mode, swig emits no destroy function. */ + if (CPlusPlus) + Printf(freebody, "delete %s", Swig_cparm_name(0,0)); + else + Printf(freebody, "free((char*) %s)", Swig_cparm_name(0,0)); } + Printv(freebody, ";\n}\n", NIL); + + Replaceall(klass->header,"$freeproto", freeproto); + Printv(f_wrappers, freebody, NIL); + + klass->destructor_defined = 1; + current = NO_CPP; + Delete(freefunc); + Delete(freeproto); + Delete(freebody); + return SWIG_OK; } -} - -/* ---------------------------------------------------------------------- - * void RUBY::cpp_member_func(char *name, char *iname, SwigType *t, ParmList *l) - * - * Method for adding C++ member function - * - * INPUTS: - * name - name of the member function - * iname - renaming (if given) - * t - Return datatype - * l - Parameter list - * - * By default, we're going to create a function of the form : - * - * Foo_bar(this,args) - * - * Where Foo is the classname, bar is the member name and the this pointer - * is explicitly attached to the beginning. - * - * The renaming only applies to the member function part, not the full - * classname. - * - * --------------------------------------------------------------------- */ - -void RUBY::cpp_memberfunction(DOH *node) { - current = MEMBER_FUNC; - this->Language::cpp_memberfunction(node); - current = NO_CPP; -} -/* --------------------------------------------------------------------- - * void RUBY::cpp_constructor(char *name, char *iname, ParmList *l) - * - * Method for adding C++ member constructor - * - * INPUTS: - * name - Name of the constructor (usually same as classname) - * iname - Renamed version - * l - parameters - * -------------------------------------------------------------------- */ - -void RUBY::cpp_constructor(DOH *node) { - current = CONSTRUCTOR; - this->Language::cpp_constructor(node); - current = NO_CPP; -} - -/* --------------------------------------------------------------------- - * void RUBY::cpp_destructor(char *name, char *iname) - * - * Method for adding C++ member destructor - * - * INPUT: - * name - Name of the destructor (classname) - * iname - Renamed destructor - * - * -------------------------------------------------------------------- */ - -void RUBY::cpp_destructor(DOH *node) { - char *name, *newname; - - name = GetChar(node,"name"); - newname = GetChar(node,"scriptname"); - current = DESTRUCTOR; - this->Language::cpp_destructor(node); - - String *freefunc = NewString(""); - String *freeproto = NewString(""); - String *freebody = NewString(""); - - Printv(freefunc, "free_", klass->cname, 0); - Printv(freeproto, "static void ", freefunc, "(", klass->type, " *);\n", 0); - Printv(freebody, "static void\n", - freefunc, "(", klass->type, " *", Swig_cparm_name(0,0), ") {\n", - tab4, 0); - if (AddMethods) { - Printv(freebody, Swig_name_destroy(name), "(", Swig_cparm_name(0,0), ")", 0); - } else { - /* When no addmethods mode, swig emits no destroy function. */ - if (CPlusPlus) - Printv(freebody, Swig_cppdestructor_call(), 0); - else - Printv(freebody, Swig_cdestructor_call(), 0); - } - Printv(freebody, ";\n}\n", 0); - if (CPlusPlus) { - Insert(freefunc,0,"VOIDFUNC("); - Append(freefunc,")"); + /* --------------------------------------------------------------------- + * membervariableHandler() + * + * This creates a pair of functions to set/get the variable of a member. + * -------------------------------------------------------------------- */ + + virtual int + membervariableHandler(Node *n) { + current = MEMBER_VAR; + Language::membervariableHandler(n); + current = NO_CPP; + return SWIG_OK; } - Replace(klass->header,"$freefunc", freefunc, DOH_REPLACE_ANY); - Replace(klass->header,"$freeproto", freeproto, DOH_REPLACE_ANY); - Printv(f_wrappers, freebody, 0); - - klass->destructor_defined = 1; - current = NO_CPP; - Delete(freefunc); - Delete(freeproto); - Delete(freebody); -} - -/* --------------------------------------------------------------------- - * void RUBY::cpp_variable(char *name, char *iname, SwigType *t) - * - * Wrap a C++ data member - * - * INPUTS : - * name = Name of the C++ member - * iname = Name as used in the interpreter - * t = Datatype - * - * This creates a pair of functions to set/get the variable of a member. - * -------------------------------------------------------------------- */ - -void RUBY::cpp_variable(DOH *node) { - current = MEMBER_VAR; - this->Language::cpp_variable(node); - current = NO_CPP; -} - -/* ----------------------------------------------------------------------- - * void RUBY::cpp_static_func(char *name, char *iname, SwigType *t, ParmList *l) - * - * Wrap a static C++ function - * - * INPUTS: - * name = Real name of the function - * iname = New name in interpreter - * t = Return datatype - * l = Parameters - * ---------------------------------------------------------------------- */ - -void RUBY::cpp_staticfunction(DOH *node) { - current = STATIC_FUNC; - this->Language::cpp_staticfunction(node); - current = NO_CPP; -} - -/* ---------------------------------------------------------------------- - * void RUBY::cpp_declare_const(char *name, char *iname, SwigType *t, char *value) - * - * Create a C++ constant - * - * INPUTS : - * name = Real name of the constant - * iname = new name - * t = Datatype - * value = value as a string - * - * --------------------------------------------------------------------- */ - - -void RUBY::cpp_constant(DOH *node) { - current = CLASS_CONST; - this->Language::cpp_constant(node); - current = NO_CPP; -} - -/* --------------------------------------------------------------------- - * void RUBY::cpp_static_var(char *name, char *iname, SwigType *t) - * - * Wrap a static C++ variable - * - * INPUT : - * name = name of the variable - * iname = interpreter name - * t = Datatype - * - * --------------------------------------------------------------------- */ - -void RUBY::cpp_staticvariable(DOH *node) { - current = STATIC_VAR; - this->Language::cpp_staticvariable(node); - current = NO_CPP; -} - -/* ----------------------------------------------------------------------- - * RUBY::cpp_class_decl(char *name, char *rename, char *type) - * - * A forward class declaration - * ----------------------------------------------------------------------- */ - -void RUBY::cpp_class_decl(DOH *node) { - String *cname = Getattr(node,"name"); - String *rename = Getattr(node,"scriptname"); - String *ctype = Getattr(node,"classtype"); - String *valid_name = NewString((rename ? rename : cname)); - validate_const_name(Char(valid_name)); - klass->set_name(Char(cname), Char(rename), Char(valid_name)); - SET_RCLASS(classes, Char(cname), klass); - if (ctype && Len(ctype) > 0) { - char temp[256]; - sprintf(temp,"%s %s", Char(ctype), Char(cname)); - SET_RCLASS(classes, temp, klass); + /* ----------------------------------------------------------------------- + * staticmemberfunctionHandler() + * + * Wrap a static C++ function + * ---------------------------------------------------------------------- */ + + virtual int + staticmemberfunctionHandler(Node *n) { + current = STATIC_FUNC; + Language::staticmemberfunctionHandler(n); + current = NO_CPP; + return SWIG_OK; } - /* - char s[256]; - sprintf(s,"extern VALUE %s;\n", Char(klass->vname)); - Printf(f_header, s); - */ - klass = new RClass(); - Delete(valid_name); -} - -/* -------------------------------------------------------------------- - * void RUBY::pragma(char *target, char *var, char *value) - * - * A pragma declaration - * -------------------------------------------------------------------- */ - -void RUBY::pragma(DOH *node) { - String *cmd = Getattr(node,"name"); - String *value = Getattr(node,"value"); - if (Cmp(cmd, "free") == 0) { - char name[64]; - if (sscanf(Char(value), " %s ", name) != 1) { - Printf(stderr, "%s:%d. Invalid free pragma.\n", - Getfile(node), Getline(node)); - return; - } - Setattr(klass->freemethods, name, name); - } else if (Cmp(cmd, "include") == 0) { - char name[64]; - if (sscanf(Char(value), " %s ", name) != 1) { - Printf(stderr, "%s:%d. Invalid include pragma.\n", - Getfile(node), Getline(node)); - return; - } - Printv(klass->includes,tab4, "rb_include_module($class, ", - "rb_eval_string(\"", name, "\"));\n", 0); - } else if (Cmp(cmd, "alias") == 0) { - char alias[64], name[64]; - if (sscanf(Char(value), " %s %s ", alias, name) != 2) { - Printf(stderr, "%s:%d. Invalid alias pragma.\n", - Getfile(node), Getline(node)); - return; - } - Printv(klass->aliases, tab4, "rb_define_alias($class, ", - "\"", alias, "\", \"", name, "\");\n", 0); - } else if (Cmp(cmd, "pred") == 0) { - char *tok; - tok = strtok(Char(value), " \t"); - while (tok) { - Setattr(klass->predmethods, tok, tok); - tok = strtok(0, " \t"); - } - } else if (Cmp(cmd, "debug") == 0) { - Printf(f_header, "/* %s */\n", value); - Printf(f_wrappers, "/* %s */\n", value); - Printf(f_init, "/* %s */\n", value); - Printf(stderr, "%s\n", value); + + /* ---------------------------------------------------------------------- + * memberconstantHandler() + * + * Create a C++ constant + * --------------------------------------------------------------------- */ + + virtual int + memberconstantHandler(Node *n) { + current = CLASS_CONST; + Language::memberconstantHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* --------------------------------------------------------------------- + * staticmembervariableHandler() + * --------------------------------------------------------------------- */ + + virtual int + staticmembervariableHandler(Node *n) { + current = STATIC_VAR; + Language::staticmembervariableHandler(n); + current = NO_CPP; + return SWIG_OK; } -} - -/* --------------------------------------------------------------------- - * RUBY::import(char *filename) - * - * Imports a SWIG module as a separate file. - *---------------------------------------------------------------------- */ +}; /* class RUBY */ + +/* ----------------------------------------------------------------------------- + * swig_ruby() - Instantiate module + * ----------------------------------------------------------------------------- */ -void RUBY::import(String *modname) { - Printf(f_init, "rb_f_require(Qnil, rb_str_new2(\"%s\"));\n", modname); +extern "C" Language * +swig_ruby(void) { + return new RUBY(); } + /* * Local Variables: * c-basic-offset: 2 * End: */ - - - - diff --git a/Source/Modules1.1/ruby.h b/Source/Modules1.1/ruby.h deleted file mode 100644 index 8844945ea..000000000 --- a/Source/Modules1.1/ruby.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************** - * Ruby module for SWIG - * - * $Header$ - * - * Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - * Copyright (C) 2000 Information-technology Promotion Agency, Japan - * - * Masaki Fukushima - * - ********************************************************************/ - -class RUBY : public Language { - protected: - virtual String *make_wrapper_name(char *cname); - virtual char *validate_const_name(char *name); - virtual char *ruby_typemap_lookup(char *, SwigType *, String_or_char *, char *, char *, Wrapper * = 0); - virtual int to_VALUE(SwigType *, char *, DOHString *, int = 0); - virtual int from_VALUE(SwigType *, char *, char *, DOHString *); - public: - /* Virtual functions required by the SWIG parser */ - virtual void parse_args(int, char *argv[]); - virtual void initialize(String *module); - virtual void function(DOH *node); - virtual void variable(DOH *node); - virtual void constant(DOH *node); - virtual void close(void); - virtual void nativefunction(DOH *); - virtual void create_command(String *, String *); - virtual void import(String *); - - /* C++ language extensions. */ - virtual void cpp_memberfunction(DOH *); - virtual void cpp_constructor(DOH *); - virtual void cpp_destructor(DOH *); - virtual void cpp_open_class(DOH *); - virtual void cpp_close_class(); - virtual void cpp_inherit(List *bases); - virtual void cpp_variable(DOH *); - virtual void cpp_staticfunction(DOH *); - virtual void cpp_constant(DOH *); - virtual void cpp_staticvariable(DOH *); - - /* Declaration of a class, but not a full definition */ - virtual void cpp_class_decl(DOH *); - - /* Pragma directive */ - virtual void pragma(DOH *node); -}; - -/* - * Local Variables: - * c-basic-offset: 2 - * End: - */ diff --git a/Source/Modules1.1/s-exp.cxx b/Source/Modules1.1/s-exp.cxx new file mode 100644 index 000000000..2a9f2dcc1 --- /dev/null +++ b/Source/Modules1.1/s-exp.cxx @@ -0,0 +1,401 @@ +/* ----------------------------------------------------------------------------- + * s-exp.cxx + * + * A parse tree represented as Lisp s-expressions. + * + * Author(s) : Matthias Koeppe (mkoeppe@mail.math.uni-magdeburg.de) + * + * Copyright (C) 2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +/* Derived from xml.cxx 1.1.2.2 */ + +char cvsroot_s_exp_cxx[] = "$Header$"; +static const char *usage = "\ +S-Exp Options (available with -sexp)\n\ + -typemaplang lang - Typemap language.\n\n"; + +#include "swigmod.h" + +//static Node *view_top = 0; +static File *out = 0; + +class Sexp : public Language { +public: + int indent_level; + Sexp() : indent_level( 0 ) {} + virtual ~Sexp() {} + virtual void main(int argc, char *argv[]) { + SWIG_typemap_lang("sexp"); + for( int iX = 0; iX < argc; iX++ ) + { + if( strcmp( argv[iX], "-typemaplang" ) == 0 ) + { + Swig_mark_arg (iX); + iX++; + SWIG_typemap_lang(argv[iX]); + Swig_mark_arg (iX); + continue; + } + if( strcmp( argv[iX], "-help" ) == 0 ) + { + fputs( usage, stderr ); + } + } + } + + DOHHash *print_circle_hash; + int print_circle_count; + int hanging_parens; + bool need_whitespace; + bool need_newline; + + /* Top of the parse tree */ + virtual int top(Node *n) + { + if( out == 0 ) + { + String *outfile = Getattr(n,"outfile"); + Replaceall(outfile,"_wrap.cxx", ".lisp"); + out = NewFile(outfile,"w"); + if (!out) + { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + } + Language::top(n); + Printf( out, ";;; Lisp parse tree produced by SWIG\n" ); + print_circle_hash = DohNewHash(); + print_circle_count = 0; + hanging_parens = 0; + need_whitespace = 0; + need_newline = 0; + Sexp_print_node(n); + flush_parens(); + return SWIG_OK; + } + + void print_indent() + { + int i; + for (i = 0; i < indent_level; i++) + { + Printf(out, " "); + } + } + + void open_paren(const String *oper) + { + flush_parens(); + Printf(out, "("); + if (oper) Printf(out, "%s ", oper); + indent_level += 2; + } + + void close_paren(bool need_newline = false) + { + hanging_parens++; + if (need_newline) + print_lazy_whitespace(); + indent_level -= 2; + } + + void flush_parens() + { + int i; + if (hanging_parens) { + for (i = 0; i<hanging_parens; i++) + Printf(out, ")"); + hanging_parens = 0; + need_newline = true; + need_whitespace = true; + } + if (need_newline) { + Printf(out, "\n"); + print_indent(); + need_newline = false; + need_whitespace = false; + } + else if (need_whitespace) { + Printf(out, " "); + need_whitespace = false; + } + } + + void print_lazy_whitespace() + { + need_whitespace = 1; + } + + void print_lazy_newline() + { + need_newline = 1; + } + + bool internal_key_p(DOH *key) + { + return ((Cmp(key,"nodeType") == 0) + || (Cmp(key,"firstChild") == 0) + || (Cmp(key,"lastChild") == 0) + || (Cmp(key,"parentNode") == 0) + || (Cmp(key,"nextSibling") == 0) + || (Cmp(key,"previousSibling") == 0) + || (Cmp(key,"csym:nextSibling") == 0) + || (Cmp(key,"csym:previousSibling") == 0) + || (Cmp(key,"typepass:visit") == 0) + || (Cmp(key,"allocate:visit") == 0) + || (*(Char(key)) == '$')); + } + + bool boolean_key_p(DOH *key) + { + return ((Cmp(key,"allocate:default_constructor") == 0) + || (Cmp(key,"allocate:default_destructor") == 0) + || (Cmp(key,"allows_typedef") == 0) + || (Cmp(key,"feature:immutable") == 0)); + } + + bool list_key_p(DOH *key) + { + return ((Cmp(key, "parms") == 0) + || (Cmp(key, "baselist") == 0)); + } + + bool plist_key_p(DOH *key) + // true if KEY is the name of data that is a mapping from keys to + // values, which should be printed as a plist. + { + return ((Cmp(key, "typescope") == 0)); + } + + bool maybe_plist_key_p(DOH *key) + { + return (Strncmp(key, "tmap:", 5) == 0); + } + + bool print_circle(DOH *obj, bool list_p) + // We have a complex object, which might be referenced several + // times, or even recursively. Use Lisp's reader notation for + // circular structures (#n#, #n=). + // + // An object can be printed in list-mode or object-mode; LIST_P toggles. + // return TRUE if OBJ still needs to be printed + { + flush_parens(); + // Following is a silly hack. It works around the limitation of + // DOH's hash tables that only work with string keys! + char address[16]; + sprintf(address, "%x%c", (unsigned int)obj, list_p ? 'L' : 'O'); + DOH *placeholder = Getattr(print_circle_hash, address); + if (placeholder) { + Printv(out, placeholder, NIL); + return false; + } + else { + String *placeholder = NewStringf("#%d#", ++print_circle_count); + Setattr(print_circle_hash, address, placeholder); + Printf(out, "#%d=", print_circle_count); + return true; + } + } + + void Sexp_print_value_of_key(DOH *value, DOH *key) + { + if ((Cmp(key, "parms") == 0) || (Cmp(key, "wrap:parms") == 0) + || (Cmp(key, "kwargs") == 0) || (Cmp(key, "pattern") == 0)) + Sexp_print_parms(value); + else if (plist_key_p(key)) + Sexp_print_plist(value); + else if (maybe_plist_key_p(key)) { + if (DohIsMapping(value)) + Sexp_print_plist(value); + else + Sexp_print_doh(value); + } + else if (list_key_p(key)) + Sexp_print_list(value); + else if (boolean_key_p(key)) + Sexp_print_boolean(value); + else + Sexp_print_doh(value); + } + + void Sexp_print_boolean(DOH *obj) + { + flush_parens(); + /* See DOH/Doh/base.c, DohGetInt() */ + if (DohIsString(obj)) { + if (atoi(Char(obj)) != 0) + Printf(out, "t"); + else Printf(out, "nil"); + } + else Printf(out, "nil"); + } + + void Sexp_print_list(DOH *obj) + { + if (print_circle(obj, true)) { + open_paren(NIL); + for (; obj; obj = nextSibling(obj)) { + Sexp_print_doh(obj); + print_lazy_whitespace(); + } + close_paren(true); + } + } + + void Sexp_print_parms(DOH *obj) + // print it as a list of plists + { + if (print_circle(obj, true)) { + open_paren(NIL); + for (; obj; obj = nextSibling(obj)) { + if (DohIsMapping(obj)) { + DOH *k; + open_paren(NIL); + for (k = Firstkey(obj); k; k = Nextkey(obj)) { + if (!internal_key_p(k)) { + DOH *value = Getattr(obj, k); + Sexp_print_as_keyword(k); + Sexp_print_value_of_key(value, k); + print_lazy_whitespace(); + } + } + close_paren(true); + } + else Sexp_print_doh(obj); + print_lazy_whitespace(); + } + close_paren(true); + } + } + + void Sexp_print_doh(DOH *obj) + { + flush_parens(); + if (DohIsString(obj)) { + String *o = Str(obj); + Replaceall( o, "\\", "\\\\" ); + Replaceall( o, "\"", "\\\"" ); + Printf(out,"\"%s\"", o); + Delete(o); + } + else { + if (print_circle(obj, false)) { + // Dispatch type + if (nodeType(obj)) { + Sexp_print_node(obj); + } + + else if (DohIsMapping(obj)) { + DOH *k; + open_paren(NIL); + for (k = Firstkey(obj); k; k = Nextkey(obj)) { + if (!internal_key_p(k)) { + DOH *value = Getattr(obj, k); + flush_parens(); + open_paren(NIL); + Sexp_print_doh(k); + Printf(out, " . "); + Sexp_print_value_of_key(value, k); + close_paren(); + } + } + close_paren(); + } + else { + // What is it? + Printf(out,"#<DOH %x>", obj); + } + } + } + } + + void Sexp_print_as_keyword(const DOH *k) + { + /* Print key, replacing ":" with "-" because : is CL's package prefix */ + flush_parens(); + String *key = NewString(k); + Replaceall(key, ":", "-"); + Replaceall(key, "_", "-"); + Printf(out,":%s ", key); + Delete(key); + } + + void Sexp_print_plist_noparens(DOH *obj) + { + /* attributes map names to objects */ + String *k; + bool first; + for (k = Firstkey(obj), first = true; k; k = Nextkey(obj), first=false) { + if (!internal_key_p(k)) { + DOH *value = Getattr(obj, k); + flush_parens(); + if (!first) { + Printf(out, " "); + } + Sexp_print_as_keyword(k); + /* Print value */ + Sexp_print_value_of_key(value, k); + } + } + } + + void Sexp_print_plist(DOH *obj) + { + flush_parens(); + if (print_circle(obj, true)) { + open_paren(NIL); + Sexp_print_plist_noparens(obj); + close_paren(); + } + } + + void Sexp_print_attributes(Node * obj) + { + Sexp_print_plist_noparens(obj); + } + + void Sexp_print_node(Node *obj) + { + Node *cobj; + open_paren(nodeType(obj)); + /* A node has an attribute list... */ + Sexp_print_attributes(obj); + /* ... and child nodes. */ + cobj = firstChild(obj); + if (cobj) { + print_lazy_newline(); + flush_parens(); + Sexp_print_as_keyword("children"); + open_paren(NIL); + for (; cobj; cobj = nextSibling(cobj)) { + Sexp_print_node(cobj); + } + close_paren(); + } + close_paren(); + } + + + virtual int functionWrapper(Node *n) + { + ParmList *l = Getattr(n,"parms"); + Wrapper *f = NewWrapper(); + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); + return SWIG_OK; + } + +}; + + +extern "C" +{ + Language * swig_sexp( void ) + { + return new Sexp(); + } +} diff --git a/Source/Modules1.1/swig11.h b/Source/Modules1.1/swig11.h deleted file mode 100644 index cfc222861..000000000 --- a/Source/Modules1.1/swig11.h +++ /dev/null @@ -1,121 +0,0 @@ -/* ----------------------------------------------------------------------------- - * swig11.h - * - * Main header file for the SWIG1.1 core. - * - * Author(s) : David Beazley (beazley@cs.uchicago.edu) - * - * Copyright (C) 1998-2000. The University of Chicago - * Copyright (C) 1995-1998. The University of Utah and The Regents of the - * University of California. - * - * See the file LICENSE for information on usage and redistribution. - * - * $Header$ - * ----------------------------------------------------------------------------- */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "swigver.h" - -extern "C" { -#include "swig.h" -} - -/* Global variables. */ - -extern FILE *f_runtime; // Runtime code -extern DOH *f_header; // Headers -extern DOH *f_wrappers; // Wrappers -extern DOH *f_init; // Initialization code -extern FILE *f_input; -extern int CPlusPlus; // C++ mode -extern int AddMethods; // AddMethods mode -extern int NewObject; // NewObject mode -extern int NoInclude; // NoInclude flag -extern char output_dir[512]; // Output directory -extern int Verbose; -extern int ReadOnly; // Read only mode -extern int Native; // Native mode - -/* Miscellaneous stuff */ - -#define tab4 " " -#define tab8 " " - -// Modes for different types of inheritance - -#define INHERIT_FUNC 0x1 -#define INHERIT_VAR 0x2 -#define INHERIT_CONST 0x4 -#define INHERIT_ALL (INHERIT_FUNC | INHERIT_VAR | INHERIT_CONST) - -/* Language Class */ -class Language { -public: - virtual void parse_args(int argc, char *argv[]) = 0; - virtual void initialize(String *modname) = 0; - virtual void close(void) = 0; - virtual void import(String *modname); - - /* Basic function, variable, constant API (required) */ - virtual void function(DOH *node) = 0; - virtual void variable(DOH *node) = 0; - virtual void constant(DOH *node) = 0; - virtual void nativefunction(DOH *node); - virtual void create_command(String *cname, String *iname); - - /* Optional C++ handling */ - virtual void cpp_open_class(DOH *node); - virtual void cpp_memberfunction(DOH *node); - virtual void cpp_constructor(DOH *node); - virtual void cpp_destructor(DOH *node); - virtual void cpp_variable(DOH *node); - virtual void cpp_staticfunction(DOH *node); - virtual void cpp_constant(DOH *node); - virtual void cpp_staticvariable(DOH *node); - virtual void cpp_close_class(); - - virtual void cpp_class_decl(DOH *node); - virtual void cpp_inherit(List *bases); - - /* Miscellaneous features */ - - virtual void add_typedef(SwigType *t, String *name); - virtual void pragma(DOH *node); - -}; - -/* Emit functions */ - -extern void new_create_function(char *, char *, SwigType *, ParmList *); -extern void emit_set_get(DOH *node); -extern void emit_set_action(DOHString_or_char *decl); - -/* These are in the new core */ -extern "C" void *Preprocessor_define(void *, int); - -// Misc - -extern int emit_args(DOH *node, Wrapper *f); -extern void emit_func_call(DOH *node, Wrapper *f); -extern int check_numopt(ParmList *); -extern void SWIG_config_file(const String_or_char *); - -/* C++ utility functions */ -extern int cplus_check_abstract(DOH *node); -extern void cplus_walk_inherit(DOH *cls, void (*action)(DOH *base, void *clientdata), void *clientdata); - -extern Language *lang; - -/* swig11.h ends here */ - - - - - - - - diff --git a/Source/Modules1.1/swigmod.h b/Source/Modules1.1/swigmod.h new file mode 100644 index 000000000..2668b0cb5 --- /dev/null +++ b/Source/Modules1.1/swigmod.h @@ -0,0 +1,255 @@ +/* ----------------------------------------------------------------------------- + * swigmod.h + * + * Main header file for SWIG modules + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2000. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * + * $Header$ + * ----------------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "swigver.h" + +extern "C" { +#include "swig.h" +extern Hash *Preprocessor_define(const String_or_char *str, int swigmacro); +} + +#include "swigwarn.h" + +#define NOT_VIRTUAL 0 +#define PLAIN_VIRTUAL 1 +#define PURE_VIRTUAL 2 + +extern char *input_file; +extern int line_number; +extern int start_line; +extern int CPlusPlus; // C++ mode +extern int Extend; // Extend mode +extern int NoInclude; // NoInclude flag +extern int Verbose; +extern int IsVirtual; +extern int ImportMode; +extern int NoExcept; // -no_except option + +/* Miscellaneous stuff */ + +#define tab2 " " +#define tab4 " " +#define tab8 " " + +class Dispatcher { + public: + + virtual int emit_one(Node *n); + virtual int emit_children(Node *n); + virtual int defaultHandler(Node *n); + + /* Top of the parse tree */ + virtual int top(Node *n) = 0; + + /* SWIG directives */ + + virtual int applyDirective(Node *n); + virtual int clearDirective(Node *n); + virtual int constantDirective(Node *n); + virtual int extendDirective(Node *n); + virtual int fragmentDirective(Node *n); + virtual int importDirective(Node *n); + virtual int includeDirective(Node *n); + virtual int insertDirective(Node *n); + virtual int moduleDirective(Node *n); + virtual int nativeDirective(Node *n); + virtual int pragmaDirective(Node *n); + virtual int typemapDirective(Node *n); + virtual int typemapitemDirective(Node *n); + virtual int typemapcopyDirective(Node *n); + virtual int typesDirective(Node *n); + + /* C/C++ parsing */ + + virtual int cDeclaration(Node *n); + virtual int externDeclaration(Node *n); + virtual int enumDeclaration(Node *n); + virtual int enumvalueDeclaration(Node *n); + virtual int classDeclaration(Node *n); + virtual int classforwardDeclaration(Node *n); + virtual int constructorDeclaration(Node *n); + virtual int destructorDeclaration(Node *n); + virtual int accessDeclaration(Node *n); + virtual int usingDeclaration(Node *n); + virtual int namespaceDeclaration(Node *n); + virtual int templateDeclaration(Node *n); +}; + +/************************************************************************ + * class language: + * + * This class defines the functions that need to be supported by the + * scripting language being used. The translator calls these virtual + * functions to output different types of code for different languages. + *************************************************************************/ + +class Language : public Dispatcher { +public: + Language(); + virtual ~Language(); + virtual int emit_one(Node *n); + + /* Parse command line options */ + + virtual void main(int argc, char *argv[]); + + /* Top of the parse tree */ + + virtual int top(Node *n); + + /* SWIG directives */ + + + virtual int applyDirective(Node *n); + virtual int clearDirective(Node *n); + virtual int constantDirective(Node *n); + virtual int extendDirective(Node *n); + virtual int fragmentDirective(Node *n); + virtual int importDirective(Node *n); + virtual int includeDirective(Node *n); + virtual int insertDirective(Node *n); + virtual int moduleDirective(Node *n); + virtual int nativeDirective(Node *n); + virtual int pragmaDirective(Node *n); + virtual int typemapDirective(Node *n); + virtual int typemapcopyDirective(Node *n); + virtual int typesDirective(Node *n); + + /* C/C++ parsing */ + + virtual int cDeclaration(Node *n); + virtual int externDeclaration(Node *n); + virtual int enumDeclaration(Node *n); + virtual int enumvalueDeclaration(Node *n); + virtual int classDeclaration(Node *n); + virtual int classforwardDeclaration(Node *n); + virtual int constructorDeclaration(Node *n); + virtual int destructorDeclaration(Node *n); + virtual int accessDeclaration(Node *n); + virtual int namespaceDeclaration(Node *n); + virtual int usingDeclaration(Node *n); + + /* Function handlers */ + + virtual int functionHandler(Node *n); + virtual int globalfunctionHandler(Node *n); + virtual int memberfunctionHandler(Node *n); + virtual int staticmemberfunctionHandler(Node *n); + virtual int callbackfunctionHandler(Node *n); + + /* Variable handlers */ + + virtual int variableHandler(Node *n); + virtual int globalvariableHandler(Node *n); + virtual int membervariableHandler(Node *n); + virtual int staticmembervariableHandler(Node *n); + + /* C++ handlers */ + + virtual int memberconstantHandler(Node *n); + virtual int constructorHandler(Node *n); + virtual int copyconstructorHandler(Node *n); + virtual int destructorHandler(Node *n); + virtual int classHandler(Node *n); + + /* Miscellaneous */ + + virtual int typedefHandler(Node *n); + + /* Low-level code generation */ + + virtual int constantWrapper(Node *n); + virtual int variableWrapper(Node *n); + virtual int functionWrapper(Node *n); + virtual int nativeWrapper(Node *n); + + /* Miscellaneous */ + + virtual int validIdentifier(String *s); /* valid identifier? */ + virtual int addSymbol(String *s, Node *n); /* Add symbol */ + virtual Node *symbolLookup(String *s); /* Symbol lookup */ + virtual Node *classLookup(SwigType *s); /* Class lookup */ + + protected: + /* Patch C++ pass-by-value */ + static void patch_parms(Parm *p); + + /* Allow overloaded functions */ + void allow_overloading(int val = 1); + + /* Allow multiple-input typemaps */ + void allow_multiple_input(int val = 1); + + /* Wrapping class query */ + int is_wrapping_class(); + + /* Return the node for the current class */ + Node *getCurrentClass() const; + + /* Return the real name of the current class */ + String *getClassName() const; + + /* Return the current class prefix */ + String *getClassPrefix() const; + + /* Fully qualified type name to use */ + String *getClassType() const; + + private: + Hash *symbols; + Hash *classtypes; + int overloading; + int multiinput; +}; + +extern int SWIG_main(int, char **, Language *); +extern void emit_args(SwigType *, ParmList *, Wrapper *f); +extern void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */ +extern void SWIG_config_file(const String_or_char *); +extern void SWIG_config_cppext(const char *ext); + +extern "C" void SWIG_typemap_lang(const char *); +extern void SWIG_library_directory(const char *); +extern int emit_num_arguments(ParmList *); +extern int emit_num_required(ParmList *); +extern int emit_isvarargs(ParmList *); +extern void emit_attach_parmmaps(ParmList *, Wrapper *f); +extern void emit_action(Node *n, Wrapper *f); +extern List *Swig_overload_rank(Node *n); +extern String *Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *); + + +extern "C" { + typedef Language *(*ModuleFactory)(void); +} + +extern void Swig_register_module(const char *name, ModuleFactory fac); +extern ModuleFactory Swig_find_module(const char *name); + +/* swig11.h ends here */ + + + + + + + + + diff --git a/Source/Modules1.1/tcl8.cxx b/Source/Modules1.1/tcl8.cxx index 7f2913082..0f9738715 100644 --- a/Source/Modules1.1/tcl8.cxx +++ b/Source/Modules1.1/tcl8.cxx @@ -9,1112 +9,824 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_tcl8_cxx[] = "$Header$"; -#include "swig11.h" -#include "tcl8.h" -#include <ctype.h> +#include "swigmod.h" -static char *usage = (char*)"\ -Tcl 8.0 Options (available with -tcl)\n\ - -module name - Set name of module\n\ +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +static const char *usage = (char*)"\ +Tcl 8 Options (available with -tcl)\n\ + -ldflags - Print runtime libraries to link with\n\ -prefix name - Set a prefix to be appended to all names\n\ -namespace - Build module into a Tcl 8 namespace. \n\ - -noobject - Omit code for object oriented interface.\n\n"; - -static String *mod_init = 0; -static String *cmd_info = 0; -static String *var_info = 0; -static String *methods = 0; -static String *attributes = 0; + -pkgversion - Set package version.\n\n"; +static String *cmd_tab = 0; /* Table of command names */ +static String *var_tab = 0; /* Table of global variables */ +static String *const_tab = 0; /* Constant table */ +static String *methods_tab = 0; /* Methods table */ +static String *attr_tab = 0; /* Attribute table */ static String *prefix = 0; static String *module = 0; -static int nspace = 0; -static int shadow = 1; -static String *init_name = 0; -static String *ns_name = 0; -static int have_constructor; -static int have_destructor; - -static String *class_name = 0; -static String *class_type = 0; -static String *real_classname = 0; -static Hash *class_methods = 0; -static Hash *class_attributes = 0; -static Hash *repeatcmd = 0; - - -/* ----------------------------------------------------------------------------- - * TCL8::parse_args() - * ----------------------------------------------------------------------------- */ - -void -TCL8::parse_args(int argc, char *argv[]) { - int i; - Swig_swiglib_set("tcl"); +static int nspace = 0; +static String *init_name = 0; +static String *ns_name = 0; +static int have_constructor; +static int have_destructor; +static String *destructor_action = 0; +static String *version = (String *) "0.0"; +static String *class_name = 0; + +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; +static File *f_runtime = 0; + +class TCL8 : public Language { +public: + + /* ------------------------------------------------------------ + * TCL8::main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { - for (i = 1; i < argc; i++) { + SWIG_library_directory("tcl"); + + for (int i = 1; i < argc; i++) { if (argv[i]) { - if (strcmp(argv[i],"-prefix") == 0) { - if (argv[i+1]) { - prefix = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else Swig_arg_error(); - } else if (strcmp(argv[i],"-namespace") == 0) { - nspace = 1; + if (strcmp(argv[i],"-prefix") == 0) { + if (argv[i+1]) { + prefix = NewString(argv[i+1]); Swig_mark_arg(i); - } else if (strcmp(argv[i],"-noobject") == 0) { - shadow = 0; + Swig_mark_arg(i+1); + i++; + } else Swig_arg_error(); + } else if (strcmp(argv[i],"-pkgversion") == 0) { + if (argv[i+1]) { + version = NewString(argv[i+1]); Swig_mark_arg(i); - } else if (strcmp(argv[i],"-help") == 0) { - fputs(usage,stderr); + Swig_mark_arg(i+1); + i++; } + } else if (strcmp(argv[i],"-namespace") == 0) { + nspace = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_TCL_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } } + } + Preprocessor_define("SWIGTCL 1",0); + Preprocessor_define("SWIGTCL8 1", 0); + SWIG_typemap_lang("tcl8"); + SWIG_config_file("tcl8.swg"); + allow_overloading(); } - if ((nspace) && module) { - ns_name = Copy(module); - } else if (prefix) { - ns_name = Copy(prefix); + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ - } - if (prefix) - Append(prefix,"_"); - - Preprocessor_define((void *) "SWIGTCL 1",0); - Preprocessor_define((void *) "SWIGTCL8 1", 0); - Swig_set_config_file("tcl8.swg"); -} + virtual int top(Node *n) { -/* ----------------------------------------------------------------------------- - * TCL8::initialize() - * ----------------------------------------------------------------------------- */ - -void -TCL8::initialize(String *modname) { - - mod_init = NewString(""); - cmd_info = NewString(""); - var_info = NewString(""); - repeatcmd = NewHash(); - class_methods = NewHash(); - class_attributes = NewHash(); - - Swig_banner(f_runtime); - - /* Include a Tcl configuration file */ - if (NoInclude) { - Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); - } - if (Swig_insert_file("common.swg",f_runtime) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate 'common.swg' in SWIG library.\n"); - Swig_exit (EXIT_FAILURE); - } - if (Swig_insert_file("swigtcl8.swg",f_runtime) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate 'swigtcl8.swg' in SWIG library.\n"); - Swig_exit (EXIT_FAILURE); - } - if (!module) module = NewString(modname); - - /* Fix capitalization for Tcl */ - char *c = Char(module); - while (c && *c) { - *c = (char) tolower(*c); - c++; - } - /* Now create an initialization function */ - init_name = NewStringf("%s_Init",module); - c = Char(init_name); - *c = toupper(*c); - - if (!ns_name) ns_name = Copy(module); - - /* If namespaces have been specified, set the prefix to the module name */ - if ((nspace) && (!prefix)) { - prefix = NewStringf("%s_",module); - } else { - prefix = NewString(""); - } - - Printf(f_header,"#define SWIG_init %s\n", init_name); - if (!module) module = NewString("swig"); - Printf(f_header,"#define SWIG_name \"%s\"\n", module); - if (nspace) { - Printf(f_header,"#define SWIG_prefix \"%s::\"\n", ns_name); - Printf(f_header,"#define SWIG_namespace \"%s\"\n\n", ns_name); - } else { - Printf(f_header,"#define SWIG_prefix \"%s\"\n", prefix); - Printf(f_header,"#define SWIG_namespace \"\"\n\n"); - } - Printf(f_header,"#ifdef __cplusplus\n"); - Printf(f_header,"extern \"C\" {\n"); - Printf(f_header,"#endif\n"); - Printf(f_header,"#ifdef MAC_TCL\n"); - Printf(f_header,"#pragma export on\n"); - Printf(f_header,"#endif\n"); - Printf(f_header,"SWIGEXPORT(int) %s(Tcl_Interp *);\n", init_name); - Printf(f_header,"#ifdef MAC_TCL\n"); - Printf(f_header,"#pragma export off\n"); - Printf(f_header,"#endif\n"); - Printf(f_header,"#ifdef __cplusplus\n"); - Printf(f_header,"}\n"); - Printf(f_header,"#endif\n"); - - Printf(f_init,"SWIGEXPORT(int) %s(Tcl_Interp *interp) {\n", init_name); - Printf(f_init,"int i;\n"); - Printf(f_init,"if (interp == 0) return TCL_ERROR;\n"); - - /* Check to see if we're adding support for Tcl8 nspaces */ - if (nspace) { - Printf(f_init,"Tcl_Eval(interp,\"namespace eval %s { }\");\n", ns_name); + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + /* Initialize some variables for the object interface */ + + cmd_tab = NewString(""); + var_tab = NewString(""); + methods_tab = NewString(""); + const_tab = NewString(""); + + Swig_banner(f_runtime); + + /* Include a Tcl configuration file */ + if (NoInclude) { + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); + } + + /* Set the module name, namespace, and prefix */ + + module = NewStringf("%(lower)s", Getattr(n,"name")); + init_name = NewStringf("%(title)s_Init",module); + + ns_name = prefix ? Copy(prefix) : Copy(module); + if (prefix) Append(prefix,"_"); + + /* Generate some macros used throughout code generation */ + + Printf(f_header,"#define SWIG_init %s\n", init_name); + Printf(f_header,"#define SWIG_name \"%s\"\n", module); + if (nspace) { + Printf(f_header,"#define SWIG_prefix \"%s::\"\n", ns_name); + Printf(f_header,"#define SWIG_namespace \"%s\"\n\n", ns_name); + } else { + Printf(f_header,"#define SWIG_prefix \"%s\"\n", prefix); + } + Printf(f_header,"#define SWIG_version \"%s\"\n", version); + + Printf(cmd_tab, "\nstatic swig_command_info swig_commands[] = {\n"); + Printf(var_tab, "\nstatic swig_var_info swig_variables[] = {\n"); + Printf(const_tab, "\nstatic swig_const_info swig_constants[] = {\n"); + + Printf(f_wrappers,"#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); + + /* Start emitting code */ + Language::top(n); + + /* Done. Close up the module */ + Printv(cmd_tab, tab4, "{0, 0, 0}\n", "};\n",NIL); + Printv(var_tab, tab4, "{0,0,0,0}\n", "};\n",NIL); + Printv(const_tab, tab4, "{0,0,0,0,0,0}\n", "};\n", NIL); + + Printv(f_wrappers, cmd_tab, var_tab, const_tab,NIL); + + /* Dump the pointer equivalency table */ + SwigType_emit_type_table(f_runtime, f_wrappers); + + Printf(f_wrappers,"#ifdef __cplusplus\n}\n#endif\n"); + + /* Close the init function and quit */ + Printf(f_init,"return TCL_OK;\n}\n"); + + /* Close all of the files */ + Printv(f_runtime, f_header, f_wrappers,NIL); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + return SWIG_OK; } + + /* ------------------------------------------------------------ + * functionWrapper() + * ------------------------------------------------------------ */ + + virtual int functionWrapper(Node *n) { + String *name = Getattr(n,"name"); /* Like to get rid of this */ + String *iname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + ParmList *parms = Getattr(n,"parms"); + String *overname = 0; + + Parm *p; + int i; + String *tm; + Wrapper *f; + String *incode, *cleanup, *outarg, *argstr, *args; + int num_arguments = 0; + int num_required = 0; + int varargs = 0; + + char source[64]; + + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); + } else { + if (!addSymbol(iname,n)) return SWIG_ERROR; + } + + incode = NewString(""); + cleanup = NewString(""); + outarg = NewString(""); + argstr = NewString("\""); + args = NewString(""); + + f = NewWrapper(); + String *wname = Swig_name_wrapper(iname); + if (overname) { + Append(wname, overname); + } + Setattr(n,"wrap:name",wname); - Printf(cmd_info, "\nstatic swig_command_info swig_commands[] = {\n"); - Printf(var_info, "\nstatic swig_var_info swig_variables[] = {\n"); - Printv(f_init, - "for (i = 0; swig_types_initial[i]; i++) {\n", - "swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n", - "}\n", 0); -} - -/* ----------------------------------------------------------------------------- - * TCL8::close() - * ----------------------------------------------------------------------------- */ - -void -TCL8::close(void) { - - Printv(cmd_info, tab4, "{0, 0, 0}\n", "};\n",0); - Printv(var_info, tab4, "{0,0,0,0}\n", "};\n",0); - - Printf(f_wrappers,"%s", cmd_info); - Printf(f_wrappers,"%s", var_info); - - Printf(f_init,"for (i = 0; swig_commands[i].name; i++) {\n"); - Printf(f_init,"Tcl_CreateObjCommand(interp, (char *) swig_commands[i].name, swig_commands[i].wrapper, swig_commands[i].clientdata, NULL);\n"); - Printf(f_init,"}\n"); - - Printf(f_init,"for (i = 0; swig_variables[i].name; i++) {\n"); - Printf(f_init,"Tcl_SetVar(interp, (char *) swig_variables[i].name, \"\", TCL_GLOBAL_ONLY);\n"); - Printf(f_init,"Tcl_TraceVar(interp, (char *) swig_variables[i].name, TCL_TRACE_READS | TCL_GLOBAL_ONLY, swig_variables[i].get, (ClientData) swig_variables[i].addr);\n"); - Printf(f_init,"Tcl_TraceVar(interp, (char *) swig_variables[i].name, TCL_TRACE_WRITES | TCL_GLOBAL_ONLY, swig_variables[i].set, (ClientData) swig_variables[i].addr);\n"); - Printf(f_init,"}\n"); - - /* Dump the pointer equivalency table */ - SwigType_emit_type_table(f_runtime, f_wrappers); - - /* Close the init function and quit */ - Printf(f_init,"return TCL_OK;\n"); - Printf(f_init,"}\n"); -} - -/* ----------------------------------------------------------------------------- - * TCL8::create_command() - * ----------------------------------------------------------------------------- */ - -void -TCL8::create_command(String *cname, String *iname) { - - String *wname = Swig_name_wrapper(cname); - Printv(cmd_info, tab4, "{ SWIG_prefix \"", iname, "\", ", wname, ", NULL},\n", 0); - - /* Add interpreter name to repeatcmd hash table. This hash is used in C++ code - generation to try and find repeated wrapper functions. */ - - Setattr(repeatcmd,iname,wname); -} - -/* ----------------------------------------------------------------------------- - * TCL8::create_function() - * ----------------------------------------------------------------------------- */ + Printv(f->def, + "static int\n ", wname, "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {", + NIL); + + /* Print out variables for storing arguments. */ + emit_args(type,parms, f); + + /* Attach standard typemaps */ + emit_attach_parmmaps(parms,f); + Setattr(n,"wrap:parms",parms); + + /* Get number of require and total arguments */ + num_arguments = emit_num_arguments(parms); + num_required = emit_num_required(parms); + varargs = emit_isvarargs(parms); + + /* Unmarshal parameters */ + + for (i = 0, p = parms; i < num_arguments; i++) { + /* Skip ignored arguments */ + + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + String *ln = Getattr(p,"lname"); + + /* Produce string representations of the source and target arguments */ + sprintf(source,"objv[%d]",i+1); + + if (i == num_required) Putc('|',argstr); + if ((tm = Getattr(p,"tmap:in"))) { + String *parse = Getattr(p,"tmap:in:parse"); + if (!parse) { + Replaceall(tm,"$target",ln); + Replaceall(tm,"$source",source); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",source); + + if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) { + Replaceall(tm,"$disown","SWIG_POINTER_DISOWN"); + } else { + Replaceall(tm,"$disown","0"); + } -void -TCL8::function(DOH *node) { - char *name, *iname; - SwigType *d; - ParmList *l; - Parm *p; - int pcount,i,j; - char *tm; - Wrapper *f; - String *incode, *cleanup, *outarg, *argstr, *args; - int numopt= 0; - - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - d = Getattr(node,"type"); - l = Getattr(node,"parms"); - - incode = NewString(""); - cleanup = NewString(""); - outarg = NewString(""); - argstr = NewString("\""); - args = NewString(""); - - f = NewWrapper(); - Printv(f, - "static int\n ", Swig_name_wrapper(iname), "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {\n", - 0); - - /* Print out variables for storing arguments. */ - pcount = emit_args(node, f); - numopt = check_numopt(l); - - /* Extract parameters. */ - i = 0; - j = 0; - p = l; - while (p != 0) { - char source[64]; - char target[64]; - char argnum[64]; - SwigType *pt = Gettype(p); - String *pn = Getname(p); - - /* Produce string representations of the source and target arguments */ - sprintf(source,"objv[%d]",j+1); - sprintf(target,"%s", Char(Getlname(p))); - sprintf(argnum,"%d",j+1); - - /* See if this argument is being ignored */ - if (!Getignore(p)) { - if (j == (pcount-numopt)) Putc('|',argstr); - if ((tm = Swig_typemap_lookup((char*)"in",pt,pn,source,target,f))) { - Putc('o',argstr); - Printf(args,",0"); - Printf(incode,"%s\n", tm); - Replace(incode,"$argnum",argnum, DOH_REPLACE_ANY); - Replace(incode,"$arg",source, DOH_REPLACE_ANY); - } else { - switch(SwigType_type(pt)) { - case T_INT: - case T_UINT: - Putc('i', argstr); - Printf(args,",&%s",target); - break; - - case T_BOOL: - Putc('i',argstr); - { - char tb[32]; - sprintf(tb,"tempb%d",i); - Wrapper_add_localv(f,tb,"int",tb,0); - Printf(args,",&%s",tb); - Printv(incode, target, " = (bool) ", tb, ";\n", 0); + Putc('o',argstr); + Printf(args,",0"); + if (i >= num_required) { + Printf(incode, "if (objc > %d) {\n", i+1); + } + Printf(incode,"%s\n", tm); + if (i >= num_required) { + Printf(incode, "}\n"); } - break; - - case T_SHORT: - case T_USHORT: - Putc('h',argstr); - Printf(args,",&%s",target); - break; - - case T_LONG: - case T_ULONG: - Putc('l',argstr); - Printf(args,",&%s",target); - break; - - case T_SCHAR: - case T_UCHAR: - Putc('b',argstr); - Printf(args,",&%s", target); - break; - - case T_FLOAT: - Putc('f',argstr); - Printf(args,",&%s", target); - break; - - case T_DOUBLE: - Putc('d',argstr); - Printf(args,",&%s", target); - break; - - case T_CHAR : - Putc('c',argstr); - Printf(args,",&%s",target); - break; - - case T_VOID : - break; - - case T_USER: - SwigType_add_pointer(pt); - SwigType_remember(pt); - Putc('p',argstr); - Printv(args, ",&", target, ", SWIGTYPE", SwigType_manglestr(pt), 0); - SwigType_del_pointer(pt); - break; - - case T_STRING: - Putc('s',argstr); - Printf(args,",&%s",target); - break; - - case T_POINTER: case T_ARRAY: case T_REFERENCE: - { - SwigType *lt; + } else { + Printf(argstr,"%s",parse); + Printf(args,",&%s",ln); + if (Strcmp(parse,"p") == 0) { + SwigType *lt = SwigType_ltype(pt); SwigType_remember(pt); - Putc('p',argstr); - lt = Swig_clocal_type(pt); if (Cmp(lt,"p.void") == 0) { - Printv(args, ",&", target, ", 0", 0); + Printf(args,",0"); } else { - Printv(args, ",&", target, ", SWIGTYPE", SwigType_manglestr(pt), 0); + Printf(args,",SWIGTYPE%s", SwigType_manglestr(pt)); } Delete(lt); - break; } - default : - Printf(stderr,"%s:%d: Unable to use type %s as a function argument.\n", - Getfile(node), Getline(node), SwigType_str(pt,0)); - break; } + p = Getattr(p,"tmap:in:next"); + continue; + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument.\n", SwigType_str(pt,0)); + } + p = nextSibling(p); + } + + if (!varargs) { + Putc(':',argstr); + } else { + Putc(';',argstr); + /* If variable length arguments we need to emit the in typemap here */ + if (p && (tm = Getattr(p,"tmap:in"))) { + sprintf(source,"objv[%d]", i+1); + Printf(incode,"if (objc > %d) {\n", i); + Replaceall(tm,"$input",source); + Printv(incode,tm,"\n", NIL); + Printf(incode,"}\n"); + } + } + + Printf(argstr,"%s\"",usage_string(Char(iname),type,parms)); + + Printv(f->code, + "if (SWIG_GetArgs(interp, objc, objv,", argstr, args, ") == TCL_ERROR) SWIG_fail;\n", + NIL); + + Printv(f->code,incode,NIL); + + /* Insert constraint checking code */ + for (p = parms; p;) { + if ((tm = Getattr(p,"tmap:check"))) { + Replaceall(tm,"$target",Getattr(p,"lname")); + Printv(f->code,tm,"\n",NIL); + p = Getattr(p,"tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert cleanup code */ + for (i = 0, p = parms; p; i++) { + if ((tm = Getattr(p,"tmap:freearg"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); } - j++; } - /* Check to see if there was any sort of a constaint typemap */ - if ((tm = Swig_typemap_lookup((char*)"check",pt,pn,source,target,0))) { - Printf(incode,"%s\n", tm); - Replace(incode,"$argnum",argnum, DOH_REPLACE_ANY); - Replace(incode,"$arg",source, DOH_REPLACE_ANY); + + /* Insert argument output code */ + for (i=0,p = parms; p;i++) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","(Tcl_GetObjResult(interp))"); + Replaceall(tm,"$result","(Tcl_GetObjResult(interp))"); + Replaceall(tm,"$arg",Getattr(p,"emit:input")); + Replaceall(tm,"$input",Getattr(p,"emit:input")); + Printv(outarg,tm,"\n",NIL); + p = Getattr(p,"tmap:argout:next"); + } else { + p = nextSibling(p); + } } - /* Check if there was any cleanup code (save it for later) */ - if ((tm = Swig_typemap_lookup((char*)"freearg",pt,pn,target,(char*)"tcl_result",0))) { - Printf(cleanup,"%s\n", tm); - Replace(cleanup,"$argnum",argnum, DOH_REPLACE_ANY); - Replace(cleanup,"$arg",source,DOH_REPLACE_ANY); + + /* Now write code to make the function call */ + emit_action(n,f); + + /* Need to redo all of this code (eventually) */ + + /* Return value if necessary */ + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source", "result"); + Replaceall(tm,"$target", "Tcl_GetObjResult(interp)"); + Replaceall(tm,"$result", "Tcl_GetObjResult(interp)"); + Printf(f->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s in function %s.\n", SwigType_str(type,0), name); } - /* Look for output arguments */ - if ((tm = Swig_typemap_lookup((char*)"argout",pt,pn,target,(char*)"tcl_result",0))) { - Printf(outarg,"%s\n", tm); - Replace(outarg,"$argnum",argnum, DOH_REPLACE_ANY); - Replace(outarg,"$arg",source, DOH_REPLACE_ANY); + + /* Dump output argument code */ + Printv(f->code,outarg,NIL); + + /* Dump the argument cleanup code */ + Printv(f->code,cleanup,NIL); + + /* Look for any remaining cleanup */ + if (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n", tm); + } + } + + if ((tm = Swig_typemap_lookup_new("ret",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n", tm); } - i++; - p = Getnext(p); + Printv(f->code, "return TCL_OK;\n", NIL); + Printv(f->code, "fail:\n", cleanup, "return TCL_ERROR;\n", NIL); + Printv(f->code,"}\n", NIL); + + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); + Replaceall(f->code,"$symname", iname); + + /* Dump out the function */ + Wrapper_print(f,f_wrappers); + + if (!Getattr(n,"sym:overloaded")) { + /* Register the function with Tcl */ + Printv(cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", Swig_name_wrapper(iname), ", NULL},\n", NIL); + } else { + if (!Getattr(n,"sym:nextSibling")) { + /* Emit overloading dispatch function */ + + int maxargs; + String *dispatch = Swig_overload_dispatch(n,"return %s(clientData, interp, objc, objv);",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + + Printv(df->def, + "static int\n", dname, + "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {", + NIL); + Printf(df->code,"Tcl_Obj *CONST *argv = objv+1;\n"); + Printf(df->code,"int argc = objc-1;\n"); + Printv(df->code,dispatch,"\n",NIL); + Printf(df->code,"Tcl_SetResult(interp,(char *) \"No matching function for overloaded '%s'\", TCL_STATIC);\n", iname); + Printf(df->code,"return TCL_ERROR;\n"); + Printv(df->code,"}\n",NIL); + Wrapper_print(df,f_wrappers); + Printv(cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", dname, ", NULL},\n", NIL); + DelWrapper(df); + Delete(dispatch); + Delete(dname); + } + } + + Delete(incode); + Delete(cleanup); + Delete(outarg); + Delete(argstr); + Delete(args); + DelWrapper(f); + return SWIG_OK; } - Printf(argstr,":%s\"",usage_string(iname,d,l)); - Printv(f, - "if (SWIG_GetArgs(interp, objc, objv,", argstr, args, ") == TCL_ERROR) return TCL_ERROR;\n", - 0); - - Printv(f,incode,0); - - /* Now write code to make the function call */ - emit_func_call(node,f); - - /* Return value if necessary */ - if ((tm = Swig_typemap_lookup((char*)"out",d,name,(char*)"result",(char*)"tcl_result",0))) { - Printf(f,"%s\n", tm); - } else { - switch(SwigType_type(d)) { - case T_BOOL: - case T_INT: - case T_SHORT: - case T_LONG : - case T_SCHAR: - case T_UINT: - case T_USHORT: - case T_ULONG: - case T_UCHAR: - Printv(f, "Tcl_SetObjResult(interp,Tcl_NewIntObj((long) result));\n",0); - break; - - /* Is a single character. We return it as a string */ - case T_CHAR : - Printv(f, "Tcl_SetObjResult(interp,Tcl_NewStringObj(&result,1));\n",0); - break; - - case T_DOUBLE : - case T_FLOAT : - Printv(f, "Tcl_SetObjResult(interp,Tcl_NewDoubleObj((double) result));\n",0); - break; - - case T_USER : - - /* Okay. We're returning malloced memory at this point. - Probably dangerous, but safe programming is for wimps. */ - SwigType_add_pointer(d); - SwigType_remember(d); - Printv(f, "Tcl_SetObjResult(interp,SWIG_NewPointerObj((void *) result,SWIGTYPE", - SwigType_manglestr(d), "));\n", 0); - - SwigType_del_pointer(d); - break; - - case T_STRING: - Printv(f, "Tcl_SetObjResult(interp,Tcl_NewStringObj(result,-1));\n",0); - break; - case T_POINTER: case T_REFERENCE: case T_ARRAY: - SwigType_remember(d); - Printv(f, "Tcl_SetObjResult(interp,SWIG_NewPointerObj((void *) result,SWIGTYPE", - SwigType_manglestr(d), "));\n", - 0); - break; - - case T_VOID: - break; - - default : - Printf(stderr,"%s:%d. Unable to use return type %s in function %s.\n", - Getfile(node), Getline(node), SwigType_str(d,0), name); - break; + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *setname = 0; + String *getname = 0; + Wrapper *setf = 0, *getf = 0; + int readonly = 0; + String *tm; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + /* Create a function for getting a variable */ + getf = NewWrapper(); + getname = Swig_name_wrapper(Swig_name_get(iname)); + Printv(getf->def,"static char *",getname,"(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {",NIL); + Wrapper_add_local(getf,"value", "Tcl_Obj *value = 0"); + + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source", name); + Replaceall(tm,"$target","value"); + Replaceall(tm,"$result", "value"); + Printf(getf->code, "%s\n",tm); + Printf(getf->code, "if (value) {\n"); + Printf(getf->code, "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n"); + Printf(getf->code, "Tcl_DecrRefCount(value);\n"); + Printf(getf->code, "}\n"); + Printf(getf->code, "return NULL;\n"); + Printf(getf->code,"}\n"); + Wrapper_print(getf,f_wrappers); + } else { + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Can't link to variable of type %s\n", SwigType_str(t,0)); + DelWrapper(getf); + return SWIG_NOWRAP; } + DelWrapper(getf); + + /* Try to create a function setting a variable */ + if (!Getattr(n,"feature:immutable")) { + setf = NewWrapper(); + setname = Swig_name_wrapper(Swig_name_set(iname)); + Printv(setf->def,"static char *",setname, "(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {",NIL); + Wrapper_add_local(setf,"value", "Tcl_Obj *value = 0"); + Wrapper_add_local(setf,"name1o", "Tcl_Obj *name1o = 0"); + + if ((tm = Swig_typemap_lookup_new("varin", n, name, 0))) { + Replaceall(tm,"$source","value"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input", "value"); + Printf(setf->code,"name1o = Tcl_NewStringObj(name1,-1);\n"); + Printf(setf->code,"value = Tcl_ObjGetVar2(interp, name1o, 0, flags);\n"); + Printf(setf->code,"Tcl_DecrRefCount(name1o);\n"); + Printf(setf->code,"if (!value) return NULL;\n"); + Printf(setf->code,"%s\n", tm); + Printf(setf->code,"return NULL;\n"); + Printf(setf->code,"}\n"); + if (setf) Wrapper_print(setf,f_wrappers); + } else { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF,input_file, line_number, + "Variable %s will be read-only without a varin typemap.\n", name); + readonly = 1; + } + DelWrapper(setf); + } + + Printv(var_tab, tab4,"{ SWIG_prefix \"", iname, "\", 0, (swig_variable_func) ", getname, ",", NIL); + if (readonly || Getattr(n,"feature:immutable")) { + static int readonlywrap = 0; + if (!readonlywrap) { + Wrapper *ro = NewWrapper(); + Printf(ro->def, "static const char *swig_readonly(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {"); + Printv(ro->code, "return (char*) \"Variable is read-only\";\n", "}\n", NIL); + Wrapper_print(ro,f_wrappers); + readonlywrap = 1; + DelWrapper(ro); + } + Printf(var_tab, "(swig_variable_func) swig_readonly},\n"); + } else { + Printv(var_tab, "(swig_variable_func) ", setname, "},\n",NIL); + } + Delete(setname); + Delete(getname); + return SWIG_OK; } - /* Dump output argument code */ - Printv(f,outarg,0); + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ - /* Dump the argument cleanup code */ - Printv(f,cleanup,0); + virtual int constantWrapper(Node *n) { + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *value = Getattr(n,"value"); + String *tm; - /* Look for any remaining cleanup */ - if (NewObject) { - if ((tm = Swig_typemap_lookup((char*)"newfree",d,iname,(char*)"result",(char*)"",0))) { - Printf(f,"%s\n", tm); + if (!addSymbol(iname,n)) return SWIG_ERROR; + + /* Special hook for member pointer */ + if (SwigType_type(type) == T_MPOINTER) { + String *wname = Swig_name_wrapper(iname); + Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type,wname), value); + value = Char(wname); } + if ((tm = Swig_typemap_lookup_new("consttab",n,name,0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value",value); + Printf(const_tab,"%s,\n", tm); + } else if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) { + Replaceall(tm,"$source", value); + Replaceall(tm,"$target", name); + Replaceall(tm,"$value",value); + Printf(f_init, "%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_CONST_UNDEF, + input_file, line_number, "Unsupported constant value.\n"); + return SWIG_NOWRAP; + } + return SWIG_OK; } - if ((tm = Swig_typemap_lookup((char*)"ret",d,name,(char*)"result",(char*)"",0))) { - Printf(f,"%s\n", tm); - } - Printv(f, "return TCL_OK;\n}\n", 0); + /* ------------------------------------------------------------ + * nativeWrapper() + * ------------------------------------------------------------ */ - /* Substitute the cleanup code */ - Replace(f,"$cleanup",cleanup,DOH_REPLACE_ANY); - Replace(f,"$name", iname, DOH_REPLACE_ANY); + virtual int nativeWrapper(Node *n) { + String *name = Getattr(n,"sym:name"); + String *funcname = Getattr(n,"wrap:name"); + if (!addSymbol(funcname,n)) return SWIG_ERROR; - /* Dump out the function */ - Printf(f_wrappers,"%s",f); + Printf(f_init,"\t Tcl_CreateObjCommand(interp, SWIG_prefix \"%s\", (swig_wrapper_func) %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",name, funcname); + return SWIG_OK; + } - /* Register the function with Tcl */ - Printv(cmd_info, tab4, "{ SWIG_prefix \"", iname, "\", ", Swig_name_wrapper(iname), ", NULL},\n", 0); + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ - Delete(incode); - Delete(cleanup); - Delete(outarg); - Delete(argstr); - Delete(args); - Delete(f); -} + virtual int classHandler(Node *n) { + + String *mangled_classname = 0; + String *real_classname = 0; -/* ----------------------------------------------------------------------------- - * TCL8::variable() - * ----------------------------------------------------------------------------- */ + have_constructor = 0; + have_destructor = 0; + destructor_action = 0; -static Hash *setf = 0; -static Hash *getf = 0; + class_name = Getattr(n,"sym:name"); + if (!addSymbol(class_name,n)) return SWIG_ERROR; -void -TCL8::variable(DOH *node) { - char *name, *iname; - SwigType *t; + real_classname = Getattr(n,"name"); + mangled_classname = Swig_name_mangle(real_classname); - String *setname; - String *getname; + attr_tab = NewString(""); + Printf(attr_tab, "static swig_attribute swig_"); + Printv(attr_tab, mangled_classname, "_attributes[] = {\n", NIL); + + methods_tab = NewStringf(""); + Printf(methods_tab,"static swig_method swig_"); + Printv(methods_tab, mangled_classname, "_methods[] = {\n", NIL); - int isarray = 0; - int readonly = 0; - int setable = 1; - int tc; + /* Generate normal wrappers */ + Language::classHandler(n); - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - t = Getattr(node,"type"); + SwigType *t = Copy(Getattr(n,"name")); + SwigType_add_pointer(t); + + // Catch all: eg. a class with only static functions and/or variables will not have 'remembered' + // SwigType_remember(t); + String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname); + SwigType_remember_clientdata(t,wrap_class); - if (!setf) setf = NewHash(); - if (!getf) getf = NewHash(); + // t = Copy(Getattr(n,"classtype")); + // SwigType_add_pointer(t); - /* See if there were any typemaps */ - if (Swig_typemap_search((char *)"varin",t,name) || (Swig_typemap_search((char*)"varout",t,name))) { - Printf(stderr,"%s:%d. Warning. varin/varout typemap methods not supported.", - Getfile(node), Getline(node)); - } + String *rt = Copy(Getattr(n,"classtype")); + SwigType_add_pointer(rt); - if (ReadOnly) readonly = 1; - isarray = SwigType_isarray(t); - tc = SwigType_type(t); - setname = Getattr(setf,t); - getname = Getattr(getf,t); - - /* Dump a collection of set/get functions suitable for variable tracing */ - if (!getname) { - Wrapper *get, *set; - - setname = NewStringf("swig_%s_set", Swig_string_mangle(t)); - getname = NewStringf("swig_%s_get", Swig_string_mangle(t)); - get = NewWrapper(); - set = NewWrapper(); - Printv(set, "static char *", setname, "(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {\n",0); - Printv(get, "static char *", getname, "(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {\n",0); - - SwigType *lt = Swig_clocal_type(t); - if ((tc != T_USER) && (!isarray)) - SwigType_add_pointer(lt); - Wrapper_add_localv(get,"addr",SwigType_lstr(lt,"addr"),0); - Wrapper_add_localv(set,"addr",SwigType_lstr(lt,"addr"),0); - Printv(set, "addr = (", SwigType_lstr(lt,0), ") clientData;\n", 0); - Printv(get, "addr = (", SwigType_lstr(lt,0), ") clientData;\n", 0); - if ((tc != T_USER) && (!isarray)) - SwigType_del_pointer(lt); - Delete(lt); - Wrapper_add_local(set, "value", "char *value"); - Wrapper_add_local(get, "value", "Tcl_Obj *value"); - - Printv(set, "value = Tcl_GetVar2(interp, name1, name2, flags);\n", - "if (!value) return NULL;\n", 0); - - switch(tc) { - case T_INT: - case T_SHORT: - case T_USHORT: - case T_LONG: - case T_UCHAR: - case T_SCHAR: - case T_BOOL: - Printv(set, "*(addr) = (", SwigType_str(t,0), ") atol(value);\n", 0); - Wrapper_add_local(get,"value","Tcl_Obj *value"); - Printv(get, - "value = Tcl_NewIntObj((int) *addr);\n", - "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n", - "Tcl_DecrRefCount(value);\n", - 0); - break; - - case T_UINT: - case T_ULONG: - Printv(set, "*(addr) = (", SwigType_str(t,0), ") strtoul(value,0,0);\n",0); - Wrapper_add_local(get,"value","Tcl_Obj *value"); - Printv(get, - "value = Tcl_NewIntObj((int) *addr);\n", - "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n", - "Tcl_DecrRefCount(value);\n", - 0); - break; - - case T_FLOAT: - case T_DOUBLE: - Printv(set, "*(addr) = (", SwigType_str(t,0), ") atof(value);\n",0); - Wrapper_add_local(get,"value","Tcl_Obj *value"); - Printv(get, - "value = Tcl_NewDoubleObj((double) *addr);\n", - "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n", - "Tcl_DecrRefCount(value);\n", - 0); - break; - - case T_CHAR: - Printv(set, "*(addr) = *value;\n",0); - Wrapper_add_local(get,"temp", "char temp[2]"); - Printv(get, "temp[0] = *addr; temp[1] = 0;\n", - "Tcl_SetVar2(interp,name1,name2,temp,flags);\n", - 0); - break; - - case T_USER: - /* User defined type. We return it as a pointer */ - SwigType_add_pointer(t); - SwigType_remember(t); - Printv(set, "{\n", - "void *ptr;\n", - "if (SWIG_ConvertPtrFromString(interp,value,&ptr,SWIGTYPE", SwigType_manglestr(t), ") != TCL_OK) {\n", - "return \"Type Error\";\n", - "}\n", - "*(addr) = *((", SwigType_lstr(t,0), ") ptr);\n", - "}\n", - 0); - - SwigType_del_pointer(t); - Wrapper_add_local(get,"value", "Tcl_Obj *value"); - SwigType_add_pointer(t); - SwigType_remember(t); - Printv(get, "value = SWIG_NewPointerObj(addr, SWIGTYPE", SwigType_manglestr(t), ");\n", - "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n", - "Tcl_DecrRefCount(value);\n",0); - SwigType_del_pointer(t); - - break; - - case T_STRING: - Printv(set, "if (*addr) free(*addr);\n", - "*addr = (char *) malloc(strlen(value)+1);\n", - "strcpy(*addr,value);\n", - 0); - Printv(get, "Tcl_SetVar2(interp,name1,name2,*addr, flags);\n",0); - break; - - case T_ARRAY: - { - SwigType *aop; - SwigType *ta = Copy(t); - aop = SwigType_pop(ta); - /* Printf(stdout,"'%s' '%s'\n", ta, aop);*/ - setable = 0; - readonly = 1; - if (SwigType_type(ta) == T_CHAR) { - String *dim = SwigType_array_getdim(aop,0); - if (dim && Len(dim)) { - Printf(set, "strncpy(addr,value,%s);\n", dim); - setable = 1; - readonly = ReadOnly; - } - Printv(get, "Tcl_SetVar2(interp,name1,name2,addr, flags);\n",0); + // Register the class structure with the type checker + /* Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_classname); */ + if (have_destructor) { + Printv(f_wrappers, "static void swig_delete_", class_name, "(void *obj) {\n", NIL); + if (destructor_action) { + Printv(f_wrappers, SwigType_str(rt,"arg1"), " = (", SwigType_str(rt,0), ") obj;\n", NIL); + Printv(f_wrappers, destructor_action, NIL); + } else { + if (CPlusPlus) { + Printv(f_wrappers," delete (", SwigType_str(rt,0), ") obj;\n",NIL); } else { - Printf(stderr,"%s:%d: Array variable '%s' will be read-only.\n", Getfile(node), Getline(node), name); - Wrapper_add_local(get,"value","Tcl_Obj *value"); - SwigType_remember(t); - Printv(get, - "value = SWIG_NewPointerObj(addr, SWIGTYPE", SwigType_manglestr(t), ");\n", - "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n", - "Tcl_DecrRefCount(value);\n", - 0); + Printv(f_wrappers," free((char *) obj);\n",NIL); } - Delete(ta); - Delete(aop); } - break; - - case T_POINTER: case T_REFERENCE: - SwigType_remember(t); - Printv(set, "{\n", - "void *ptr;\n", - "if (SWIG_ConvertPtrFromString(interp,value,&ptr,SWIGTYPE", SwigType_manglestr(t), ") != TCL_OK) {\n", - "return \"Type Error\";\n", - "}\n", - "*(addr) = (", SwigType_lstr(t,0), ") ptr;\n", - "}\n", - 0); - - Wrapper_add_local(get,"value","Tcl_Obj *value"); - Printv(get, - "value = SWIG_NewPointerObj(*addr, SWIGTYPE", SwigType_manglestr(t), ");\n", - "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n", - "Tcl_DecrRefCount(value);\n", - 0); - - break; - case T_VOID: - break; - - default: - Printf(stderr,"TCL8::link_variable. Unknown type %s!\n", SwigType_str(t,0)); - break; + Printf(f_wrappers,"}\n"); } - Printv(set, "return NULL;\n", "}\n",0); - Printv(get, "return NULL;\n", "}\n",0); - Printf(f_wrappers,"%s",get); - Setattr(getf,Copy(t),getname); - if (setable) { - Printf(f_wrappers,"%s",set); - Setattr(setf,Copy(t),setname); - } - Delete(get); - Delete(set); - } - Printv(var_info, tab4,"{ SWIG_prefix \"", iname, "\", (void *) ", isarray ? "" : "&", name, ",", getname, ",", 0); - - if (readonly) { - static int readonlywrap = 0; - if (!readonlywrap) { - Wrapper *ro = NewWrapper(); - Printf(ro, "static char *swig_readonly(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {\n"); - Printv(ro, "return \"Variable is read-only\";\n", "}\n", 0); - Printf(f_wrappers,"%s",ro); - readonlywrap = 1; - Delete(ro); + + Printf(methods_tab, " {0,0}\n};\n"); + Printv(f_wrappers,methods_tab,NIL); + + Printf(attr_tab, " {0,0,0}\n};\n"); + Printv(f_wrappers,attr_tab,NIL); + + /* Handle inheritance */ + + String *base_class = NewString(""); + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "name"); + if ((!bname) || Getattr(base,"feature:ignore") || (!Getattr(base,"module"))) { + base = Nextitem(baselist); + continue; + } + String *bmangle = Swig_name_mangle(bname); + Printv(f_wrappers,"extern swig_class _wrap_class_", bmangle, ";\n", NIL); + Printf(base_class,"&_wrap_class_%s",bmangle); + base = Nextitem(baselist); + Putc(',',base_class); + Delete(bmangle); + } } - Printf(var_info, "swig_readonly},\n"); - } else { - Printv(var_info, setname, "},\n",0); - } -} -/* ----------------------------------------------------------------------------- - * TCL8::constant() - * ----------------------------------------------------------------------------- */ + Printv(f_wrappers,"static swig_class *swig_",mangled_classname,"_bases[] = {", base_class,"0};\n", NIL); + Delete(base_class); -void -TCL8::constant(DOH *node) { - char *name; - SwigType *type; - char *value; - int OldStatus = ReadOnly; - SwigType *t; - char var_name[256]; - char *tm; - String *rvalue; - ReadOnly = 1; - DOH *nnode; - - name = GetChar(node,"name"); - type = Getattr(node,"type"); - value = GetChar(node,"value"); - nnode = Copy(node); - - /* Make a static variable */ - sprintf(var_name,"_wrap_const_%s",name); - - if (SwigType_type(type) == T_STRING) { - rvalue = NewStringf("\"%s\"",value); - } else if (SwigType_type(type) == T_CHAR) { - rvalue = NewStringf("\'%s\'",value); - } else { - rvalue = NewString(value); - } - if ((tm = Swig_typemap_lookup((char*)"const",type,name,Char(rvalue),name,0))) { - Printf(f_init,"%s\n",tm); - } else { - /* Create variable and assign it a value */ - switch(SwigType_type(type)) { - case T_BOOL: case T_INT: case T_DOUBLE: - Printf(f_header,"static %s %s = %s;\n", SwigType_str(type,0), var_name, value); - Setattr(nnode,"name",var_name); - variable(nnode); - break; - - case T_SHORT: - case T_LONG: - case T_SCHAR: - Printf(f_header,"static %s %s = %s;\n", SwigType_str(type,0), var_name, value); - Printf(f_header,"static char *%s_char;\n", var_name); - if (CPlusPlus) - Printf(f_init,"\t %s_char = new char[32];\n",var_name); - else - Printf(f_init,"\t %s_char = (char *) malloc(32);\n",var_name); - - Printf(f_init,"\t sprintf(%s_char,\"%%ld\", (long) %s);\n", var_name, var_name); - sprintf(var_name,"%s_char",var_name); - t = NewString("char"); - SwigType_add_pointer(t); - Setattr(nnode,"name",var_name); - Setattr(nnode,"type",t); - variable(nnode); - Delete(t); - break; - - case T_UINT: - case T_USHORT: - case T_ULONG: - case T_UCHAR: - Printf(f_header,"static %s %s = %s;\n", SwigType_str(type,0), var_name, value); - Printf(f_header,"static char *%s_char;\n", var_name); - if (CPlusPlus) - Printf(f_init,"\t %s_char = new char[32];\n",var_name); - else - Printf(f_init,"\t %s_char = (char *) malloc(32);\n",var_name); - - Printf(f_init,"\t sprintf(%s_char,\"%%lu\", (unsigned long) %s);\n", var_name, var_name); - sprintf(var_name,"%s_char",var_name); - t = NewSwigType(T_CHAR); - SwigType_add_pointer(t); - Setattr(nnode,"name",var_name); - Setattr(nnode,"type",t); - variable(nnode); - Delete(t); - break; - - case T_FLOAT: - Printf(f_header,"static %s %s = (%s) (%s);\n", SwigType_lstr(type,0), var_name, SwigType_lstr(type,0), value); - Setattr(nnode,"name",var_name); - variable(nnode); - break; - - case T_CHAR: - SwigType_add_pointer(type); - Printf(f_header,"static %s %s = \"%s\";\n", SwigType_lstr(type,0), var_name, value); - Setattr(nnode,"name",var_name); - Setattr(nnode,"type",type); - variable(nnode); - SwigType_del_pointer(type); - break; - - case T_STRING: - Printf(f_header,"static %s %s = \"%s\";\n", SwigType_lstr(type,0), var_name, value); - Setattr(nnode,"name",var_name); - variable(nnode); - break; - - case T_POINTER: case T_ARRAY: case T_REFERENCE: - Printf(f_header,"static %s = %s;\n", SwigType_lstr(type,var_name), value); - Printf(f_header,"static char *%s_char;\n", var_name); - if (CPlusPlus) - Printf(f_init,"\t %s_char = new char[%d];\n",var_name,(int) Len(SwigType_manglestr(type))+ 20); - else - Printf(f_init,"\t %s_char = (char *) malloc(%d);\n",var_name, (int) Len(SwigType_manglestr(type))+ 20); - - t = NewSwigType(T_CHAR); - SwigType_add_pointer(t); - SwigType_remember(type); - Printf(f_init,"\t SWIG_MakePtr(%s_char, (void *) %s, SWIGTYPE%s);\n", - var_name, var_name, SwigType_manglestr(type)); - sprintf(var_name,"%s_char",var_name); - Setattr(nnode,"type",t); - Setattr(nnode,"name",var_name); - variable(nnode); - Delete(t); - break; - - default: - Printf(stderr,"%s:%d. Unsupported constant value.\n", Getfile(node), Getline(node)); - break; + Printv(f_wrappers, "swig_class _wrap_class_", mangled_classname, " = { \"", class_name, + "\", &SWIGTYPE", SwigType_manglestr(t), ",",NIL); + + if (have_constructor) { + Printf(f_wrappers,"%s", Swig_name_wrapper(Swig_name_construct(class_name))); + } else { + Printf(f_wrappers,"0"); } - } - Delete(rvalue); - Delete(nnode); - ReadOnly = OldStatus; -} - -/* ----------------------------------------------------------------------------- - * TCL8::usage_string() - * ----------------------------------------------------------------------------- */ - -char * -TCL8::usage_string(char *iname, SwigType *, ParmList *l) { - static String *temp = 0; - Parm *p; - int i, numopt,pcount; - - if (!temp) temp = NewString(""); - Clear(temp); - if (nspace) { - Printf(temp,"%s::%s", ns_name,iname); - } else { - Printf(temp,"%s ", iname); - } - - /* Now go through and print parameters */ - i = 0; - pcount = ParmList_len(l); - numopt = check_numopt(l); - for (p = l; p; p = Getnext(p)) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); - - /* Only print an argument if not ignored */ - if (!Swig_typemap_search((char*)"ignore",pt,pn)) { - if (i >= (pcount-numopt)) - Putc('?',temp); - /* If parameter has been named, use that. Otherwise, just print a type */ - if (SwigType_type(pt) != T_VOID) { - if (Len(pn) > 0) { - Printf(temp, "%s",pn); - } else { - Printf(temp,"%s", SwigType_str(pt,0)); - } - } - if (i >= (pcount-numopt)) Putc('?',temp); - Putc(' ',temp); - i++; + if (have_destructor) { + Printv(f_wrappers, ", swig_delete_", class_name,NIL); + } else { + Printf(f_wrappers,",0"); } + Printv(f_wrappers, ", swig_", mangled_classname, "_methods, swig_", mangled_classname, "_attributes, swig_", mangled_classname,"_bases };\n", NIL); + Printv(cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, &_wrap_class_", mangled_classname, "},\n", NIL); + Delete(t); + Delete(mangled_classname); + return SWIG_OK; } - return Char(temp); -} -/* ----------------------------------------------------------------------------- - * TCL8::nativefunction(); - * ----------------------------------------------------------------------------- */ -void -TCL8::nativefunction(DOH *node) { - char *name; - char *funcname; + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ - name = GetChar(node,"scriptname"); - funcname = GetChar(node,"name"); + virtual int memberfunctionHandler(Node *n) { + String *name = Getattr(n,"name"); + String *iname = GetChar(n,"sym:name"); - if ((Swig_proto_cmp("f(ClientData,p.Tcl_Interp,int,p.p.Tcl_Obj).int", node) == 0) || - (Swig_proto_cmp("f(ClientData,p.Tcl_Interp,int,a().p.Tcl_Obj).int", node) == 0)) { - Printf(f_init,"\t Tcl_CreateObjCommand(interp, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",name, funcname); - } + String *realname, *rname; - if ((Swig_proto_cmp("f(ClientData,p.Tcl_Interp,int,p.p.char).int", node) == 0) || - (Swig_proto_cmp("f(ClientData,p.Tcl_Interp,int,a().p.char).int", node) == 0)) { - Printf(f_init,"\t Tcl_CreateCommand(interp, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",name, funcname); - } - -} + Language::memberfunctionHandler(n); -/* ----------------------------------------------------------------------------- - * C++ Handling - * ----------------------------------------------------------------------------- */ + realname = iname ? iname : name; + rname = Swig_name_wrapper(Swig_name_member(class_name, realname)); + if (!Getattr(n,"sym:nextSibling")) { + Printv(methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL); + } + Delete(rname); + return SWIG_OK; + } -void -TCL8::cpp_open_class(DOH *node) { - this->Language::cpp_open_class(node); + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ - char *classname = GetChar(node,"name"); - char *rename = GetChar(node,"scriptname"); - char *ctype = GetChar(node,"classtype"); - int strip = GetInt(node,"strip"); - - if (shadow) { - static int included_object = 0; - if (!included_object) { - if (Swig_insert_file("object.swg",f_header) == -1) { - Printf(stderr,"SWIG : Fatal error. Unable to locate 'object.swg' in SWIG library.\n"); - Swig_exit (EXIT_FAILURE); - } - included_object = 1; + virtual int membervariableHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + String *rname; + + Language::membervariableHandler(n); + Printv(attr_tab, tab4, "{ \"-", symname, "\",", NIL); + rname = Swig_name_wrapper(Swig_name_get(Swig_name_member(class_name,symname))); + Printv(attr_tab, rname, ", ", NIL); + Delete(rname); + if (!Getattr(n,"feature:immutable")) { + rname = Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name,symname))); + Printv(attr_tab, rname, "},\n",NIL); + Delete(rname); + } else { + Printf(attr_tab, "0 },\n"); } + return SWIG_OK; + } - attributes = NewString(""); - /* Printf(attributes, "static swig_attribute swig_"); - Printv(attributes, classname, "_attributes[] = {\n", 0); */ - - methods = NewString(""); - /* Printf(methods,"static swig_method swig_"); - Printv(methods, classname, "_methods[] = {\n", 0); */ + /* ------------------------------------------------------------ + * constructorHandler() + * ------------------------------------------------------------ */ - have_constructor = 0; - have_destructor = 0; + virtual int constructorHandler(Node *n) { + Language::constructorHandler(n); + have_constructor = 1; + return SWIG_OK; + } - Delete(class_name); - Delete(class_type); - Delete(real_classname); + /* ------------------------------------------------------------ + * destructorHandler() + * ------------------------------------------------------------ */ - class_name = rename ? NewString(rename) : NewString(classname); - class_type = strip ? NewString("") : NewStringf("%s ",ctype); - real_classname = NewString(classname); + virtual int destructorHandler(Node *n) { + Language::destructorHandler(n); + have_destructor = 1; + destructor_action = Getattr(n,"wrap:action"); + return SWIG_OK; } -} -void -TCL8::cpp_close_class() { - SwigType *t; - String *code = NewString(""); + /* ------------------------------------------------------------ + * validIdentifier() + * ------------------------------------------------------------ */ - this->Language::cpp_close_class(); - if (shadow) { - t = NewStringf("%s%s", class_type, real_classname); - SwigType_add_pointer(t); + virtual int validIdentifier(String *s) { + if (Strchr(s,' ')) return 0; + return 1; + } - if (have_destructor) { - Printv(code, "static void swig_delete_", class_name, "(void *obj) {\n", 0); - if (CPlusPlus) { - Printv(code," delete (", SwigType_str(t,0), ") obj;\n",0); - } else { - Printv(code," free((char *) obj);\n",0); - } - Printf(code,"}\n"); - } + /* ------------------------------------------------------------ + * usage_string() + * ------------------------------------------------------------ */ - Printf(code,"static swig_method swig_"); - Printv(code, real_classname, "_methods[] = {\n", 0); - Printv(code,methods,0); - Printf(code, " {0,0}\n};\n"); - Setattr(class_methods,real_classname,methods); - - Printf(code, "static swig_attribute swig_"); - Printv(code, real_classname, "_attributes[] = {\n", 0); - Printv(code,attributes,0); - Printf(code, " {0,0,0}\n};\n"); - Setattr(class_attributes,real_classname,attributes); + char * + usage_string(char *iname, SwigType *, ParmList *l) { + static String *temp = 0; + Parm *p; + int i, numopt,pcount; - Printv(code, "static swig_class _wrap_class_", class_name, " = { \"", class_name, - "\", &SWIGTYPE", SwigType_manglestr(t), ",",0); - - if (have_constructor) { - Printf(code, "%s", Swig_name_wrapper(Swig_name_construct(class_name))); + if (!temp) temp = NewString(""); + Clear(temp); + if (nspace) { + Printf(temp,"%s::%s", ns_name,iname); } else { - Printf(code,"0"); + Printf(temp,"%s ", iname); } - if (have_destructor) { - Printv(code, ", swig_delete_", class_name,0); - } else { - Printf(code,",0"); + /* Now go through and print parameters */ + i = 0; + pcount = ParmList_len(l); + numopt = 0; /*check_numopt(l); */ + for (p = l; p; p = nextSibling(p)) { + + SwigType *pt = Getattr(p,"type"); + String *pn = Getattr(p,"name"); + /* Only print an argument if not ignored */ + if (!checkAttribute(p,"tmap:in:numinputs","0")) { + if (i >= (pcount-numopt)) + Putc('?',temp); + if (Len(pn) > 0) { + Printf(temp, "%s",pn); + } else { + Printf(temp,"%s", SwigType_str(pt,0)); + } + if (i >= (pcount-numopt)) Putc('?',temp); + Putc(' ',temp); + i++; + } } - Printv(code, ", swig_", real_classname, "_methods, swig_", real_classname, "_attributes };\n", 0); - Printf(f_wrappers,"%s",code); - - Printv(cmd_info, tab4, "{ SWIG_prefix \"", class_name, "\", SwigObjectCmd, &_wrap_class_", class_name, "},\n", 0); + return Char(temp); } - Delete(code); -} - -void TCL8::cpp_memberfunction(DOH *node) { - char *name, *iname; - char *realname; - char temp[1024]; - String *rname; - - this->Language::cpp_memberfunction(node); - if (shadow) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - realname = iname ? iname : name; - /* Add stubs for this member to our class handler function */ +}; - strcpy(temp, Char(Swig_name_member(class_name,realname))); - rname = Getattr(repeatcmd,temp); - if (!rname) rname = Swig_name_wrapper(temp); +/* ---------------------------------------------------------------------- + * swig_tcl() - Instantiate module + * ---------------------------------------------------------------------- */ - Printv(methods, tab4, "{\"", realname, "\", ", rname, "}, \n", 0); - } +extern "C" Language * +swig_tcl(void) { + return new TCL8(); } -void TCL8::cpp_variable(DOH *node) { - char *name, *iname; - char *realname; - char temp[1024]; - String *rname; - this->Language::cpp_variable(node); - if (shadow) { - name = GetChar(node,"name"); - iname = GetChar(node,"scriptname"); - realname = iname ? iname : name; - Printv(attributes, tab4, "{ \"-", realname, "\",", 0); - - /* Try to figure out if there is a wrapper for this function */ - strcpy(temp, Char(Swig_name_get(Swig_name_member(class_name,realname)))); - rname = Getattr(repeatcmd,temp); - if (!rname) rname = Swig_name_wrapper(temp); - Printv(attributes, rname, ", ", 0); - - if (!ReadOnly) { - strcpy(temp, Char(Swig_name_set(Swig_name_member(class_name,realname)))); - rname = Getattr(repeatcmd,temp); - if (!rname) rname = Swig_name_wrapper(temp); - Printv(attributes, rname, "},\n",0); - } else { - Printf(attributes, "0 },\n"); - } - } -} -void -TCL8::cpp_constructor(DOH *node) { - this->Language::cpp_constructor(node); - have_constructor = 1; -} - -void -TCL8::cpp_destructor(DOH *node) { - this->Language::cpp_destructor(node); - have_destructor = 1; -} - -void -TCL8::cpp_inherit(List *bases) { - String *b; - Printf(stdout,"bases = %s\n", bases); - for (b = Firstitem(bases); b; b = Nextitem(bases)) { - Printf(stdout,"base: %s\n", b); - String *s = Getattr(class_methods,b); - if (s) { - Append(methods,s); - } - s = Getattr(class_attributes,b); - if (s) { - Append(attributes,s); - } - } -} diff --git a/Source/Modules1.1/tcl8.h b/Source/Modules1.1/tcl8.h deleted file mode 100644 index 4bafbab6e..000000000 --- a/Source/Modules1.1/tcl8.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Simplified Wrapper and Interface Generator (SWIG) - * - * Author : David Beazley - * - * Department of Computer Science - * University of Chicago - * 1100 E 58th Street - * Chicago, IL 60637 - * beazley@cs.uchicago.edu - * - * Please read the file LICENSE for the copyright and terms by which SWIG - * can be used and distributed. - *******************************************************************************/ - -/************************************************************************** - * class TCL8 - * - * A TCL implementation for Tcl 8.0. Basically the same as the other - * Tcl module, but with different code generation. - **************************************************************************/ - -class TCL8 : public Language { -private: - char *usage_string(char *, SwigType *, ParmList *); - -public : - virtual void parse_args(int, char *argv[]); - virtual void initialize(String *); - virtual void function(DOH *node); - virtual void variable(DOH *node); - virtual void constant(DOH *node); - virtual void close(void); - virtual void nativefunction(DOH *); - virtual void create_command(String *, String *); - - // Stubs for processing C++ classes in Tcl - - virtual void cpp_open_class(DOH *node); - virtual void cpp_close_class(); - virtual void cpp_memberfunction(DOH *); - virtual void cpp_variable(DOH *); - virtual void cpp_constructor(DOH *); - virtual void cpp_destructor(DOH *); - virtual void cpp_inherit(List *bases); - -}; - - - - - - diff --git a/Source/Modules1.1/typepass.cxx b/Source/Modules1.1/typepass.cxx new file mode 100644 index 000000000..3e4f74338 --- /dev/null +++ b/Source/Modules1.1/typepass.cxx @@ -0,0 +1,966 @@ +/* ----------------------------------------------------------------------------- + * typepass.cxx + * + * This module builds all of the internal type information by collecting + * typedef declarations as well as registering classes, structures, and unions. + * This information is needed to correctly handle shadow classes and other + * advanced features. This phase of compilation is also used to perform + * type-expansion. All types are fully qualified with namespace prefixes + * and other information needed for compilation. + * + * This module also handles the %varargs directive by looking for + * "feature:varargs" and substituting ... with an alternative set of + * arguments. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2002. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_typepass_cxx[] = "$Header$"; + +#include "swigmod.h" + +struct normal_node { + Symtab *symtab; + Hash *typescope; + List *normallist; + normal_node *next; +}; + +static normal_node *patch_list = 0; + +class TypePass : public Dispatcher { + Node *inclass; + Node *module; + int importmode; + String *nsname; + Hash *classhash; + List *normalize; + + /* Normalize a type. Replaces type with fully qualified version */ + + void normalize_type(SwigType *ty) { + SwigType *qty; + /*qty = Swig_symbol_type_qualify(ty,0);*/ + /* if (SwigType_istemplate(ty)) { + qty = Swig_symbol_type_qualify(ty,0); + Clear(ty); + Append(ty,qty); + } + */ + + if (CPlusPlus) { + Replaceall(ty,"struct ",""); + Replaceall(ty,"union ",""); + Replaceall(ty,"class ",""); + } + + qty = SwigType_typedef_qualified(ty); + /* Printf(stdout,"%s --> %s\n", ty, qty);*/ + Clear(ty); + Append(ty,qty); + Delete(qty); + } + + /* Normalize a parameter list */ + + void normalize_parms(ParmList *p) { + while (p) { + SwigType *ty = Getattr(p,"type"); + normalize_type(ty); + String *value = Getattr(p,"value"); + if (value) { + Node *n = Swig_symbol_clookup(value,0); + if (n) { + String *q = Swig_symbol_qualified(n); + if (q && Len(q)) { + String *vb = Swig_scopename_last(value); + Clear(value); + Printf(value,"%s::%s", SwigType_namestr(q), vb); + Delete(q); + } + } + } + if (value && SwigType_istemplate(value)) { + String *nv = SwigType_namestr(value); + Setattr(p,"value",nv); + } + p = nextSibling(p); + } + } + + void normalize_later(ParmList *p) { + while (p) { + SwigType *ty = Getattr(p,"type"); + Append(normalize,ty); + p = nextSibling(p); + } + } + + /* Walk through entries in normalize list and patch them up */ + void normalize_list() { + Hash *currentsym = Swig_symbol_current(); + + normal_node *nn = patch_list; + normal_node *np; + while (nn) { + Swig_symbol_setscope(nn->symtab); + SwigType_set_scope(nn->typescope); + SwigType *t; + for (t = Firstitem(nn->normallist); t; t = Nextitem(nn->normallist)) { + normalize_type(t); + } + Delete(nn->normallist); + np = nn->next; + delete(nn); + nn = np; + } + Swig_symbol_setscope(currentsym); + } + + /* generate C++ inheritance type-relationships */ + void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) { + + if (first == cls) return; /* The Marcelo check */ + if (!cls) cls = first; + + List *ilist = Getattr(cls,"bases"); + if (!ilist) { + List *nlist = Getattr(cls,"baselist"); + if (nlist) { + int len = Len(nlist); + int i; + for (i = 0; i < len; i++) { + Node *bcls = 0; + int clsforward = 0; + String *bname = Getitem(nlist,i); + String *sname = bname; + String *tname = 0; + + /* Try to locate the base class. We look in the symbol table and we chase + typedef declarations to get to the base class if necessary */ + Symtab *st = Getattr(cls,"sym:symtab"); + + if (SwigType_istemplate(bname)) { + tname = SwigType_typedef_resolve_all(bname); + sname = tname; + } + while (1) { + String *qsname = SwigType_typedef_qualified(sname); + bcls = Swig_symbol_clookup(qsname,st); + Delete(qsname); + if (bcls) { + if (Strcmp(nodeType(bcls),"class") != 0) { + /* Not a class. The symbol could be a typedef. */ + if (checkAttribute(bcls,"storage","typedef")) { + SwigType *decl = Getattr(bcls,"decl"); + if (!decl || !(Len(decl))) { + sname = Getattr(bcls,"type"); + st = Getattr(bcls,"sym:symtab"); + if (SwigType_istemplate(sname)) { + if (tname) Delete(tname); + tname = SwigType_typedef_resolve_all(sname); + sname = tname; + } + continue; + } + } + if (Strcmp(nodeType(bcls),"classforward") != 0) { + Swig_error(Getfile(bname),Getline(bname),"'%s' is not a class. \n",bname); + } else { + Swig_warning(WARN_TYPE_INCOMPLETE,Getfile(bname),Getline(bname),"Base class '%s' is incomplete.\n", bname); + clsforward = 1; + } + bcls = 0; + } else { + if (Getattr(bcls,"typepass:visit")) { + if (!ilist) ilist = NewList(); + Append(ilist,bcls); + } else { + Swig_error(Getfile(bcls),Getline(bcls),"class '%s' must be defined before it is used as a base class.\n", bname); + } + } + } + break; + } + + if (tname) Delete(tname); + if (!bcls) { + if (!clsforward) { + if (!Getmeta(bname,"already_warned")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname),Getline(bname),"Nothing known about class '%s'. Ignored.\n", SwigType_namestr(bname)); + if (Strchr(bname,'<')) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Maybe you forgot to instantiate '%s' using %%template.\n", SwigType_namestr(bname)); + } + Setmeta(bname,"already_warned","1"); + } + } + SwigType_inherit(clsname,bname, cast); + } + } + } + if (ilist) { + Setattr(cls,"bases",ilist); + } + } + if (!ilist) return; + int len = Len(ilist); + int i; + for (i = 0; i < len; i++) { + Node *n = Getitem(ilist,i); + String *bname = Getattr(n,"name"); + Node *bclass = n; /* Getattr(n,"class"); */ + Hash *scopes = Getattr(bclass,"typescope"); + SwigType_inherit(clsname,bname, cast); + if (!importmode) { + String *btype = Copy(bname); + SwigType_add_pointer(btype); + SwigType_remember(btype); + Delete(btype); + } + if (scopes) { + SwigType_inherit_scope(scopes); + } + /* Set up inheritance in the symbol table */ + Symtab *s = Swig_symbol_current(); + Symtab *st = Getattr(cls,"symtab"); + Swig_symbol_setscope(st); + Swig_symbol_inherit(Getattr(bclass,"symtab")); + Swig_symbol_setscope(s); + + /* Recursively hit base classes */ + String *newcast = NewStringf("(%s *)%s", SwigType_namestr(Getattr(bclass,"name")), cast); + cplus_inherit_types(first,bclass,clsname, newcast); + Delete(newcast); + } + } + + /* Clean overloaded list. Removes templates, friends, ignored, and errors */ + + void clean_overloaded(Node *n) { + Node *nn = Getattr(n,"sym:overloaded"); + Node *first = 0; + int cnt = 0; + while (nn) { + if ((Strcmp(nodeType(nn),"template") == 0) || + (Getattr(nn,"feature:ignore")) || + (Getattr(nn,"error")) || + ((Strcmp(nodeType(nn),"using") == 0) && !firstChild(nn)) || + (checkAttribute(nn,"storage","friend"))) { + /* Remove from overloaded list */ + Node *ps = Getattr(nn,"sym:previousSibling"); + Node *ns = Getattr(nn,"sym:nextSibling"); + if (ps) { + Setattr(ps,"sym:nextSibling",ns); + } + if (ns) { + Setattr(ns,"sym:previousSibling",ps); + } + Delattr(nn,"sym:previousSibling"); + Delattr(nn,"sym:nextSibling"); + Delattr(nn,"sym:overloaded"); + nn = ns; + continue; + } else if ((Strcmp(nodeType(nn),"using") == 0)) { + /* A possibly dangerous parse tree hack. We're going to + cut the parse tree node out and stick in the resolved + using declarations */ + + Node *ps = Getattr(nn,"sym:previousSibling"); + Node *ns = Getattr(nn,"sym:nextSibling"); + Node *un = firstChild(nn); + Node *pn = un; + + if (!first) { + first = un; + } + while (pn) { + Node *ppn = Getattr(pn,"sym:nextSibling"); + Setattr(pn,"sym:overloaded",first); + Setattr(pn,"sym:overname", NewStringf("%s_%d", Getattr(nn,"sym:overname"), cnt++)); + if (ppn) pn = ppn; + else break; + } + if (ps) { + Setattr(ps,"sym:nextSibling",un); + Setattr(un,"sym:previousSibling",ps); + } + if (ns) { + Setattr(ns,"sym:previousSibling", pn); + Setattr(pn,"sym:nextSibling",ns); + } + if (!first) { + first = un; + Setattr(nn,"sym:overloaded",first); + } + } else { + if (!first) first = nn; + Setattr(nn,"sym:overloaded",first); + } + nn = Getattr(nn,"sym:nextSibling"); + } + if (!first || (first && !Getattr(first,"sym:nextSibling"))) { + Delattr(n,"sym:overloaded"); + } + } + +public: + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + importmode = 0; + module = Getattr(n,"module"); + inclass = 0; + normalize = 0; + nsname = 0; + classhash = Getattr(n,"classes"); + emit_children(n); + normalize_list(); + SwigType_set_scope(0); + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * moduleDirective() + * ------------------------------------------------------------ */ + + virtual int moduleDirective(Node *n) { + if (!module) { + module = n; + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * importDirective() + * ------------------------------------------------------------ */ + + virtual int importDirective(Node *n) { + String *oldmodule = module; + int oldimport = importmode; + importmode = 1; + module = 0; + emit_children(n); + importmode = oldimport; + module = oldmodule; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * includeDirective() + * externDirective() + * extendDirective() + * ------------------------------------------------------------ */ + + virtual int includeDirective(Node *n) { return emit_children(n); } + virtual int externDeclaration(Node *n) { return emit_children(n); } + virtual int extendDirective(Node *n) { return emit_children(n); } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *tdname = Getattr(n,"tdname"); + String *unnamed = Getattr(n,"unnamed"); + String *storage = Getattr(n,"storage"); + String *kind = Getattr(n,"kind"); + Node *oldinclass = inclass; + List *olist = normalize; + Symtab *symtab; + String *nname = 0; + String *fname = 0; + String *scopename = 0; + + normalize = NewList(); + + if (name) { + + if (SwigType_istemplate(name)) { + // We need to fully resolve the name to make templates work correctly */ + Node *cn; + fname = SwigType_typedef_resolve_all(name); + if (Strcmp(fname,name) != 0) { + cn = Swig_symbol_clookup_local(fname,0); + if ((!cn) || (Strcmp(nodeType(cn),"template") == 0)) { + Swig_symbol_cadd(fname,n); + SwigType_typedef_class(fname); + scopename = Copy(fname); + } else { + Swig_warning(WARN_TYPE_REDEFINED,Getfile(n),Getline(n),"Template '%s' was already wrapped as '%s' at %s:%d.\n", + SwigType_namestr(name), SwigType_namestr(Getattr(cn,"name")), Getfile(cn), Getline(cn)); + scopename = 0; + } + } else { + Swig_symbol_cadd(fname,n); + SwigType_typedef_class(fname); + scopename = Copy(fname); + } + } else { + if ((CPlusPlus) || (unnamed)) { + SwigType_typedef_class(name); + } else { + SwigType_typedef_class(NewStringf("%s %s", kind, name)); + } + scopename = Copy(name); + } + } else { + scopename = 0; + } + + Setattr(n,"typepass:visit","1"); + + /* Need to set up a typedef if unnamed */ + if (unnamed && tdname && (Cmp(storage,"typedef") == 0)) { + SwigType_typedef(unnamed,tdname); + } + + if (nsname) { + nname = NewStringf("%s::%s", nsname, name); + } + SwigType_new_scope(scopename); + SwigType_attach_symtab(Getattr(n,"symtab")); + + /* Inherit type definitions into the class */ + if (name) { + cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name)); + } + + inclass = n; + symtab = Swig_symbol_setscope(Getattr(n,"symtab")); + emit_children(n); + Swig_symbol_setscope(symtab); + + Hash *ts = SwigType_pop_scope(); + Setattr(n,"typescope",ts); + Setattr(n,"module",module); + + /* Normalize deferred types */ + { + normal_node *nn = new normal_node(); + nn->normallist = normalize; + nn->symtab = Getattr(n,"symtab"); + nn->next = patch_list; + nn->typescope = Getattr(n,"typescope"); + patch_list = nn; + } + + normalize = olist; + + inclass = oldinclass; + + /* If in a namespace, patch the class name */ + if (nname) { + Setattr(n,"name",nname); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * namespaceDeclaration() + * ------------------------------------------------------------ */ + + virtual int templateDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *ttype = Getattr(n,"templatetype"); + if (Strcmp(ttype,"class") == 0) { + String *rname = SwigType_typedef_resolve_all(name); + SwigType_typedef_class(rname); + Delete(rname); + } else if (Strcmp(ttype,"classforward") == 0) { + String *rname = SwigType_typedef_resolve_all(name); + SwigType_typedef_class(rname); + Delete(rname); + /* SwigType_typedef_class(name);*/ + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classforwardDeclaration() + * ------------------------------------------------------------ */ + + virtual int classforwardDeclaration(Node *n) { + + /* Temporary hack. Can't do inside a class because it breaks + C nested structure wrapping */ + + if ((!inclass) || (CPlusPlus)) { + String *name = Getattr(n,"name"); + String *nname; + SwigType_typedef_class(name); + if (nsname) { + nname = NewStringf("%s::%s", nsname, name); + Setattr(n,"name",nname); + } + + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * namespaceDeclaration() + * ------------------------------------------------------------ */ + + virtual int namespaceDeclaration(Node *n) { + Symtab *symtab; + String *name = Getattr(n,"name"); + String *alias = Getattr(n,"alias"); + List *olist = normalize; + normalize = NewList(); + if (alias) { + Typetab *ts = Getattr(n,"typescope"); + if (!ts) { + Node *ns; + /* Create a empty scope for the alias */ + ns = Getattr(n,"namespace"); + if (ns) { + SwigType_scope_alias(name, Getattr(ns,"typescope")); + } + ts = Getattr(ns,"typescope"); + Setattr(n,"typescope",ts); + } + /* Namespace alias */ + return SWIG_OK; + } else { + if (name) { + Node *nn = Swig_symbol_clookup(name,n); + Hash *ts = Getattr(nn,"typescope"); + if (!ts) { + SwigType_new_scope(name); + SwigType_attach_symtab(Getattr(n,"symtab")); + } else { + SwigType_set_scope(ts); + } + } + String *oldnsname = nsname; + nsname = Swig_symbol_qualified(Getattr(n,"symtab")); + symtab = Swig_symbol_setscope(Getattr(n,"symtab")); + emit_children(n); + Swig_symbol_setscope(symtab); + + if (name) { + Hash *ts = SwigType_pop_scope(); + Setattr(n,"typescope",ts); + } + + /* Normalize deferred types */ + { + normal_node *nn = new normal_node(); + nn->normallist = normalize; + nn->symtab = Getattr(n,"symtab"); + nn->next = patch_list; + nn->typescope = Getattr(n,"typescope"); + patch_list = nn; + } + normalize = olist; + + Delete(nsname); + nsname = oldnsname; + return SWIG_OK; + } + } + + /* ------------------------------------------------------------ + * cDeclaration() + * ------------------------------------------------------------ */ + + virtual int cDeclaration(Node *n) { + + if (NoExcept) { + Delattr(n,"throws"); + } + + /* Search for var args */ + if (Getattr(n,"feature:varargs")) { + ParmList *v = Getattr(n,"feature:varargs"); + Parm *p = Getattr(n,"parms"); + Parm *pp = 0; + while (p) { + SwigType *t = Getattr(p,"type"); + if (Strcmp(t,"v(...)") == 0) { + if (pp) { + set_nextSibling(pp,Copy(v)); + } else { + Setattr(n,"parms", Copy(v)); + } + break; + } + pp = p; + p = nextSibling(p); + } + } + + /* Normalize types. */ + SwigType *ty = Getattr(n,"type"); + normalize_type(ty); + SwigType *decl = Getattr(n,"decl"); + if (decl) { + normalize_type(decl); + } + normalize_parms(Getattr(n,"parms")); + normalize_parms(Getattr(n,"throws")); + + if (checkAttribute(n,"storage","typedef")) { + String *name = Getattr(n,"name"); + ty = Getattr(n,"type"); + decl = Getattr(n,"decl"); + SwigType *t = Copy(ty); + { + /* If the typename is qualified, make sure the scopename is fully qualified when making a typedef */ + if (Swig_scopename_check(t)) { + String *base, *prefix, *qprefix; + base = Swig_scopename_last(t); + prefix = Swig_scopename_prefix(t); + qprefix = SwigType_typedef_qualified(prefix); + Delete(t); + t = NewStringf("%s::%s", qprefix,base); + Delete(base); + Delete(prefix); + Delete(qprefix); + } + } + SwigType_push(t,decl); + if (CPlusPlus) { + Replaceall(t,"struct ",""); + Replaceall(t,"union ",""); + Replaceall(t,"class ",""); + } + SwigType_typedef(t,name); + } + /* If namespaces are active. We need to patch the name with a namespace prefix */ + if (nsname && !inclass) { + String *name = Getattr(n,"name"); + if (name) { + String *nname = NewStringf("%s::%s", nsname, name); + Setattr(n,"name", nname); + Delete(nname); + } + } + clean_overloaded(n); + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * constructorDeclaration() + * ------------------------------------------------------------ */ + + virtual int constructorDeclaration(Node *n) { + if (NoExcept) { + Delattr(n,"throws"); + } + + /* Search for var args */ + if (Getattr(n,"feature:varargs")) { + ParmList *v = Getattr(n,"feature:varargs"); + Parm *p = Getattr(n,"parms"); + Parm *pp = 0; + while (p) { + SwigType *t = Getattr(p,"type"); + if (Strcmp(t,"v(...)") == 0) { + if (pp) { + set_nextSibling(pp,Copy(v)); + } else { + Setattr(n,"parms", Copy(v)); + } + break; + } + pp = p; + p = nextSibling(p); + } + } + normalize_parms(Getattr(n,"parms")); + normalize_parms(Getattr(n,"throws")); + + /* If in a namespace, patch the class name */ + if (nsname) { + String *nname = NewStringf("%s::%s", nsname, Getattr(n,"name")); + Setattr(n,"name",nname); + } + clean_overloaded(n); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * destructorDeclaration() + * ------------------------------------------------------------ */ + + virtual int destructorDeclaration(Node *n) { + /* If in a namespace, patch the class name */ + if (nsname) { + String *nname = NewStringf("%s::%s", nsname, Getattr(n,"name")); + Setattr(n,"name",nname); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constantDirective() + * ------------------------------------------------------------ */ + + virtual int constantDirective(Node *n) { + SwigType *ty = Getattr(n,"type"); + if (ty) { + Setattr(n,"type",SwigType_typedef_qualified(ty)); + } + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * enumDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumDeclaration(Node *n) { + String *name = Getattr(n,"name"); + if (name) { + SwigType *t = NewStringf("enum %s", name); + SwigType_typedef(t,name); + Delete(t); + } + emit_children(n); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * enumvalueDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumvalueDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *value = Getattr(n,"value"); + if (!value) value = name; + if (Strcmp(value,name) == 0) { + String *new_value; + if ((nsname) || (inclass)) { + new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value); + } else { + new_value = NewString(value); + } + Setattr(n,"value",new_value); + Delete(new_value); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * usingDeclaration() + * ------------------------------------------------------------ */ + + virtual int usingDeclaration(Node *n) { + if (Getattr(n,"namespace")) { + /* using namespace id */ + + /* For a namespace import. We set up inheritance in the type system */ + Node *ns = Getattr(n,"node"); + if (ns) { + Typetab *ts = Getattr(ns,"typescope"); + if (ts) { + SwigType_using_scope(ts); + } + } + return SWIG_OK; + } else { + Node *ns; + /* using id */ + + if (Getattr(n,"sym:symtab")) { + ns = Swig_symbol_clookup(Getattr(n,"uname"), Getattr(n,"sym:symtab")); + } else { + ns = 0; + } + if (!ns) { + if (!Getattr(n,"access") || ((Strcmp(Getattr(n,"access"),"public") == 0))) { + Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n,"uname"))); + } + } else { + + /* Only a single symbol is being used. There are only a few symbols that + we actually care about. These are typedef, class declarations, and enum */ + + String *ntype = nodeType(ns); + if (Strcmp(ntype,"cdecl") == 0) { + if (checkAttribute(ns,"storage","typedef")) { + /* A typedef declaration */ + String *uname = Getattr(n,"uname"); + SwigType_typedef_using(uname); + } else { + /* A normal C declaration. */ + if ((inclass) && (!Getattr(n,"feature:ignore")) && (Getattr(n,"sym:name"))) { + Node *c = ns; + Node *unodes = 0, *last_unodes = 0; + int ccount = 0; + String *symname = Getattr(n,"sym:name"); + while (c) { + if (Strcmp(nodeType(c),"cdecl") == 0) { + if (!(checkAttribute(c,"storage","static") + || checkAttribute(c,"storage","typedef") + || checkAttribute(c,"storage","friend") + || (Getattr(c,"feature:extend") && !Getattr(c,"code")) + || Getattr(c,"feature:ignore"))) { + + String *csymname = Getattr(c,"sym:name"); + if (!csymname || (Strcmp(csymname,symname) == 0)) { + /* Check for existence in overload list already */ + { + String *decl = Getattr(c,"decl"); + Node *over = Getattr(n,"sym:overloaded"); + int match = 0; + while (over) { + String *odecl = Getattr(over,"decl"); + if (Cmp(decl, odecl) == 0) { + match = 1; + break; + } + over = Getattr(over,"sym:nextSibling"); + } + if (match) { + c = Getattr(c,"csym:nextSibling"); + continue; + } + } + Node *nn = copyNode(c); + if (!Getattr(nn,"sym:name")) Setattr(nn,"sym:name", symname); + + if (!Getattr(nn,"feature:ignore")) { + Setattr(nn,"parms",CopyParmList(Getattr(c,"parms"))); + ccount++; + if (!last_unodes) { + last_unodes = nn; + unodes = nn; + } else { + Setattr(nn,"previousSibling",last_unodes); + Setattr(last_unodes,"nextSibling", nn); + Setattr(nn,"sym:previousSibling", last_unodes); + Setattr(last_unodes,"sym:nextSibling", nn); + Setattr(nn,"sym:overloaded", unodes); + Setattr(unodes,"sym:overloaded", unodes); + last_unodes = nn; + } + } else { + Delete(nn); + } + } + } + } + c = Getattr(c,"csym:nextSibling"); + } + if (unodes) { + set_firstChild(n,unodes); + if (ccount > 1) { + if (!Getattr(n,"sym:overloaded")) { + Setattr(n,"sym:overloaded",n); + Setattr(n,"sym:overname","_SWIG_0"); + } + } + } + } + } + } else if ((Strcmp(ntype,"class") == 0) || ((Strcmp(ntype,"classforward") == 0))) { + /* We install the using class name as kind of a typedef back to the original class */ + String *uname = Getattr(n,"uname"); + /* Import into current type scope */ + SwigType_typedef_using(uname); + } else if (Strcmp(ntype,"enum") == 0) { + SwigType_typedef_using(Getattr(n,"uname")); + } + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * typemapDirective() + * ------------------------------------------------------------ */ + + virtual int typemapDirective(Node *n) { + if (inclass || nsname) { + Node *items = firstChild(n); + while (items) { + Parm *pattern = Getattr(items,"pattern"); + Parm *parms = Getattr(items,"parms"); + normalize_later(pattern); + normalize_later(parms); + items = nextSibling(items); + } + } + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * typemapcopyDirective() + * ------------------------------------------------------------ */ + + virtual int typemapcopyDirective(Node *n) { + if (inclass || nsname) { + Node *items = firstChild(n); + ParmList *pattern = Getattr(n,"pattern"); + normalize_later(pattern); + while (items) { + ParmList *npattern = Getattr(items,"pattern"); + normalize_later(npattern); + items = nextSibling(items); + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * applyDirective() + * ------------------------------------------------------------ */ + + virtual int applyDirective(Node *n) { + if (inclass || nsname) { + ParmList *pattern = Getattr(n,"pattern"); + normalize_later(pattern); + Node *items = firstChild(n); + while (items) { + Parm *apattern = Getattr(items,"pattern"); + normalize_later(apattern); + items = nextSibling(items); + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * clearDirective() + * ------------------------------------------------------------ */ + + virtual int clearDirective(Node *n) { + if (inclass || nsname) { + Node *p; + for (p = firstChild(n); p; p = nextSibling(p)) { + ParmList *pattern = Getattr(p,"pattern"); + normalize_later(pattern); + } + } + return SWIG_OK; + } +}; + +void Swig_process_types(Node *n) { + if (!n) return; + TypePass *t = new TypePass; + t->top(n); + delete t; +} + + + + + + + diff --git a/Source/Modules1.1/xml.cxx b/Source/Modules1.1/xml.cxx index e3891b1c6..261f3e348 100644 --- a/Source/Modules1.1/xml.cxx +++ b/Source/Modules1.1/xml.cxx @@ -1,304 +1,318 @@ -/* ----------------------------------------------------------------------------- - * xml.cxx +/* ----------------------------------------------------------------------------- + * Xml.cxx * - * Generate XML representation + * A web-base parse tree Xml using SWILL. This is an optional + * feature that's normally disabled. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) * - * Author(s) : SWIG core: David Beazley (beazley@cs.uchicago.edu) - * XML module: Klaus Wiederaenders (kwconsulting@compuserve.com) - * Copyright (C) 1999-2001. The University of Chicago - * See the file LICENSE for information on usage and redistribution. + * Copyright (C) 2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -/* DB: I had to take some features related to package naming out of this to - get the new type system to work. These need to be put back in at some - point. */ - -static char cvsroot[] = "$Header$"; +char cvsroot_xml_cxx[] = "$Header$"; +static const char *usage = "\ +XML Options (available with -xml)\n\ + -xml output.xml - Use output.xml as output file (extension .xml mandatory)\n\ + -xmllang lang - Typedef language.\n\n"; -#include <time.h> -#include "swig11.h" -#include "xml.h" -#include "dohobj.h" +#include "swigmod.h" -static char *usage = (char*)"\ -XML Options (available with -xml)\n\ - -o filename - Output file\n\ - -dtd filename - Stylsheet file\n\n"; - -static String *dtdfile = 0; -static String *xmlfile = 0; -static int indent = 0; -static const int indentsize = 2; -static const char * indentchar = " "; -FILE *f_xml = 0; -extern "C" +//static Node *view_top = 0; +static File *out = 0; + +class XML +: public Language { -static String * emit_indent( int indent ) -{ - String *out; - out = NewString(""); - for(int iX = 0; iX < indent; iX ++ ) - Append( out, indentchar ); - return Swig_temp_result(out); -} -void xml(DOH *node) -{ - if (ObjGetMark(node)) - { - Printf( f_xml, "%s<swigxml:node ident=\"ID%0X\" />\n", - emit_indent( indent ), node); - return; - } - indent += indentsize; - ObjSetMark(node, 1); - while (node) - { - DohBase * base = (DohBase *) node; - if( !base ) - return; - switch( base->type ) - { - case 1: - Replace( node, "<", "<", DOH_REPLACE_ANY ); - Replace( node, "&", "&", DOH_REPLACE_ANY ); - Printf( f_xml, "%s", node ); - break; - case 2: - { - indent += indentsize; - DOH *item; - - item = Firstitem(node); - while (item) - { - DohBase * itembase = (DohBase *) item; - if( itembase && itembase->type == DOHTYPE_STRING ) - { - Printf( f_xml, - "%s<swigxml:item name=\"%s\" ident=\"ID%0X\" />\n", - emit_indent( indent ), Char( item ), item ); - } - else - { - Printf( f_xml, "%s<swigxml:item ident=\"ID%0X\">\n", - emit_indent( indent ), item ); - xml( item ); - Printf( f_xml, "%s</swigxml:item>\n", - emit_indent( indent ) ); - - } - item = Nextitem(node); - } - indent -= indentsize; - break; - } - case 3: - { - String * none = NewString("swigxml:none"); - DOH * tag = Getattr( node, "tag" ); - if( !tag ) - { - /* - ObjSetMark(node, 0); - Printf( f_xml, "------- %s\n", Char( Str( node ))); - ObjSetMark(node, 1); - */ - tag = none; - } - DOH * name = Getattr( node, "name" ); - char * ttt = Char( tag ); - - if( tag && ::strchr( Char(tag), ':' ) == 0 ) - Insert( tag, 0, "swigxml:" ); - // check for simple node - int length = Len( node ); - if( Getattr( node, "tag" ) ) - --length; - if( Getattr( node, "prev" ) ) - --length; - if( Getattr( node, "next" ) ) - --length; - if( Getattr( node, "parent" ) ) - --length; - if( Getattr( node, "last" ) ) - --length; - if( length == 1 && name ) - { // Yes, it's simple - if( Len( name) ) - Printf( f_xml, "%s<%s name=\"%s\" ident=\"ID%0X\" />\n", - emit_indent( indent ), Char( tag ), Char( name ), - node ); - else - Printf( f_xml, "%s<%s ident=\"ID%0X\" />\n", - emit_indent( indent ), Char( tag ), node ); - Delete( none ); - break; - } - if( Len( name) ) - Printf( f_xml, "%s<%s name=\"%s\" ident=\"ID%0X\">\n", - emit_indent( indent ), Char( tag ), Char( name ), node ); - else - Printf( f_xml, "%s<%s ident=\"ID%0X\">\n", - emit_indent( indent ), Char( tag ), node ); - indent += indentsize; - - DOH * key = Firstkey(node); - while (key) - { - char * kkkk = Char( key ); - DOH * attr = Getattr( node, key ); - char * aaaa = Char( Getattr( node, key ) ); - DohBase * attrbase = (DohBase *) attr; - if( ::strcmp( Char( key ), "tag") - && ::strcmp( Char( key ), "code") - && ::strcmp( Char( key ), "name") - && attrbase && attrbase->type == DOHTYPE_STRING) - { - Replace( attr, "\"", """, DOH_REPLACE_ANY ); - Printf( f_xml, - "%s<swigxml:%s string=\"%s\" ident=\"ID%0X\" />\n", - emit_indent( indent ), Char( key ), Char( attr ), - attr ); - } - else - { - if( ::strcmp( Char( key ), "prev" ) - && ::strcmp( Char( key ), "next" ) - && ::strcmp( Char( key ), "parent" ) - && ::strcmp( Char( key ), "tag" ) - && ::strcmp( Char( key ), "name" ) - && ::strcmp( Char( key ), "last" ) ) - { - Printf( f_xml, "%s<swigxml:%s ident=\"ID%0X\">\n", - emit_indent( indent ), Char( key ), key ); - xml( attr ); - Printf( f_xml, "%s</swigxml:%s>\n", - emit_indent( indent ), Char( key ) ); - } - - } - key = Nextkey(node); - } - indent -= indentsize; - Printf( f_xml, "%s</%s>\n", emit_indent( indent ), Char( tag ) ); - Delete( none ); - break; - } - case 4: - Printf( f_xml, "%s ", "DOHTYPE_VOID" ); - break; - case 5: - Printf( f_xml, "%s ", "DOHTYPE_FILE" ); - break; - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - Printf( f_xml, "%d ", base->type ); - ; - } - ObjSetMark(node, 0); - node = Swig_next(node); - } - indent -= indentsize; -} +public: -int xml_init(int argc, char *argv[]) -{ - int i; - int help = 0; - - // Get options - for (i = 1; i < argc; i++) - { - if (argv[i]) - { - if(strcmp(argv[i],"-xml") == 0) - { - if (argv[i+1]) - { - xmlfile = NewString(argv[i+1]); - // don't do this: Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } - else - { - Swig_arg_error(); - } - continue; - } - if(strcmp(argv[i],"-dtd") == 0) - { - if (argv[i+1]) - { - dtdfile = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } - else - { - Swig_arg_error(); - } - continue; - } - if (strcmp(argv[i],"-help") == 0) - { - fputs(usage,stderr); - Swig_mark_arg(i); - help = 1; - } - } - } - - if (help) return 0; - Preprocessor_define((void *) "SWIGXML 1", 0); - if( ! Swig_swiglib_get() ) - Swig_swiglib_set("xml"); - - return 0; -} + int indent_level; + long id; + XML() + : indent_level( 0 ) + , id( 0 ) + { + } -DOH *xml_run(DOH *node) -{ - time_t now; - time( &now ); - char buffer[32]; - ::strcpy( buffer, ctime(&now)); - buffer[24] = '\0'; - char * filename = Char(xmlfile); - if ((f_xml = fopen( filename,"w")) == 0) { - fprintf(stderr,"Unable to open %s\n", filename); - Swig_exit(1); - } - Printf( f_xml, "<!-- Generated by Swig XML at %s -->\n", buffer ); - - if( dtdfile ) - { - Printf( f_xml, "<!DOCTYPE swigxml:swig SYSTEM \"%s\">\n", dtdfile); - } - - Printf( f_xml, "<swigxml:swig" - " name=\"namespaces\"" - " xmlns:swigxml=\"http://jniplusplus.sourceforge.net\"" - " xmlns:swig=\"http://swig.sourceforge.net\"" - " xmlns:c=\"http://www.ansi.org\"" - " ident=\"ID000000\">\n" ); - xml(node); - Printf( f_xml, "</swigxml:swig>\n" ); - - fclose(f_xml); - return node; -} + virtual ~XML() + { + } + + virtual void main(int argc, char *argv[]) + { + SWIG_typemap_lang("xml"); + for( int iX = 0; iX < argc; iX++ ) + { + if( strcmp( argv[iX], "-xml" ) == 0 ) + { + char * extension = argv[iX+1]+strlen(argv[iX+1])-4; + if( strcmp( extension, ".xml" ) ) + continue; + iX++; + Swig_mark_arg (iX); + String * outfile = NewString( argv[iX] ); + out = NewFile(outfile,"w"); + if (!out) + { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + continue; + } + if( strcmp( argv[iX], "-xmllang" ) == 0 ) + { + Swig_mark_arg (iX); + iX++; + SWIG_typemap_lang(argv[iX]); + Swig_mark_arg (iX); + continue; + } + if( strcmp( argv[iX], "-help" ) == 0 ) + { + fputs( usage, stderr ); + } + } + } + + /* Top of the parse tree */ + + virtual int top(Node *n) + { + if( out == 0 ) + { + String *outfile = Getattr(n,"outfile"); + Replaceall(outfile,"_wrap.cxx", ".xml"); + out = NewFile(outfile,"w"); + if (!out) + { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + } + Printf( out, "<?xml version=\"1.0\" ?> \n" ); + Xml_print_tree(n); + return SWIG_OK; + } + + + + void print_indent(int l) + { + int i; + for (i = 0; i < indent_level; i++) + { + Printf(out, " "); + } + if (l) + { + Printf(out, " "); + } + } + + void Xml_print_tree(DOH *obj) + { + while (obj) + { + Xml_print_node(obj); + obj = nextSibling(obj); + } + } + + void Xml_print_attributes(Node * obj) + { + String *k; + indent_level += 4; + print_indent(0); + Printf( out, "<attributelist id=\"%ld\" addr=\"%x\" >\n", ++id, obj ); + indent_level += 4; + + k = Firstkey(obj); + while (k) + { + if ((Cmp(k,"nodeType") == 0) + || (Cmp(k,"firstChild") == 0) + || (Cmp(k,"lastChild") == 0) + || (Cmp(k,"parentNode") == 0) + || (Cmp(k,"nextSibling") == 0) + || (Cmp(k,"previousSibling") == 0) + || (*(Char(k)) == '$')) + { + /* Do nothing */ + } + else if (Cmp(k,"module") == 0) + { + Xml_print_module( Getattr(obj,k) ); + } + else if (Cmp(k,"baselist") == 0) + { + Xml_print_baselist( Getattr(obj,k) ); + } + else if (Cmp(k,"typescope") == 0) + { + Xml_print_typescope( Getattr(obj,k) ); + } + else if (Cmp(k,"typetab") == 0) + { + Xml_print_typetab( Getattr(obj,k) ); + } + else if (Cmp(k,"kwargs") == 0) + { + Xml_print_kwargs( Getattr(obj,k) ); + } + else if (Cmp(k,"parms") == 0 || Cmp(k, "pattern") == 0 ) + { + Xml_print_parmlist( Getattr(obj,k) ); + } + else + { + DOH *o; + print_indent(0); + if (DohIsString(Getattr(obj,k))) + { + o = Str(Getattr(obj,k)); + Replaceall( k, ":", "_" ); + Replaceall( o, "<", "<" ); + Replaceall( o, "&", "&" ); + Replaceall( o, "\"", """ ); + Replaceall( o, "\\", "\\\\" ); + Printf(out,"<attribute name=\"%s\" value=\"%s\" id=\"%ld\" addr=\"%x\" />\n", k, o, ++id, o ); + Delete(o); + } + else + { + o = Getattr(obj,k); + Replaceall( k, ":", "_" ); + Printf(out,"<attribute name=\"%s\" value=\"%x\" id=\"%ld\" addr=\"%x\" />\n", k, o, ++id, o ); + } + } + k = Nextkey(obj); + } + indent_level -= 4; + print_indent(0); + Printf( out, "</attributelist >\n" ); + indent_level -= 4; + } + void Xml_print_node(Node *obj) + { + Node *cobj; + + print_indent(0); + Printf(out,"<%s id=\"%ld\" addr=\"%x\" >\n", nodeType(obj), ++id, obj); + Xml_print_attributes( obj ); + cobj = firstChild(obj); + if (cobj) + { + indent_level += 4; + Printf(out,"\n"); + Xml_print_tree(cobj); + indent_level -= 4; + } + else + { + print_indent(1); + Printf(out,"\n"); + } + print_indent(0); + Printf(out,"</%s >\n", nodeType(obj)); + } + + + void Xml_print_parmlist(ParmList *p) + { + + print_indent(0); + Printf( out, "<parmlist id=\"%ld\" addr=\"%x\" >\n", ++id, p ); + indent_level += 4; + while(p) + { + print_indent(0); + Printf( out, "<parm id=\"%ld\">\n", ++id ); + Xml_print_attributes( p ); + print_indent(0); + Printf( out, "</parm >\n" ); + p = nextSibling(p); + } + indent_level -= 4; + print_indent(0); + Printf( out, "</parmlist >\n" ); + } + + void Xml_print_baselist(List *p) + { + + print_indent(0); + Printf( out, "<baselist id=\"%ld\" addr=\"%x\" >\n", ++id, p ); + indent_level += 4; + String *s; + for (s = Firstitem(p); s; s = Nextitem(p)) + { + print_indent(0); + Printf( out, "<base name=\"%s\" id=\"%ld\" addr=\"%x\" />\n", s, ++id, s ); + } + indent_level -= 4; + print_indent(0); + Printf( out, "</baselist >\n" ); + } + + void Xml_print_module(Node *p) + { + + print_indent(0); + Printf( out, "<attribute name=\"module\" value=\"%s\" id=\"%ld\" addr=\"%x\" />\n", Getattr( p, "name"), ++id, p ); + } + + void Xml_print_kwargs(Hash *p) + { + Xml_print_hash( p, "kwargs" ); + } + + void Xml_print_typescope(Hash *p) + { + + Xml_print_hash( p, "typescope" ); + } + + void Xml_print_typetab(Hash *p) + { + + Xml_print_hash( p, "typetab" ); + } + + + void Xml_print_hash(Hash *p, const char * markup) + { + + print_indent(0); + Printf( out, "<%s id=\"%ld\" addr=\"%x\" >\n", markup, ++id, p ); + Xml_print_attributes( p ); + indent_level += 4; + Node * n = Firstitem( p ); + while(n) + { + print_indent(0); + Printf( out, "<%ssitem id=\"%ld\" addr=\"%x\" >\n", markup, ++id, n ); + Xml_print_attributes( n ); + Printf( out, "</%ssitem >\n", markup ); + print_indent(0); + Printf( out, " />\n" ); + n = Nextkey(p); + } + indent_level -= 4; + print_indent(0); + Printf( out, "</%s >\n", markup ); + } + +}; + + +extern "C" +{ + Language * swig_xml( void ) + { + return new XML(); + } } diff --git a/Source/Modules1.1/xml.dtd b/Source/Modules1.1/xml.dtd deleted file mode 100644 index 68e40e33e..000000000 --- a/Source/Modules1.1/xml.dtd +++ /dev/null @@ -1,119 +0,0 @@ -<!ELEMENT swig:top (swigxml:child)> -<!ATTLIST swig:top name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swig:pragma (swigxml:value,swigxml:lang?)> -<!ATTLIST swig:pragma name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swig:file ((swigxml:type|swigxml:child)+)> -<!ATTLIST swig:file name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swig:module EMPTY> -<!ATTLIST swig:module name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swig:insert (swigxml:code,swigxml:section?,swigxml:method?,swigxml:type?)> -<!ATTLIST swig:insert name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swig:types (swigxml:parms)> -<!ATTLIST swig:types name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swig:typemap (swigxml:parms?,(swigxml:srctype|swigxml:code),swigxml:method,swigxml:type,swigxml:lang?,swigxml:srcname?)> -<!ATTLIST swig:typemap name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swig:constant (swigxml:value,swigxml:type?)> -<!ATTLIST swig:constant name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swig:apply (swigxml:parms?,swigxml:type)> -<!ATTLIST swig:apply name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swig:addmethods (swigxml:child)> -<!ATTLIST swig:addmethods name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT c:class ((swigxml:child|swigxml:classtype|swigxml:namespace|swigxml:bases|swigxml:scriptname|swigxml:symbols|swigxml:altname)+)> -<!ATTLIST c:class name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:destructor (swigxml:code?,swigxml:storage?)> -<!ATTLIST c:destructor name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:function (swigxml:abstract?,swigxml:parms?,swigxml:code?,swigxml:storage?,swigxml:type)> -<!ATTLIST c:function name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:variable (swigxml:storage?,swigxml:value?,swigxml:type)> -<!ATTLIST c:variable name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:access EMPTY> -<!ATTLIST c:access name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:typedef (swigxml:type)> -<!ATTLIST c:typedef name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:enum (swigxml:child)> -<!ATTLIST c:enum name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT c:enumvalue (swigxml:value?)> -<!ATTLIST c:enumvalue name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:child ((swig:addmethods|swig:apply|swig:constant|swig:types|swig:insert|swig:file|swig:module|swig:typemap|swig:pragma|c:class|c:destructor|c:function|c:access|c:variable|c:typedef|c:enum|c:enumvalue)+)> -<!ATTLIST swigxml:child name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:swig (swig:top)> -<!ATTLIST swigxml:swig name CDATA #REQUIRED xmlns:swigxml CDATA #REQUIRED xmlns:swig CDATA #REQUIRED xmlns:c CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:type EMPTY> -<!ATTLIST swigxml:type name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:code (#PCDATA)> -<!ATTLIST swigxml:code name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:method EMPTY> -<!ATTLIST swigxml:method name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:value EMPTY> -<!ATTLIST swigxml:value name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:lang EMPTY> -<!ATTLIST swigxml:lang name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:parms (swigxml:parm+|swigxml:none+)> -<!ATTLIST swigxml:parms name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:parm (swigxml:value?,swigxml:type)> -<!ATTLIST swigxml:parm name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:storage EMPTY> -<!ATTLIST swigxml:storage name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:classtype EMPTY> -<!ATTLIST swigxml:classtype name CDATA #IMPLIED string (struct|class|union) #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:namespace EMPTY> -<!ATTLIST swigxml:namespace name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:bases (swigxml:item+)> -<!ATTLIST swigxml:bases name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:item EMPTY> -<!ATTLIST swigxml:item name CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:node EMPTY> -<!ATTLIST swigxml:node ident CDATA #REQUIRED> - -<!ELEMENT swigxml:scriptname EMPTY> -<!ATTLIST swigxml:scriptname name CDATA #REQUIRED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:abstract EMPTY> -<!ATTLIST swigxml:abstract name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:section EMPTY> -<!ATTLIST swigxml:section name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:srctype EMPTY> -<!ATTLIST swigxml:srctype name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:srcname EMPTY> -<!ATTLIST swigxml:srcname name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:none (swigxml:type)> -<!ATTLIST swigxml:none name CDATA #IMPLIED ident CDATA #REQUIRED> - -<!ELEMENT swigxml:altname EMPTY> -<!ATTLIST swigxml:altname name CDATA #IMPLIED string CDATA #REQUIRED ident CDATA #REQUIRED> diff --git a/Source/Modules1.1/xml.h b/Source/Modules1.1/xml.h deleted file mode 100644 index 79532957c..000000000 --- a/Source/Modules1.1/xml.h +++ /dev/null @@ -1,18 +0,0 @@ -/**************************************************************************** - * Simplified Wrapper and Interface Generator (SWIG) - * - * Author : David Beazley - * - * Department of Computer Science - * University of Chicago - * 1100 E 58th Street - * Chicago, IL 60637 - * beazley@cs.uchicago.edu - * - * Please read the file LICENSE for the copyright and terms by which SWIG - * can be used and distributed. - ****************************************************************************/ - -extern "C" DOH *xml_run(DOH *node); -extern "C" int xml_init(int argc, char *argv[]); - diff --git a/Source/Preprocessor/Makefile.in b/Source/Preprocessor/Makefile.in index 24320f5e9..ac1bed800 100644 --- a/Source/Preprocessor/Makefile.in +++ b/Source/Preprocessor/Makefile.in @@ -6,7 +6,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ SRCS = expr.c cpp.c -OBJS = expr.o cpp.o +OBJS = expr.@OBJEXT@ cpp.@OBJEXT@ prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -15,11 +15,11 @@ CC = @CC@ AR = @AR@ RANLIB = @RANLIB@ CFLAGS = @CFLAGS@ -INCLUDE = -I$(srcdir)/. -I$(srcdir)/../Swig -I$(srcdir)/../DOH/Include +INCLUDES = -I$(srcdir)/. -I$(srcdir)/../Swig -I$(srcdir)/../DOH/Include -I$(srcdir)/../Include TARGET = libcpp.a -.c.o: - $(CC) $(CFLAGS) $(INCLUDE) -c -o $*.o $< +.c.@OBJEXT@: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $*.@OBJEXT@ $< all: $(TARGET) @@ -28,4 +28,4 @@ $(TARGET): $(OBJS) $(RANLIB) $(TARGET) clean: - rm -f *.o *~ core *.so *.a *_wrap.* + rm -f *.@OBJEXT@ *~ core *.so *.a *_wrap.* diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index f0f11b67c..9fa55a0e6 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -15,49 +15,36 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_cpp_c[] = "$Header$"; #include "preprocessor.h" #include <ctype.h> -static DOHHash *cpp = 0; /* C preprocessor data */ +static Hash *cpp = 0; /* C preprocessor data */ static int include_all = 0; /* Follow all includes */ +static int ignore_missing = 0; +static int import_all = 0; /* Follow all includes, but as %import statements */ static int single_include = 1; /* Only include each file once */ -static int silent_errors = 0; -static DOHHash *included_files = 0; - -/* Handle an error */ - -static void cpp_error(DOHString *file, int line, char *fmt, ...) { - va_list ap; - if (silent_errors) return; - va_start(ap,fmt); - if (line > 0) { - Printf(stderr,"%s:%d ", file, line); - } else { - Printf(stderr,"%s:EOF ",file); - } - vPrintf(stderr,fmt,ap); - va_end(ap); -} +static Hash *included_files = 0; +static List *dependencies = 0; /* Test a character to see if it starts an identifier */ static int -isidentifier(char c) { +isidentifier(int c) { if ((isalpha(c)) || (c == '_') || (c == '$')) return 1; else return 0; } /* Test a character to see if it valid in an identifier (after the first letter) */ static int -isidchar(char c) { +isidchar(int c) { if ((isalnum(c)) || (c == '_') || (c == '$')) return 1; else return 0; } /* Skip whitespace */ static void -skip_whitespace(DOH *s, DOH *out) { +skip_whitespace(File *s, File *out) { int c; while ((c = Getc(s)) != EOF) { if (!isspace(c)) { @@ -69,7 +56,7 @@ skip_whitespace(DOH *s, DOH *out) { /* Skip to a specified character taking line breaks into account */ static int -skip_tochar(DOHFile *s, int ch, DOHFile *out) { +skip_tochar(File *s, int ch, File *out) { int c; while ((c = Getc(s)) != EOF) { if (out) Putc(c,out); @@ -89,8 +76,8 @@ copy_location(DOH *s1, DOH *s2) { Setline(s2,Getline(s1)); } -static DOHString *cpp_include(DOHString_or_char *fn) { - DOHString *s; +static String *cpp_include(String_or_char *fn) { + String *s; if (single_include) { if (Getattr(included_files,fn)) return 0; Setattr(included_files,fn,fn); @@ -98,18 +85,31 @@ static DOHString *cpp_include(DOHString_or_char *fn) { s = Swig_include(fn); if (!s) { Seek(fn,0,SEEK_SET); - cpp_error(Getfile(fn),Getline(fn),"Unable to find '%s'\n", fn); + if (ignore_missing) { + Swig_warning(WARN_PP_MISSING_FILE,Getfile(fn),Getline(fn),"Unable to find '%s'\n", fn); + } else { + Swig_error(Getfile(fn),Getline(fn),"Unable to find '%s'\n", fn); + } } else { Seek(s,0,SEEK_SET); + if (!dependencies) { + dependencies = NewList(); + } + Append(dependencies, Copy(Swig_last_file())); } return s; } +List *Preprocessor_depend(void) { + return dependencies; +} + /* ----------------------------------------------------------------------------- * void Preprocessor_cpp_init() - Initialize the preprocessor * ----------------------------------------------------------------------------- */ void Preprocessor_init() { - DOHHash *s; + extern void Preprocessor_expr_init(void); + Hash *s; cpp = NewHash(); s = NewHash(); Setattr(cpp,"symbols",s); @@ -123,6 +123,15 @@ void Preprocessor_include_all(int a) { include_all = a; } +void Preprocessor_import_all(int a) { + import_all = a; +} + +void Preprocessor_ignore_missing(int a) { + ignore_missing = a; +} + + /* ----------------------------------------------------------------------------- * Preprocessor_define() * @@ -130,30 +139,30 @@ void Preprocessor_include_all(int a) { * SWIG macro semantics. * ----------------------------------------------------------------------------- */ -DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) +Hash *Preprocessor_define(const String_or_char *_str, int swigmacro) { - DOHString *macroname = 0, *argstr = 0, *macrovalue = 0, *file = 0, *s = 0; - DOHHash *macro = 0, *symbols = 0, *m1; - DOHList *arglist = 0; + String *macroname = 0, *argstr = 0, *macrovalue = 0, *file = 0, *s = 0; + Hash *macro = 0, *symbols = 0, *m1; + List *arglist = 0; int c, line; + int varargs = 0; + String_or_char *str = (String_or_char *) _str; assert(cpp); assert(str); /* First make sure that string is actually a string */ if (DohCheck(str)) { - s = Copy(str); + s = NewString(str); copy_location(str,s); str = s; } else { str = NewString((char *) str); - Seek(str,0,SEEK_SET); } + Seek(str,0,SEEK_SET); line = Getline(str); file = Getfile(str); - /* Printf(stdout,"%s:%d '%s'\n", file,line,str); */ - /* Skip over any leading whitespace */ skip_whitespace(str,0); @@ -169,7 +178,7 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) else Putc(c,argstr); } if (c != ')') { - cpp_error(Getfile(str),Getline(str), "Missing \')\' in macro parameters\n"); + Swig_error(Getfile(str),Getline(str), "Missing \')\' in macro parameters\n"); goto macro_error; } break; @@ -178,7 +187,7 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) } else if (isspace(c)) { break; } else { - cpp_error(Getfile(str),Getline(str),"Illegal character in macro name\n"); + Swig_error(Getfile(str),Getline(str),"Illegal character in macro name\n"); goto macro_error; } } @@ -197,18 +206,38 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) argname = NewString(""); while ((c = Getc(argstr)) != EOF) { if (c == ',') { - Append(arglist,argname); + /* Check for varargs */ + if (Strstr(argname,".")) { + if (Strcmp(argname,"...") != 0) { + Swig_error(Getfile(str),Getline(str),"Illegal macro argument name '%s'\n", argname); + } else { + Append(arglist,"__VA_ARGS__"); + varargs = 1; + } + } else { + Append(arglist,argname); + } Delete(argname); argname = NewString(""); - } else if (isidchar(c)) { + } else if (isidchar(c) || (c == '.')) { Putc(c,argname); - } else if (!isspace(c)) { - cpp_error(Getfile(str),Getline(str),"Illegal character in macro name\n"); + } else if (!(isspace(c) || (c == '\\'))) { + Swig_error(Getfile(str),Getline(str),"Illegal character in macro argument name\n"); goto macro_error; } } if (Len(argname)) { - Append(arglist,argname); + /* Check for varargs */ + if (Strstr(argname,".")) { + if (Strcmp(argname,"...") != 0) { + Swig_error(Getfile(str),Getline(str),"Illegal macro argument name '%s'\n", argname); + } else { + Append(arglist,"__VA_ARGS__"); + varargs = 1; + } + } else { + Append(arglist,argname); + } Delete(argname); } } @@ -216,16 +245,70 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) if (!swigmacro) { Replace(macrovalue,"\\\n"," ", DOH_REPLACE_NOQUOTE); } + + /* Look for special # substitutions. We only consider # that appears + outside of quotes and comments */ + + { + int state = 0; + char *cc = Char(macrovalue); + while (*cc) { + switch(state) { + case 0: + if (*cc == '#') *cc = '\001'; + else if (*cc == '/') state = 10; + else if (*cc == '\'') state = 20; + else if (*cc == '\"') state = 30; + break; + case 10: + if (*cc == '*') state = 11; + else if (*cc == '/') state = 15; + else { + state = 0; + cc--; + } + break; + case 11: + if (*cc == '*') state = 12; + break; + case 12: + if (*cc == '/') state = 0; + else if (*cc != '*') state = 11; + break; + case 15: + if (*cc == '\n') state = 0; + break; + case 20: + if (*cc == '\'') state = 0; + if (*cc == '\\') state = 21; + break; + case 21: + state = 20; + break; + case 30: + if (*cc == '\"') state = 0; + if (*cc == '\\') state = 31; + break; + case 31: + state = 30; + break; + default: + break; + } + cc++; + } + } + /* Get rid of whitespace surrounding # */ - Replace(macrovalue,"#","\001",DOH_REPLACE_NOQUOTE); + /* Replace(macrovalue,"#","\001",DOH_REPLACE_NOQUOTE); */ while(strstr(Char(macrovalue),"\001 ")) { - Replace(macrovalue,"\001 ","\001", DOH_REPLACE_NOQUOTE); + Replace(macrovalue,"\001 ","\001", DOH_REPLACE_ANY); } while(strstr(Char(macrovalue)," \001")) { - Replace(macrovalue," \001","\001", DOH_REPLACE_NOQUOTE); + Replace(macrovalue," \001","\001", DOH_REPLACE_ANY); } /* Replace '##' with a special token */ - Replace(macrovalue,"\001\001","\002", DOH_REPLACE_NOQUOTE); + Replace(macrovalue,"\001\001","\002", DOH_REPLACE_ANY); /* Go create the macro */ macro = NewHash(); @@ -234,6 +317,9 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) if (arglist) { Setattr(macro,"args",arglist); Delete(arglist); + if (varargs) { + Setattr(macro,"varargs","1"); + } } Setattr(macro,"value",macrovalue); Delete(macrovalue); @@ -245,7 +331,7 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) symbols = Getattr(cpp,"symbols"); if ((m1 = Getattr(symbols,macroname))) { if (Cmp(Getattr(m1,"value"),macrovalue)) - cpp_error(Getfile(str),Getline(str),"Macro '%s' redefined. Previous definition in \'%s\', Line %d\n", macroname, Getfile(m1), Getline(m1)); + Swig_error(Getfile(str),Getline(str),"Macro '%s' redefined. Previous definition in \'%s\', Line %d\n", macroname, Getfile(m1), Getline(m1)); } Setattr(symbols,macroname,macro); Delete(str); @@ -263,9 +349,9 @@ DOHHash *Preprocessor_define(DOHString_or_char *str, int swigmacro) * * Undefines a macro. * ----------------------------------------------------------------------------- */ -void Preprocessor_undef(DOHString_or_char *str) +void Preprocessor_undef(String_or_char *str) { - DOH *symbols; + Hash *symbols; assert(cpp); symbols = Getattr(cpp,"symbols"); Delattr(symbols,str); @@ -277,11 +363,11 @@ void Preprocessor_undef(DOHString_or_char *str) * Isolates macro arguments and returns them in a list. For each argument, * leading and trailing whitespace is stripped (ala K&R, pg. 230). * ----------------------------------------------------------------------------- */ -static DOHList * -find_args(DOHString *s) +static List * +find_args(String *s) { - DOHList *args; - DOHString *str; + List *args; + String *str; int c, level; long pos; @@ -344,7 +430,7 @@ find_args(DOHString *s) c = Getc(s); } unterm: - cpp_error(Getfile(args),Getline(args),"Unterminated macro call.\n"); + Swig_error(Getfile(args),Getline(args),"Unterminated macro call.\n"); return args; } @@ -355,9 +441,9 @@ find_args(DOHString *s) * or bare. * ----------------------------------------------------------------------------- */ -static DOHString * -get_filename(DOHString *str) { - DOHString *fn; +static String * +get_filename(String *str) { + String *fn; int c; skip_whitespace(str,0); @@ -377,6 +463,31 @@ get_filename(DOHString *str) { return fn; } +static String * +get_options(String *str) { + + int c; + skip_whitespace(str,0); + c = Getc(str); + if (c == '(') { + String *opt; + int level = 1; + opt = NewString("("); + while (((c = Getc(str)) != EOF)) { + Putc(c,opt); + if (c == ')') { + level--; + if (!level) return opt; + } + if (c == '(') level++; + } + Delete(opt); + return 0; + } else { + Ungetc(c,str); + return 0; + } +} /* ----------------------------------------------------------------------------- * expand_macro() * @@ -386,12 +497,13 @@ get_filename(DOHString *str) { DOH *expanded_value = 0; -static DOHString * -expand_macro(DOHString_or_char *name, DOHList *args) +static String * +expand_macro(String_or_char *name, List *args) { DOH *symbols, *ns, *macro, *margs, *mvalue, *temp, *tempa, *e; DOH *Preprocessor_replace(DOH *); int i, l; + int isvarargs = 0; symbols = Getattr(cpp,"symbols"); if (!symbols) return 0; @@ -420,14 +532,37 @@ expand_macro(DOHString_or_char *name, DOHList *args) assert(mvalue); margs = Getattr(macro,"args"); + if (Getattr(macro,"varargs")) { + isvarargs = 1; + /* Variable length argument macro. We need to collect all of the extra arguments into a single argument */ + if (Len(args) >= (Len(margs)-1)) { + int i; + int vi, na; + String *vararg = NewString(""); + vi = Len(margs)-1; + na = Len(args); + for (i = vi; i < na; i++) { + Append(vararg,Getitem(args,i)); + if ((i+1) < na) { + Append(vararg,","); + } + } + /* Remove arguments */ + for (i = vi; i < na; i++) { + Delitem(args,vi); + } + Append(args,vararg); + Delete(vararg); + } + } /* If there are arguments, see if they match what we were given */ if ((margs) && (Len(margs) != Len(args))) { - if (Len(margs) > 1) - cpp_error(Getfile(args),Getline(args),"Macro '%s' expects %d arguments\n", name, Len(margs)); - else if (Len(margs) == 1) - cpp_error(Getfile(args),Getline(args),"Macro '%s' expects 1 argument\n", name); + if (Len(margs) > (1+isvarargs)) + Swig_error(Getfile(args),Getline(args),"Macro '%s' expects %d arguments\n", name, Len(margs)-isvarargs); + else if (Len(margs) == (1+isvarargs)) + Swig_error(Getfile(args),Getline(args),"Macro '%s' expects 1 argument\n", name); else - cpp_error(Getfile(args),Getline(args),"Macro '%s' expects no arguments\n", name); + Swig_error(Getfile(args),Getline(args),"Macro '%s' expects no arguments\n", name); return 0; } @@ -480,27 +615,49 @@ expand_macro(DOHString_or_char *name, DOHList *args) } Replace(ns,temp,rep, DOH_REPLACE_ANY); } + if (isvarargs) { + if ((Strcmp(aname,"__VA_ARGS__") == 0) && (Len(arg) == 0)) { + /* Zero length __VA_ARGS__ macro argument. We search for commas that might appear before and nuke them */ + char *a, *s, *t; + s = Char(ns); + a = strstr(s,"__VA_ARGS__"); + while (a) { + t = a-1; + if (*t == '\002') { + t--; + while (t >= s) { + if (isspace((int) *t)) t--; + else if (*t == ',') { + *t = ' '; + } else break; + } + } + a = strstr(a+11,"__VA_ARGS__"); + } + } + } Replace(ns, aname, arg, DOH_REPLACE_ID); } } Replace(ns,"\002","",DOH_REPLACE_ANY); /* Get rid of concatenation tokens */ Replace(ns,"\001","#",DOH_REPLACE_ANY); /* Put # back (non-standard C) */ - /* Expand this macro even further */ e = Preprocessor_replace(ns); Delete(ns); Delattr(macro,"*expanded*"); if (Getattr(macro,"swigmacro")) { - DOHString *g; - DOHString *f = NewString(""); - Printf(f,"%%macro %s, \"%s\", %d {\n", name, Getfile(macro), Getline(macro)); + String *g; + String *f = NewString(""); Seek(e,0,SEEK_SET); copy_location(macro,e); g = Preprocessor_parse(e); - Printf(f,"%s\n", g); - Printf(f,"}\n"); + + /* Drop the macro in place, but with a marker around it */ + Printf(f,"/*@%s,%d,%s@*/%s/*@@*/", Getfile(macro), Getline(macro), name, g); + + /* Printf(f," }\n"); */ Delete(g); Delete(e); e = f; @@ -511,6 +668,24 @@ expand_macro(DOHString_or_char *name, DOHList *args) } /* ----------------------------------------------------------------------------- + * evaluate_args() + * + * Evaluate the arguments of a macro + * ----------------------------------------------------------------------------- */ + +List *evaluate_args(List *x) { + String *a; + String *Preprocessor_replace(String *); + + List *nl = NewList(); + + for (a = Firstitem(x); a; a = Nextitem(x)) { + Append(nl,Preprocessor_replace(a)); + } + return nl; +} + +/* ----------------------------------------------------------------------------- * DOH *Preprocessor_replace(DOH *s) * * Performs a macro substitution on a string s. Returns a new string with @@ -575,6 +750,7 @@ Preprocessor_replace(DOH *s) DOH *arg = 0; args = NewList(); arg = NewString(""); + if (isidchar(c)) Putc(c,arg); while ((c = Getc(s)) != EOF) { if (!isidchar(c)) { Seek(s,-1,SEEK_CUR); @@ -585,8 +761,8 @@ Preprocessor_replace(DOH *s) Append(args,arg); Delete(arg); } - if (!args) { - cpp_error(Getfile(id),Getline(id),"No arguments given to defined()\n"); + if ((!args) || (!Len(args))) { + Swig_error(Getfile(id),Getline(id),"No arguments given to defined()\n"); state = 0; break; } @@ -608,7 +784,10 @@ Preprocessor_replace(DOH *s) break; } if (Cmp(id,"__FILE__") == 0) { - Printf(ns,"\"%s\"",Getfile(s)); + String *fn = Copy(Getfile(s)); + Replaceall(fn,"\\","\\\\"); + Printf(ns,"\"%s\"",fn); + Delete(fn); state = 0; break; } @@ -623,6 +802,12 @@ Preprocessor_replace(DOH *s) } else { args = 0; } + if (args) { + List *nargs = evaluate_args(args); + Delete(args); + args = nargs; + } + e = expand_macro(id,args); if (e) { Printf(ns,"%s",e); @@ -668,13 +853,13 @@ Preprocessor_replace(DOH *s) if (state == 1) { /* See if this is the special "defined" macro */ if (Cmp(id,"defined") == 0) { - cpp_error(Getfile(id),Getline(id),"No arguments given to defined()\n"); + Swig_error(Getfile(id),Getline(id),"No arguments given to defined()\n"); } else if ((m = Getattr(symbols,id))) { DOH *e; /* Yes. There is a macro here */ /* See if the macro expects arguments */ if (Getattr(m,"args")) { - cpp_error(Getfile(id),Getline(id),"Macro arguments expected.\n"); + Swig_error(Getfile(id),Getline(id),"Macro arguments expected.\n"); } e = expand_macro(id,0); Printf(ns,"%s",e); @@ -698,52 +883,24 @@ Preprocessor_replace(DOH *s) static int check_id(DOH *s) { - int c, state = 0; - int hasvalue = 0; + static SwigScanner *scan = 0; + int c; + Seek(s,0,SEEK_SET); - while ((c = Getc(s)) != EOF) { - switch(state) { - case 0: - if (isdigit(c)) { - hasvalue =1; - state = 1; - } - else if (isidentifier(c)) return 1; - else if (c == '\"') { - skip_tochar(s,'\"',0); - hasvalue = 1; - } else if (c == '\'') { - skip_tochar(s,'\'',0); - hasvalue = 1; - } else if (c == '/') state = 3; - break; - case 1: - if (isspace(c)) state = 0; - hasvalue = 1; - break; - case 3: - if (c == '*') state = 10; - else if (c == '/') state = 20; - else { - Ungetc(c,s); - state = 0; - } - break; - case 10: - if (c == '*') state = 11; - break; - case 11: - if (c == '/') state = 0; - else if (c != '*') state = 10; - break; - case 20: - if (c == '\n') state = 0; - break; - } + if (!scan) { + scan = NewSwigScanner(); + } + + SwigScanner_clear(scan); + s = Copy(s); + Seek(s,SEEK_SET,0); + SwigScanner_push(scan,s); + while ((c = SwigScanner_token(scan))) { + if ((c == SWIG_TOKEN_ID) || (c == SWIG_TOKEN_LBRACE) || (c == SWIG_TOKEN_RBRACE)) return 1; } - if (!hasvalue) return 1; return 0; + } /* addline(). Utility function for adding lines to a chunk */ @@ -775,7 +932,7 @@ static void add_chunk(DOH *ns, DOH *chunk, int allow) { } /* ----------------------------------------------------------------------------- - * DOH *Preprocessor_parse(DOH *s) + * Preprocessor_parse() * * Parses the string s. Returns a new string containing the preprocessed version. * @@ -787,12 +944,13 @@ static void add_chunk(DOH *ns, DOH *chunk, int allow) { * included inline (with all preprocessor directives included). * ----------------------------------------------------------------------------- */ -DOH * -Preprocessor_parse(DOH *s) +String * +Preprocessor_parse(String *s) { - DOH *ns; /* New string containing the preprocessed text */ - DOH *chunk, *symbols, *sval, *decl; - DOH *id = 0, *value = 0, *comment = 0; + String *ns; /* New string containing the preprocessed text */ + String *chunk, *sval, *decl; + Hash *symbols; + String *id = 0, *value = 0, *comment = 0; int i, state, val, e, c; int start_line = 0; int allow = 1; @@ -802,6 +960,9 @@ Preprocessor_parse(DOH *s) int cpp_lines = 0; int cond_lines[256]; + /* Blow away all carriage returns */ + Replace(s,"\015","",DOH_REPLACE_ANY); + ns = NewString(""); /* Return result */ decl = NewString(""); @@ -842,12 +1003,12 @@ Preprocessor_parse(DOH *s) else if (c == '\"') { start_line = Getline(s); if (skip_tochar(s,'\"',chunk) < 0) { - cpp_error(Getfile(s),-1,"Unterminated string constant starting at line %d\n",start_line); + Swig_error(Getfile(s),-1,"Unterminated string constant starting at line %d\n",start_line); } } else if (c == '\'') { start_line = Getline(s); if (skip_tochar(s,'\'',chunk) < 0) { - cpp_error(Getfile(s),-1,"Unterminated character constant starting at line %d\n",start_line); + Swig_error(Getfile(s),-1,"Unterminated character constant starting at line %d\n",start_line); } } else if (c == '/') state = 30; /* Comment */ @@ -896,8 +1057,13 @@ Preprocessor_parse(DOH *s) if (c == '\n') { Ungetc(c,s); state = 50; + } else { + state = 42; + if (!isspace(c)) { + Ungetc(c,s); + } } - else state = 42; + copy_location(s,value); break; } @@ -922,6 +1088,12 @@ Preprocessor_parse(DOH *s) state = 50; } else if (c == '/') { state = 45; + } else if (c == '\"') { + Putc(c,value); + skip_tochar(s,'\"',value); + } else if (c == '\'') { + Putc(c,value); + skip_tochar(s,'\'',value); } else { Putc(c,value); if (c == '\\') state = 44; @@ -982,9 +1154,9 @@ Preprocessor_parse(DOH *s) if ((m) && !(Getattr(m,"args"))) { v = Copy(Getattr(m,"value")); if (Len(v)) { - silent_errors = 1; + Swig_error_silent(1); v1 = Preprocessor_replace(v); - silent_errors = 0; + Swig_error_silent(0); /* Printf(stdout,"checking '%s'\n", v1); */ if (!check_id(v1)) { if (Len(comment) == 0) @@ -1021,20 +1193,20 @@ Preprocessor_parse(DOH *s) } } else if (Cmp(id,"else") == 0) { if (level <= 0) { - cpp_error(Getfile(s),Getline(id),"Misplaced #else.\n"); + Swig_error(Getfile(s),Getline(id),"Misplaced #else.\n"); } else { cond_lines[level-1] = Getline(id); if (allow) { allow = 0; mask = 0; } else if (level == start_level) { - allow = 1; + allow = 1*mask; } } } else if (Cmp(id,"endif") == 0) { level--; if (level < 0) { - cpp_error(Getfile(id),Getline(id),"Extraneous #endif ignored.\n"); + Swig_error(Getfile(id),Getline(id),"Extraneous #endif.\n"); level = 0; } else { if (level < start_level) { @@ -1053,7 +1225,7 @@ Preprocessor_parse(DOH *s) val = Preprocessor_expr(sval,&e); if (e) { Seek(value,0,SEEK_SET); - /* cpp_error(Getfile(value),Getline(value),"Could not evaluate '%s'\n", value); */ + Swig_warning(WARN_PP_EVALUATION,Getfile(value),Getline(value),"Could not evaluate '%s'\n", value); allow = 0; } else { if (val == 0) @@ -1063,7 +1235,7 @@ Preprocessor_parse(DOH *s) } } else if (Cmp(id,"elif") == 0) { if (level == 0) { - cpp_error(Getfile(s),Getline(id),"Misplaced #elif.\n"); + Swig_error(Getfile(s),Getline(id),"Misplaced #elif.\n"); } else { cond_lines[level-1] = Getline(id); if (allow) { @@ -1075,7 +1247,7 @@ Preprocessor_parse(DOH *s) val = Preprocessor_expr(sval,&e); if (e) { Seek(value,0,SEEK_SET); - /* cpp_error(Getfile(value),Getline(value),"Could not evaluate '%s'\n", value); */ + Swig_warning(WARN_PP_EVALUATION,Getfile(value),Getline(value),"Could not evaluate '%s'\n", value); allow = 0; } else { if (val) @@ -1087,24 +1259,36 @@ Preprocessor_parse(DOH *s) } } else if (Cmp(id,"line") == 0) { } else if (Cmp(id,"include") == 0) { - if ((include_all) && (allow)) { + if (((include_all) || (import_all)) && (allow)) { DOH *s1, *s2, *fn; Seek(value,0,SEEK_SET); fn = get_filename(value); s1 = cpp_include(fn); if (s1) { - Printf(ns,"%%file(\"include\") \"%s\" {\n", Swig_last_file()); + if (include_all) + Printf(ns,"%%includefile \"%s\" [\n", Swig_last_file()); + else if (import_all) + Printf(ns,"%%importfile \"%s\" [\n", Swig_last_file()); s2 = Preprocessor_parse(s1); addline(ns,s2,allow); - Printf(ns,"\n}\n"); + Printf(ns,"\n]\n"); Delete(s2); } Delete(s1); Delete(fn); } } else if (Cmp(id,"pragma") == 0) { + if (Strncmp(value,"SWIG ",5) == 0) { + char *c = Char(value)+5; + while (*c && (isspace((int)*c))) c++; + if (*c) { + if (Strncmp(c,"nowarn=",7) == 0) { + Swig_warnfilter(c+7,1); + } + } + } } else if (Cmp(id,"level") == 0) { - cpp_error(Getfile(s),Getline(id),"cpp debug: level = %d, startlevel = %d\n", level, start_level); + Swig_error(Getfile(s),Getline(id),"cpp debug: level = %d, startlevel = %d\n", level, start_level); } for (i = 0; i < cpp_lines; i++) Putc('\n',ns); @@ -1124,8 +1308,9 @@ Preprocessor_parse(DOH *s) } /* %#cpp - an embedded C preprocessor directive (we strip off the %) */ else if (c == '#') { + add_chunk(ns,chunk,allow); Putc(c,chunk); - state = 0; + state = 107; } else if (isidentifier(c)) { Clear(decl); Putc('%',decl); @@ -1155,6 +1340,22 @@ Preprocessor_parse(DOH *s) state = 105; } break; + + case 107: + Putc(c,chunk); + if (c == '\n') { + addline(ns,chunk,allow); + Clear(chunk); + state = 0; + } else if (c == '\\') { + state = 108; + } + break; + + case 108: + Putc(c,chunk); + state = 107; + break; case 110: if (!isidchar(c)) { @@ -1163,22 +1364,31 @@ Preprocessor_parse(DOH *s) if ((Cmp(decl,"%include") == 0) || (Cmp(decl,"%import") == 0) || (Cmp(decl,"%extern") == 0)) { /* Got some kind of file inclusion directive */ if (allow) { - DOH *s1, *s2, *fn; + DOH *s1, *s2, *fn, *opt; + + if (Cmp(decl,"%extern") == 0) { + Swig_warning(WARN_DEPRECATED_EXTERN, Getfile(s),Getline(s),"%%extern is deprecated. Use %%import instead.\n"); + Clear(decl); + Printf(decl,"%%import"); + } + opt = get_options(s); fn = get_filename(s); s1 = cpp_include(fn); if (s1) { add_chunk(ns,chunk,allow); copy_location(s,chunk); - Printf(ns,"%%file(\"%s\") \"%s\" {\n", Char(decl)+1, Swig_last_file()); + Printf(ns,"%sfile%s \"%s\" [\n", decl, opt, Swig_last_file()); if ((Cmp(decl,"%import") == 0) || (Cmp(decl,"%extern") == 0)) { Preprocessor_define("WRAPEXTERN 1", 0); + Preprocessor_define("SWIGIMPORT 1", 0); } s2 = Preprocessor_parse(s1); if ((Cmp(decl,"%import") == 0) || (Cmp(decl,"%extern") == 0)) { + Preprocessor_undef("SWIGIMPORT"); Preprocessor_undef("WRAPEXTERN"); } addline(ns,s2,allow); - Printf(ns,"\n}\n"); + Printf(ns,"\n]\n"); Delete(s2); Delete(s1); } @@ -1209,15 +1419,17 @@ Preprocessor_parse(DOH *s) Putc(c,value); if (c == '%') { int i = 0; - char *d = "enddef\n"; - for (i = 0; i < 7; i++) { + char *d = "enddef"; + for (i = 0; i < 6; i++) { c = Getc(s); Putc(c,value); if (c != d[i]) break; } - if (i == 7) { + c = Getc(s); + Ungetc(c,s); + if ((i == 6) && (isspace(c))) { /* Got the macro */ - for (i = 0; i < 8; i++) { + for (i = 0; i < 7; i++) { Delitem(value,DOH_END); } if (allow) { @@ -1237,18 +1449,18 @@ Preprocessor_parse(DOH *s) } } while (level > 0) { - cpp_error(Getfile(s),-1,"Missing #endif for conditional starting on line %d\n", cond_lines[level-1]); + Swig_error(Getfile(s),-1,"Missing #endif for conditional starting on line %d\n", cond_lines[level-1]); level--; } if (state == 150) { Seek(value,0,SEEK_SET); - cpp_error(Getfile(s),-1,"Missing %%enddef for macro starting on line %d\n",Getline(value)); + Swig_error(Getfile(s),-1,"Missing %%enddef for macro starting on line %d\n",Getline(value)); } if ((state >= 105) && (state < 107)) { - cpp_error(Getfile(s),-1,"Unterminated %%{ ... %%} block starting on line %d\n", start_line); + Swig_error(Getfile(s),-1,"Unterminated %%{ ... %%} block starting on line %d\n", start_line); } if ((state >= 30) && (state < 40)) { - cpp_error(Getfile(s),-1,"Unterminated comment starting on line %d\n", start_line); + Swig_error(Getfile(s),-1,"Unterminated comment starting on line %d\n", start_line); } add_chunk(ns,chunk,allow); copy_location(s,chunk); diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 13ca42d96..39a54149c 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -10,7 +10,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_expr_c[] = "$Header$"; #include "preprocessor.h" @@ -19,6 +19,7 @@ static SwigScanner *scan = 0; typedef struct { int op; long value; + String *svalue; } exprval; #define EXPR_TOP 1 @@ -66,95 +67,122 @@ static void reduce_op() { sp = 0; return; } - switch(stack[sp-1].value) { - case SWIG_TOKEN_STAR: - stack[sp-2].value = stack[sp-2].value * stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_EQUALTO: - stack[sp-2].value = stack[sp-2].value == stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_NOTEQUAL: - stack[sp-2].value = stack[sp-2].value != stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_PLUS: - stack[sp-2].value = stack[sp-2].value + stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_MINUS: - stack[sp-2].value = stack[sp-2].value - stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_AND: - stack[sp-2].value = stack[sp-2].value & stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_LAND: - stack[sp-2].value = stack[sp-2].value && stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_OR: - stack[sp-2].value = stack[sp-2].value | stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_LOR: - stack[sp-2].value = stack[sp-2].value || stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_XOR: - stack[sp-2].value = stack[sp-2].value ^ stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_LESSTHAN: - stack[sp-2].value = stack[sp-2].value < stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_GREATERTHAN: - stack[sp-2].value = stack[sp-2].value > stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_LTEQUAL: - stack[sp-2].value = stack[sp-2].value <= stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_GTEQUAL: - stack[sp-2].value = stack[sp-2].value >= stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_NOT: - stack[sp-1].value = ~stack[sp].value; - sp--; - break; - case SWIG_TOKEN_LNOT: - stack[sp-1].value = !stack[sp].value; - sp--; - break; - case EXPR_UMINUS: - stack[sp-1].value = -stack[sp].value; - sp--; - break; - case SWIG_TOKEN_SLASH: - stack[sp-2].value = stack[sp-2].value / stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_PERCENT: - stack[sp-2].value = stack[sp-2].value % stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_LSHIFT: - stack[sp-2].value = stack[sp-2].value << stack[sp].value; - sp -= 2; - break; - case SWIG_TOKEN_RSHIFT: - stack[sp-2].value = stack[sp-2].value >> stack[sp].value; - sp -= 2; - break; - default: - errmsg = "Syntax error"; - sp = 0; - break; + if (stack[sp-2].svalue || stack[sp].svalue) { + /* A string expression */ + if (!(stack[sp-2].svalue && stack[sp].svalue)) { + errmsg = "Can't mix strings and integers in expression"; + sp = 0; + return; + } + switch(stack[sp-1].value) { + case SWIG_TOKEN_EQUALTO: + stack[sp-2].value = (Strcmp(stack[sp-2].svalue,stack[sp].svalue) == 0); + Delete(stack[sp-2].svalue); + Delete(stack[sp].svalue); + sp -= 2; + break; + case SWIG_TOKEN_NOTEQUAL: + stack[sp-2].value = (Strcmp(stack[sp-2].svalue,stack[sp].svalue) != 0); + Delete(stack[sp-2].svalue); + Delete(stack[sp].svalue); + sp -= 2; + break; + default: + errmsg = "Syntax error"; + sp = 0; + break; + } + } else { + switch(stack[sp-1].value) { + case SWIG_TOKEN_STAR: + stack[sp-2].value = stack[sp-2].value * stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_EQUALTO: + stack[sp-2].value = stack[sp-2].value == stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_NOTEQUAL: + stack[sp-2].value = stack[sp-2].value != stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_PLUS: + stack[sp-2].value = stack[sp-2].value + stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_MINUS: + stack[sp-2].value = stack[sp-2].value - stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_AND: + stack[sp-2].value = stack[sp-2].value & stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_LAND: + stack[sp-2].value = stack[sp-2].value && stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_OR: + stack[sp-2].value = stack[sp-2].value | stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_LOR: + stack[sp-2].value = stack[sp-2].value || stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_XOR: + stack[sp-2].value = stack[sp-2].value ^ stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_LESSTHAN: + stack[sp-2].value = stack[sp-2].value < stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_GREATERTHAN: + stack[sp-2].value = stack[sp-2].value > stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_LTEQUAL: + stack[sp-2].value = stack[sp-2].value <= stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_GTEQUAL: + stack[sp-2].value = stack[sp-2].value >= stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_NOT: + stack[sp-1].value = ~stack[sp].value; + sp--; + break; + case SWIG_TOKEN_LNOT: + stack[sp-1].value = !stack[sp].value; + sp--; + break; + case EXPR_UMINUS: + stack[sp-1].value = -stack[sp].value; + sp--; + break; + case SWIG_TOKEN_SLASH: + stack[sp-2].value = stack[sp-2].value / stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_PERCENT: + stack[sp-2].value = stack[sp-2].value % stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_LSHIFT: + stack[sp-2].value = stack[sp-2].value << stack[sp].value; + sp -= 2; + break; + case SWIG_TOKEN_RSHIFT: + stack[sp-2].value = stack[sp-2].value >> stack[sp].value; + sp -= 2; + break; + default: + errmsg = "Syntax error"; + sp = 0; + break; + } } stack[sp].op = EXPR_VALUE; } @@ -187,6 +215,7 @@ Preprocessor_expr(DOH *s, int *error) { assert(scan); Seek(s,0,SEEK_SET); + /* Printf(stdout,"evaluating : '%s'\n", s); */ *error = 0; SwigScanner_clear(scan); SwigScanner_push(scan,s); @@ -208,7 +237,10 @@ Preprocessor_expr(DOH *s, int *error) { } if ((token == SWIG_TOKEN_INT) || (token == SWIG_TOKEN_UINT) || (token == SWIG_TOKEN_LONG) || (token == SWIG_TOKEN_ULONG)) { /* A number. Reduce EXPR_TOP to an EXPR_VALUE */ - stack[sp].value = (long) atol(Char(SwigScanner_text(scan))); + char *c = Char(SwigScanner_text(scan)); + stack[sp].value = (long) strtol(c,0,0); + stack[sp].svalue = 0; + /* stack[sp].value = (long) atol(Char(SwigScanner_text(scan))); */ stack[sp].op = EXPR_VALUE; } else if (token == SWIG_TOKEN_PLUS) { } else if ((token == SWIG_TOKEN_MINUS) || (token == SWIG_TOKEN_LNOT) || (token==SWIG_TOKEN_NOT)) { @@ -216,12 +248,21 @@ Preprocessor_expr(DOH *s, int *error) { stack[sp].value = token; stack[sp++].op = EXPR_OP; stack[sp].op = EXPR_TOP; + stack[sp].svalue = 0; } else if ((token == SWIG_TOKEN_LPAREN)) { stack[sp++].op = EXPR_GROUP; stack[sp].op = EXPR_TOP; stack[sp].value = 0; - } else if (token == SWIG_TOKEN_ENDLINE) { } - else goto syntax_error; + stack[sp].svalue = 0; + } else if (token == SWIG_TOKEN_ENDLINE) { + } else if ((token == SWIG_TOKEN_STRING)) { + stack[sp].svalue = NewString(SwigScanner_text(scan)); + stack[sp].op = EXPR_VALUE; + } else if ((token == SWIG_TOKEN_ID)) { + stack[sp].value = 0; + stack[sp].svalue = 0; + stack[sp].op = EXPR_VALUE; + } else goto syntax_error; break; case EXPR_VALUE: /* A value is on the stack. We may reduce or evaluate depending on what the next token is */ @@ -302,6 +343,7 @@ Preprocessor_expr(DOH *s, int *error) { break; } break; + default: fprintf(stderr,"Internal error in expression evaluator.\n"); abort(); diff --git a/Source/Preprocessor/preprocessor.h b/Source/Preprocessor/preprocessor.h index a32501164..eb4f8feda 100644 --- a/Source/Preprocessor/preprocessor.h +++ b/Source/Preprocessor/preprocessor.h @@ -15,19 +15,21 @@ #define _PREPROCESSOR_H #include "swig.h" +#include "swigwarn.h" #ifdef __cplusplus extern "C" { #endif - -extern void Preprocessor_expr_init(void); -extern int Preprocessor_expr(DOHString *s, int *error); -extern char *Preprocessor_expr_error(void); -extern DOH *Preprocessor_define(DOHString_or_char *str, int swigmacro); -extern void Preprocessor_undef(DOHString_or_char *name); -extern void Preprocessor_init(); -extern DOH *Preprocessor_parse(DOH *s); -extern void Preprocessor_include_all(int); +extern int Preprocessor_expr(String *s, int *error); +extern char *Preprocessor_expr_error(void); +extern Hash *Preprocessor_define(const String_or_char *str, int swigmacro); +extern void Preprocessor_undef(String_or_char *name); +extern void Preprocessor_init(); +extern String *Preprocessor_parse(String *s); +extern void Preprocessor_include_all(int); +extern void Preprocessor_import_all(int); +extern void Preprocessor_ignore_missing(int); +extern List *Preprocessor_depend(void); #ifdef __cplusplus } diff --git a/Source/README b/Source/README new file mode 100644 index 000000000..db46fd03d --- /dev/null +++ b/Source/README @@ -0,0 +1,32 @@ +SWIG Source directory + +This directory currently contains a mix of legacy SWIG1.1 code and +recent development work. As a result, it's still a little messy. +Here is a rough breakdown of the directories: + + Source/DOH - A core set of basic datatypes including + strings, lists, hashes, and files. Used + extensively by the rest of SWIG. + + Source/Swig - Swig core. Type-system, utility functions. + + Source/Preprocessor - SWIG C Preprocessor + + Source/CParse - SWIG C Parser (still messy) + + Source/Modules1.1 - Old SWIG1.1 derived language modules. + Remaining legacy code. + + +The following directories may be in CVS, but are largely deprecated: + + Source/Modules - Some experimental module work. New + modules may be added here eventually. + + Source/LParse - Experimental parser. Officially dead + as CParse is more capable. + + Source/SWIG1.1 - Old SWIG1.1 core. Completely empty now. + + + diff --git a/Source/Swig/Makefile.in b/Source/Swig/Makefile.in index 9503e0ab2..1186c6887 100644 --- a/Source/Swig/Makefile.in +++ b/Source/Swig/Makefile.in @@ -5,10 +5,10 @@ srcdir = @srcdir@ VPATH = @srcdir@ -SRCS = map.c wrapfunc.c naming.c tree.c stype.c scanner.c include.c getopt.c misc.c \ - parms.c cwrap.c typemap.c module.c main.c -OBJS = map.o wrapfunc.o naming.o tree.o stype.o scanner.o include.o getopt.o misc.o \ - parms.o cwrap.o typemap.o module.o main.o +SRCS = wrapfunc.c naming.c tree.c stype.c typesys.c scanner.c include.c getopt.c misc.c \ + parms.c cwrap.c typemap.c warn.c symbol.c error.c fragment.c +OBJS = wrapfunc.@OBJEXT@ naming.@OBJEXT@ tree.@OBJEXT@ stype.@OBJEXT@ typesys.@OBJEXT@ scanner.@OBJEXT@ include.@OBJEXT@ getopt.@OBJEXT@ misc.@OBJEXT@ \ + parms.@OBJEXT@ cwrap.@OBJEXT@ typemap.@OBJEXT@ warn.@OBJEXT@ symbol.@OBJEXT@ error.@OBJEXT@ fragment.@OBJEXT@ prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -17,11 +17,11 @@ CC = @CC@ AR = @AR@ RANLIB = @RANLIB@ CFLAGS = @CFLAGS@ -INCLUDE = -I$(srcdir)/. -I$(srcdir)/../DOH/Include -I$(srcdir)/../Include +INCLUDES = -I$(srcdir)/. -I$(srcdir)/../DOH/Include -I$(srcdir)/../Include TARGET = libswig.a -.c.o: - $(CC) $(CFLAGS) $(INCLUDE) -c -o $*.o $< +.c.@OBJEXT@: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $*.@OBJEXT@ $< all: $(TARGET) @@ -30,4 +30,4 @@ $(TARGET): $(OBJS) $(RANLIB) $(TARGET) clean: - rm -f *.o *~ core *.so *.a *_wrap.* + rm -f *.@OBJEXT@ *~ core *.so *.a *_wrap.* diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index a5fd6d9ba..5abcab2ab 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -13,10 +13,18 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_cwrap_c[] = "$Header$"; #include "swig.h" +static Parm *nonvoid_parms(Parm *p) { + if (p) { + SwigType *t = Getattr(p,"type"); + if (SwigType_type(t) == T_VOID) return 0; + } + return p; +} + /* ----------------------------------------------------------------------------- * Swig_parm_name() * @@ -25,11 +33,11 @@ static char cvsroot[] = "$Header$"; String * Swig_cparm_name(Parm *p, int i) { - String *name = NewStringf("arg%d",i); + String *name = NewStringf("arg%d",i+1); if (p) { - Setlname(p,name); + Setattr(p,"lname",name); } - return Swig_temp_result(name); + return name; } /* ----------------------------------------------------------------------------- @@ -41,99 +49,67 @@ Swig_cparm_name(Parm *p, int i) { String * Swig_clocal(SwigType *t, String_or_char *name, String_or_char *value) { - String *decl = 0; + String *decl; - /* *((char *) decl) = 'x';*/ decl = NewString(""); + switch(SwigType_type(t)) { - case T_USER: - SwigType_add_pointer(t); - if (value) - Printf(decl,"%s = (%s) &%s", SwigType_lstr(t,name), SwigType_lstr(t,0), value); - else - Printf(decl,"%s", SwigType_lstr(t,name)); - SwigType_del_pointer(t); - break; case T_REFERENCE: - if (value) - Printf(decl,"%s = (%s) &%s", SwigType_lstr(t,name), SwigType_lstr(t,0), value); - else - Printf(decl,"%s", SwigType_lstr(t,name)); + if (value) { + Printf(decl,"%s = (%s) &%s_defvalue", SwigType_lstr(t,name), SwigType_lstr(t,0), name); + } else { + Printf(decl,"%s = 0", SwigType_lstr(t,name)); + } break; case T_VOID: break; + case T_VARARGS: + Printf(decl,"void *%s = 0", name); + break; + default: - if (value) - Printf(decl,"%s = %s", SwigType_lstr(t,name), value); - else + if (value) { + Printf(decl,"%s = (%s) %s", SwigType_lstr(t,name), SwigType_lstr(t,0), SwigType_lcaststr(t,value)); + } else { Printf(decl,"%s", SwigType_lstr(t,name)); + } } - return Swig_temp_result(decl); + return decl; } /* ----------------------------------------------------------------------------- - * Swig_clocal_type() + * Swig_wrapped_var_convert() * - * Creates a string that declares a C local variable type. Converts references - * and user defined types to pointers. + * Converts a member variable for use in the get and set wrapper methods. + * This function only converts user defined types to pointers. * ----------------------------------------------------------------------------- */ -SwigType * -Swig_clocal_type(SwigType *t) { +String * +Swig_wrapped_var_type(SwigType *t) { SwigType *ty; - switch(SwigType_type(t)) { - case T_USER: - SwigType_add_pointer(t); - ty = SwigType_ltype(t); - SwigType_del_pointer(t); - break; - default: - ty = SwigType_ltype(t); - break; + ty = Copy(t); + + if (SwigType_isclass(t)) { + SwigType_add_pointer(ty); } return ty; } -/* ----------------------------------------------------------------------------- - * Swig_clocal_deref() - * - * Creates a string that can be used to deref a local variable wrapped with - * the Swig_clocal() function. - * ----------------------------------------------------------------------------- */ - String * -Swig_clocal_deref(SwigType *t, String_or_char *name) { - switch(SwigType_type(t)) { - case T_USER: - return Swig_temp_result(NewStringf("*%s",name)); - break; - case T_VOID: - return Swig_temp_result(NewString("")); - break; - default: +Swig_wrapped_var_deref(SwigType *t, String_or_char *name) { + if (SwigType_isclass(t)) { + return NewStringf("*%s",name); + } else { return SwigType_rcaststr(t,name); - break; } } -/* ----------------------------------------------------------------------------- - * Swig_clocal_assign() - * - * Assigns a value to a local - * ----------------------------------------------------------------------------- */ - String * -Swig_clocal_assign(SwigType *t, String_or_char *name) { - switch(SwigType_type(t)) { - case T_VOID: - return Swig_temp_result(NewString("")); - break; - case T_USER: - return Swig_temp_result(NewStringf("&%s", name)); - break; - default: +Swig_wrapped_var_assign(SwigType *t, String_or_char *name) { + if (SwigType_isclass(t)) { + return NewStringf("&%s",name); + } else { return SwigType_lcaststr(t,name); - break; } } @@ -151,17 +127,41 @@ int Swig_cargs(Wrapper *w, ParmList *p) { String *pname; String *local; String *lname; + SwigType *altty; + String *type; + int tycode; i = 0; while (p != 0) { lname = Swig_cparm_name(p,i); - pt = Gettype(p); - pname = Getname(p); - pvalue = Getvalue(p); - local = Swig_clocal(pt,lname,pvalue); - Wrapper_add_localv(w,lname,local,0); - i++; - p = Getnext(p); + pt = Getattr(p,"type"); + if ((SwigType_type(pt) != T_VOID)) { + pname = Getattr(p,"name"); + pvalue = Getattr(p,"value"); + altty = Getattr(p,"alttype"); + type = Getattr(p,"type"); + tycode = SwigType_type(type); + if (tycode == T_REFERENCE) { + if (pvalue) { + String *defname, *defvalue; + defname = NewStringf("%s_defvalue", lname); + defvalue = NewStringf("%s = %s", SwigType_str(type,defname), pvalue); + Wrapper_add_localv(w,defname, defvalue, NIL); + Delete(defname); + Delete(defvalue); + } + } else if (!pvalue && (tycode == T_POINTER)) { + pvalue = (String *) "0"; + } + if (!altty) { + local = Swig_clocal(pt,lname,pvalue); + } else { + local = Swig_clocal(altty,lname, pvalue); + } + Wrapper_add_localv(w,lname,local,NIL); + i++; + } + p = nextSibling(p); } return(i); } @@ -173,27 +173,21 @@ int Swig_cargs(Wrapper *w, ParmList *p) { * function call. * ----------------------------------------------------------------------------- */ -void Swig_cresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_char *decl) { +String *Swig_cresult(SwigType *t, const String_or_char *name, const String_or_char *decl) { String *fcall; fcall = NewString(""); - - if (SwigType_type(t) != T_VOID) - Wrapper_add_localv(w,name, Swig_clocal(t,name,0), 0); - switch(SwigType_type(t)) { case T_VOID: break; - case T_USER: - SwigType_add_pointer(t); - Printf(fcall,"%s = (%s) malloc(sizeof(", name, SwigType_lstr(t,0)); - SwigType_del_pointer(t); - Printf(fcall, "%s));\n", SwigType_str(t,0)); - Printf(fcall, "*(%s) = ", name); - break; case T_REFERENCE: + Printf(fcall,"{\n"); Printf(fcall,"%s = ", SwigType_str(t,"_result_ref")); break; + case T_USER: + Printf(fcall,"%s = ", name); + break; + default: /* Normal return value */ Printf(fcall,"%s = (%s)", name, SwigType_lstr(t,0)); @@ -201,7 +195,7 @@ void Swig_cresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_char } /* Now print out function call */ - Printv(fcall,decl,0); + Printv(fcall,decl,NIL); /* A sick hack */ { @@ -213,75 +207,9 @@ void Swig_cresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_char if (SwigType_type(t) == T_REFERENCE) { Printf(fcall,"%s = (%s) &_result_ref;\n", name, SwigType_lstr(t,0)); + Printf(fcall,"}\n"); } - - if (Replace(w,"$function",fcall, DOH_REPLACE_ANY) == 0) { - Printv(w, fcall, 0); - } - Delete(fcall); -} - -/* ----------------------------------------------------------------------------- - * Swig_cppresult() - * - * This function generates the C++ code needed to set the result. This uses - * the C++ default copy constructor for user defined objects. - * ----------------------------------------------------------------------------- */ - -void Swig_cppresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_char *decl) { - String *fcall; - - fcall = NewString(""); - if (SwigType_type(t) != T_VOID) - Wrapper_add_localv(w,name, Swig_clocal(t,name,0), 0); - - switch(SwigType_type(t)) { - case T_VOID: - break; - case T_USER: - { - SwigType *temp = Copy(t); - while (SwigType_isconst(temp)) { - SwigType_pop(temp); - } - Printf(fcall, "%s = new %s(", name, SwigType_str(temp,0)); - Delete(temp); - } - break; - case T_REFERENCE: - Printf(fcall, "%s = ", SwigType_str(t,"_result_ref")); - break; - default: - Printf(fcall,"%s = (%s)", name, SwigType_lstr(t,0)); - break; - } - - /* Now print out function call */ - Printv(fcall, decl, 0); - - switch(SwigType_type(t)) { - case T_USER: - Printf(fcall,");\n"); - break; - case T_REFERENCE: - Printf(fcall,";\n"); - Printf(fcall, "%s = (%s) &_result_ref;\n", name, SwigType_lstr(t,0)); - break; - default: - /* A sick hack */ - { - char *c = Char(decl) + Len(decl) - 1; - if (!((*c == ';') || (*c == '}'))) - Printf(fcall, ";"); - } - Printf(fcall,"\n"); - break; - } - - if (Replace(w,"$function",fcall, DOH_REPLACE_ANY) == 0) { - Printv(w, fcall, 0); - } - Delete(fcall); + return fcall; } /* ----------------------------------------------------------------------------- @@ -296,25 +224,31 @@ void Swig_cppresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_cha String * Swig_cfunction_call(String_or_char *name, ParmList *parms) { - DOH *func; + String *func; int i = 0; + int comma = 0; Parm *p = parms; SwigType *pt; + String *nname; func = NewString(""); - Printf(func,"%s(", name); + nname = SwigType_namestr(name); + Printf(func,"%s(", nname); while (p) { String *pname; - pt = Gettype(p); - pname = Swig_cparm_name(p,i); - Printf(func,"%s", Swig_clocal_deref(pt, pname)); - i++; - p = Getnext(p); - if (p) - Printf(func,","); + pt = Getattr(p,"type"); + + if ((SwigType_type(pt) != T_VOID)) { + if (comma) Printf(func,","); + pname = Swig_cparm_name(p,i); + Printf(func,"%s", SwigType_rcaststr(pt, pname)); + comma = 1; + i++; + } + p = nextSibling(p); } Printf(func,")"); - return Swig_temp_result(func); + return func; } /* ----------------------------------------------------------------------------- @@ -324,32 +258,58 @@ Swig_cfunction_call(String_or_char *name, ParmList *parms) { * * arg0->name(arg1, arg2, arg3, ..., argn) * + * self is an argument that defines how to handle the first argument. Normally, + * it should be set to "this->". With C++ proxy classes enabled, it could be + * set to "(*this)->" or some similar sequence. * ----------------------------------------------------------------------------- */ String * -Swig_cmethod_call(String_or_char *name, ParmList *parms) { - DOH *func; +Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self) { + String *func, *nname; int i = 0; Parm *p = parms; SwigType *pt; + int comma = 0; + + if (!self) self = (char *) "(this)->"; func = NewString(""); - if (!p) return Swig_temp_result(func); - Printf(func,"%s->%s(", Swig_cparm_name(p,0), name); + nname = SwigType_namestr(name); + if (!p) return func; + Append(func,self); + pt = Getattr(p,"type"); + + /* If the method is invoked through a dereferenced pointer, we don't add any casts + (needed for smart pointers). Otherwise, we cast to the appropriate type */ + + if (Strstr(func,"*this")) { + Replaceall(func,"this", Swig_cparm_name(p,0)); + } else { + Replaceall(func,"this", SwigType_rcaststr(pt, Swig_cparm_name(p,0))); + } + + if (SwigType_istemplate(name)) { + Printf(func,"template %s(", nname); + } else { + Printf(func,"%s(", nname); + } i++; - p = Getnext(p); + p = nextSibling(p); while (p) { String *pname; - pt = Gettype(p); - pname = Swig_cparm_name(p,i); - Printf(func,"%s", Swig_clocal_deref(pt, pname)); - i++; - p = Getnext(p); - if (p) - Printf(func,","); + pt = Getattr(p,"type"); + if ((SwigType_type(pt) != T_VOID)) { + if (comma) Printf(func,","); + pname = Swig_cparm_name(p,i); + Printf(func,"%s", SwigType_rcaststr(pt, pname)); + comma = 1; + i++; + } + p = nextSibling(p); } Printf(func,")"); - return Swig_temp_result(func); + Delete(nname); + return func; } /* ----------------------------------------------------------------------------- @@ -366,7 +326,7 @@ Swig_cconstructor_call(String_or_char *name) { func = NewString(""); Printf(func,"(%s *) calloc(1, sizeof(%s))", name, name); - return Swig_temp_result(func); + return func; } @@ -382,24 +342,30 @@ Swig_cconstructor_call(String_or_char *name) { String * Swig_cppconstructor_call(String_or_char *name, ParmList *parms) { - DOH *func; + String *func; + String *nname; int i = 0; + int comma = 0; Parm *p = parms; SwigType *pt; + nname = SwigType_namestr(name); func = NewString(""); - Printf(func,"new %s(", name); + Printf(func,"new %s(", nname); while (p) { String *pname; - pt = Gettype(p); - pname = Swig_cparm_name(p,i); - Printf(func,"%s", Swig_clocal_deref(pt, pname)); - i++; - p = Getnext(p); - if (p) - Printf(func,","); + pt = Getattr(p,"type"); + if ((SwigType_type(pt) != T_VOID)) { + if (comma) Printf(func,","); + pname = Swig_cparm_name(p,i); + Printf(func,"%s", SwigType_rcaststr(pt, pname)); + comma = 1; + i++; + } + p = nextSibling(p); } Printf(func,")"); - return Swig_temp_result(func); + Delete(nname); + return func; } @@ -413,12 +379,10 @@ Swig_cppconstructor_call(String_or_char *name, ParmList *parms) { String * Swig_cdestructor_call() { - DOH *func; - + String *func; func = NewString(""); - Printf(func,"free((char *) %s)", Swig_cparm_name(0,0)); - return Swig_temp_result(func); + return func; } @@ -432,11 +396,11 @@ Swig_cdestructor_call() { String * Swig_cppdestructor_call() { - DOH *func; + String *func; func = NewString(""); Printf(func,"delete %s", Swig_cparm_name(0,0)); - return Swig_temp_result(func); + return func; } /* ----------------------------------------------------------------------------- @@ -449,22 +413,17 @@ Swig_cppdestructor_call() { * ----------------------------------------------------------------------------- */ String * -Swig_cmemberset_call(String_or_char *name, SwigType *type) { - DOH *func; +Swig_cmemberset_call(String_or_char *name, SwigType *type, String_or_char *self) { + String *func; func = NewString(""); - - /* - if (SwigType_type(type) == T_USER) { - Printf(func,"%s %s->%s; ", Swig_clocal_assign(type,""), Swig_cparm_name(0,0), name); - } else { - Printf(func,"%s ", Swig_clocal_assign(type,"")); + if (!self) self = NewString("(this)->"); + else self = NewString(self); + Replaceall(self,"this",Swig_cparm_name(0,0)); + if (SwigType_type(type) != T_ARRAY) { + Printf(func,"if (%s) %s%s = %s",Swig_cparm_name(0,0), self,name, Swig_wrapped_var_deref(type, Swig_cparm_name(0,1))); } - */ - /* Printf(func,"(%s->%s = ", Swig_cparm_name(0,0), name); - Printf(func,"%s)", Swig_clocal_deref(type, (pname = Swig_cparm_name(0,1)))); - */ - Printf(func,"%s->%s = %s",Swig_cparm_name(0,0),name, Swig_clocal_deref(type, Swig_cparm_name(0,1))); - return Swig_temp_result(func); + Delete(self); + return(func); } @@ -478,499 +437,358 @@ Swig_cmemberset_call(String_or_char *name, SwigType *type) { * ----------------------------------------------------------------------------- */ String * -Swig_cmemberget_call(String_or_char *name, SwigType *t) { - DOH *func; - +Swig_cmemberget_call(String_or_char *name, SwigType *t, String_or_char *self) { + String *func; + if (!self) self = NewString("(this)->"); + else self = NewString(self); + Replaceall(self,"this",Swig_cparm_name(0,0)); func = NewString(""); - Printf(func,"%s (%s->%s)", Swig_clocal_assign(t,""),Swig_cparm_name(0,0), name); - return Swig_temp_result(func); -} - - -static void fix_parm_names(ParmList *p) { - int i = 0; - while (p) { - if (!Getname(p)) { - char temp[64]; - sprintf(temp,"arg%d",i); - Setname(p,temp); - } - i++; - p = Getnext(p); - } + Printf(func,"%s (%s%s)", Swig_wrapped_var_assign(t,""),self, name); + Delete(self); + return func; } /* ----------------------------------------------------------------------------- - * Swig_cfunction_wrapper() + * Swig_MethodToFunction(Node *n) * - * This function creates a C wrapper around a C++ method. Returns a Wrapper - * object containing the code, parameters, and so forth. + * Converts a C++ method node to a function accessor function. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cfunction_wrapper(String_or_char *funcname, - SwigType *rtype, - ParmList *parms, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; +int +Swig_MethodToFunction(Node *n, String *classname, int flags) { + String *name, *qualifier; + ParmList *parms; + SwigType *type; + Parm *p; + String *self = 0; - w = NewWrapper(); + /* If smart pointer, change self derefencing */ + if (flags & CWRAP_SMART_POINTER) { + self = NewString("(*this)->"); + } + /* If node is a member template expansion, we don't allow added code */ - /* Set the name of the function */ - Setname(w,funcname); + if (Getattr(n,"templatetype")) flags &= ~(CWRAP_EXTEND); - l = CopyParmList(parms); - fix_parm_names(l); - Printf(w,"%s %s(%s) {\n", SwigType_str(rtype,0), funcname, ParmList_str(l)); - if (code) { - Printv(w, code, "\n", 0); + name = Getattr(n,"name"); + qualifier = Getattr(n,"qualifier"); + parms = CopyParmList(nonvoid_parms(Getattr(n,"parms"))); + + type = NewString(classname); + if (qualifier) { + SwigType_push(type,qualifier); } - - Printf(w,"}\n"); - Setattr(w,"type",rtype); - Setattr(w,"parms",l); - Delete(l); - return w; -} + SwigType_add_pointer(type); + p = NewParm(type,"self"); + Setattr(p,"hidden","1"); + set_nextSibling(p,parms); + Delete(type); -/* ----------------------------------------------------------------------------- - * Swig_cmethod_wrapper() - * - * This function creates a C wrapper around a C++ method. Returns a Wrapper - * object containing the code, parameters, and so forth. - * ----------------------------------------------------------------------------- */ - -Wrapper * -Swig_cmethod_wrapper(String_or_char *classname, - String_or_char *methodname, - SwigType *rtype, - ParmList *parms, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; - Parm *p; - SwigType *t; + /* Generate action code for the access */ + if (!(flags & CWRAP_EXTEND)) { + Setattr(n,"wrap:action", Swig_cresult(Getattr(n,"type"),"result", Swig_cmethod_call(name,p,self))); + } else { + String *code; + String *mangled; + String *membername = Swig_name_member(classname, name); + mangled = Swig_name_mangle(membername); - w = NewWrapper(); + code = Getattr(n,"code"); + type = Getattr(n,"type"); - /* Set the name of the function */ - Setname(w,Swig_name_member(classname, methodname)); + /* Check if the method is overloaded. If so, and it has code attached, we append an extra suffix + to avoid a name-clash in the generated wrappers. This allows overloaded methods to be defined + in C. */ - l = CopyParmList(parms); - t = NewString(classname); - SwigType_add_pointer(t); - p = NewParm(t,"self"); - Setnext(p,l); - Delete(t); - - l = p; - fix_parm_names(l); + if (Getattr(n,"sym:overloaded") && code) { + Append(mangled,Getattr(n,"sym:overname")); + } - Printf(w,"%s %s(%s) {\n", SwigType_str(rtype,0), Swig_name_member(classname, methodname), ParmList_str(l)); + Setattr(n,"wrap:action", Swig_cresult(Getattr(n,"type"),"result", Swig_cfunction_call(mangled,p))); - if (!code) { - /* No code supplied. Write a function manually */ - if (SwigType_type(rtype) != T_VOID) { - Printf(w,"return "); - } - - Printf(w,"self->%s(", methodname); - p = Getnext(l); - while (p) { - Printf(w,"%s", Getname(p)); - p = Getnext(p); - if (p) - Printf(w,","); + /* See if there is any code that we need to emit */ + if (code) { + String *body; + String *tmp = NewStringf("%s(%s)", mangled, ParmList_str(p)); + body = SwigType_str(type,tmp); + Delete(tmp); + Printv(body,code,"\n",NIL); + Setattr(n,"wrap:code",body); } - Printf(w,");\n"); - Printf(w,"}\n"); - } else { - Printv(w, code, "\n", 0); - Printf(w,"}\n"); + Delete(membername); + Delete(mangled); } - Setattr(w,"type",rtype); - Setattr(w,"parms",l); - Delete(l); - return w; + Setattr(n,"parms",p); + Delete(p); + Delete(self); + return SWIG_OK; } - /* ----------------------------------------------------------------------------- - * Swig_cconstructor_wrapper() + * Swig_ConstructorToFunction() * * This function creates a C wrapper for a C constructor function. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cconstructor_wrapper(String_or_char *classname, - ParmList *parms, - String_or_char *code) +int +Swig_ConstructorToFunction(Node *n, String *classname, int cplus, int flags) { - Wrapper *w; - ParmList *l; - SwigType *t; - - w = NewWrapper(); - - /* Set the name of the function */ - Setname(w,Swig_name_construct(classname)); - - l = CopyParmList(parms); - t = NewString(classname); - SwigType_add_pointer(t); - - /* Patch up the argument names */ - fix_parm_names(l); - - Printf(w,"%s %s(%s) {\n", SwigType_str(t,0), Swig_name_construct(classname), ParmList_str(l)); - - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"return (%s) calloc(1,sizeof(%s));\n", SwigType_str(t,0), classname); + ParmList *parms; + SwigType *type; + String *membername; + String *mangled; + membername = Swig_name_construct(classname); + mangled = Swig_name_mangle(membername); + + parms = CopyParmList(nonvoid_parms(Getattr(n,"parms"))); + type = NewString(classname); + SwigType_add_pointer(type); + + if (flags & CWRAP_EXTEND) { + String *code = Getattr(n,"code"); + if (code) { + String *wrap; + String *s = NewStringf("%s(%s)", mangled, ParmList_str(parms)); + wrap = SwigType_str(type,s); + Delete(s); + Printv(wrap,code,"\n",NIL); + Setattr(n,"wrap:code",wrap); + Delete(wrap); + } + Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cfunction_call(mangled,parms))); } else { - Printv(w, code, "\n", 0); + if (cplus) { + Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cppconstructor_call(classname,parms))); + } else { + Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cconstructor_call(classname))); + } } - Printf(w,"}\n"); - Setattr(w,"type",t); - Setattr(w,"parms",l); - Delete(l); - Delete(t); - return w; + Setattr(n,"type",type); + Setattr(n,"parms", parms); + Delete(type); + Delete(parms); + Delete(mangled); + Delete(membername); + return SWIG_OK; } /* ----------------------------------------------------------------------------- - * Swig_cppconstructor_wrapper() + * Swig_DestructorToFunction() * - * This function creates a C wrapper for a C++ constructor function. + * This function creates a C wrapper for a destructor function. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cppconstructor_wrapper(String_or_char *classname, - ParmList *parms, - String_or_char *code) +int +Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags) { - Wrapper *w; - ParmList *l; - SwigType *t; + SwigType *type; Parm *p; - w = NewWrapper(); - - /* Set the name of the function */ - Setname(w,Swig_name_construct(classname)); - - l = CopyParmList(parms); - t = NewString(classname); - SwigType_add_pointer(t); - - /* Patch up the argument names */ - fix_parm_names(l); - - Printf(w,"%s %s(%s) {\n", SwigType_str(t,0), Swig_name_construct(classname), ParmList_str(l)); - - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"return new %s", SwigType_str(t,0)); - p = l; - if (p) { - Printf(w,"("); - while (p) { - Printf(w,"%s", Getname(p)); - p = Getnext(p); - if (p) - Printf(w,","); - } - Printf(w,")"); + type = NewString(classname); + SwigType_add_pointer(type); + p = NewParm(type,"self"); + Delete(type); + type = NewString("void"); + + if (flags & CWRAP_EXTEND) { + String *membername, *mangled, *code; + membername = Swig_name_destroy(classname); + mangled = Swig_name_mangle(membername); + code = Getattr(n,"code"); + if (code) { + String *s = NewStringf("void %s(%s)", mangled, ParmList_str(p)); + Printv(s,code,"\n",NIL); + Setattr(n,"wrap:code",s); + Delete(s); } - Printf(w,";\n"); + Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cfunction_call(mangled,p))); + Delete(membername); + Delete(mangled); } else { - Printv(w, code, "\n", 0); + if (cplus) { + Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cppdestructor_call())); + } else { + Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cdestructor_call())); + } } - Printf(w,"}\n"); - Setattr(w,"type",t); - Setattr(w,"parms",l); - Delete(l); - Delete(t); - return w; + Setattr(n,"type",type); + Setattr(n,"parms", p); + Delete(type); + Delete(p); + return SWIG_OK; } - /* ----------------------------------------------------------------------------- - * Swig_cdestructor_wrapper() + * Swig_MembersetToFunction() * - * This function creates a C wrapper for a C destructor. + * This function creates a C wrapper for setting a structure member. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cdestructor_wrapper(String_or_char *classname, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; - SwigType *t; +int +Swig_MembersetToFunction(Node *n, String *classname, int flags) { + String *name; + ParmList *parms; Parm *p; + SwigType *t; + SwigType *ty; + SwigType *type; + String *membername; + String *mangled; + String *self= 0; - w = NewWrapper(); - - /* Set the name of the function */ - Setname(w, Swig_name_destroy(classname)); - - t = NewString(classname); - SwigType_add_pointer(t); - p = NewParm(t,"self"); - l = p; - Delete(t); - - t = NewString("void"); - - Printf(w,"%s %s(%s) {\n", SwigType_str(t,0), Swig_name_destroy(classname), ParmList_str(l)); - - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"free((char *) self);\n"); - } else { - Printv(w, code, "\n", 0); + if (flags & CWRAP_SMART_POINTER) { + self = NewString("(*this)->"); } - Printf(w,"}\n"); - Setattr(w,"type",t); - Setattr(w,"parms",l); - Delete(l); - Delete(t); - return w; -} - - -/* ----------------------------------------------------------------------------- - * Swig_cppdestructor_wrapper() - * - * This function creates a C wrapper for a C++ destructor. - * ----------------------------------------------------------------------------- */ - -Wrapper * -Swig_cppdestructor_wrapper(String_or_char *classname, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; - SwigType *t; - Parm *p; - w = NewWrapper(); + name = Getattr(n,"name"); + type = Getattr(n,"type"); - /* Set the name of the function */ - Setname(w, Swig_name_destroy(classname)); + membername = Swig_name_member(classname, Swig_name_set(name)); + mangled = Swig_name_mangle(membername); t = NewString(classname); SwigType_add_pointer(t); - p = NewParm(t,"self"); - - l = p; + parms = NewParm(t,"self"); Delete(t); - t = NewString("void"); - - Printf(w,"%s %s(%s) {\n", SwigType_str(t,0), Swig_name_destroy(classname), ParmList_str(l)); + ty = Swig_wrapped_var_type(type); + p = NewParm(ty,name); + set_nextSibling(parms,p); - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"delete self;\n"); + /* If the type is a pointer or reference. We mark it with a special wrap:disown attribute */ + if (SwigType_check_decl(type,"p.")) { + Setattr(p,"wrap:disown","1"); + } + Delete(p); + + if (flags & CWRAP_EXTEND) { + String *code = Getattr(n,"code"); + if (code) { + String *s = NewStringf("void %s(%s)", mangled, ParmList_str(parms)); + Printv(s,code,"\n",NIL); + Setattr(n,"wrap:code",s); + Delete(s); + } + Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cfunction_call(mangled,parms))); } else { - Printv(w, code, "\n", 0); + Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cmemberset_call(name,type,self))); } - Printf(w,"}\n"); - Setattr(w,"type",t); - Setattr(w,"parms",l); - Delete(l); - Delete(t); - return w; + Setattr(n,"type","void"); + Setattr(n,"parms", parms); + Delete(parms); + Delete(ty); + Delete(membername); + Delete(mangled); + Delete(self); + return SWIG_OK; } /* ----------------------------------------------------------------------------- - * Swig_cmemberset_wrapper() + * Swig_MembergetToFunction() * - * This function creates a C wrapper for setting a C++ structure member. + * This function creates a C wrapper for setting a structure member. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cmemberset_wrapper(String_or_char *classname, - String_or_char *membername, - SwigType *type, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; - Parm *p; +int +Swig_MembergetToFunction(Node *n, String *classname, int flags) { + String *name; + ParmList *parms; SwigType *t; - SwigType *lt; - - w = NewWrapper(); - - /* Set the name of the function */ - Setname(w, Swig_name_member(classname, Swig_name_set(membername))); - - t = NewString(classname); - SwigType_add_pointer(t); - p = NewParm(t,"self"); - l = p; - Delete(t); - - lt = Swig_clocal_type(type); - p = NewParm(lt,"value"); - Setnext(l,p); - - Printf(w,"void %s(%s) {\n", Getname(w), ParmList_str(l)); + SwigType *ty; + SwigType *type; + String *membername; + String *mangled; + String *self = 0; - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"self->%s = %s;\n", membername, Swig_clocal_deref(lt,"value")); - Printf(w,"return %s self->%s;\n", Swig_clocal_assign(lt,""), membername); - } else { - Printv(w, code, "\n", 0); + if (flags & CWRAP_SMART_POINTER) { + self = NewString("(*this)->"); } - Printf(w,"}\n"); - /* Wrapper_Settype(w,lt); */ - Setattr(w,"type","void"); - Setattr(w,"parms", l); - Delete(l); - Delete(lt); - return w; -} + name = Getattr(n,"name"); + type = Getattr(n,"type"); -/* ----------------------------------------------------------------------------- - * Swig_cmemberget_wrapper() - * - * This function creates a C wrapper for getting a structure member - * ----------------------------------------------------------------------------- */ - -Wrapper * -Swig_cmemberget_wrapper(String_or_char *classname, - String_or_char *membername, - SwigType *type, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; - Parm *p; - SwigType *t; - SwigType *lt; - - w = NewWrapper(); - - /* Set the name of the function */ - Setname(w,Swig_name_member(classname, Swig_name_get(membername))); + membername = Swig_name_member(classname, Swig_name_get(name)); + mangled = Swig_name_mangle(membername); t = NewString(classname); SwigType_add_pointer(t); - p = NewParm(t,"self"); - l = p; + parms = NewParm(t,"self"); Delete(t); - lt = Swig_clocal_type(type); - Printf(w,"%s %s(%s) {\n", SwigType_str(lt,0), Getname(w), ParmList_str(l)); - - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"return %s self->%s;", Swig_clocal_assign(lt,""), membername); + ty = Swig_wrapped_var_type(type); + if (flags & CWRAP_EXTEND) { + String *code = Getattr(n,"code"); + if (code) { + String *tmp = NewStringf("%s(%s)", mangled, ParmList_str(parms)); + String *s = SwigType_str(ty,tmp); + Delete(tmp); + Printv(s,code,"\n",NIL); + Setattr(n,"wrap:code",s); + Delete(s); + } + Setattr(n,"wrap:action", Swig_cresult(ty,"result",Swig_cfunction_call(mangled,parms))); } else { - Printv(w, code, "\n", 0); + Setattr(n,"wrap:action", Swig_cresult(ty,"result",Swig_cmemberget_call(name,type,self))); } - Printf(w,"}\n"); - Setattr(w,"type",lt); - Setattr(w,"parms",l); - Delete(l); - Delete(lt); - return w; + Setattr(n,"type",ty); + Setattr(n,"parms", parms); + Delete(parms); + Delete(ty); + Delete(membername); + Delete(mangled); + return SWIG_OK; } /* ----------------------------------------------------------------------------- - * Swig_cvarset_wrapper() + * Swig_VarsetToFunction() * * This function creates a C wrapper for setting a global variable. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cvarset_wrapper(String_or_char *varname, - SwigType *type, - String_or_char *code) -{ - Wrapper *w; - ParmList *l; - Parm *p; - SwigType *lt; +int +Swig_VarsetToFunction(Node *n) { + String *name,*nname; + ParmList *parms; + SwigType *type, *ty; - w = NewWrapper(); + name = Getattr(n,"name"); + type = Getattr(n,"type"); - /* Set the name of the function */ - Setname(w,Swig_name_set(varname)); + nname = SwigType_namestr(name); - lt = Swig_clocal_type(type); - p = NewParm(lt,"value"); - l = p; + ty = Swig_wrapped_var_type(type); + parms = NewParm(ty,"value"); + Delete(ty); - Printf(w,"%s %s(%s) {\n", SwigType_str(lt,0), Getname(w), ParmList_str(l)); - - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"%s = %s;\n", varname, Swig_clocal_deref(lt,"value")); - Printf(w,"return %s;\n", Swig_clocal_assign(lt,varname)); - } else { - Printv(w, code, "\n", 0); - Replace(w,"$target",varname, DOH_REPLACE_ANY); - Replace(w,"$source","value", DOH_REPLACE_ANY); - Replace(w,"$ltype", SwigType_str(lt,""), DOH_REPLACE_ANY); - Replace(w,"$rtype", SwigType_str(type,""), DOH_REPLACE_ANY); - } - Printf(w,"}\n"); - Setattr(w,"type",lt); - Setattr(w,"parms",l); - Delete(l); - Delete(lt); - return w; + Setattr(n,"wrap:action", NewStringf("%s = %s;\n", nname, Swig_wrapped_var_deref(type,Swig_cparm_name(0,0)))); + Setattr(n,"type","void"); + Setattr(n,"parms",parms); + Delete(parms); + Delete(nname); + return SWIG_OK; } /* ----------------------------------------------------------------------------- - * Swig_cvarget_wrapper() + * Swig_VargetToFunction() * - * This function creates a C wrapper for getting a structure member + * This function creates a C wrapper for getting a global variable. * ----------------------------------------------------------------------------- */ -Wrapper * -Swig_cvarget_wrapper(String_or_char *varname, - SwigType *type, - String_or_char *code) -{ - Wrapper *w; - ParmList *l = 0; - SwigType *lt; - - w = NewWrapper(); - - /* Set the name of the function */ - Setname(w,Swig_name_get(varname)); +int +Swig_VargetToFunction(Node *n) { + String *name, *nname; + SwigType *type, *ty; - lt = Swig_clocal_type(type); + name = Getattr(n,"name"); + type = Getattr(n,"type"); - Printf(w,"%s %s(%s) {\n", SwigType_str(lt,0), Getname(w), ParmList_str(l)); + nname = SwigType_namestr(name); + ty = Swig_wrapped_var_type(type); - if (!code) { - /* No code supplied. Write a function manually */ - Printf(w,"return %s;", Swig_clocal_assign(type,varname)); - } else { - Printv(w, code, "\n", 0); - } - Printf(w,"}\n"); - Setattr(w,"type",lt); - Setattr(w,"parms",l); - Delete(l); - Delete(lt); - return w; + Setattr(n,"wrap:action", Swig_cresult(ty,"result",Swig_wrapped_var_assign(type,nname))); + Setattr(n,"type",ty); + Delattr(n,"parms"); + Delete(nname); + Delete(ty); + return SWIG_OK; } - - - - - diff --git a/Source/Swig/error.c b/Source/Swig/error.c new file mode 100644 index 000000000..a728510eb --- /dev/null +++ b/Source/Swig/error.c @@ -0,0 +1,198 @@ +/* ----------------------------------------------------------------------------- + * error.c + * + * Error handling functions. These are used to issue warnings and + * error messages. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +#include "swig.h" +#include <stdarg.h> +#include <ctype.h> + +char cvsroot_error_c[] = "$Header$"; + +/* ----------------------------------------------------------------------------- + * Commentary on the warning filter. + * + * The warning filter is a string of numbers prefaced by (-) or (+) to + * indicate whether or not a warning message is displayed. For example: + * + * "-304-201-140+210+201" + * + * The filter string is scanned left to right and the first occurrence + * of a warning number is used to determine printing behavior. + * + * The same number may appear more than once in the string. For example, in the + * above string, "201" appears twice. This simply means that warning 201 + * was disabled after it was previously enabled. This may only be temporary + * setting--the first number may be removed later in which case the warning + * is reenabled. + * ----------------------------------------------------------------------------- */ + +static int silence = 0; /* Silent operation */ +static String *filter = 0; /* Warning filter */ +static int warnall = 0; +static int nwarning = 0; + +/* ----------------------------------------------------------------------------- + * Swig_warning() + * + * Issue a warning message + * ----------------------------------------------------------------------------- */ + +void +Swig_warning(int wnum, const String_or_char *filename, int line, const char *fmt, ...) { + String *out; + char *msg; + int wrn = 1; + va_list ap; + if (silence) return; + + va_start(ap,fmt); + + out = NewString(""); + vPrintf(out,fmt,ap); + { + char temp[64], *t; + t = temp; + msg = Char(out); + while (isdigit(*msg)) { + *(t++) = *(msg++); + } + if (t != temp) { + msg++; + wnum = atoi(temp); + } + } + + /* Check in the warning filter */ + if (filter) { + char temp[32]; + char *c; + sprintf(temp,"%d",wnum); + c = Strstr(filter,temp); + if (c) { + if (*(c-1) == '-') wrn = 0; /* Warning disabled */ + if (*(c-1) == '+') wrn = 1; /* Warning enabled */ + } + } + if (warnall || wrn) { + if (wnum) { + Printf(stderr,"%s:%d: Warning(%d): ", filename, line, wnum); + } else { + Printf(stderr,"%s:%d: Warning: ", filename, line, wnum); + } + Printf(stderr,"%s",msg); + nwarning++; + } + Delete(out); + va_end(ap); +} + +/* ----------------------------------------------------------------------------- + * Swig_error() + * + * Issue an error message + * ----------------------------------------------------------------------------- */ + +static int nerrors = 0; + +void +Swig_error(const String_or_char *filename, int line, const char *fmt, ...) { + va_list ap; + + if (silence) return; + + va_start(ap,fmt); + if (line > 0) { + Printf(stderr,"%s:%d: ", filename, line); + } else { + Printf(stderr,"%s:EOF: ", filename); + } + vPrintf(stderr,fmt,ap); + va_end(ap); + nerrors++; +} + +/* ----------------------------------------------------------------------------- + * Swig_error_count() + * + * Returns number of errors received. + * ----------------------------------------------------------------------------- */ + +int +Swig_error_count(void) { + return nerrors; +} + +/* ----------------------------------------------------------------------------- + * Swig_error_silent() + * + * Set silent flag + * ----------------------------------------------------------------------------- */ + +void +Swig_error_silent(int s) { + silence = s; +} + + +/* ----------------------------------------------------------------------------- + * Swig_warnfilter() + * + * Takes a comma separate list of warning numbers and puts in the filter. + * ----------------------------------------------------------------------------- */ + +void +Swig_warnfilter(const String_or_char *wlist, int add) { + char *c; + String *s; + + if (!filter) filter = NewString(""); + s = NewString(wlist); + c = Char(s); + c = strtok(c,", "); + while (c) { + if (isdigit(*c) || (*c == '+') || (*c == '-')) { + if (add) { + Insert(filter,0,c); + if (isdigit(*c)) { + Insert(filter,0,"-"); + } + } else { + char temp[32]; + if (isdigit(*c)) { + sprintf(temp,"-%s",c); + } else { + strcpy(temp,c); + } + Replace(filter,temp,"", DOH_REPLACE_FIRST); + } + } + c = strtok(NULL,", "); + } + Delete(s); +} + +void +Swig_warnall(void) { + warnall = 1; +} + + +/* ----------------------------------------------------------------------------- + * Swig_warn_count() + * + * Return the number of warnings + * ----------------------------------------------------------------------------- */ + +int +Swig_warn_count(void) { + return nwarning; +} + diff --git a/Source/Swig/fragment.c b/Source/Swig/fragment.c new file mode 100644 index 000000000..b039759a3 --- /dev/null +++ b/Source/Swig/fragment.c @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------- + * fragment.c + * + * This file manages named code fragments. Code fragments are typically + * used to hold helper-code that may or may not be included in the wrapper + * file (depending on what features are actually used in the interface). + * + * By using fragments, it's possible to greatly reduce the amount of + * wrapper code and to generate cleaner wrapper files. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_fragment_c[] = "$Header$"; + +#include "swig.h" + +static Hash *fragments = 0; + +/* ----------------------------------------------------------------------------- + * Swig_fragment_register() + * + * Add a fragment. + * ----------------------------------------------------------------------------- */ + +void +Swig_fragment_register(String *name, String *section, String *code) { + String *ccode; + if (!fragments) { + fragments = NewHash(); + } + ccode = Copy(code); + Setmeta(ccode,"section",Copy(section)); + Setattr(fragments,Copy(name),ccode); +} + +/* ----------------------------------------------------------------------------- + * Swig_fragment_emit() + * + * Emit a fragment + * ----------------------------------------------------------------------------- */ + +void +Swig_fragment_emit(String *name) { + String *code; + if (!fragments) return; + + code = Getattr(fragments,name); + if (code) { + String *section = Getmeta(code,"section"); + if (section) { + File *f = Swig_filebyname(section); + if (!f) { + Swig_error(Getfile(code),Getline(code),"Bad section '%s' for code fragment '%s'\n", section,name); + } else { + Printf(f,"%s\n",code); + } + } + Delattr(fragments,name); + } +} diff --git a/Source/Swig/getopt.c b/Source/Swig/getopt.c index 7c71bee8b..77f53cf9b 100644 --- a/Source/Swig/getopt.c +++ b/Source/Swig/getopt.c @@ -18,7 +18,7 @@ * Should have cleaner error handling in general. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_getopt_c[] = "$Header$"; #include "swig.h" diff --git a/Source/Swig/include.c b/Source/Swig/include.c index 9d0bc24cd..288bd662d 100644 --- a/Source/Swig/include.c +++ b/Source/Swig/include.c @@ -11,7 +11,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_include_c[] = "$Header$"; #include "swig.h" @@ -19,7 +19,6 @@ static char cvsroot[] = "$Header$"; static List *directories = 0; /* List of include directories */ static String *lastpath = 0; /* Last file that was included */ -static int bytes_read = 0; /* Bytes read */ static String *swiglib = 0; /* Location of SWIG library */ static String *lang_config = 0; /* Language configuration file */ @@ -178,7 +177,6 @@ Swig_read_file(FILE *f) { * Opens a file and returns it as a string. * ----------------------------------------------------------------------------- */ -static int readbytes = 0; String * Swig_include(const String_or_char *name) { FILE *f; @@ -187,20 +185,13 @@ Swig_include(const String_or_char *name) { f = Swig_open(name); if (!f) return 0; str = Swig_read_file(f); - bytes_read = bytes_read + Len(str); fclose(f); Seek(str,0,SEEK_SET); Setfile(str,lastpath); Setline(str,1); - readbytes += Len(str); return str; } -int -Swig_bytes_read() { - return readbytes; -} - /* ----------------------------------------------------------------------------- * Swig_insert_file() * @@ -249,4 +240,82 @@ Swig_filebyname(const String_or_char *filename) { return Getattr(named_files,filename); } +/* ----------------------------------------------------------------------------- + * Swig_file_suffix() + * + * Returns the suffix of a file + * ----------------------------------------------------------------------------- */ + +char * +Swig_file_suffix(const String_or_char *filename) { + char *d; + char *c = Char(filename); + if (strlen(c)) { + d = c + Len(filename) - 1; + while (d != c) { + if (*d == '.') return d; + d--; + } + return c+Len(filename); + } + return c; +} + +/* ----------------------------------------------------------------------------- + * Swig_file_basename() + * + * Returns the filename with no suffix attached. + * ----------------------------------------------------------------------------- */ +char * +Swig_file_basename(const String_or_char *filename) +{ + static char tmp[1024]; + char *c; + strcpy(tmp,Char(filename)); + c = Swig_file_suffix(tmp); + *c = 0; + return tmp; +} + +/* ----------------------------------------------------------------------------- + * Swig_file_filename() + * + * Return the file with any leading path stripped off + * ----------------------------------------------------------------------------- */ +char * +Swig_file_filename(const String_or_char *filename) +{ + static char tmp[1024]; + const char *delim = SWIG_FILE_DELIMETER; + char *c; + + strcpy(tmp,Char(filename)); + if ((c=strrchr(tmp,*delim))) return c+1; + else return tmp; +} + +/* ----------------------------------------------------------------------------- + * Swig_file_dirname() + * + * Return the name of the directory associated with a file + * ----------------------------------------------------------------------------- */ +char * +Swig_file_dirname(const String_or_char *filename) +{ + static char tmp[1024]; + const char *delim = SWIG_FILE_DELIMETER; + char *c; + strcpy(tmp,Char(filename)); + if (!strstr(tmp,delim)) { + return ""; + } + c = tmp + strlen(tmp) -1; + while (*c != *delim) c--; + *(++c) = 0; + return tmp; +} + + + + diff --git a/Source/Swig/main.c b/Source/Swig/main.c deleted file mode 100644 index 623d1a442..000000000 --- a/Source/Swig/main.c +++ /dev/null @@ -1,103 +0,0 @@ -/* ----------------------------------------------------------------------------- - * main.c - * - * SWIG main program. - * - * Author(s) : David Beazley (beazley@cs.uchicago.edu) - * - * Copyright (C) 1999-2000. The University of Chicago - * See the file LICENSE for information on usage and redistribution. - * ----------------------------------------------------------------------------- */ - -#include "swigconfig.h" -#include "swigver.h" -#include "swig.h" - -static char *usage = (char*)"\ -\nGeneral Options\n\ - -version - Print SWIG version number\n\ - -help - This output.\n\n"; - -/* ----------------------------------------------------------------------------- - * Swig_main() - * - * Entry point to SWIG. This should only be called after all of the available - * modules have been registered (presumably by the real main function). - * ----------------------------------------------------------------------------- */ - -int Swig_main(int argc, char **argv, char **modules) { - int i; - int help = 0; - int freeze = 0; - Hash *top = 0; - - /* Initialize the SWIG core */ - Swig_init(); - Swig_init_args(argc,argv); - - /* Look for command line options */ - for (i = 1; i < argc; i++) { - if (argv[i]) { - if (strcmp(argv[i],"-freeze") == 0) { - freeze= 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-version") == 0) { - fprintf(stderr,"\nSWIG Version %s %s\n", - SWIG_VERSION, SWIG_SPIN); - fprintf(stderr,"Copyright (c) 1995-1998, University of Utah and the Regents of the University of California\n"); - fprintf(stderr,"Copyright (c) 1998-2000, University of Chicago\n"); - Swig_exit (EXIT_SUCCESS); - } else if (strcmp(argv[i],"-help") == 0) { - Printf(stderr,"%s",usage); - Swig_mark_arg(i); - help = 1; - } else { - if (!Swig_check_marked(i)) { - Module *m; - m = Swig_load_module(argv[i]+1); - if (m) { - Swig_mark_arg(i); - Swig_init_module(m, argc, argv); - } - } - } - } - } - - /* Load the default modules (always enabled) */ - if (modules) { - int i = 0; - while (modules[i]) { - Module *m; - m = Swig_load_module(modules[i]); - if (m) { - Swig_init_module(m,argc,argv); - } else { - Printf(stderr,"Swig: default module '%s' not found!\n", modules[i]); - } - i++; - } - } - - if (help) Swig_exit(EXIT_SUCCESS); - /* Check the arguments */ - Swig_check_options(); - - /* Get the input file name and create a starting node */ - top = NewHash(); - Settag(top,"swig:initial"); - Setname(top,argv[argc-1]); - - /* Run the modules */ - Swig_run_modules(top); - - while(freeze); - return 0; -} - -void Swig_exit(int n) { - exit(n); -} - - - diff --git a/Source/Swig/map.c b/Source/Swig/map.c deleted file mode 100644 index f1384ba8a..000000000 --- a/Source/Swig/map.c +++ /dev/null @@ -1,352 +0,0 @@ -/* ----------------------------------------------------------------------------- - * map.c - * - * This file provides support for defining %map rules that match lists of - * parameters to objects defining code generation rules. - * - * Author(s) : David Beazley (beazley@cs.uchicago.edu) - * - * Copyright (C) 1999-2000. The University of Chicago - * See the file LICENSE for information on usage and redistribution. - * ----------------------------------------------------------------------------- */ - -static char cvsroot[] = "$Header$"; - -#include "swig.h" - -/* ----------------------------------------------------------------------------- - * Synopsis - * - * One of the problems in creating wrappers is that of defining rules for - * managing various datatypes and function parameters. In SWIG1.1, - * this sort of customization was managed using a mechanism known as - * "typemaps". This module generalizes the idea even further and provides - * generic set of functions that can be used to define and match rules - * that are associated with lists of datatypes. - * - * The functions in this file are intended to be rather generic. They are only - * responsible for the storage and matching of rules. Other parts of the - * code can use these to implement typemaps, argmaps, or anything else. - * ----------------------------------------------------------------------------- */ - -/* ----------------------------------------------------------------------------- - * Swig_map_add_parmrule() - * - * Adds a new mapping rule for a list of parameters. The parms input to this - * function should be a properly constructed parameter list with associated - * attributes (type and name). The 'obj' attribute can be any DOH object. - * - * The structure of how data might be stored is as follows: - * - * ruleset (hash) - * -------------- - * parm1 ---------> rule (hash) - * ------------- - * parm2 -----------> rule (hash) - * *obj* --> obj ------------ - * parm3 - * *obj* -->obj - * - * For multiple arguments, we end up building a large tree of hash tables. - * The object will be stored in the *obj* attribute of the last hash table. - * ----------------------------------------------------------------------------- */ - -void -Swig_map_add_parmrule(Hash *ruleset, Hash *parms, DOH *obj) -{ - Hash *p, *n; - - /* Walk down the parms list and create a series of hash tables */ - p = parms; - n = ruleset; - - while (p) { - String *ty, *name, *key; - Hash *nn; - ty = Getattr(p,"type"); - name = Getattr(p,"name"); - - /* Create a hash table key */ - - key = NewStringf("*map:%s-%s",name,ty); - - /* See if there is already a entry with this type in the table */ - nn = Getattr(n,key); - if (!nn) { - /* No. Go ahead and create it */ - nn = NewHash(); - Setattr(n,key,nn); - } - Delete(key); - n = nn; - p = Swig_next(p); - } - - /* No more parameters. At this point, n points to the very last hash table in our search. - We'll stick our object there */ - - Setattr(n,"*obj*",obj); -} - -/* ----------------------------------------------------------------------------- - * Swig_map_add_typerule() - * - * Adds a rule for a single type and name. - * ----------------------------------------------------------------------------- */ - -void -Swig_map_add_typerule(Hash *ruleset, DOH *type, String_or_char *name, DOH *obj) { - Hash *p; - - p = NewHash(); - Setattr(p,"type",type); - if (name) - Setattr(p,"name", name); - - Swig_map_add_parmrule(ruleset,p,obj); - Delete(p); -} - -typedef struct MatchObject { - Hash *ruleset; /* Hash table of rules */ - Hash *p; /* Parameter on which checking starts */ - int depth; /* Depth of the match */ - struct MatchObject *next; /* Next match object */ -} MatchObject; - - -static MatchObject *matchstack = 0; - -/* ----------------------------------------------------------------------------- - * Swig_map_match_parms() - * - * Perform a longest map match for a list of parameters and a set of mapping rules. - * Returns the corresponding rule object and the number of parameters that were - * matched. - * - * Note: If the ruleset has a 'parent' attribute, this function will walk its - * way up and try to find a match. This can be used to implement scoped - * mappings. - * ----------------------------------------------------------------------------- */ - -DOH * -Swig_map_match_parms(Hash *ruleset, Hash *parms, int *nmatch) -{ - MatchObject *mo; - - DOH *bestobj = 0; - int bestdepth = -1; - - *nmatch = 0; - - mo = (MatchObject *) malloc(sizeof(MatchObject)); - mo->ruleset = ruleset; - mo->depth = 0; - mo->p = parms; - mo->next = 0; - - matchstack = mo; - - /* Loop over all candidates until we find the best one */ - - while (matchstack) { - Hash *rs; - Hash *p; - int depth = 0; - DOH *obj; - String *key; - String *ty; - String *name; - String *nm; - int matched = 0; - - mo = matchstack; - /* See if there is a match at this level */ - rs = mo->ruleset; - obj = Getattr(rs,"*obj*"); - if (obj) { - if (mo->depth > bestdepth) { - bestdepth = mo->depth; - bestobj = obj; - } - } - p = mo->p; - - /* No more parameters. Oh well */ - if (!p) { - matchstack = mo->next; - free(mo); - continue; - } - - /* Generate some keys for checking the next parameter */ - - depth = mo->depth; - name = Getattr(p,"name"); - ty = Getattr(p,"type"); - - - if (!SwigType_isarray(ty)) { - key = NewStringf("*map:-%s",ty); - /* See if there is a generic name match for this type */ - nm = Getattr(rs,key); - if (nm) { - /* Yes! Add to our stack. Just reuse mo for this */ - mo->ruleset = nm; - mo->p = Swig_next(p); - mo->depth++; - mo = 0; - matched++; - } - - /* See if there is a specific name match for this type */ - Clear(key); - Printf(key,"*map:%s-%s",name,ty); - nm = Getattr(rs,key); - if (nm) { - if (!mo) { - mo = (MatchObject *) malloc(sizeof(MatchObject)); - mo->next = matchstack; - matchstack = mo; - } - mo->ruleset = nm; - mo->p = Swig_next(p); - mo->depth = depth+1; - matched++; - } - Delete(key); - } else { - /* The next parameter is an array. This is pretty nasty because we have to do a bunch of checks - related to array indices */ - - int ndim; - int i, j, n; - int ncheck; - String *ntype; - - key = NewString(""); - - /* Drop the mo record. This is too complicated */ - matchstack = mo->next; - free(mo); - mo = 0; - - /* Get the number of array dimensions */ - ndim = SwigType_array_ndim(ty); - - /* First, we test all of the generic-unnamed parameters */ - ncheck = 1 << ndim; - - j = ncheck-1; - for (i = 0; i < ncheck; i++, j--) { - int k = j; - ntype = Copy(ty); - for (n = 0; n < ndim; n++, k = k >> 1) { - if (k & 1) { - SwigType_array_setdim(ntype,n,""); - } - } - Clear(key); - Printf(key,"*map:-%s",ntype); - Printf(stdout,"matcharray : %s\n", key); - nm = Getattr(rs,key); - if (nm) { - mo = (MatchObject *) malloc(sizeof(MatchObject)); - mo->ruleset = nm; - mo->p = Swig_next(p); - mo->depth = depth+1; - mo->next = matchstack; - matchstack = mo; - matched++; - mo = 0; - } - Delete(ntype); - } - - /* Next check all of the named parameters */ - ncheck = 1 << ndim; - - j = ncheck-1; - for (i = 0; i < ncheck; i++, j--) { - int k = j; - ntype = Copy(ty); - for (n = 0; n < ndim; n++, k = k >> 1) { - if (k & 1) { - SwigType_array_setdim(ntype,n,""); - } - } - Clear(key); - Printf(key,"*map:%s-%s",name,ntype); - Printf(stdout,"matcharray : %s\n", key); - nm = Getattr(rs,key); - if (nm) { - mo = (MatchObject *) malloc(sizeof(MatchObject)); - mo->ruleset = nm; - mo->p = Swig_next(p); - mo->depth = depth+1; - mo->next = matchstack; - matchstack = mo; - matched++; - mo = 0; - } - Delete(ntype); - } - Delete(key); - } - if ((!matched) && mo) { - matchstack = mo->next; - free(mo); - } - } - if (bestobj) { - *nmatch = bestdepth; - } else { - /* If there is no match at all. I guess we can check for a default type */ - DOH *rs; - String *key; - String *dty = SwigType_default(Getattr(parms,"type")); - key = NewStringf("*map:-%s",dty); - - rs = Getattr(ruleset,key); - if (rs) { - bestobj = Getattr(rs,"*obj*"); - if (bestobj) *nmatch = 1; - } - Delete(key); - Delete(dty); - } - if (!bestobj) { - DOH *prules = Getattr(ruleset,"parent"); - if (prules) { - bestobj = Swig_map_match_parms(prules,parms,nmatch); - } - } - return bestobj; -} - -/* ----------------------------------------------------------------------------- - * Swig_map_match_type() - * - * Match a rule for a single type - * ----------------------------------------------------------------------------- */ - -DOH * -Swig_map_match_type(Hash *ruleset, DOH *type, String_or_char *name) { - Hash *p; - DOH *obj; - int nmatch; - - p = NewHash(); - Setattr(p,"type",type); - if (name) - Setattr(p,"name",name); - - obj = Swig_map_match_parms(ruleset,p,&nmatch); - Delete(p); - return obj; -} - - - - - diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 7899e4e37..e1217d513 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -9,7 +9,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_misc_c[] = "$Header$"; #include "swig.h" #include "swigver.h" @@ -42,73 +42,17 @@ Swig_banner(File *f) { Printf(f, "/* ----------------------------------------------------------------------------\n\ * This file was automatically generated by SWIG (http://www.swig.org).\n\ - * Version %s %s\n\ + * Version %s\n\ * \n\ * This file is not intended to be easily readable and contains a number of \n\ * coding conventions designed to improve portability and efficiency. Do not make\n\ * changes to this file unless you know what you are doing--modify the SWIG \n\ * interface file instead. \n\ - * ----------------------------------------------------------------------------- */\n\n", SWIG_VERSION, SWIG_SPIN); + * ----------------------------------------------------------------------------- */\n\n", SWIG_VERSION); } /* ----------------------------------------------------------------------------- - * Swig_section() - * - * Print a comment denoting a section of wrapper code - * ----------------------------------------------------------------------------- */ - -void Swig_section(File *f, const String_or_char *name) { - Printf(f,"/* -----------------------------------------------------------------------------\n"); - Printf(f," * %s\n", name); - Printf(f," * ----------------------------------------------------------------------------- */\n"); -} - -/* ----------------------------------------------------------------------------- - * Swig_temp_result() - * - * This function is used to return a "temporary" result--a result that is only - * guaranteed to exist for a short period of time. Typically this is used by - * functions that return strings and other intermediate results that are - * used in print statements. - * - * Note: this is really a bit of a kludge to make it easier to work with - * temporary variables (so that the caller doesn't have to worry about - * memory management). In theory, it is possible to break this if an - * operation produces so many temporaries that it overflows the internal - * array before they are used. However, in practice, this would only - * occur for very deep levels of recursion or functions taking lots of - * parameters---neither of which occur very often in SWIG (if at all). - * Also, a user can prevent destruction of a temporary object by increasing - * it's reference count using DohIncref(). - * - * It is an error to place two identical results onto this list. It is also - * an error for a caller to free anything returned by this function. - * - * Note: SWIG1.1 did something similar to this in a less-organized manner. - * ----------------------------------------------------------------------------- */ - -#define MAX_RESULT 512 - -static DOH *results[MAX_RESULT]; -static int results_index = 0; -static int results_init = 0; - -DOH *Swig_temp_result(DOH *x) { - int i; - if (!results_init) { - for (i = 0; i < MAX_RESULT; i++) results[i] = 0; - results_init = 1; - } - /* Printf(stdout,"results_index = %d, %x, '%s'\n", results_index, x, x); */ - if (results[results_index]) Delete(results[results_index]); - results[results_index] = x; - results_index = (results_index + 1) % MAX_RESULT; - return x; -} - - -/* ----------------------------------------------------------------------------- * Swig_string_escape() * * Takes a string object and produces a string with escape codes added to it. @@ -142,7 +86,108 @@ String *Swig_string_escape(String *s) { } return ns; } - + + +/* ----------------------------------------------------------------------------- + * Swig_string_upper() + * + * Takes a string object and convets it to all caps. + * ----------------------------------------------------------------------------- */ + +String *Swig_string_upper(String *s) { + String *ns; + int c; + ns = NewString(""); + + while ((c = Getc(s)) != EOF) { + Putc(toupper(c),ns); + } + return ns; +} + +/* ----------------------------------------------------------------------------- + * Swig_string_lower() + * + * Takes a string object and convets it to all lower. + * ----------------------------------------------------------------------------- */ + +String *Swig_string_lower(String *s) { + String *ns; + int c; + ns = NewString(""); + + while ((c = Getc(s)) != EOF) { + Putc(tolower(c),ns); + } + return ns; +} + + +/* ----------------------------------------------------------------------------- + * Swig_string_title() + * + * Takes a string object and convets it to all lower. + * ----------------------------------------------------------------------------- */ + +String *Swig_string_title(String *s) { + String *ns; + int first = 1; + int c; + ns = NewString(""); + + while ((c = Getc(s)) != EOF) { + Putc(first ? toupper(c) : tolower(c),ns); + first = 0; + } + return ns; +} + +/* ----------------------------------------------------------------------------- + * Swig_string_typecode() + * + * Takes a string with possible type-escapes in it and replaces them with + * real C datatypes. + * ----------------------------------------------------------------------------- */ + +String *Swig_string_typecode(String *s) { + String *ns; + int c; + String *tc; + ns = NewString(""); + while ((c = Getc(s)) != EOF) { + if (c == '`') { + tc = NewString(""); + while ((c = Getc(s)) != EOF) { + if (c == '`') break; + Putc(c,tc); + } + Printf(ns,"%s",SwigType_str(tc,0)); + } else { + Putc(c,ns); + if (c == '\'') { + while ((c = Getc(s)) != EOF) { + Putc(c,ns); + if (c == '\'') break; + if (c == '\\') { + c = Getc(s); + Putc(c,ns); + } + } + } else if (c == '\"') { + while ((c = Getc(s)) != EOF) { + Putc(c,ns); + if (c == '\"') break; + if (c == '\\') { + c = Getc(s); + Putc(c,ns); + } + } + } + } + } + return ns; +} + /* ----------------------------------------------------------------------------- * Swig_string_mangle() * @@ -160,28 +205,188 @@ String *Swig_string_mangle(String *s) { } /* ----------------------------------------------------------------------------- - * Swig_proto_cmp() + * Swig_scopename_prefix() * - * Compares a function prototype against an expected type-string. - * For example, Swig_proto_cmp("f(p.void,p.Tcl_Interp,int,p.p.char).int", node) + * Take a qualified name like "A::B::C" and return the scope name. + * In this case, "A::B". Returns NULL if there is no base. * ----------------------------------------------------------------------------- */ -int -Swig_proto_cmp(const String_or_char *pat, DOH *node) { - SwigType *ty; - SwigType *ct; - ParmList *p; - int r; - - ty = Gettype(node); - p = Getparms(node); - if (!ty || !p) return -1; - ct = Copy(ty); - SwigType_add_function(ct,p); - SwigType_strip_qualifiers(ct); - r = Cmp(pat,ct); - Delete(ct); - return r; +String * +Swig_scopename_prefix(String *s) { + char tmp[1024]; + char *c, *cc; + if (!Strstr(s,"::")) return 0; + strcpy(tmp,Char(s)); + c = tmp; + cc = c; + while (*c) { + if (strncmp(c,"::",2) == 0) { + cc = c; + c += 2; + } else { + if (*c == '<') { + int level = 1; + c++; + while (*c && level) { + if (*c == '<') level++; + if (*c == '>') level--; + c++; + } + } else { + c++; + } + } + } + + *cc = 0; + if (cc != tmp) { + return NewString(tmp); + } else { + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * Swig_scopename_last() + * + * Take a qualified name like "A::B::C" and returns the last. In this + * case, "C". + * ----------------------------------------------------------------------------- */ + +String * +Swig_scopename_last(String *s) { + char tmp[1024]; + char *c, *cc; + if (!Strstr(s,"::")) return NewString(s); + strcpy(tmp,Char(s)); + c = tmp; + cc = c; + + while (*c) { + if (strncmp(c,"::",2) == 0) { + cc = c; + c += 2; + } else { + if (*c == '<') { + int level = 1; + c++; + while (*c && level) { + if (*c == '<') level++; + if (*c == '>') level--; + c++; + } + } else { + c++; + } + } + } + return NewString(cc+2); +} + +/* ----------------------------------------------------------------------------- + * Swig_scopename_first() + * + * Take a qualified name like "A::B::C" and returns the first scope name. + * In this case, "A". Returns NULL if there is no base. + * ----------------------------------------------------------------------------- */ + +String * +Swig_scopename_first(String *s) { + char tmp[1024]; + char *c; + if (!Strstr(s,"::")) return 0; + strcpy(tmp,Char(s)); + c = tmp; + while (*c) { + if (strncmp(c,"::",2) == 0) { + break; + } else { + if (*c == '<') { + int level = 1; + c++; + while (*c && level) { + if (*c == '<') level++; + if (*c == '>') level--; + c++; + } + } else { + c++; + } + } + } + if (*c && (c != tmp)) { + *c = 0; + return NewString(tmp); + } else { + return 0; + } +} + + +/* ----------------------------------------------------------------------------- + * Swig_scopename_suffix() + * + * Take a qualified name like "A::B::C" and returns the suffix. + * In this case, "B::C". Returns NULL if there is no suffix. + * ----------------------------------------------------------------------------- */ + +String * +Swig_scopename_suffix(String *s) { + char tmp[1024]; + char *c; + if (!Strstr(s,"::")) return 0; + strcpy(tmp,Char(s)); + c = tmp; + while (*c) { + if (strncmp(c,"::",2) == 0) { + break; + } else { + if (*c == '<') { + int level = 1; + c++; + while (*c && level) { + if (*c == '<') level++; + if (*c == '>') level--; + c++; + } + } else { + c++; + } + } + } + if (*c && (c != tmp)) { + return NewString(c+2); + } else { + return 0; + } +} +/* ----------------------------------------------------------------------------- + * Swig_scopename_check() + * + * Checks to see if a name is qualified with a scope name + * ----------------------------------------------------------------------------- */ + +int Swig_scopename_check(String *s) { + char *c = Char(s); + if (!Strstr(s,"::")) return 0; + while (*c) { + if (strncmp(c,"::",2) == 0) { + return 1; + } else { + if (*c == '<') { + int level = 1; + c++; + while (*c && level) { + if (*c == '<') level++; + if (*c == '>') level--; + c++; + } + } else { + c++; + } + } + } + return 0; } @@ -193,7 +398,20 @@ Swig_proto_cmp(const String_or_char *pat, DOH *node) { void Swig_init() { + /* Set some useful string encoding methods */ DohEncoding("escape", Swig_string_escape); + DohEncoding("upper", Swig_string_upper); + DohEncoding("lower", Swig_string_lower); + DohEncoding("title", Swig_string_title); + DohEncoding("typecode",Swig_string_typecode); + + /* Initialize typemaps */ Swig_typemap_init(); + /* Initialize symbol table */ + Swig_symbol_init(); + + /* Initialize type system */ + SwigType_typesystem_init(); + } diff --git a/Source/Swig/module.c b/Source/Swig/module.c deleted file mode 100644 index 3c5916858..000000000 --- a/Source/Swig/module.c +++ /dev/null @@ -1,210 +0,0 @@ -/* ----------------------------------------------------------------------------- - * module.c - * - * This file implements the SWIG module system. Modules are simply - * pieces of code that manipulate tree objects. Each module is defined - * by 4 quantities: - * - * - Module name (used to select the module on the command line) - * - init function (called with the SWIG command line options). - * - start function (called to launch the module) - * - start tag (starting tag expected by the module) - * - * Currently modules must be statically linked with SWIG. However, it - * is anticipated that the module system may eventually support - * dynamic loading. - * - * Author(s) : David Beazley (beazley@cs.uchicago.edu) - * - * Copyright (C) 1999-2000. The University of Chicago - * See the file LICENSE for information on usage and redistribution. - * ----------------------------------------------------------------------------- */ - -#include "swig.h" - -#ifdef DYNAMIC_MODULES -#include <dlfcn.h> -#endif - -static char cvsroot[] = "$Header$"; - -struct Module { - String *modname; - int (*initfunc)(int argc, char **argv); - DOH *(*startfunc)(DOH *); - String *starttag; - struct Module *next; -}; - -static Module *Modules = 0; -static Hash *LoadedModules = 0; - -/* ----------------------------------------------------------------------------- - * Swig_register_module() - * - * Register a new module with the system - * ----------------------------------------------------------------------------- */ - -void -Swig_register_module(const String_or_char *modname, const String_or_char *starttag, - int (*initfunc)(int argc, char **argv), - DOH *(*startfunc)(DOH *)) -{ - Module *m; - m = (Module *) malloc(sizeof(Module)); - m->modname = NewString(modname); - m->starttag = NewString(starttag); - m->initfunc = initfunc; - m->startfunc = startfunc; - m->next = Modules; - Modules = m; -} - -/* ----------------------------------------------------------------------------- - * Swig_load_module() - * - * Load a module. Returns the module object. - * ----------------------------------------------------------------------------- */ - -Module * -Swig_load_module(const String_or_char *modname) { - Module *m; - static int dlcheck = 0; - m = Modules; - - while (m) { - if (Cmp(m->modname, modname) == 0) { - /* Create a new entry in the loaded modules table */ - List *ml; - if (!LoadedModules) LoadedModules = NewHash(); - ml = Getattr(LoadedModules,m->starttag); - if (!ml) { - ml = NewList(); - Setattr(LoadedModules,m->starttag,ml); - } - Append(ml,NewVoid(m,0)); - return m; - } - m = m->next; - } - /* Module is not a built-in module. See if we can dynamically load it */ - -#ifdef DYNAMIC_MODULES - if (dlcheck) return 0; - { - DOH *filename; - void *handle; - void (*init)(void) = 0; - char initfunc[256]; - FILE *f; - filename = NewStringf("./swig%s.so", modname); - f = Swig_open(filename); - if (!f) return 0; - fclose(f); - - Clear(filename); - Append(filename,Swig_last_file()); - - sprintf(initfunc,"%smodule",Char(modname)); - handle = dlopen(Char(filename), RTLD_NOW | RTLD_GLOBAL); - if (!handle) { - Printf(stdout,"%s\n", dlerror()); - return 0; - } - - init = (void (*)(void)) dlsym(handle,initfunc); - if (!init) { - Printf(stdout,"Dynamic module %s doesn't define %s()\n", initfunc); - return 0; - } - (*init)(); /* Register function */ - dlcheck = 1; - m = Swig_load_module(modname); - dlcheck = 0; - return m; - } -#else - return 0; -#endif -} - -/* ----------------------------------------------------------------------------- - * Swig_init_module() - * - * Initialize a module - * ----------------------------------------------------------------------------- */ - -int Swig_init_module(Module *m, int argc, char **argv) { - return (*m->initfunc)(argc,argv); -} - -/* ----------------------------------------------------------------------------- - * Swig_start_module() - * - * Start a module - * ----------------------------------------------------------------------------- */ - -DOH * -Swig_start_module(Module *m, DOH *obj) { - return (*m->startfunc)(obj); -} - -/* ----------------------------------------------------------------------------- - * Swig_run_modules() - * - * Given a tree node. This function tries to run it through all of the loaded - * modules. This works by looking at the "tag" attribute of the node and - * searching for a loaded module that can handle that tag. If no module can be - * found, processing stops and an error is generated. - * - * If more than one module can work on a given tag, those modules will be - * executed one after the other. Caveat: if one of those modules outputs - * a different type of tree, processing immediately stops. - * ----------------------------------------------------------------------------- */ - -DOH *Swig_run_modules(DOH *node) { - String *tag; - List *ml; - DOH *newnode; - String *newtag; - int i; - - tag = Getattr(node,"tag"); - if (!tag) { - Printf(stderr,"Whoa. No tag attribute on node passed to Swig_module_run.\n"); - exit(EXIT_FAILURE); - } - /* Get the set of modules that can respond to this node */ - while (node) { - if (!LoadedModules) { - Printf(stderr,"No modules loaded.\n"); - return 0; - } - ml = Getattr(LoadedModules,tag); - if ((!ml) || (Len(ml) == 0)) { - Printf(stderr,"Internal error. No module defined for handling '%s'\n", tag); - return 0; - } - newnode = 0; - newtag = 0; - for (i = 0; i < Len(ml); i++) { - Module *m; - m = (Module *) Data(Getitem(ml,i)); - assert(m); - newnode = (*m->startfunc)(node); - if (!newnode) return node; /* Done */ - newtag = Getattr(newnode,"tag"); - if (!newtag) { - Printf(stderr,"Fatal error. Module '%s' returns untagged object.\n", m->modname); - exit(EXIT_FAILURE); - } - if (Cmp(newtag,tag)) break; /* Tag is different. Oh well */ - } - if (Cmp(newtag,tag) == 0) break; /* Hmmm. The tag is the same but we already did everything */ - node = newnode; - tag = newtag; - } - return 0; -} - - diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index 5b82276c3..2aa92db58 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -9,7 +9,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_naming_c[] = "$Header$"; #include "swig.h" #include <ctype.h> @@ -25,11 +25,99 @@ static Hash *naming_hash = 0; * ----------------------------------------------------------------------------- */ void -Swig_name_register(String_or_char *method, String_or_char *format) { +Swig_name_register(const String_or_char *method, const String_or_char *format) { if (!naming_hash) naming_hash = NewHash(); Setattr(naming_hash,method,format); } +void +Swig_name_unregister(const String_or_char *method) { + if (naming_hash) { + Delattr(naming_hash,method); + } +} + +static int name_mangle(String *r) { + char *c; + int special; + special = 0; + Replaceall(r,"::","_"); + c = Char(r); + while (*c) { + if (!isalnum(*c) && (*c != '_')) { + special = 1; + switch(*c) { + case '+': + *c = 'a'; + break; + case '-': + *c = 's'; + break; + case '*': + *c = 'm'; + break; + case '/': + *c = 'd'; + break; + case '<': + *c = 'l'; + break; + case '>': + *c = 'g'; + break; + case '=': + *c = 'e'; + break; + case ',': + *c = 'c'; + break; + case '(': + *c = 'p'; + break; + case ')': + *c = 'P'; + break; + case '[': + *c = 'b'; + break; + case ']': + *c = 'B'; + break; + case '^': + *c = 'x'; + break; + case '&': + *c = 'A'; + break; + case '|': + *c = 'o'; + break; + case '~': + *c = 'n'; + break; + case '!': + *c = 'N'; + break; + case '%': + *c = 'M'; + break; + case '.': + *c = 'f'; + break; + case '?': + *c = 'q'; + break; + default: + *c = '_'; + break; + } + } + c++; + } + if (special) Append(r,"___"); + return special; +} + /* ----------------------------------------------------------------------------- * Swig_name_mangle() * @@ -37,16 +125,10 @@ Swig_name_register(String_or_char *method, String_or_char *format) { * ----------------------------------------------------------------------------- */ String * -Swig_name_mangle(String_or_char *s) { - String *r = NewString(""); - char *c; - Append(r,s); - c = Char(r); - while (*c) { - if (!isalnum(*c)) *c = '_'; - c++; - } - return Swig_temp_result(r); +Swig_name_mangle(const String_or_char *s) { + String *r = NewString(s); + name_mangle(r); + return r; } /* ----------------------------------------------------------------------------- @@ -56,7 +138,7 @@ Swig_name_mangle(String_or_char *s) { * ----------------------------------------------------------------------------- */ String * -Swig_name_wrapper(String_or_char *fname) { +Swig_name_wrapper(const String_or_char *fname) { String *r; String *f; @@ -69,8 +151,8 @@ Swig_name_wrapper(String_or_char *fname) { Append(r,f); } Replace(r,"%f",fname, DOH_REPLACE_ANY); - Replace(r,":","_", DOH_REPLACE_ANY); - return Swig_temp_result(r); + name_mangle(r); + return r; } @@ -81,11 +163,13 @@ Swig_name_wrapper(String_or_char *fname) { * ----------------------------------------------------------------------------- */ String * -Swig_name_member(String_or_char *classname, String_or_char *mname) { +Swig_name_member(const String_or_char *classname, const String_or_char *mname) { String *r; String *f; - char *cname, *c; + String *rclassname; + char *cname; + rclassname = SwigType_namestr(classname); r = NewString(""); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash,"member"); @@ -94,12 +178,17 @@ Swig_name_member(String_or_char *classname, String_or_char *mname) { } else { Append(r,f); } - cname = Char(classname); - c = strchr(cname, ' '); - if (c) cname = c+1; + cname = Char(rclassname); + if ((strncmp(cname,"struct ", 7) == 0) || + ((strncmp(cname,"class ", 6) == 0)) || + ((strncmp(cname,"union ", 6) == 0))) { + cname = strchr(cname, ' ')+1; + } Replace(r,"%c",cname, DOH_REPLACE_ANY); Replace(r,"%m",mname, DOH_REPLACE_ANY); - return Swig_temp_result(r); + /* name_mangle(r);*/ + Delete(rclassname); + return r; } /* ----------------------------------------------------------------------------- @@ -109,7 +198,7 @@ Swig_name_member(String_or_char *classname, String_or_char *mname) { * ----------------------------------------------------------------------------- */ String * -Swig_name_get(String_or_char *vname) { +Swig_name_get(const String_or_char *vname) { String *r; String *f; @@ -122,7 +211,8 @@ Swig_name_get(String_or_char *vname) { Append(r,f); } Replace(r,"%v",vname, DOH_REPLACE_ANY); - return Swig_temp_result(r); + Replace(r,"::","_", DOH_REPLACE_ANY); + return r; } /* ----------------------------------------------------------------------------- @@ -132,7 +222,7 @@ Swig_name_get(String_or_char *vname) { * ----------------------------------------------------------------------------- */ String * -Swig_name_set(String_or_char *vname) { +Swig_name_set(const String_or_char *vname) { String *r; String *f; @@ -145,7 +235,8 @@ Swig_name_set(String_or_char *vname) { Append(r,f); } Replace(r,"%v",vname, DOH_REPLACE_ANY); - return Swig_temp_result(r); + Replace(r,"::","_", DOH_REPLACE_ANY); + return r; } /* ----------------------------------------------------------------------------- @@ -155,10 +246,13 @@ Swig_name_set(String_or_char *vname) { * ----------------------------------------------------------------------------- */ String * -Swig_name_construct(String_or_char *classname) { +Swig_name_construct(const String_or_char *classname) { String *r; String *f; - char *cname, *c; + String *rclassname; + char *cname; + + rclassname = SwigType_namestr(classname); r = NewString(""); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash,"construct"); @@ -168,14 +262,52 @@ Swig_name_construct(String_or_char *classname) { Append(r,f); } - cname = Char(classname); - c = strchr(cname, ' '); - if (c) cname = c+1; + cname = Char(rclassname); + if ((strncmp(cname,"struct ", 7) == 0) || + ((strncmp(cname,"class ", 6) == 0)) || + ((strncmp(cname,"union ", 6) == 0))) { + cname = strchr(cname, ' ')+1; + } + Replace(r,"%c",cname, DOH_REPLACE_ANY); + Delete(rclassname); + return r; +} + + +/* ----------------------------------------------------------------------------- + * Swig_name_copyconstructor() + * + * Returns the name of the accessor function used to copy an object. + * ----------------------------------------------------------------------------- */ + +String * +Swig_name_copyconstructor(const String_or_char *classname) { + String *r; + String *f; + String *rclassname; + char *cname; + + rclassname = SwigType_namestr(classname); + r = NewString(""); + if (!naming_hash) naming_hash = NewHash(); + f = Getattr(naming_hash,"construct"); + if (!f) { + Append(r,"copy_%c"); + } else { + Append(r,f); + } + + cname = Char(rclassname); + if ((strncmp(cname,"struct ", 7) == 0) || + ((strncmp(cname,"class ", 6) == 0)) || + ((strncmp(cname,"union ", 6) == 0))) { + cname = strchr(cname, ' ')+1; + } Replace(r,"%c",cname, DOH_REPLACE_ANY); - return Swig_temp_result(r); + Delete(rclassname); + return r; } - /* ----------------------------------------------------------------------------- * Swig_name_destroy() @@ -183,10 +315,12 @@ Swig_name_construct(String_or_char *classname) { * Returns the name of the accessor function used to destroy an object. * ----------------------------------------------------------------------------- */ -String *Swig_name_destroy(String_or_char *classname) { +String *Swig_name_destroy(const String_or_char *classname) { String *r; String *f; - char *cname, *c; + String *rclassname; + char *cname; + rclassname = SwigType_namestr(classname); r = NewString(""); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash,"destroy"); @@ -196,14 +330,297 @@ String *Swig_name_destroy(String_or_char *classname) { Append(r,f); } - cname = Char(classname); - c = strchr(cname, ' '); - if (c) cname = c+1; - + cname = Char(rclassname); + if ((strncmp(cname,"struct ", 7) == 0) || + ((strncmp(cname,"class ", 6) == 0)) || + ((strncmp(cname,"union ", 6) == 0))) { + cname = strchr(cname, ' ')+1; + } Replace(r,"%c",cname, DOH_REPLACE_ANY); - return Swig_temp_result(r); + Delete(rclassname); + return r; +} + +/* ----------------------------------------------------------------------------- + * Swig_name_object_set() + * + * Sets an object associated with a name and optional declarators. + * ----------------------------------------------------------------------------- */ + +void +Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object) { + DOH *n; + + /* Printf(stdout,"name: '%s', '%s'\n", name, decl);*/ + n = Getattr(namehash,name); + if (!n) { + n = NewHash(); + Setattr(namehash,name,n); + } + /* Add an object based on the declarator value */ + if (!decl) { + Setattr(n,NewString("*"),object); + } else { + Setattr(n,Copy(decl),object); + } +} + +/* ----------------------------------------------------------------------------- + * Swig_name_object_get() + * + * Return an object associated with an optional class prefix, name, and + * declarator. This function operates according to name matching rules + * described for the %rename directive in the SWIG manual. + * ----------------------------------------------------------------------------- */ + +static DOH *get_object(Hash *n, String *decl) { + DOH *rn = 0; + if (!n) return 0; + if (decl) { + rn = Getattr(n,decl); + } else { + rn = Getattr(n,"*"); + } + return rn; +} + +DOH * +Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl) { + String *tname; + DOH *rn = 0; + Hash *n; + char *ncdecl = 0; + + if (!namehash) return 0; + + /* DB: This removed to more tightly control feature/name matching */ + /* if ((decl) && (SwigType_isqualifier(decl))) { + ncdecl = strchr(Char(decl),'.'); + ncdecl++; + } + */ + + /* Perform a class-based lookup (if class prefix supplied) */ + if (prefix) { + if (Len(prefix)) { + tname = NewStringf("%s::%s",prefix,name); + n = Getattr(namehash,tname); + rn = get_object(n,decl); + if ((!rn) && ncdecl) rn = get_object(n,ncdecl); + if (!rn) rn = get_object(n,0); + Delete(tname); + } + /* A wildcard-based class lookup */ + if (!rn) { + tname = NewStringf("*::%s",name); + n = Getattr(namehash,tname); + rn = get_object(n,decl); + if ((!rn) && ncdecl) rn = get_object(n,ncdecl); + if (!rn) rn = get_object(n,0); + Delete(tname); + } + } else { + /* Lookup in the global namespace only */ + tname = NewStringf("::%s",name); + n = Getattr(namehash,tname); + rn = get_object(n,decl); + if ((!rn) && ncdecl) rn = get_object(n,ncdecl); + if (!rn) rn = get_object(n,0); + Delete(tname); + } + /* Catch-all */ + if (!rn) { + n = Getattr(namehash,name); + rn = get_object(n,decl); + if ((!rn) && ncdecl) rn = get_object(n,ncdecl); + if (!rn) rn = get_object(n,0); + } + return rn; +} + +/* ----------------------------------------------------------------------------- + * Swig_name_object_inherit() + * + * Implements name-based inheritance scheme. + * ----------------------------------------------------------------------------- */ + +void +Swig_name_object_inherit(Hash *namehash, String *base, String *derived) { + String *key; + String *bprefix; + String *dprefix; + char *cbprefix; + int plen; + + if (!namehash) return; + + bprefix = NewStringf("%s::",base); + dprefix = NewStringf("%s::",derived); + cbprefix = Char(bprefix); + plen = strlen(cbprefix); + for (key = Firstkey(namehash); key; key = Nextkey(namehash)) { + char *k = Char(key); + if (strncmp(k,cbprefix,plen) == 0) { + Hash *n, *newh; + String *nkey, *okey; + + nkey = NewStringf("%s%s",dprefix,k+plen); + n = Getattr(namehash,key); + newh = Getattr(namehash,nkey); + if (!newh) { + newh = NewHash(); + Setattr(namehash,nkey,newh); + } + for (okey = Firstkey(n); okey; okey = Nextkey(n)) { + String *ovalue = Getattr(n,okey); + if (!Getattr(newh,okey)) { + Setattr(newh,okey,Copy(ovalue)); + } + } + } + } +} + +/* ----------------------------------------------------------------------------- + * Swig_features_get() + * + * Given a node, this function merges features. + * ----------------------------------------------------------------------------- */ + +static void merge_features(Hash *features, Node *n) { + String *key; + if (!features) return; + for (key = Firstkey(features); key; key = Nextkey(features)) { + if (Getattr(n,key)) { + continue; + } + Setattr(n,key,Copy(Getattr(features,key))); + } +} + +void +Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *node) { + String *tname; + DOH *rn = 0; + Hash *n; + char *ncdecl = 0; + + if (!features) return; + + if ((decl) && (SwigType_isqualifier(decl))) { + ncdecl = strchr(Char(decl),'.'); + ncdecl++; + } + + if (name) { + /* Perform a class-based lookup (if class prefix supplied) */ + if (prefix) { + if (Len(prefix)) { + tname = NewStringf("%s::%s",prefix,name); + n = Getattr(features,tname); + rn = get_object(n,decl); + merge_features(rn,node); + if (ncdecl) { + rn = get_object(n,ncdecl); + merge_features(rn,node); + } + rn = get_object(n,0); + merge_features(rn,node); + Delete(tname); + } + /* A wildcard-based class lookup */ + tname = NewStringf("*::%s",name); + n = Getattr(features,tname); + rn = get_object(n,decl); + merge_features(rn,node); + if (ncdecl) { + rn = get_object(n,ncdecl); + merge_features(rn,node); + } + rn = get_object(n,0); + merge_features(rn,node); + Delete(tname); + + /* A class-generic feature */ + if (Len(prefix)) { + tname = NewStringf("%s::",prefix); + n = Getattr(features,tname); + rn = get_object(n,0); + merge_features(rn,node); + Delete(tname); + } + + } else { + /* Lookup in the global namespace only */ + tname = NewStringf("::%s",name); + n = Getattr(features,tname); + rn = get_object(n,decl); + merge_features(rn,node); + if (ncdecl) { + rn = get_object(n,ncdecl); + merge_features(rn,node); + } + rn = get_object(n,0); + merge_features(rn,node); + Delete(tname); + } + /* Catch-all */ + n = Getattr(features,name); + rn = get_object(n,decl); + merge_features(rn,node); + if (ncdecl) { + rn = get_object(n,ncdecl); + merge_features(rn,node); + } + rn = get_object(n,0); + merge_features(rn,node); + } + /* Global features */ + n = Getattr(features,""); + rn = get_object(n,0); + merge_features(rn,node); + } +/* ----------------------------------------------------------------------------- + * Swig_feature_set() + * + * Sets a feature name and value. + * ----------------------------------------------------------------------------- */ + +void +Swig_feature_set(Hash *features, String *name, SwigType *decl, String *featurename, DOH *value) { + Hash *n; + Hash *fhash; + /* Printf(stdout,"feature: %s %s %s %s\n", name, decl, featurename, value);*/ + + n = Getattr(features,name); + if (!n) { + n = NewHash(); + Setattr(features,name,n); + } + if (!decl) { + fhash = Getattr(n,"*"); + if (!fhash) { + fhash = NewHash(); + Setattr(n,"*",fhash); + } + } else { + fhash = Getattr(n,decl); + if (!fhash) { + fhash = NewHash(); + Setattr(n,Copy(decl),fhash); + } + } + if (value) { + Setattr(fhash,featurename,value); + } else { + Delattr(fhash,featurename); + } +} + + + diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index db6de504e..2dd8d5fbc 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -14,7 +14,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_parms_c[] = "$Header$"; #include "swig.h" @@ -42,27 +42,36 @@ Parm *NewParm(SwigType *type, String_or_char *n) { Parm *CopyParm(Parm *p) { SwigType *t; - char *name; - char *lname; - char *value; - int ignore; + String *name; + String *lname; + String *value; + String *ignore; + String *alttype; Parm *np = NewHash(); t = Getattr(p,"type"); - name = GetChar(p,"name"); - lname = GetChar(p,"lname"); - value = GetChar(p,"value"); - ignore = GetInt(p,"ignore"); - - Setattr(np,"type",Copy(t)); + name = Getattr(p,"name"); + lname = Getattr(p,"lname"); + value = Getattr(p,"value"); + ignore = Getattr(p,"ignore"); + alttype = Getattr(p,"alttype"); + + if (t) + Setattr(np,"type",Copy(t)); if (name) - Setattr(np,"name",name); + Setattr(np,"name",Copy(name)); if (lname) - Setattr(np,"lname", lname); + Setattr(np,"lname", Copy(lname)); if (value) - Setattr(np,"value", value); + Setattr(np,"value", Copy(value)); if (ignore) - SetInt(np,"ignore", ignore); + Setattr(np,"ignore", Copy(ignore)); + if (alttype) + Setattr(np,"alttype", Copy(alttype)); + + Setfile(np,Getfile(p)); + Setline(np,Getline(p)); + return np; } @@ -81,12 +90,12 @@ CopyParmList(ParmList *p) { while (p) { np = CopyParm(p); if (pp) { - Setnext(pp,np); + set_nextSibling(pp,np); } else { fp = np; } pp = np; - p = Getnext(p); + p = nextSibling(p); } return fp; } @@ -98,13 +107,30 @@ CopyParmList(ParmList *p) { int ParmList_numarg(ParmList *p) { int n = 0; while (p) { - if (!Getignore(p)) n++; - p = Getnext(p); + if (!Getattr(p,"ignore")) n++; + p = nextSibling(p); } return n; } /* ----------------------------------------------------------------------------- + * int ParmList_numrequired(). Return number of required arguments + * ----------------------------------------------------------------------------- */ + +int ParmList_numrequired(ParmList *p) { + int i = 0; + while (p) { + SwigType *t = Getattr(p,"type"); + String *value = Getattr(p,"value"); + if (value) return i; + if (!(SwigType_type(t) == T_VOID)) i++; + else break; + p = nextSibling(p); + } + return i; +} + +/* ----------------------------------------------------------------------------- * int ParmList_len() * ----------------------------------------------------------------------------- */ @@ -112,7 +138,7 @@ int ParmList_len(ParmList *p) { int i = 0; while (p) { i++; - p = Getnext(p); + p = nextSibling(p); } return i; } @@ -129,13 +155,13 @@ String *ParmList_str(ParmList *p) { out = NewString(""); while(p) { - t = Gettype(p); - Printf(out,"%s", SwigType_str(t,Getname(p))); - p = Getnext(p); + t = Getattr(p,"type"); + Printf(out,"%s", SwigType_str(t,Getattr(p,"name"))); + p = nextSibling(p); if (p) Printf(out,","); } - return Swig_temp_result(out); + return out; } /* --------------------------------------------------------------------- @@ -150,13 +176,17 @@ String *ParmList_protostr(ParmList *p) { out = NewString(""); while(p) { - t = Gettype(p); + if (Getattr(p,"hidden")) { + p = nextSibling(p); + continue; + } + t = Getattr(p,"type"); Printf(out,"%s", SwigType_str(t,0)); - p = Getnext(p); + p = nextSibling(p); if (p) Printf(out,","); } - return Swig_temp_result(out); + return out; } diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 680db572d..8fc2d0ac4 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -12,7 +12,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_scanner_c[] = "$Header$"; #include "swig.h" #include <ctype.h> @@ -598,22 +598,46 @@ look(SwigScanner *s) { if ((c = nextchar(s)) == 0) return SWIG_TOKEN_LONG; if ((c == 'u') || (c == 'U')) { return SWIG_TOKEN_ULONG; + } else if ((c == 'l') || (c == 'L')) { + state = 870; } else { retract(s,1); return SWIG_TOKEN_LONG; } + break; + + /* A long long integer */ + + case 870: + if ((c = nextchar(s)) == 0) return SWIG_TOKEN_LONGLONG; + if ((c == 'u') || (c == 'U')) { + return SWIG_TOKEN_ULONGLONG; + } else { + retract(s,1); + return SWIG_TOKEN_LONGLONG; + } /* An unsigned number */ case 88: if ((c = nextchar(s)) == 0) return SWIG_TOKEN_UINT; if ((c == 'l') || (c == 'L')) { - return SWIG_TOKEN_ULONG; + state = 880; } else { - retract(s,1); - return SWIG_TOKEN_UINT; + retract(s,1); + return SWIG_TOKEN_UINT; } + break; + /* Possibly an unsigned long long or unsigned long */ + case 880: + if ((c = nextchar(s)) == 0) return SWIG_TOKEN_ULONG; + if ((c == 'l') || (c == 'L')) return SWIG_TOKEN_ULONGLONG; + else { + retract(s,1); + return SWIG_TOKEN_ULONG; + } + /* A character constant */ case 9: if ((c = nextchar(s)) == 0) { diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 64ff0ceab..40bac71c8 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -10,7 +10,7 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_stype_c[] = "$Header$"; #include "swig.h" #include <ctype.h> @@ -38,12 +38,12 @@ static char cvsroot[] = "$Header$"; * * All type constructors are denoted by a trailing '.': * - * 'p.' = Pointer - * 'r.' = Reference - * 'a(n).' = Array of size n - * 'f(..,..).' = Function with arguments - * 'q(str).' = Qualifier (such as const or volatile) - * 't(...).' = Template specifier??? + * 'p.' = Pointer (*) + * 'r.' = Reference (&) + * 'a(n).' = Array of size n [n] + * 'f(..,..).' = Function with arguments (args) + * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) + * 'm(qual).' = Pointer to member (qual::*) * * The encoding follows the order that you might describe a type in words. * For example "p.a(200).int" is "A pointer to array of int's" and @@ -124,6 +124,18 @@ SwigType *NewSwigType(int t) { case T_UCHAR: return NewString("unsigned char"); break; + case T_STRING: { + SwigType *t = NewString("char"); + SwigType_add_pointer(t); + return t; + break; + } + case T_LONGLONG: + return NewString("long long"); + break; + case T_ULONGLONG: + return NewString("unsigned long long"); + break; case T_VOID: return NewString("void"); break; @@ -147,6 +159,10 @@ SwigType_add_pointer(SwigType *t) { void SwigType_del_pointer(SwigType *t) { char *c = Char(t); + if (strncmp(c,"q(",2) == 0) { + Delete(SwigType_pop(t)); + c = Char(t); + } if (strncmp(c,"p.",2)) { printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n"); abort(); @@ -155,6 +171,19 @@ SwigType_del_pointer(SwigType *t) { } /* ----------------------------------------------------------------------------- + * SwigType_add_memberpointer() + * + * Add a pointer to a member to a type + * ----------------------------------------------------------------------------- */ + +void +SwigType_add_memberpointer(SwigType *t, String_or_char *name) { + String *temp = NewStringf("m(%s).", name); + Insert(t,0,temp); + Delete(temp); +} + +/* ----------------------------------------------------------------------------- * SwigType_add_array() * * Adds an array constructor to a type @@ -168,6 +197,25 @@ SwigType_add_array(SwigType *t, String *size) { } /* ----------------------------------------------------------------------------- + * SwigType_pop_arrays() + * + * Pop all arrays off as a single item + * ----------------------------------------------------------------------------- */ + +SwigType * +SwigType_pop_arrays(SwigType *t) { + String *ta; + if (!SwigType_isarray(t)) return 0; + ta = NewString(""); + while (SwigType_isarray(t)) { + SwigType *td = SwigType_pop(t); + Append(ta,td); + Delete(td); + } + return ta; +} + +/* ----------------------------------------------------------------------------- * SwigType_add_reference() * * Adds a reference constructor to a type. @@ -187,8 +235,57 @@ SwigType_add_reference(SwigType *t) { void SwigType_add_qualifier(SwigType *t, String *qual) { char temp[256]; - sprintf(temp,"q(%s).",Char(qual)); - Insert(t,0,temp); + if (!SwigType_isqualifier(t)) { + sprintf(temp,"q(%s).",Char(qual)); + Insert(t,0,temp); + } else { + /* Already has a qualifier on it. We are going to generate a + canonical qualifier string */ + String *qt; + char *c, *qc; + String *newq; + + qt = SwigType_pop(t); /* Rip off the old qualifier */ + /* See if the added qualifier is already there */ + if (strstr(Char(qt),Char(qual))) { + /* Already added this qualifier */ + SwigType_push(t,qt); + Delete(qt); + return; + } + /* We need to add the qualifier to the qualifier list */ + /* To do this, we keep the qualifiers in alphabetical order */ + newq = NewString("q("); + qc = Char(qual); + c = Char(qt)+2; + c = strtok(c," )."); + while (c) { + if (!strlen(c)) { + c = strtok(NULL," )."); + continue; + } + if (qc) { + if (strcmp(c,qc) < 0) { + Printf(newq,"%s",c); + } else { + Printf(newq,"%s %s", qc,c); + qc = 0; + } + } else { + Printf(newq,"%s",c); + } + c = strtok(NULL," )."); + if (c) Putc(' ',newq); + } + if (qc) { + Printf(newq," %s",qc); + } + Putc(')',newq); + Putc('.',newq); + SwigType_push(t,newq); + Delete(newq); + Delete(qt); + } } /* ----------------------------------------------------------------------------- @@ -201,20 +298,84 @@ SwigType_add_qualifier(SwigType *t, String *qual) { void SwigType_add_function(SwigType *t, ParmList *parms) { String *pstr; + Parm *p; Insert(t,0,")."); pstr = NewString("f("); - - while (parms) { - Printf(pstr,"%s",Gettype(parms)); - parms = Getnext(parms); - if (parms) - Putc(',',pstr); + p = parms; + for (p = parms; p; p = nextSibling(p)) { + if (p != parms) Putc(',',pstr); + Printf(pstr,"%s", Getattr(p,"type")); } Insert(t,0,pstr); Delete(pstr); } +SwigType * +SwigType_pop_function(SwigType *t) { + SwigType *f = 0; + SwigType *g = 0; + char *c = Char(t); + if (strncmp(c,"q(",2) == 0) { + f = SwigType_pop(t); + c = Char(t); + } + if (strncmp(c,"f(",2)) { + printf("Fatal error. SwigType_pop_function applied to non-function.\n"); + abort(); + } + g = SwigType_pop(t); + if (f) SwigType_push(g,f); + Delete(f); + return g; +} + +ParmList * +SwigType_function_parms(SwigType *t) { + List *l = SwigType_parmlist(t); + Hash *p, *pp = 0, *firstp = 0; + DOH *obj; + for (obj = Firstitem(l); obj; obj = Nextitem(l)) { + p = NewParm(obj,0); + if (!firstp) firstp = p; + if (pp) { + set_nextSibling(pp,p); + } + pp = p; + } + Delete(l); + return firstp; +} + +/* ----------------------------------------------------------------------------- + * SwigType_add_template() + * + * Adds a template to a type. This template is encoded in the SWIG type + * mechanism and produces a string like this: + * + * vector<int *> ----> "vector<(p.int)>" + * ----------------------------------------------------------------------------- */ + +void +SwigType_add_template(SwigType *t, ParmList *parms) { + Parm *p; + + Append(t,"<("); + p = parms; + for (p = parms; p; p = nextSibling(p)) { + String *v; + if (Getattr(p,"default")) continue; + if (p != parms) Append(t,","); + v = Getattr(p,"value"); + if (v) { + Append(t,v); + } else { + Append(t,Getattr(p,"type")); + } + } + Append(t,")>"); +} + /* ----------------------------------------------------------------------------- * static isolate_element() * @@ -228,8 +389,7 @@ isolate_element(char *c) { if (*c == '.') { Putc(*c,result); return result; - } - else if (*c == '(') { + } else if (*c == '(') { int nparen = 1; Putc(*c,result); c++; @@ -263,6 +423,7 @@ List *SwigType_split(SwigType *t) { int len; c = Char(t); + list = NewList(); while (*c) { item = isolate_element(c); @@ -312,6 +473,7 @@ void SwigType_push(SwigType *t, String *cons) { if (!cons) return; if (!Len(cons)) return; + if (Len(t)) { char *c = Char(cons); if (c[strlen(c)-1] != '.') @@ -326,7 +488,7 @@ void SwigType_push(SwigType *t, String *cons) * Splits a comma separated list of components into strings. * ----------------------------------------------------------------------------- */ -List *SwigType_parmlist(String *p) { +List *SwigType_parmlist(const String *p) { DOH *item; List *list; char *c; @@ -404,20 +566,37 @@ String *SwigType_parm(SwigType *t) { * SwigType_isfunction() * SwigType_isqualifier() * - * Testing functions for querying a datatype + * Testing functions for querying a raw datatype * ----------------------------------------------------------------------------- */ int SwigType_ispointer(SwigType *t) { char *c; + if (!t) return 0; c = Char(t); + if (strncmp(c,"q(",2) == 0) { + c = strchr(c,'.'); + if (!c) return 0; + c++; + } if (strncmp(c,"p.",2) == 0) { return 1; } return 0; } +int SwigType_ismemberpointer(SwigType *t) { + char *c; + if (!t) return 0; + c = Char(t); + if (strncmp(c,"m(",2) == 0) { + return 1; + } + return 0; +} + int SwigType_isreference(SwigType *t) { char *c; + if (!t) return 0; c = Char(t); if (strncmp(c,"r.",2) == 0) { return 1; @@ -427,6 +606,7 @@ int SwigType_isreference(SwigType *t) { int SwigType_isarray(SwigType *t) { char *c; + if (!t) return 0; c = Char(t); if (strncmp(c,"a(",2) == 0) { return 1; @@ -436,8 +616,16 @@ int SwigType_isarray(SwigType *t) { int SwigType_isfunction(SwigType *t) { char *c; - + if (!t) { + return 0; + } c = Char(t); + if (strncmp(c,"q(",2) == 0) { + /* Might be a 'const' function. Try to skip over the 'const' */ + c = strchr(c,'.'); + if (c) c++; + else return 0; + } if (strncmp(c,"f(",2) == 0) { return 1; } @@ -446,6 +634,7 @@ int SwigType_isfunction(SwigType *t) { int SwigType_isqualifier(SwigType *t) { char *c; + if (!t) return 0; c = Char(t); if (strncmp(c,"q(",2) == 0) { return 1; @@ -455,21 +644,79 @@ int SwigType_isqualifier(SwigType *t) { int SwigType_isconst(SwigType *t) { char *c; + if (!t) return 0; c = Char(t); - if (strncmp(c,"q(const)",8) == 0) { - return 1; + if (strncmp(c,"q(",2) == 0) { + String *q = SwigType_parm(t); + if (strstr(Char(q),"const")) { + Delete(q); + return 1; + } + Delete(q); + } + /* Hmmm. Might be const through a typedef */ + if (SwigType_issimple(t)) { + int ret; + SwigType *td = SwigType_typedef_resolve(t); + if (td) { + ret = SwigType_isconst(td); + Delete(td); + return ret; + } } return 0; } +int SwigType_ismutable(SwigType *t) { + int r; + SwigType *qt = SwigType_typedef_resolve_all(t); + if (SwigType_isreference(qt)) { + Delete(SwigType_pop(qt)); + } + r = SwigType_isconst(qt); + Delete(qt); + return r ? 0 : 1; +} + int SwigType_isenum(SwigType *t) { char *c = Char(t); + if (!t) return 0; if (strncmp(c,"enum ",5) == 0) { return 1; } return 0; } +int SwigType_issimple(SwigType *t) { + char *c = Char(t); + if (!t) return 0; + while (*c) { + if (*c == '<') { + int nest = 1; + c++; + while (*c && nest) { + if (*c == '<') nest++; + if (*c == '>') nest--; + c++; + } + c--; + } + if (*c == '.') return 0; + c++; + } + return 1; +} + +int SwigType_isvarargs(const SwigType *t) { + if (Strcmp(t,"v(...)") == 0) return 1; + return 0; +} + +int SwigType_istemplate(const SwigType *t) { + if (Strstr(t,"<(")) return 1; + return 0; +} + /* ----------------------------------------------------------------------------- * SwigType_base() * @@ -481,20 +728,35 @@ SwigType *SwigType_base(SwigType *t) { c = Char(t); d = c + strlen(c); + + /* Check for a type constructor */ + if ((d > c) && (*(d-1) == '.')) d--; + while (d > c) { d--; - if (*d == '.') return Swig_temp_result(NewString(d+1)); + if (*d == '>') { + /* Skip over template--that's part of the base name */ + int ntemp = 1; + d--; + while ((d > c) && (ntemp > 0)) { + if (*d == '>') ntemp++; + if (*d == '<') ntemp--; + d--; + } + } + if (*d == ')') { + /* Skip over params */ + int nparen = 1; + d--; + while ((d > c) && (nparen > 0)) { + if (*d == ')') nparen++; + if (*d == '(') nparen--; + d--; + } + } + if (*d == '.') return NewString(d+1); } - return Swig_temp_result(NewString(c)); -} - -void SwigType_setbase(SwigType *t, String_or_char *n) { - SwigType *p; - p = SwigType_prefix(t); - Clear(t); - Append(t,p); - Append(t,n); - Delete(p); + return NewString(c); } /* ----------------------------------------------------------------------------- @@ -509,8 +771,32 @@ String *SwigType_prefix(SwigType *t) { c = Char(t); d = c + strlen(c); + + /* Check for a type constructor */ + if ((d > c) && (*(d-1) == '.')) d--; + while (d > c) { d--; + if (*d == '>') { + int nest = 1; + d--; + while ((d > c) && (nest)) { + if (*d == '>') nest++; + if (*d == '<') nest--; + d--; + } + } + if (*d == ')') { + /* Skip over params */ + int nparen = 1; + d--; + while ((d > c) && (nparen)) { + if (*d == ')') nparen++; + if (*d == '(') nparen--; + d--; + } + } + if (*d == '.') { char t = *(d+1); *(d+1) = 0; @@ -522,6 +808,125 @@ String *SwigType_prefix(SwigType *t) { return NewString(""); } + + +/* ----------------------------------------------------------------------------- + * SwigType_templateprefix() + * + * Returns the prefix before the first template definition. + * For example: + * + * Foo<(p.int)>::bar + * + * Results in "Foo" + * ----------------------------------------------------------------------------- */ + +String * +SwigType_templateprefix(SwigType *t) { + char *c; + String *r; + String *s = NewString(t); + c = Char(s); + while (*c) { + if (*c == '<') { + *c = 0; + r = NewString(Char(s)); + Delete(s); + return r; + } + c++; + } + return s; +} + +/* ----------------------------------------------------------------------------- + * SwigType_templatesuffix() + * + * Returns text after a template substitution. Used to handle scope names + * for example: + * + * Foo<(p.int)>::bar + * + * returns "::bar" + * ----------------------------------------------------------------------------- */ + +String * +SwigType_templatesuffix(const SwigType *t) { + char *c; + c = Char(t); + while (*c) { + if ((*c == '<') && (*(c+1) == '(')) { + int nest = 1; + c++; + while (*c && nest) { + if (*c == '<') nest++; + if (*c == '>') nest--; + c++; + } + return NewString(c); + } + c++; + } + return NewString(""); +} + +/* ----------------------------------------------------------------------------- + * SwigType_templateargs() + * + * Returns the template part + * ----------------------------------------------------------------------------- */ + +String * +SwigType_templateargs(SwigType *t) { + String *result = NewString(""); + char *c; + c = Char(t); + while (*c) { + if ((*c == '<') && (*(c+1) == '(')) { + int nest = 1; + Putc(*c,result); + c++; + while (*c && nest) { + Putc(*c,result); + if (*c == '<') nest++; + if (*c == '>') nest--; + c++; + } + return result; + } + c++; + } + Delete(result); + return 0; +} + +/* ----------------------------------------------------------------------------- + * SwigType_strip_qualifiers() + * + * Strip all qualifiers from a type and return a new type + * ----------------------------------------------------------------------------- */ + +static Hash *memoize_stripped = 0; + +SwigType * +SwigType_strip_qualifiers(SwigType *t) { + SwigType *r; + List *l; + SwigType *e; + if (!memoize_stripped) memoize_stripped = NewHash(); + r = Getattr(memoize_stripped,t); + if (r) return Copy(r); + + l = SwigType_split(t); + r = NewString(""); + for (e = Firstitem(l); e; e = Nextitem(l)) { + if (SwigType_isqualifier(e)) continue; + Append(r,e); + } + Setattr(memoize_stripped,Copy(t),Copy(r)); + return r; +} + /* ----------------------------------------------------------------------------- * SwigType_array_ndim() * @@ -553,7 +958,7 @@ String *SwigType_array_getdim(SwigType *t, int n) { c++; n--; } - if (n == 0) return Swig_temp_result(SwigType_parm(c)); + if (n == 0) return SwigType_parm(c); return 0; } @@ -592,17 +997,34 @@ void SwigType_array_setdim(SwigType *t, int n, String_or_char *rep) { } /* ----------------------------------------------------------------------------- + * SwigType_array_type() + * + * Return the base type of an array + * ----------------------------------------------------------------------------- */ + +SwigType * +SwigType_array_type(SwigType *ty) { + SwigType *t; + t = Copy(ty); + while (SwigType_isarray(t)) { + Delete(SwigType_pop(t)); + } + return t; +} + +/* ----------------------------------------------------------------------------- * SwigType_default() * * Create the default string for this datatype. This takes a type and strips it * down to its most primitive form--resolving all typedefs and removing operators. * * Rules: - * Pointers: p.SWIGPOINTER - * References: r.SWIGREFERENCE - * Arrays: a().SWIGARRAY + * Pointers: p.SWIGTYPE + * References: r.SWIGTYPE + * Arrays: a().SWIGTYPE * Types: SWIGTYPE - * + * MemberPointer: m(CLASS).SWIGTYPE + * Enums: enum SWIGENUM * ----------------------------------------------------------------------------- */ static Hash *default_cache = 0; @@ -621,12 +1043,24 @@ SwigType *SwigType_default(SwigType *t) { if (r != t) Delete(r); r = r1; } + if (SwigType_isqualifier(r)) { + if (r == t) r = Copy(t); + do { + Delete(SwigType_pop(r)); + } while (SwigType_isqualifier(r)); + } if (SwigType_ispointer(r)) { - def = NewString("p.SWIGPOINTER"); + def = NewString("p.SWIGTYPE"); } else if (SwigType_isreference(r)) { - def = NewString("r.SWIGREFERENCE"); + def = NewString("r.SWIGTYPE"); } else if (SwigType_isarray(r)) { - def = NewString("a().SWIGARRAY"); + def = NewString("a().SWIGTYPE"); + } else if (SwigType_ismemberpointer(r)) { + def = NewString("m(CLASS).SWIGTYPE"); + } else if (SwigType_isenum(r)) { + def = NewString("enum SWIGTYPE"); + } else if (SwigType_isvarargs(r)) { + def = NewString("v(...)"); } else { def = NewString("SWIGTYPE"); } @@ -636,7 +1070,56 @@ SwigType *SwigType_default(SwigType *t) { } /* ----------------------------------------------------------------------------- - * SwigType_str(DOH *s, DOH *id) + * SwigType_namestr() + * + * Returns a string of the base type. Takes care of template expansions + * ----------------------------------------------------------------------------- */ + +String * +SwigType_namestr(const SwigType *t) { + String *r; + String *suffix; + List *p; + char tmp[256]; + char *c, *d, *e; + int i, sz; + + if (!SwigType_istemplate(t)) return NewString(t); + + c = Strstr(t,"<("); + + d = Char(t); + e = tmp; + while (d != c) { + *(e++) = *(d++); + } + *e = 0; + r = NewString(tmp); + Putc('<',r); + + p = SwigType_parmlist(t); + sz = Len(p); + for (i = 0; i < sz; i++) { + Append(r,SwigType_str(Getitem(p,i),0)); + if ((i+1) < sz) Putc(',',r); + } + Putc(' ',r); + Putc('>',r); + suffix = SwigType_templatesuffix(t); + Append(r,suffix); + Delete(suffix); +#if 0 + if (SwigType_istemplate(r)) { + SwigType *rr = SwigType_namestr(r); + Delete(r); + return rr; + } +#endif + return r; +} + +/* ----------------------------------------------------------------------------- + * SwigType_str() * * Create a C string representation of a datatype. * ----------------------------------------------------------------------------- */ @@ -668,15 +1151,32 @@ SwigType_str(SwigType *s, const String_or_char *id) } else { nextelement = 0; } - if (SwigType_ispointer(element)) { + if (SwigType_isqualifier(element)) { + DOH *q = 0; + q = SwigType_parm(element); + Insert(result,0," "); + Insert(result,0,q); + Delete(q); + } else if (SwigType_ispointer(element)) { Insert(result,0,"*"); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } + } else if (SwigType_ismemberpointer(element)) { + String *q; + q = SwigType_parm(element); + Insert(result,0,"::*"); + Insert(result,0,q); + if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { + Insert(result,0,"("); + Append(result,")"); + } + Delete(q); } - else if (SwigType_isreference(element)) Insert(result,0,"&"); - else if (SwigType_isarray(element)) { + else if (SwigType_isreference(element)) { + Insert(result,0,"&"); + } else if (SwigType_isarray(element)) { DOH *size; Append(result,"["); size = SwigType_parm(element); @@ -696,199 +1196,109 @@ SwigType_str(SwigType *s, const String_or_char *id) } Append(result,")"); Delete(parms); - } else if (SwigType_isqualifier(element)) { - DOH *q = 0; - q = SwigType_parm(element); - Insert(result,0," "); - Insert(result,0,q); - Delete(q); } else { - Insert(result,0," "); - Insert(result,0,element); - } - element = nextelement; - } - Delete(elements); - return Swig_temp_result(result); -} - -/* ----------------------------------------------------------------------------- - * SwigType_lstr(DOH *s, DOH *id) - * - * Produces a type-string that is suitable as a lvalue in an expression. - * That is, a type that can be freely assigned a value without violating - * any C assignment rules. - * - * - Qualifiers such as 'const' and 'volatile' are stripped. - * - Arrays are converted into a *single* pointer (i.e., - * double [][] becomes double *). - * - References are converted into a pointer. - * - Typedef names that refer to read-only types will be replaced - * with an equivalent assignable version. - * -------------------------------------------------------------------- */ - -String * -SwigType_lstr(SwigType *s, const String_or_char *id) -{ - String *result; - String *element = 0, *nextelement; - List *elements; - int nelements, i; - int firstarray = 1; - SwigType *td, *rs, *tc = 0; - if (id) { - result = NewString(Char(id)); - } else { - result = NewString(""); - } - if (SwigType_isconst(s)) { - tc = Copy(s); - Delete(SwigType_pop(tc)); - rs = tc; - } else { - rs = s; - } - td = SwigType_typedef_resolve(rs); - if ((td) && (SwigType_isconst(td) || SwigType_isarray(td))) { - elements = SwigType_split(td); - } else if (td && SwigType_isenum(td)) { - elements = SwigType_split("int"); - } else { - elements = SwigType_split(rs); - } - if (td) Delete(td); - nelements = Len(elements); - - if (nelements > 0) { - element = Getitem(elements,0); - } - /* Now, walk the type list and start emitting */ - for (i = 0; i < nelements; i++) { - if (i < (nelements - 1)) { - nextelement = Getitem(elements,i+1); - } else { - nextelement = 0; - } - if (SwigType_ispointer(element)) { - Insert(result,0,"*"); - if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { - Insert(result,0,"("); - Append(result,")"); - } - firstarray = 0; - } else if (SwigType_isreference(element)) { - Insert(result,0,"*"); - } else if (SwigType_isarray(element)) { - if (firstarray) { - Insert(result,0,"*"); - while (nextelement && (SwigType_isarray(nextelement))) { - i++; - nextelement = Getitem(elements,i+1); - } - if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { - Insert(result,0,"("); - Append(result,")"); - } - firstarray = 0; + if (Strcmp(element,"v(...)") == 0) { + Insert(result,0,"..."); } else { - DOH *size; - Append(result,"["); - size = SwigType_parm(element); - Append(result,size); - Append(result,"]"); - Delete(size); - } - } else if (SwigType_isfunction(element)) { - DOH *parms, *p; - int j, plen; - Append(result,"("); - parms = SwigType_parmlist(element); - plen = Len(parms); - for (j = 0; j < plen; j++) { - p = SwigType_str(Getitem(parms,j),0); - Append(result,p); - if (j < (plen-1)) Append(result,","); + String *bs = SwigType_namestr(element); + Insert(result,0," "); + Insert(result,0,bs); + Delete(bs); } - Append(result,")"); - Delete(parms); - } else if (SwigType_isqualifier(element)) { - } else { - Insert(result,0," "); - Insert(result,0,element); } element = nextelement; } Delete(elements); - if (tc) Delete(tc); - return Swig_temp_result(result); + Chop(result); + return result; } - /* ----------------------------------------------------------------------------- * SwigType_ltype(SwigType *ty) * - * Returns a type object corresponding to the string created by lstr + * Create a locally assignable type * ----------------------------------------------------------------------------- */ SwigType * SwigType_ltype(SwigType *s) { String *result; - String *element, *nextelement; - SwigType *td, *rs, *tc = 0; + String *element; + SwigType *td, *tc = 0; List *elements; int nelements, i; int firstarray = 1; result = NewString(""); - - if (SwigType_isconst(s)) { - tc = Copy(s); + tc = Copy(s); + /* Nuke all leading qualifiers */ + while (SwigType_isqualifier(tc)) { Delete(SwigType_pop(tc)); - rs = tc; - } else { - rs = s; } - - td = SwigType_typedef_resolve(rs); - if ((td) && (SwigType_isconst(td) || SwigType_isarray(td))) { - elements = SwigType_split(td); - } else if (td && SwigType_isenum(td)) { - elements = SwigType_split("int"); - } else { - elements = SwigType_split(rs); + if (SwigType_issimple(tc)) { + /* Resolve any typedef definitions */ + td = SwigType_typedef_resolve(tc); + if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isenum(td) || SwigType_isreference(td))) { + /* We need to use the typedef type */ + Delete(tc); + tc = td; + } else if (td) { + Delete(td); + } } - if (td) Delete(td); + elements = SwigType_split(tc); nelements = Len(elements); /* Now, walk the type list and start emitting */ for (i = 0; i < nelements; i++) { element = Getitem(elements,i); - if (SwigType_ispointer(element)) { + if (SwigType_isqualifier(element)) { + /* Do nothing. Ignore */ + } else if (SwigType_ispointer(element)) { + Append(result,element); + firstarray = 0; + } else if (SwigType_ismemberpointer(element)) { Append(result,element); firstarray = 0; } else if (SwigType_isreference(element)) { Append(result,"p."); - } else if (SwigType_isarray(element)) { - if (firstarray) { - Append(result,"p."); - while (i < (nelements - 1)) { - element = Getitem(elements,i+1); - if (!SwigType_isarray(element)) break; - i++; - } - firstarray = 0; - } else { - Append(result,element); - } - } else if (SwigType_isfunction(element)) { - Append(result,element); - } else if (SwigType_isqualifier(element)) { + firstarray = 0; + } else if (SwigType_isarray(element) && firstarray) { + Append(result,"p."); + firstarray = 0; + } else if (SwigType_isenum(element)) { + Append(result,"int"); } else { Append(result,element); } - element = nextelement; } Delete(elements); - if (tc) Delete(tc); + Delete(tc); + return result; +} + +/* ----------------------------------------------------------------------------- + * SwigType_lstr(DOH *s, DOH *id) + * + * Produces a type-string that is suitable as a lvalue in an expression. + * That is, a type that can be freely assigned a value without violating + * any C assignment rules. + * + * - Qualifiers such as 'const' and 'volatile' are stripped. + * - Arrays are converted into a *single* pointer (i.e., + * double [][] becomes double *). + * - References are converted into a pointer. + * - Typedef names that refer to read-only types will be replaced + * with an equivalent assignable version. + * -------------------------------------------------------------------- */ + +String * +SwigType_lstr(SwigType *s, const String_or_char *id) +{ + String *result; + SwigType *tc; + + tc = SwigType_ltype(s); + result = SwigType_str(tc,id); + Delete(tc); return result; } @@ -907,6 +1317,7 @@ String *SwigType_rcaststr(SwigType *s, const String_or_char *name) { int nelements, i; int clear = 1; int firstarray = 1; + int isreference = 0; result = NewString(""); @@ -918,18 +1329,21 @@ String *SwigType_rcaststr(SwigType *s, const String_or_char *name) { rs = s; } - td = SwigType_typedef_resolve(rs); - if ((td) && (SwigType_isconst(td) || SwigType_isarray(td))) { - elements = SwigType_split(td); - } else if (td && SwigType_isenum(td)) { - elements = SwigType_split(rs); - clear = 0; + if (SwigType_issimple(rs)) { + td = SwigType_typedef_resolve(rs); + if ((td) && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) { + elements = SwigType_split(td); + } else if (td && SwigType_isenum(td)) { + elements = SwigType_split(rs); + clear = 0; + } else { + elements = SwigType_split(rs); + } + if (td) Delete(td); } else { elements = SwigType_split(rs); } - if (td) Delete(td); nelements = Len(elements); - if (nelements > 0) { element = Getitem(elements,0); } @@ -940,15 +1354,34 @@ String *SwigType_rcaststr(SwigType *s, const String_or_char *name) { } else { nextelement = 0; } - if (SwigType_ispointer(element)) { + if (SwigType_isqualifier(element)) { + DOH *q = 0; + q = SwigType_parm(element); + Insert(result,0," "); + Insert(result,0,q); + Delete(q); + clear = 0; + } else if (SwigType_ispointer(element)) { Insert(result,0,"*"); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } firstarray = 0; + } else if (SwigType_ismemberpointer(element)) { + String *q; + Insert(result,0,"::*"); + q = SwigType_parm(element); + Insert(result,0,q); + Delete(q); + if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { + Insert(result,0,"("); + Append(result,")"); + } + firstarray = 0; } else if (SwigType_isreference(element)) { Insert(result,0,"&"); + isreference = 1; } else if (SwigType_isarray(element)) { DOH *size; if (firstarray) { @@ -975,16 +1408,16 @@ String *SwigType_rcaststr(SwigType *s, const String_or_char *name) { } Append(result,")"); Delete(parms); - } else if (SwigType_isqualifier(element)) { - DOH *q = 0; - q = SwigType_parm(element); - Insert(result,0," "); - Insert(result,0,q); - Delete(q); + } else if (SwigType_isenum(element)) { + String *bs = SwigType_namestr(element); + Insert(result,0,bs); + Delete(bs); clear = 0; } else { + String *bs = SwigType_namestr(element); Insert(result,0," "); - Insert(result,0,element); + Insert(result,0,bs); + Delete(bs); } element = nextelement; } @@ -995,14 +1428,14 @@ String *SwigType_rcaststr(SwigType *s, const String_or_char *name) { cast = NewStringf("(%s)",result); } if (name) { - if (SwigType_isreference(s)) { + if (isreference) { Append(cast,"*"); } Append(cast,name); } Delete(result); Delete(tc); - return Swig_temp_result(cast); + return cast; } @@ -1020,659 +1453,156 @@ String *SwigType_lcaststr(SwigType *s, const String_or_char *name) { if (SwigType_isarray(s)) { Printf(result,"(%s)%s", SwigType_lstr(s,0),name); } else if (SwigType_isreference(s)) { - Printf(result,"(%s)", SwigType_lstr(s,0)); + Printf(result,"(%s)", SwigType_str(s,0)); if (name) - Printf(result,"&%s", name); + Printf(result,"%s", name); } else if (SwigType_isqualifier(s)) { Printf(result,"(%s)%s", SwigType_lstr(s,0),name); } else { if (name) Append(result,name); } - return Swig_temp_result(result); + return result; } String *SwigType_manglestr_default(SwigType *s) { char *c; - String *result; + String *result,*base; + SwigType *lt; + SwigType *ss = 0; + + if (SwigType_istemplate(s)) { + ss = SwigType_typedef_resolve_all(s); + s = ss; + } + lt = SwigType_ltype(s); + result = SwigType_prefix(lt); + base = SwigType_base(lt); - if (SwigType_istypedef(s)) - result = Copy(s); - else - result = SwigType_ltype(s); - Replace(result,"struct ","", DOH_REPLACE_ANY); - Replace(result,"class ","", DOH_REPLACE_ANY); - Replace(result,"union ","", DOH_REPLACE_ANY); c = Char(result); while (*c) { - if (!isalnum(*c)) *c = '_'; + if (!isalnum((int)*c)) *c = '_'; c++; } - Insert(result,0,"_"); - return Swig_temp_result(result); -} - -String *SwigType_manglestr(SwigType *s) { - return SwigType_manglestr_default(s); -} - -/* ----------------------------------------------------------------------------- - * SwigType_strip_qualifiers() - * - * Rips all qualifiers out of a type. - * ----------------------------------------------------------------------------- */ - -void SwigType_strip_qualifiers(SwigType *ty) { - /* Sick hack alert */ - Replace(ty,"q(const).","", DOH_REPLACE_ANY); - Replace(ty,"q(volatile).", "", DOH_REPLACE_ANY); -} - -/* ----------------------------------------------------------------------------- - * Scope handling - * - * These functions are used to manipulate typedefs and scopes. - * ----------------------------------------------------------------------------- */ - -#define MAX_SCOPE 8 - -static Hash *type_scopes = 0; /* Hash table of scope names */ -static Hash *scopes[MAX_SCOPE]; /* List representing the current scope */ -static String *scopenames[MAX_SCOPE]; /* Names of the various scopes */ -static int scope_level = 0; - -static void init_scopes() { - if (type_scopes) return; - type_scopes = NewHash(); - scopes[scope_level] = NewHash(); - scopenames[scope_level] = NewString("::"); - Setattr(type_scopes,"::",scopes[scope_level]); -} - -/* ----------------------------------------------------------------------------- - * SwigType_typedef() - * - * Defines a new typedef. Returns -1 if the type name is already defined. - * ----------------------------------------------------------------------------- */ - -int SwigType_typedef(SwigType *type, String_or_char *name) { - int i; - String *qname; - init_scopes(); - if (Getattr(scopes[scope_level],name)) return -1; - if (Cmp(type,name) == 0) { - return 0; - } - i = scope_level; - qname = NewString(name); - while (i >= 0) { - String *sname; - /* Printf(stdout,"Adding typedef [%d] : '%s' -> '%s'\n", i, qname, type); */ - Setattr(scopes[i],qname,type); - if (i > 0) { - sname = scopenames[i]; - if (sname) { - qname = NewStringf("%s::%s",sname,qname); - } - } - i--; - } - - /* Setattr(scopes[scope_level],name,type); */ - /* Need to modify this to include all scopes */ - - if (default_cache) - Delattr(default_cache,type); - return 0; -} - -/* ----------------------------------------------------------------------------- - * SwigType_new_scope() - * - * Creates a new scope - * ----------------------------------------------------------------------------- */ - -void SwigType_new_scope() { - init_scopes(); - scope_level++; - scopes[scope_level] = NewHash(); - scopenames[scope_level] = NewString(""); -} - -/* ----------------------------------------------------------------------------- - * SwigType_reset_scopes() - * - * Reset the scope system - * ----------------------------------------------------------------------------- */ - -void SwigType_reset_scopes() { - Delete(type_scopes); - type_scopes = 0; - init_scopes(); -} - -/* ----------------------------------------------------------------------------- - * SwigType_set_scope_name() - * - * Set the name of the current scope. Note: this will create an entry in the - * type_scopes hash. - * ----------------------------------------------------------------------------- */ - -void SwigType_set_scope_name(String_or_char *name) { - String *key; - int i; - init_scopes(); - scopenames[scope_level] = NewString(Char(name)); - key = NewString(""); - for (i = 1; i <= scope_level; i++) { - Append(key,scopenames[scope_level]); - if (i < scope_level) Append(key,"::"); - } - Setattr(type_scopes,key,scopes[scope_level]); -} - -/* ----------------------------------------------------------------------------- - * SwigType_merge_scope() - * - * Merges the contents of one scope into the current scope. - * ----------------------------------------------------------------------------- */ - -void SwigType_merge_scope(Hash *scope, String *prefix) { - String *name; - String *key; - String *type; - - init_scopes(); - key = Firstkey(scope); - while (key) { - type = Getattr(scope,key); - if (prefix) { - name = NewStringf("%s::%s",prefix,key); - } else { - name = NewString(key); - } - SwigType_typedef(type,name); - key = Nextkey(scope); - } -} - -/* ----------------------------------------------------------------------------- - * SwigType_pop_scope() - * - * Pop off the last scope. Returns the hash table for the scope that was popped off. - * ----------------------------------------------------------------------------- */ - -Hash *SwigType_pop_scope() { - Hash *s; - String *prefix; - init_scopes(); - if (scope_level == 0) return 0; - prefix = scopenames[scope_level]; - s = scopes[scope_level--]; - if (Len(s)) return s; - Delete(s); - return 0; -} - -/* ----------------------------------------------------------------------------- - * SwigType_typedef_resolve() - * - * Resolves a typedef and returns a new type string. Returns 0 if there is no - * typedef mapping. - * ----------------------------------------------------------------------------- */ - -SwigType *SwigType_typedef_resolve(SwigType *t) { - String *base; - String *type; - String *r; - int level; - - init_scopes(); - base = SwigType_base(t); - level = scope_level; - while (level >= 0) { - /* See if we know about this type */ - type = Getattr(scopes[level],base); - if (type) break; - level--; - } - if (level < 0) { - return 0; + if (SwigType_istemplate(base)) { + String *b = SwigType_namestr(base); + Delete(base); + base = b; } - r = SwigType_prefix(t); - Append(r,type); - return r; -} -/* ----------------------------------------------------------------------------- - * SwigType_typedef_resolve_all() - * - * Fully resolve a type down to its most basic datatype - * ----------------------------------------------------------------------------- */ - -SwigType *SwigType_typedef_resolve_all(SwigType *t) { - SwigType *n; - SwigType *r = Copy(t); - - while ((n = SwigType_typedef_resolve(r))) { - Delete(r); - r = n; - } - return r; -} - -/* ----------------------------------------------------------------------------- - * SwigType_istypedef() - * - * Checks a typename to see if it is a typedef. - * ----------------------------------------------------------------------------- */ + Replace(base,"struct ","", DOH_REPLACE_ANY); /* This might be problematic */ + Replace(base,"class ","", DOH_REPLACE_ANY); + Replace(base,"union ","", DOH_REPLACE_ANY); -int SwigType_istypedef(SwigType *t) { - String *base, *type; - int level; - - init_scopes(); - base = SwigType_base(t); - level = scope_level; - while (level >= 0) { - /* See if we know about this type */ - type = Getattr(scopes[level],base); - if (type) { - return 1; - } - level--; - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * SwigType_cmp() - * - * Compares two type-strings using all available typedef information. Returns 0 - * if equal, 1 if not. - * ----------------------------------------------------------------------------- */ - -int SwigType_cmp(SwigType *tpat, SwigType *type) { - String *r, *s; - char *p, *t; - - p = Char(tpat); - t = Char(type); - - if (strcmp(p,t) == 0) return 0; - - r = SwigType_typedef_resolve(type); - while (r) { - t = Char(r); - if (strcmp(p,t) == 0) { - Delete(r); - return 0; - } - s = SwigType_typedef_resolve(r); - Delete(r); - r = s; - } - return 1; -} - -/* ----------------------------------------------------------------------------- - * SwigType_type() - * - * Returns an integer code describing the datatype. This is only used for - * compatibility with SWIG1.1 language modules and is likely to go away once - * everything is based on typemaps. - * ----------------------------------------------------------------------------- */ - -int SwigType_type(SwigType *t) -{ - char *c; - /* Check for the obvious stuff */ - c = Char(t); - - if (strncmp(c,"p.",2) == 0) { - if (SwigType_type(c+2) == T_CHAR) return T_STRING; - else return T_POINTER; - } - if (strncmp(c,"a(",2) == 0) return T_ARRAY; - if (strncmp(c,"r.",2) == 0) return T_REFERENCE; - - if (strncmp(c,"q(",2) == 0) { - while(*c && (*c != '.')) c++; - if (*c) return SwigType_type(c+1); - return T_ERROR; + c = Char(base); + while (*c) { + if (*c == '<') *c = 'T'; + else if (*c == '>') *c = 't'; + else if (*c == '*') *c = 'p'; + else if (*c == '[') *c = 'a'; + else if (*c == ']') *c = 'A'; + else if (*c == '&') *c = 'R'; + else if (*c == '(') *c = 'f'; + else if (*c == ')') *c = 'F'; + else if (!isalnum((int)*c)) *c = '_'; + c++; } - if (strncmp(c,"f(",2) == 0) return T_FUNCTION; - - /* Look for basic types */ - if (strcmp(c,"int") == 0) return T_INT; - if (strcmp(c,"long") == 0) return T_LONG; - if (strcmp(c,"short") == 0) return T_SHORT; - if (strcmp(c,"unsigned") == 0) return T_UINT; - if (strcmp(c,"unsigned short") == 0) return T_USHORT; - if (strcmp(c,"unsigned long") == 0) return T_ULONG; - if (strcmp(c,"unsigned int") == 0) return T_UINT; - if (strcmp(c,"char") == 0) return T_CHAR; - if (strcmp(c,"signed char") == 0) return T_SCHAR; - if (strcmp(c,"unsigned char") == 0) return T_UCHAR; - if (strcmp(c,"float") == 0) return T_FLOAT; - if (strcmp(c,"double") == 0) return T_DOUBLE; - if (strcmp(c,"void") == 0) return T_VOID; - if (strcmp(c,"bool") == 0) return T_BOOL; - if (strncmp(c,"enum ",5) == 0) return T_INT; - /* Hmmm. Unknown type */ - if (SwigType_istypedef(t)) { - int r; - SwigType *nt = SwigType_typedef_resolve(t); - r = SwigType_type(nt); - Delete(nt); - return r; - } - return T_USER; + Append(result,base); + Insert(result,0,"_"); + Delete(lt); + Delete(base); + if (ss) Delete(ss); + return result; } -/* ----------------------------------------------------------------------------- - * SwigType_remember() - * - * This function "remembers" a datatype that was used during wrapper code generation - * so that a type-checking table can be generated later on. It is up to the language - * modules to actually call this function--it is not done automatically. - * - * Type tracking is managed through two separate hash tables. The hash 'r_mangled' - * is mapping between mangled type names (used in the target language) and - * fully-resolved C datatypes used in the source input. The second hash 'r_resolved' - * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled - * names in the scripting languages. For example, consider the following set of - * typedef declarations: - * - * typedef double Real; - * typedef double Float; - * typedef double Point[3]; - * - * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and - * 'Point' were used in an interface file and "remembered" using this function. - * The hash tables would look like this: - * - * r_mangled { - * _p_double : [ p.double, a(3).double ] - * _p_Real : [ p.double ] - * _p_Float : [ p.double ] - * _Point : [ a(3).double ] - * - * r_resolved { - * p.double : [ _p_double, _p_Real, _p_Float ] - * a(3).double : [ _p_double, _Point ] - * } - * - * Together these two hash tables can be used to determine type-equivalency between - * mangled typenames. To do this, we view the two hash tables as a large graph and - * compute the transitive closure. - * ----------------------------------------------------------------------------- */ - -static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */ -static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */ -static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */ - -void SwigType_remember(SwigType *t) { - String *mt; - SwigType *lt; - Hash *h; - SwigType *fr; - - if (!r_mangled) { - r_mangled = NewHash(); - r_resolved = NewHash(); - r_ltype = NewHash(); - } - - mt = SwigType_manglestr(t); /* Create mangled string */ - if (SwigType_istypedef(t)) - lt = Copy(t); - else - lt = SwigType_ltype(t); - Setattr(r_ltype, mt, lt); - fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */ - h = Getattr(r_mangled,mt); - if (!h) { - h = NewHash(); - Setattr(r_mangled,mt,h); - Delete(h); - } - Setattr(h,fr,mt); - - h = Getattr(r_resolved, fr); - if (!h) { - h = NewHash(); - Setattr(r_resolved,fr,h); - Delete(h); - } - Setattr(h,mt,fr); +String *SwigType_manglestr(SwigType *s) { + return SwigType_manglestr_default(s); } /* ----------------------------------------------------------------------------- - * SwigType_equivalent_mangle() + * SwigType_typename_replace() * - * Return a list of all of the mangled typenames that are equivalent to another - * mangled name. This works as follows: For each fully qualified C datatype - * in the r_mangled hash entry, we collect all of the mangled names from the - * r_resolved hash and combine them together in a list (removing duplicate entries). + * Replaces a typename in a type with something else. Needed for templates. * ----------------------------------------------------------------------------- */ -List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) { - List *l; - Hash *h; - Hash *ch; - Hash *mh; - - if (found) { - h = found; - } else { - h = NewHash(); - } - if (checked) { - ch = checked; - } else { - ch = NewHash(); - } - if (Getattr(ch,ms)) goto check_exit; /* Already checked this type */ - Setattr(h,ms,"1"); - Setattr(ch, ms, "1"); - mh = Getattr(r_mangled,ms); - if (mh) { - String *key; - key = Firstkey(mh); - while (key) { - Hash *rh; - if (Getattr(ch,key)) { - key = Nextkey(mh); - continue; - } - Setattr(ch,key,"1"); - rh = Getattr(r_resolved,key); - if (rh) { - String *rkey; - rkey = Firstkey(rh); - while (rkey) { - Setattr(h,rkey,"1"); - SwigType_equivalent_mangle(rkey,ch,h); - rkey = Nextkey(rh); +void +SwigType_typename_replace(SwigType *t, String *pat, String *rep) { + String *nt; + int i; + List *elem; + + if (!Strstr(t,pat)) return; + + if (Strcmp(t,pat) == 0) { + Replace(t,pat,rep,DOH_REPLACE_ANY); + return; + } + nt = NewString(""); + elem = SwigType_split(t); + for (i = 0; i < Len(elem); i++) { + String *e = Getitem(elem,i); + if (SwigType_issimple(e)) { + if (Strcmp(e,pat) == 0) { + /* Replaces a type of the form 'pat' with 'rep<args>' */ + Replace(e,pat,rep,DOH_REPLACE_ANY); + } else if (SwigType_istemplate(e)) { + /* Replaces a type of the form 'pat<args>' with 'rep' */ + if (Strncmp(e,pat,Len(pat)) == 0) { + String *repbase = SwigType_templateprefix(rep); + Replace(e,pat,repbase,DOH_REPLACE_ID | DOH_REPLACE_FIRST); + Delete(repbase); + } + { + List *tparms = SwigType_parmlist(e); + int j; + String *nt = SwigType_templateprefix(e); + Printf(nt,"<("); + for (j = 0; j < Len(tparms); j++) { + SwigType_typename_replace(Getitem(tparms,j), pat, rep); + Printf(nt,"%s",Getitem(tparms,j)); + if (j < (Len(tparms)-1)) Printf(nt,","); + } + Printf(nt,")>%s", SwigType_templatesuffix(e)); + Clear(e); + Append(e,nt); + Delete(nt); } } - key = Nextkey(mh); - } - } - check_exit: - if (!found) { - l = Hash_keys(h); - Delete(h); - Delete(ch); - return l; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * SwigType_inherit() - * - * Record information about inheritance. We keep a hash table that keeps - * a mapping between base classes and all of the classes that are derived - * from them. - * - * subclass is a hash that maps base-classes to all of the classes derived from them. - * ----------------------------------------------------------------------------- */ - -static Hash *subclass = 0; -static Hash *conversions = 0; - -void -SwigType_inherit(String *derived, String *base) { - Hash *h; - if (!subclass) subclass = NewHash(); - - h = Getattr(subclass,base); - if (!h) { - h = NewHash(); - Setattr(subclass,base,h); - } - Setattr(h,derived,"1"); -} - -/* ----------------------------------------------------------------------------- - * SwigType_inherit_equiv() - * - * Modify the type table to handle C++ inheritance - * ----------------------------------------------------------------------------- */ - -void SwigType_inherit_equiv(File *out) { - String *rkey, *bkey, *ckey; - String *prefix, *base; - - Hash *sub; - Hash *rh; - - if (!conversions) conversions = NewHash(); - if (!subclass) subclass = NewHash(); - - rkey = Firstkey(r_resolved); - while (rkey) { - /* rkey is actually a fully qualified type */ - - base = SwigType_base(rkey); - sub = Getattr(subclass,base); - if (!sub) { - rkey = Nextkey(r_resolved); - continue; - } - - rh = Getattr(r_resolved, rkey); - - /* Hmmm. We actually got a base-class match. We're going to try and patch things up */ - bkey = Firstkey(sub); - while (bkey) { - prefix= SwigType_prefix(rkey); - Append(prefix,bkey); - Setattr(rh,SwigType_manglestr(prefix),prefix); - - ckey = NewStringf("%s+%s",SwigType_manglestr(prefix), SwigType_manglestr(rkey)); - if (!Getattr(conversions,ckey)) { - Printf(out,"static void *%sTo%s(void *x) {\n", SwigType_manglestr(prefix), SwigType_manglestr(rkey)); - Printf(out," return (void *)((%s) ((%s) x));\n", SwigType_lstr(rkey,0), SwigType_lstr(prefix,0)); - Printf(out,"}\n"); - SetInt(conversions,ckey,1); + } else if (SwigType_isfunction(e)) { + int j; + List *fparms = SwigType_parmlist(e); + Clear(e); + Printf(e,"f("); + for (j = 0; j < Len(fparms); j++) { + SwigType_typename_replace(Getitem(fparms,j), pat, rep); + Printf(e,"%s",Getitem(fparms,j)); + if (j < (Len(fparms)-1)) Printf(e,","); } - Delete(ckey); - Delete(prefix); - bkey = Nextkey(sub); + Printf(e,")."); } - rkey = Nextkey(r_resolved); + Append(nt,e); } + Clear(t); + Append(t,nt); } /* ----------------------------------------------------------------------------- - * SwigType_type_table() + * SwigType_check_decl() * - * Generate the type-table for the type-checker. + * Checks type declarators for a match * ----------------------------------------------------------------------------- */ -void -SwigType_emit_type_table(File *f_forward, File *f_table) { - DOH *key; - String *types, *table; - int i = 0; - - if (!r_mangled) { - r_mangled = NewHash(); - r_resolved = NewHash(); - } - - Printf(f_table,"\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n"); - - SwigType_inherit_equiv(f_table); - -#ifdef DEBUG - Printf(stdout,"---r_mangled---\n"); - Printf(stdout,"%s\n", r_mangled); - - Printf(stdout,"---r_resolved---\n"); - Printf(stdout,"%s\n", r_resolved); - - Printf(stdout,"---r_ltype---\n"); - Printf(stdout,"%s\n", r_ltype); - - Printf(stdout,"---subclass---\n"); - Printf(stdout,"%s\n", subclass); - - Printf(stdout,"---scopes[0]---\n"); - Printf(stdout,"%s\n", scopes[0]); - -#endif - table = NewString(""); - types = NewString(""); - Printf(table,"static swig_type_info *swig_types_initial[] = {\n"); - key = Firstkey(r_mangled); - Printf(f_forward,"\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n"); - while (key) { - List *el; - String *en; - Printf(f_forward,"#define SWIGTYPE%s swig_types[%d] \n", key, i); - Printv(types,"static swig_type_info _swigt_", key, "[] = {", 0); - Printv(types,"{\"", key, "\", 0, \"", SwigType_str(Getattr(r_ltype,key),0),"\"},", 0); - el = SwigType_equivalent_mangle(key,0,0); - for (en = Firstitem(el); en; en = Nextitem(el)) { - String *ckey; - ckey = NewStringf("%s+%s", en, key); - if (Getattr(conversions,ckey)) { - Printf(types,"{\"%s\", %sTo%s},", en, en, key); - } else { - Printf(types,"{\"%s\"},", en); - } - Delete(ckey); - } - Delete(el); - Printf(types,"{0}};\n"); - Printv(table, "_swigt_", key, ", \n", 0); - key = Nextkey(r_mangled); - i++; - } - - Printf(table, "0\n};\n"); - Printf(f_forward,"static swig_type_info *swig_types[%d];\n", i+1); - Printf(f_forward,"\n/* -------- TYPES TABLE (END) -------- */\n\n"); - Printf(f_table,"%s\n", types); - Printf(f_table,"%s\n", table); - Printf(f_table,"\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n"); - Delete(types); - Delete(table); +int +SwigType_check_decl(SwigType *ty, const SwigType *decl) { + SwigType *t,*t1,*t2; + int r; + t = SwigType_typedef_resolve_all(ty); + t1 = SwigType_strip_qualifiers(t); + t2 = SwigType_prefix(t1); + r = Cmp(t2,decl); + Delete(t); + Delete(t1); + Delete(t2); + if (r == 0) return 1; + return 0; } - - - - - - - - - - - - diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 3012d2cc4..604c62a9d 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -22,6 +22,12 @@ #include "doh.h" +/* Status codes */ + +#define SWIG_OK 1 +#define SWIG_ERROR 0 +#define SWIG_NOWRAP 0 + /* Short names for common data types */ typedef DOH String; @@ -32,30 +38,46 @@ typedef DOH File; typedef DOH Parm; typedef DOH ParmList; typedef DOH Node; +typedef DOH Symtab; +typedef DOH Typetab; +typedef DOH SwigType; /* --- Legacy DataType interface. These type codes are provided solely - for backwards compatibility with older modules --- */ + for backwards compatibility with older modules --- */ + +/* --- The ordering of type values is used to determine type-promotion + in the parser. Do not change */ -#define T_INT 1 -#define T_SHORT 2 -#define T_LONG 3 -#define T_UINT 4 +/* Numeric types */ + +#define T_BOOL 1 +#define T_SCHAR 2 +#define T_UCHAR 3 +#define T_SHORT 4 #define T_USHORT 5 -#define T_ULONG 6 -#define T_UCHAR 7 -#define T_SCHAR 8 -#define T_BOOL 9 -#define T_DOUBLE 10 -#define T_FLOAT 11 -#define T_CHAR 12 -#define T_USER 13 -#define T_VOID 14 -#define T_ENUM 15 -#define T_STRING 20 -#define T_POINTER 21 -#define T_REFERENCE 22 -#define T_ARRAY 23 -#define T_FUNCTION 24 +#define T_ENUM 6 +#define T_INT 7 +#define T_UINT 8 +#define T_LONG 9 +#define T_ULONG 10 +#define T_LONGLONG 11 +#define T_ULONGLONG 12 +#define T_FLOAT 20 +#define T_DOUBLE 21 +#define T_NUMERIC 22 + +/* non-numeric */ + +#define T_CHAR 30 +#define T_USER 31 +#define T_VOID 32 +#define T_STRING 33 +#define T_POINTER 34 +#define T_REFERENCE 35 +#define T_ARRAY 36 +#define T_FUNCTION 37 +#define T_MPOINTER 38 +#define T_VARARGS 39 #define T_SYMBOL 98 #define T_ERROR 99 @@ -68,20 +90,21 @@ extern FILE *Swig_open(const String_or_char *name); extern String *Swig_read_file(FILE *f); extern String *Swig_include(const String_or_char *name); extern int Swig_insert_file(const String_or_char *name, File *outfile); -extern int Swig_bytes_read(); -extern void Swig_register_filebyname(const String_or_char *name, File *outfile); -extern File *Swig_filebyname(const String_or_char *name); -extern void Swig_swiglib_set(const String_or_char *name); +extern void Swig_set_config_file(const String_or_char *filename); +extern String *Swig_get_config_file(void); +extern void Swig_swiglib_set(const String_or_char *); extern String *Swig_swiglib_get(); -extern void Swig_set_config_file(const String_or_char *name); -extern String *Swig_get_config_file(); - -#define OUTFILE(x) Swig_filebyname(x) +extern void Swig_register_filebyname(const String_or_char *filename, File *outfile); +extern File *Swig_filebyname(const String_or_char *filename); +extern char *Swig_file_suffix(const String_or_char *filename); +extern char *Swig_file_basename(const String_or_char *filename); +extern char *Swig_file_filename(const String_or_char *filename); +extern char *Swig_file_dirname(const String_or_char *filename); #ifdef MACSWIG -#define SWIG_FILE_DELIMETER ":" +# define SWIG_FILE_DELIMETER ":" #else -#define SWIG_FILE_DELIMETER "/" +# define SWIG_FILE_DELIMETER "/" #endif /* --- Command line parsing --- */ @@ -159,23 +182,29 @@ extern void SwigScanner_idstart(SwigScanner *, char *idchar); #define SWIG_TOKEN_DOLLAR 46 #define SWIG_TOKEN_CODEBLOCK 47 #define SWIG_TOKEN_RSTRING 48 +#define SWIG_TOKEN_LONGLONG 49 +#define SWIG_TOKEN_ULONGLONG 50 #define SWIG_TOKEN_ILLEGAL 98 #define SWIG_TOKEN_LAST 99 /* --- Functions for manipulating the string-based type encoding --- */ -typedef DOH SwigType; extern SwigType *NewSwigType(int typecode); extern void SwigType_add_pointer(SwigType *t); +extern void SwigType_add_memberpointer(SwigType *t, String_or_char *qual); extern void SwigType_del_pointer(SwigType *t); extern void SwigType_add_array(SwigType *t, String_or_char *size); +extern SwigType *SwigType_pop_arrays(SwigType *t); extern void SwigType_add_reference(SwigType *t); extern void SwigType_add_qualifier(SwigType *t, String_or_char *qual); extern void SwigType_add_function(SwigType *t, ParmList *parms); +extern void SwigType_add_template(SwigType *t, ParmList *parms); +extern SwigType *SwigType_pop_function(SwigType *t); +extern ParmList *SwigType_function_parms(SwigType *t); extern List *SwigType_split(SwigType *t); extern String *SwigType_pop(SwigType *t); extern void SwigType_push(SwigType *t, SwigType *s); -extern List *SwigType_parmlist(SwigType *p); +extern List *SwigType_parmlist(const SwigType *p); extern String *SwigType_parm(String *p); extern String *SwigType_str(SwigType *s, const String_or_char *id); extern String *SwigType_lstr(SwigType *s, const String_or_char *id); @@ -184,35 +213,84 @@ extern String *SwigType_lcaststr(SwigType *s, const String_or_char *id); extern String *SwigType_manglestr(SwigType *t); extern SwigType *SwigType_ltype(SwigType *t); extern int SwigType_ispointer(SwigType *t); +extern int SwigType_ismemberpointer(SwigType *t); extern int SwigType_isreference(SwigType *t); extern int SwigType_isarray(SwigType *t); extern int SwigType_isfunction(SwigType *t); extern int SwigType_isqualifier(SwigType *t); extern int SwigType_isconst(SwigType *t); - +extern int SwigType_issimple(SwigType *t); +extern int SwigType_ismutable(SwigType *t); +extern int SwigType_isvarargs(const SwigType *t); +extern int SwigType_istemplate(const SwigType *t); +extern int SwigType_isenum(SwigType *t); +extern int SwigType_check_decl(SwigType *t, const String_or_char *decl); +extern SwigType *SwigType_strip_qualifiers(SwigType *t); extern String *SwigType_base(SwigType *t); +extern String *SwigType_namestr(const SwigType *t); +extern String *SwigType_templateprefix(SwigType *t); +extern String *SwigType_templatesuffix(const SwigType *t); +extern String *SwigType_templateargs(SwigType *t); extern String *SwigType_prefix(SwigType *t); -extern void SwigType_setbase(SwigType *t, String_or_char *name); +extern int SwigType_array_ndim(SwigType *t); +extern String *SwigType_array_getdim(SwigType *t, int n); +extern void SwigType_array_setdim(SwigType *t, int n, String_or_char *rep); +extern SwigType *SwigType_array_type(SwigType *t); +extern String *SwigType_default(SwigType *t); +extern void SwigType_typename_replace(SwigType *t, String *pat, String *rep); +/* --- Type-system managment --- */ +extern void SwigType_typesystem_init(); extern int SwigType_typedef(SwigType *type, String_or_char *name); -extern void SwigType_inherit(String *subclass, String *baseclass); -extern void SwigType_new_scope(); +extern int SwigType_typedef_class(String_or_char *name); +extern int SwigType_typedef_using(String_or_char *qname); +extern void SwigType_inherit(String *subclass, String *baseclass, String *cast); +extern int SwigType_issubtype(SwigType *subtype, SwigType *basetype); +extern void SwigType_scope_alias(String *aliasname, Typetab *t); +extern void SwigType_using_scope(Typetab *t); +extern void SwigType_new_scope(String_or_char *name); extern void SwigType_reset_scopes(); extern void SwigType_set_scope_name(String_or_char *name); -extern void SwigType_merge_scope(Hash *scope, String *prefix); -extern Hash *SwigType_pop_scope(); +extern void SwigType_inherit_scope(Typetab *scope); +extern Typetab *SwigType_pop_scope(); +extern Typetab *SwigType_set_scope(Typetab *h); +extern void SwigType_print_scope(Typetab *t); extern SwigType *SwigType_typedef_resolve(SwigType *t); extern SwigType *SwigType_typedef_resolve_all(SwigType *t); +extern SwigType *SwigType_typedef_qualified(SwigType *t); extern int SwigType_istypedef(SwigType *t); -extern int SwigType_cmp(String_or_char *pat, SwigType *t); -extern int SwigType_array_ndim(SwigType *t); -extern String *SwigType_array_getdim(SwigType *t, int n); -extern void SwigType_array_setdim(SwigType *t, int n, String_or_char *rep); -extern String *SwigType_default(SwigType *t); -extern int SwigType_type(SwigType *t); +extern int SwigType_isclass(SwigType *t); +extern void SwigType_attach_symtab(Symtab *syms); extern void SwigType_remember(SwigType *t); +extern void SwigType_remember_clientdata(SwigType *t, const String_or_char *clientdata); +extern void (*SwigType_remember_trace(void (*tf)(SwigType *, String *, String *)))(SwigType *, String *, String *); extern void SwigType_emit_type_table(File *f_headers, File *f_table); -extern void SwigType_strip_qualifiers(SwigType *t); +extern int SwigType_type(SwigType *t); + +/* --- Symbol table module --- */ + +extern void Swig_symbol_init(); +extern void Swig_symbol_setscopename(const String_or_char *name); +extern String *Swig_symbol_getscopename(); +extern String *Swig_symbol_qualifiedscopename(Symtab *symtab); +extern Symtab *Swig_symbol_newscope(); +extern Symtab *Swig_symbol_setscope(Symtab *); +extern Symtab *Swig_symbol_getscope(const String_or_char *symname); +extern Symtab *Swig_symbol_current(); +extern Symtab *Swig_symbol_popscope(); +extern Node *Swig_symbol_add(String_or_char *symname, Node *node); +extern void Swig_symbol_cadd(String_or_char *symname, Node *node); +extern Node *Swig_symbol_clookup(String_or_char *symname, Symtab *tab); +extern Symtab *Swig_symbol_cscope(String_or_char *symname, Symtab *tab); +extern Node *Swig_symbol_clookup_local(String_or_char *symname, Symtab *tab); +extern String *Swig_symbol_qualified(Node *node); +extern Node *Swig_symbol_isoverloaded(Node *node); +extern void Swig_symbol_remove(Node *node); +extern void Swig_symbol_alias(String_or_char *aliasname, Symtab *tab); +extern void Swig_symbol_inherit(Symtab *tab); +extern SwigType *Swig_symbol_type_qualify(SwigType *ty, Symtab *tab); +extern String *Swig_symbol_string_qualify(String *s, Symtab *tab); +extern SwigType *Swig_symbol_typedef_reduce(SwigType *ty, Symtab *tab); /* --- Parameters and Parameter Lists --- */ @@ -221,58 +299,63 @@ extern void SwigType_strip_qualifiers(SwigType *t); extern Parm *NewParm(SwigType *type, String_or_char *n); extern Parm *CopyParm(Parm *p); - - - extern ParmList *CopyParmList(ParmList *); extern int ParmList_len(ParmList *); extern int ParmList_numarg(ParmList *); +extern int ParmList_numrequired(ParmList *); extern String *ParmList_str(ParmList *); extern String *ParmList_protostr(ParmList *); /* --- Parse tree support --- */ -typedef struct { - const char *name; - int (*action)(DOH *obj, void *clientdata); -} SwigRule; - - -#define SWIG_OK 1 -#define SWIG_NORULE 0 -#define SWIG_ERROR -1 - -extern void Swig_add_rule(const String_or_char *, int (*action)(DOH *, void *)); -extern void Swig_add_rules(SwigRule ruleset[]); -extern void Swig_clear_rules(); -extern int Swig_tag_check(DOH *obj, const String_or_char *tagname); -extern int Swig_emit(DOH *obj, void *clientdata); -extern int Swig_emit_all(DOH *obj, void *clientdata); -extern void Swig_set_callback(DOH *obj, void (*cb)(void *clientdata), void *clientdata); -extern void (*Swig_set_trace(DOH *obj, void (*cb)(DOH *, DOH *), DOH *arg))(DOH *, DOH *); -extern void Swig_remove_trace(DOH *obj); -extern void Swig_node_cut(DOH *obj); -extern void Swig_node_insert(DOH *node, DOH *newnode); -extern void Swig_node_temporary(DOH *node); -extern void Swig_node_ignore(DOH *node); -extern void Swig_node_append_child(DOH *node, DOH *cld); -extern int Swig_count_nodes(DOH *node); - -extern DOH *Swig_next(DOH *obj); -extern DOH *Swig_prev(DOH *obj); +/* DOM-like node access */ + +#define nodeType(x) Getattr(x,"nodeType") +#define parentNode(x) Getattr(x,"parentNode") +#define previousSibling(x) Getattr(x,"previousSibling") +#define nextSibling(x) Getattr(x,"nextSibling") +#define firstChild(x) Getattr(x,"firstChild") +#define lastChild(x) Getattr(x,"lastChild") +extern int checkAttribute(Node *obj, const String_or_char *name, const String_or_char *value); + +/* Macros to set up the DOM tree (mostly used by the parser) */ + +#define set_nodeType(x,v) Setattr(x,"nodeType",v) +#define set_parentNode(x,v) Setattr(x,"parentNode",v) +#define set_previousSibling(x,v) Setattr(x,"previousSibling",v) +#define set_nextSibling(x,v) Setattr(x,"nextSibling",v) +#define set_firstChild(x,v) Setattr(x,"firstChild",v) +#define set_lastChild(x,v) Setattr(x,"lastChild",v) + +extern void appendChild(Node *node, Node *child); +extern void deleteNode(Node *node); +extern Node *copyNode(Node *node); + +extern void Swig_tag_nodes(Node *node, const String_or_char *attrname, DOH *value); + +extern int Swig_require(Node **node, ...); +extern int Swig_save(Node **node,...); +extern void Swig_restore(Node **node); /* Debugging of parse trees */ extern void Swig_debug_emit(int); -extern void Swig_dump_tags(DOH *obj, DOH *root); -extern void Swig_dump_tree(DOH *obj); -extern void Swig_dump_rules(); +extern void Swig_print_tags(File *obj, Node *root); +extern void Swig_print_tree(Node *obj); +extern void Swig_print_node(Node *obj); /* -- Wrapper function Object */ -typedef DOH Wrapper; +typedef struct { + Hash *localh; + String *def; + String *locals; + String *code; +} Wrapper; extern Wrapper *NewWrapper(); +extern void DelWrapper(Wrapper *w); extern void Wrapper_pretty_print(String *str, File *f); +extern void Wrapper_print(Wrapper *w, File *f); extern int Wrapper_add_local(Wrapper *w, const String_or_char *name, const String_or_char *decl); extern int Wrapper_add_localv(Wrapper *w, const String_or_char *name, ...); extern int Wrapper_check_local(Wrapper *w, const String_or_char *name); @@ -281,160 +364,115 @@ extern char *Wrapper_new_localv(Wrapper *w, const String_or_char *name, ...) /* --- Naming functions --- */ -extern void Swig_name_register(String_or_char *method, String_or_char *format); -extern String *Swig_name_mangle(String_or_char *s); -extern String *Swig_name_wrapper(String_or_char *fname); -extern String *Swig_name_member(String_or_char *classname, String_or_char *mname); -extern String *Swig_name_get(String_or_char *vname); -extern String *Swig_name_set(String_or_char *vname); -extern String *Swig_name_construct(String_or_char *classname); -extern String *Swig_name_destroy(String_or_char *classname); - -/* --- Mapping interface --- */ - -extern void Swig_map_add(Hash *ruleset, Hash *parms, DOH *obj); -extern DOH *Swig_map_match(Hash *ruleset, Hash *parms, int *nmatch); +extern void Swig_name_register(const String_or_char *method, const String_or_char *format); +extern void Swig_name_unregister(const String_or_char *method); +extern String *Swig_name_mangle(const String_or_char *s); +extern String *Swig_name_wrapper(const String_or_char *fname); +extern String *Swig_name_member(const String_or_char *classname, const String_or_char *mname); +extern String *Swig_name_get(const String_or_char *vname); +extern String *Swig_name_set(const String_or_char *vname); +extern String *Swig_name_construct(const String_or_char *classname); +extern String *Swig_name_copyconstructor(const String_or_char *classname); +extern String *Swig_name_destroy(const String_or_char *classname); + +/* --- parameterized rename functions --- */ + +extern void Swig_name_object_set(Hash *namehash, String_or_char *name, SwigType *decl, DOH *object); +extern DOH *Swig_name_object_get(Hash *namehash, String_or_char *prefix, String_or_char *name, SwigType *decl); +extern void Swig_name_object_inherit(Hash *namehash, String *base, String *derived); +extern void Swig_features_get(Hash *features, String_or_char *prefix, String_or_char *name, SwigType *decl, Node *n); +extern void Swig_feature_set(Hash *features, String_or_char *name, SwigType *decl, String_or_char *fname, String *value); /* --- Misc --- */ extern char *Swig_copy_string(const char *c); extern void Swig_banner(File *f); -extern void Swig_section(File *f, const String_or_char *s); -extern DOH *Swig_temp_result(DOH *x); extern String *Swig_string_escape(String *s); extern String *Swig_string_mangle(String *s); +extern String *Swig_scopename_prefix(String *s); +extern String *Swig_scopename_last(String *s); +extern String *Swig_scopename_first(String *s); +extern String *Swig_scopename_suffix(String *s); +extern int Swig_scopename_check(String *s); + extern void Swig_init(); +extern void Swig_warn(const char *filename, int line, const char *msg); + + +#define WARNING(msg) Swig_warn(__FILE__,__LINE__,msg) -extern int Swig_proto_cmp(const String_or_char *pat, DOH *node); +extern void Swig_warning(int num, const String_or_char *filename, int line, const char *fmt, ...); +extern void Swig_error(const String_or_char *filename, int line, const char *fmt, ...); +extern int Swig_error_count(void); +extern void Swig_error_silent(int s); +extern void Swig_warnfilter(const String_or_char *wlist, int val); +extern void Swig_warnall(void); +extern int Swig_warn_count(void); /* --- C Wrappers --- */ -extern String *Swig_clocal(SwigType *t, String_or_char *name, String_or_char *value); -extern SwigType *Swig_clocal_type(SwigType *t); -extern String *Swig_clocal_deref(SwigType *t, String_or_char *name); -extern String *Swig_clocal_assign(SwigType *t, String_or_char *name); extern String *Swig_cparm_name(Parm *p, int i); +extern String *Swig_clocal(SwigType *t, String_or_char *name, String_or_char *value); +extern String *Swig_wrapped_var_type(SwigType *t); +extern String *Swig_wrapped_var_deref(SwigType *t, String_or_char *name); +extern String *Swig_wrapped_var_assign(SwigType *t, String_or_char *name); extern int Swig_cargs(Wrapper *w, ParmList *l); -extern void Swig_cresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_char *decl); -extern void Swig_cppresult(Wrapper *w, SwigType *t, String_or_char *name, String_or_char *decl); +extern String *Swig_cresult(SwigType *t, const String_or_char *name, const String_or_char *decl); + extern String *Swig_cfunction_call(String_or_char *name, ParmList *parms); -extern String *Swig_cmethod_call(String_or_char *name, ParmList *parms); +extern String *Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self); extern String *Swig_cconstructor_call(String_or_char *name); extern String *Swig_cppconstructor_call(String_or_char *name, ParmList *parms); extern String *Swig_cdestructor_call(); extern String *Swig_cppdestructor_call(); -extern String *Swig_cmemberset_call(String_or_char *name, SwigType *t); -extern String *Swig_cmemberget_call(String_or_char *name, SwigType *t); - -extern Wrapper *Swig_cfunction_wrapper(String_or_char *funcname, - SwigType *rtype, - ParmList *parms, - String_or_char *code); - -extern Wrapper *Swig_cmethod_wrapper(String_or_char *classname, - String_or_char *methodname, - SwigType *rtype, - ParmList *parms, - String_or_char *code); - -extern Wrapper *Swig_cdestructor_wrapper(String_or_char *classname, - String_or_char *code); - -extern Wrapper *Swig_cppdestructor_wrapper(String_or_char *classname, - String_or_char *code); - -extern Wrapper *Swig_cconstructor_wrapper(String_or_char *classname, - ParmList *parms, - String_or_char *code); - -extern Wrapper *Swig_cppconstructor_wrapper(String_or_char *classname, - ParmList *parms, - String_or_char *code); - - -extern Wrapper *Swig_cmemberset_wrapper(String_or_char *classname, - String_or_char *membername, - SwigType *type, - String_or_char *code); - -extern Wrapper *Swig_cmemberget_wrapper(String_or_char *classname, - String_or_char *membername, - SwigType *type, - String_or_char *code); - -extern Wrapper *Swig_cvarset_wrapper(String_or_char *varname, - SwigType *type, - String_or_char *code); - -extern Wrapper *Swig_cvarget_wrapper(String_or_char *varname, - SwigType *type, - String_or_char *code); - - -/* --- Module loader and handler --- */ - -typedef struct Module Module; -extern void Swig_register_module(const String_or_char *modname, const String_or_char *starttag, - int (*initfunc)(int, char **), - DOH *(*startfunc)(DOH *)); - -extern Module *Swig_load_module(const String_or_char *modname); -extern int Swig_init_module(Module *m, int argc, char **argv); -extern DOH *Swig_start_module(Module *m, DOH *obj); -extern DOH *Swig_run_modules(DOH *node); - -/* --- Legacy Typemap API (somewhat simplified) --- */ - -extern void Swig_typemap_init(); -extern void Swig_typemap_register(const String_or_char *op, SwigType *type, String_or_char *name, String_or_char *code, ParmList *locals); -extern void Swig_typemap_copy(const String_or_char *op, SwigType *stype, String_or_char *sname, - SwigType *ttype, String_or_char *tname); -extern void Swig_typemap_clear(const String_or_char *op, SwigType *type, String_or_char *name); -extern void Swig_typemap_apply(SwigType *tm_type, String_or_char *tmname, SwigType *type, String_or_char *pname); -extern void Swig_typemap_clear_apply(SwigType *type, String_or_char *pname); -extern void Swig_typemap_debug(); -extern Hash *Swig_typemap_search(const String_or_char *op, SwigType *type, String_or_char *pname); -extern char *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname, String_or_char *source, String_or_char *target, Wrapper *f); -extern void Swig_typemap_new_scope(Hash *); +extern String *Swig_cmemberset_call(String_or_char *name, SwigType *type, String_or_char *self); +extern String *Swig_cmemberget_call(String_or_char *name, SwigType *t, String_or_char *self); + +/* --- Transformations --- */ + +extern int Swig_MethodToFunction(Node *n, String *classname, int flags); +extern int Swig_ConstructorToFunction(Node *n, String *classname, int cplus, int flags); +extern int Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags); +extern int Swig_MembersetToFunction(Node *n, String *classname, int flags); +extern int Swig_MembergetToFunction(Node *n, String *classname, int flags); +extern int Swig_VargetToFunction(Node *n); +extern int Swig_VarsetToFunction(Node *n); + +#define CWRAP_EXTEND 0x01 +#define CWRAP_SMART_POINTER 0x02 + +/* --- Legacy Typemap API (somewhat simplified, ha!) --- */ + +extern void Swig_typemap_init(); +extern void Swig_typemap_register(const String_or_char *op, ParmList *pattern, String_or_char *code, ParmList *locals, ParmList *kwargs); +extern int Swig_typemap_copy(const String_or_char *op, ParmList *srcpattern, ParmList *pattern); +extern void Swig_typemap_clear(const String_or_char *op, ParmList *pattern); +extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat); +extern void Swig_typemap_clear_apply(ParmList *pattern); +extern void Swig_typemap_debug(); + +extern Hash *Swig_typemap_search(const String_or_char *op, SwigType *type, String_or_char *pname, SwigType **matchtype); +extern Hash *Swig_typemap_search_multi(const String_or_char *op, ParmList *parms, int *nmatch); +extern String *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname, String_or_char *lname, + String_or_char *source, String_or_char *target, Wrapper *f); + +extern String *Swig_typemap_lookup_new(const String_or_char *op, Node *n, const String_or_char *lname, Wrapper *f); + +extern String *Swig_typemap_lookup_multi(const String_or_char *op, ParmList *parms, String_or_char *source, Wrapper *f, int *nmatch); +extern void Swig_typemap_new_scope(); extern Hash *Swig_typemap_pop_scope(); -/* --- Legacy %except directive API --- */ -extern void Swig_except_register(String_or_char *code); -extern char *Swig_except_lookup(); -extern void Swig_except_clear(); - -/* --- Attribute access macros --- */ - -#define Gettype(x) Getattr(x,"type") -#define Getname(x) Getattr(x,"name") -#define Getvalue(x) Getattr(x,"value") -#define Getlname(x) Getattr(x,"lname") -#define Getignore(x) GetInt(x,"ignore") -#define Getparms(x) Getattr(x,"parms") -#define Gettag(x) Getattr(x,"tag") -#define Getparent(x) Getattr(x,"parent") - -#define Settype(x,v) Setattr(x,"type",v) -#define Setname(x,v) Setattr(x,"name",v) -#define Setlname(x,v) Setattr(x,"lname",v) -#define Setvalue(x,v) Setattr(x,"value", v) -#define Setignore(x,v) SetInt(x,"ignore",v) -#define Settag(x,v) Setattr(x,"tag",v) -#define Setparms(x,v) Setattr(x,"parms", v) -#define Setparent(x,p) Setattr(x,"parent",p) - -#define Getnext(x) Getattr(x,"next") -#define Setnext(x,n) Setattr(x,"next",n) -#define Getprev(x) Getattr(x,"prev") -#define Setprev(x,n) Setattr(x,"prev",n) - -#define Getchild(x) Getattr(x,"child") -#define Setchild(x,c) Setattr(x,"child",c) - -extern int Swig_main(int argc, char **argv, char **modules); -extern void Swig_exit(int n); +extern void Swig_typemap_attach_parms(const String_or_char *op, ParmList *parms, Wrapper *f); + +/* --- Code fragment support --- */ +extern void Swig_fragment_register(String *name, String *section, String *code); +extern void Swig_fragment_emit(String *name); + #endif + + + diff --git a/Source/Swig/swig.i b/Source/Swig/swig.i index d90df029b..33d174ddf 100644 --- a/Source/Swig/swig.i +++ b/Source/Swig/swig.i @@ -717,11 +717,7 @@ extern FILE *Swig_open(DOH *name); extern DOH *Swig_read_file(FILE *file); extern DOH *Swig_include(DOH *name); -#ifdef MACSWIG -#define SWIG_FILE_DELIMETER ":" -#else #define SWIG_FILE_DELIMETER "/" -#endif %section "Command Line Parsing" diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c new file mode 100644 index 000000000..31a6016c3 --- /dev/null +++ b/Source/Swig/symbol.c @@ -0,0 +1,1124 @@ +/* ----------------------------------------------------------------------------- + * symbol.c + * + * This file implements the SWIG symbol table. See details below. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_symbol_c[] = "$Header$"; + +#include "swig.h" +#include "swigwarn.h" +#include <ctype.h> + +/* ----------------------------------------------------------------------------- + * Synopsis + * + * This module provides symbol table management for all of SWIG. In previous + * releases, the management of symbols was rather haphazard. This module tries + * to correct that. + * + * All symbols are associated with simple identifiers. For example, here are some + * declarations that generate symbol table entries: + * + * decl symbol + * -------------- ------------ + * void foo(int); foo + * int x; x + * typedef int *blah; blah + * + * Associated with each symbol is a Hash table that can contain any set of + * attributes that make sense for that object. For example: + * + * typedef int *blah; ----> "name" : 'blah' + * "type" : 'int' + * "decl" : 'p.' + * "storage" : 'typedef' + * + * In some cases, the symbol table needs to manage overloaded entries. For instance, + * overloaded functions. In this case, a linked list is built. The "sym:nextSibling" + * attribute is reserved to hold a link to the next entry. For example: + * + * int foo(int); --> "name" : "foo" "name" : "foo" + * int foo(int,double); "type" : "int" "type" : "int" + * "decl" : "f(int)." "decl" : "f(int,double)." + * ... ... + * "sym:nextSibling" : --------> "sym:nextSibling": --------> ... + * + * When more than one symbol has the same name, the symbol declarator is + * used to detect duplicates. For example, in the above case, foo(int) and + * foo(int,double) are different because their "decl" attribute is different. + * However, if a third declaration "foo(int)" was made, it would generate a + * conflict (due to having a declarator that matches a previous entry). + * + * Structures and classes: + * + * C/C++ symbol tables are normally managed in a few different spaces. The + * most visible namespace is reserved for functions, variables, typedef, enum values + * and such. In C, a separate tag-space is reserved for 'struct name', 'class name', + * and 'union name' declarations. In SWIG, a single namespace is used for everything + * this means that certain incompatibilities will arise with some C programs. For instance: + * + * struct Foo { + * ... + * } + * + * int Foo(); // Error. Name clash. Works in C though + * + * Due to the unified namespace for structures, special handling is performed for + * the following: + * + * typedef struct Foo { + * + * } Foo; + * + * In this case, the symbol table contains an entry for the structure itself. The + * typedef is left out of the symbol table. + * + * Target language vs C: + * + * The symbol tables are normally managed *in the namespace of the target language*. + * This means that name-collisions can be resolved using %rename and related + * directives. A quirk of this is that sometimes the symbol tables need to + * be used for C type resolution as well. To handle this, each symbol table + * also has a C-symbol table lurking behind the scenes. This is used to locate + * symbols in the C namespace. However, this symbol table is not used for error + * reporting nor is it used for anything else during code generation. + * + * Symbol table structure: + * + * Symbol tables themselves are a special kind of node that is organized just like + * a normal parse tree node. Symbol tables are organized in a tree that can be + * traversed using the SWIG-DOM API. The following attributes names are reserved. + * + * name -- Name of the scope defined by the symbol table (if any) + * This name is the C-scope name and is not affected by + * %renaming operations + * symtab -- Hash table mapping identifiers to nodes. + * csymtab -- Hash table mapping C identifiers to nodes. + * + * Reserved attributes on symbol objects: + * + * When a symbol is placed in the symbol table, the following attributes + * are set: + * + * sym:name -- Symbol name + * sym:nextSibling -- Next symbol (if overloaded) + * sym:previousSibling -- Previous symbol (if overloaded) + * sym:symtab -- Symbol table object holding the symbol + * sym:overloaded -- Set to the first symbol if overloaded + * + * These names are modeled after XML namespaces. In particular, every attribute + * pertaining to symbol table management is prefaced by the "sym:" prefix. + * ----------------------------------------------------------------------------- */ + +static Hash *current = 0; /* The current symbol table hash */ +static Hash *ccurrent = 0; /* The current c symbol table hash */ +static Hash *current_symtab = 0; /* Current symbol table node */ +static Hash *symtabs = 0; /* Hash of all symbol tables by fully-qualified name */ +static Hash *global_scope = 0; /* Global scope */ + +/* ----------------------------------------------------------------------------- + * Swig_symbol_new() + * + * Create a new symbol table object + * ----------------------------------------------------------------------------- */ + +void +Swig_symbol_init() { + current = NewHash(); + current_symtab = NewHash(); + ccurrent = NewHash(); + set_nodeType(current_symtab,"symboltable"); + Setattr(current_symtab,"symtab",current); + Setattr(current_symtab,"csymtab", ccurrent); + + /* Set the global scope */ + symtabs = NewHash(); + Setattr(symtabs,"",current_symtab); + global_scope = current_symtab; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_setscopename() + * + * Set the C scopename of the current symbol table. + * ----------------------------------------------------------------------------- */ + +void +Swig_symbol_setscopename(const String_or_char *name) { + String *qname; + assert(!Getattr(current_symtab,"name")); + Setattr(current_symtab,"name",name); + + /* Set nested scope in parent */ + + qname = Swig_symbol_qualifiedscopename(current_symtab); + + /* Save a reference to this scope */ + Setattr(symtabs,qname,current_symtab); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_getscopename() + * + * Get the C scopename of the current symbol table + * ----------------------------------------------------------------------------- */ + +String * +Swig_symbol_getscopename() { + return Getattr(current_symtab,"name"); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_getscope() + * + * Given a fully qualified C scopename, this function returns a symbol table + * ----------------------------------------------------------------------------- */ + +Symtab * +Swig_symbol_getscope(const String_or_char *name) { + if (!symtabs) return 0; + if (Strcmp(name,"::") == 0) name = ""; + return Getattr(symtabs,name); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_qualifiedscopename() + * + * Get the fully qualified C scopename of a symbol table. Note, this only pertains + * to the C/C++ scope name. It is not affected by renaming. + * ----------------------------------------------------------------------------- */ + +String * +Swig_symbol_qualifiedscopename(Symtab *symtab) { + String *result = 0; + Hash *parent; + String *name; + if (!symtab) symtab = current_symtab; + parent = parentNode(symtab); + if (parent) { + result = Swig_symbol_qualifiedscopename(parent); + } + name = Getattr(symtab,"name"); + if (name) { + if (!result) { + result = NewString(""); + } + if (Len(result)) { + Printf(result,"::%s",name); + } else { + Printf(result,"%s",name); + } + } + return result; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_newscope() + * + * Create a new scope. Returns the newly created scope. + * ----------------------------------------------------------------------------- */ + +Symtab * +Swig_symbol_newscope() +{ + Hash *n; + Hash *hsyms, *h; + + hsyms = NewHash(); + h = NewHash(); + + set_nodeType(h,"symboltable"); + Setattr(h,"symtab",hsyms); + set_parentNode(h,current_symtab); + + n = lastChild(current_symtab); + if (!n) { + set_firstChild(current_symtab,h); + } else { + set_nextSibling(n,h); + } + set_lastChild(current_symtab,h); + current = hsyms; + ccurrent = NewHash(); + Setattr(h,"csymtab",ccurrent); + current_symtab = h; + return current_symtab; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_setscope() + * + * Set the current scope. Returns the previous current scope. + * ----------------------------------------------------------------------------- */ + +Symtab * +Swig_symbol_setscope(Symtab *sym) { + Symtab *ret = current_symtab; + current_symtab = sym; + current = Getattr(sym,"symtab"); + assert(current); + ccurrent = Getattr(sym,"csymtab"); + assert(ccurrent); + return ret; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_popscope() + * + * Pop out of the current scope. Returns the popped scope and sets the + * scope to the parent scope. + * ----------------------------------------------------------------------------- */ + +Symtab * +Swig_symbol_popscope() { + Hash *h = current_symtab; + current_symtab = parentNode(current_symtab); + assert(current_symtab); + current = Getattr(current_symtab,"symtab"); + assert(current); + ccurrent = Getattr(current_symtab,"csymtab"); + assert(ccurrent); + return h; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_current() + * + * Return the current symbol table. + * ----------------------------------------------------------------------------- */ + +Symtab * +Swig_symbol_current() { + return current_symtab; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_alias() + * + * Makes an alias for a symbol in the global symbol table. + * ----------------------------------------------------------------------------- */ + +void +Swig_symbol_alias(String_or_char *aliasname, Symtab *s) { + String *qname; + qname = Swig_symbol_qualifiedscopename(current_symtab); + if (qname) { + Printf(qname,"::%s", aliasname); + } else { + qname = NewString(aliasname); + } + if (!Getattr(symtabs,qname)) { + Setattr(symtabs,qname,s); + } +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_inherit() + * + * Inherit symbols from another scope. + * ----------------------------------------------------------------------------- */ + +void Swig_symbol_inherit(Symtab *s) { + int i; + List *inherit = Getattr(current_symtab,"inherit"); + if (!inherit) { + inherit = NewList(); + Setattr(current_symtab,"inherit", inherit); + } + assert(s != current_symtab); + for (i = 0; i < Len(inherit); i++) { + Node *n = Getitem(inherit,i); + if (n == s) return; /* Already inherited */ + } + Append(inherit,s); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_cadd() + * + * Adds a node to the C symbol table only. + * ----------------------------------------------------------------------------- */ + +void +Swig_symbol_cadd(String_or_char *name, Node *n) { + Node *append = 0; + + Node *cn; + /* There are a few options for weak symbols. A "weak" symbol + is any symbol that can be replaced by another symbol in the C symbol + table. An example would be a forward class declaration. A forward + class sits in the symbol table until a real class declaration comes along. + + Certain symbols are marked as "sym:typename". These are important + symbols related to the C++ type-system and take precedence in the C + symbol table. An example might be code like this: + + template<class T> T foo(T x); + int foo(int); + + In this case, the template is marked with "sym:typename" so that it + stays in the C symbol table (so that it can be expanded using %template). + */ + + if (!name) return; + cn = Getattr(ccurrent,name); + + if (cn && (Getattr(cn,"sym:typename"))) { + /* The node in the C symbol table is a typename. Do nothing */ + /* We might append the symbol at the end */ + append = n; + } else if (cn && (Getattr(cn,"sym:weak"))) { + /* The node in the symbol table is weak. Replace it */ + Setattr(ccurrent,name, n); + } else if (cn && (Getattr(n,"sym:weak"))) { + /* The node being added is weak. Don't worry about it */ + } else if (cn && (Getattr(n,"sym:typename"))) { + /* The node being added is a typename. We definitely add it */ + Setattr(ccurrent,name,n); + append = cn; + } else if (cn && (Strcmp(nodeType(cn),"templateparm") == 0)) { + Swig_error(Getfile(n),Getline(n),"Error. Declaration of '%s' shadows template parameter at %s:%d\n", + name,Getfile(cn),Getline(cn)); + return; + } else if (cn) { + append = n; + } else if (!cn) { + /* No conflict. Add the symbol */ + Setattr(ccurrent,name,n); + } + + /* Multiple entries in the C symbol table. We append to to the symbol table */ + if (append) { + Node *fn, *pn = 0; + cn = Getattr(ccurrent,name); + fn = cn; + while (fn) { + pn = fn; + if (fn == append) { + /* already added. Bail */ + return; + } + fn = Getattr(fn,"csym:nextSibling"); + } + if (pn) { + Setattr(pn,"csym:nextSibling",append); + } + } + + /* Special typedef handling. When a typedef node is added to the symbol table, we + might have to add a type alias. This would occur if the typedef mapped to another + scope in the system. For example: + + class Foo { + }; + + typedef Foo OtherFoo; + + In this case, OtherFoo becomes an alias for Foo. */ + + { + Node *td = n; + while (td && (Strcmp(nodeType(td),"cdecl") == 0) && (checkAttribute(td,"storage","typedef"))) { + SwigType *type; + Node *td1; + type = Copy(Getattr(td,"type")); + SwigType_push(type,Getattr(td,"decl")); + td1 = Swig_symbol_clookup(type,0); + Delete(type); + if (td1 == td) break; + td = td1; + if (td) { + Symtab *st = Getattr(td,"symtab"); + if (st) { + Swig_symbol_alias(Getattr(n,"name"),st); + break; + } + } + } + } +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_add() + * + * Adds a node to the symbol table. Returns the node itself if successfully + * added. Otherwise, it returns the symbol table entry of the conflicting node. + * + * Also places the symbol in a behind-the-scenes C symbol table. This is needed + * for namespace support, type resolution, and other issues. + * ----------------------------------------------------------------------------- */ + +Node * +Swig_symbol_add(String_or_char *symname, Node *n) { + Hash *c, *cn, *cl = 0; + SwigType *decl, *ndecl; + String *cstorage, *nstorage; + int nt = 0, ct = 0; + int pn = 0; + int u1 = 0, u2 = 0; + String *name; + + /* See if the node has a name. If so, we place in the C symbol table for this + scope. We don't worry about overloading here---the primary purpose of this + is to record information for type/name resolution for later. Conflicts + in C namespaces are errors, but these will be caught by the C++ compiler + when compiling the wrapper code */ + + + /* There are a few options for weak symbols. A "weak" symbol + is any symbol that can be replaced by another symbol in the C symbol + table. An example would be a forward class declaration. A forward + class sits in the symbol table until a real class declaration comes along. + + Certain symbols are marked as "sym:typename". These are important + symbols related to the C++ type-system and take precedence in the C + symbol table. An example might be code like this: + + template<class T> T foo(T x); + int foo(int); + + In this case, the template is marked with "sym:typename" so that it + stays in the C symbol table (so that it can be expanded using %template). + */ + + name = Getattr(n,"name"); + if (name) { + Swig_symbol_cadd(name,n); + } + + /* No symbol name defined. We return. */ + if (!symname) { + Setattr(n,"sym:symtab",current_symtab); + return n; + } + + /* If node is ignored. We don't proceed any further */ + if (Getattr(n,"feature:ignore")) return n; + + /* See if the symbol already exists in the table */ + c = Getattr(current,symname); + + /* Check for a weak symbol. A weak symbol is allowed to be in the + symbol table, but is silently overwritten by other symbols. An example + would be a forward class declaration. For instance: + + class Foo; + + In this case, "Foo" sits in the symbol table. However, the + definition of Foo would replace the entry if it appeared later. */ + + if (c && Getattr(c,"sym:weak")) { + c = 0; + } + if (c) { + /* There is a symbol table conflict. There are a few cases to consider here: + (1) A conflict between a class/enum and a typedef declaration is okay. + In this case, the symbol table entry is set to the class/enum declaration + itself, not the typedef. + + (2) A conflict between namespaces is okay--namespaces are open + + (3) Otherwise, overloading is only allowed for functions + */ + + /* Check for namespaces */ + if ((Strcmp(nodeType(n),nodeType(c)) == 0) && ((Strcmp(nodeType(n),"namespace") == 0))) { + Node *cl, *pcl = 0; + cl = c; + while (cl) { + pcl = cl; + cl = Getattr(cl,"sym:nextSibling"); + } + Setattr(pcl,"sym:nextSibling",n); + Setattr(n,"sym:symtab", current_symtab); + Setattr(n,"sym:name", symname); + Setattr(n,"sym:previousSibling", pcl); + return n; + } + if (Getattr(n,"allows_typedef")) nt = 1; + if (Getattr(c,"allows_typedef")) ct = 1; + if (nt || ct) { + Node *td, *other; + String *s; + /* At least one of the nodes allows typedef overloading. Make sure that + both don't--this would be a conflict */ + + if (nt && ct) return c; + + /* Figure out which node allows the typedef */ + if (nt) { + td = n; + other = c; + } else { + td = c; + other = n; + } + /* Make sure the other node is a typedef */ + s = Getattr(other,"storage"); + if (!s || (Strcmp(s,"typedef"))) return c; /* No. This is a conflict */ + + /* Hmmm. This appears to be okay. Make sure the symbol table refers to the allow_type node */ + + if (td != c) { + Setattr(current,symname, td); + Setattr(td,"sym:symtab", current_symtab); + Setattr(td,"sym:name", symname); + } + return n; + } + + decl = Getattr(c,"decl"); + ndecl = Getattr(n,"decl"); + + { + String *nt1, *nt2; + nt1 = nodeType(n); + if (Strcmp(nt1,"template") == 0) nt1 = Getattr(n,"templatetype"); + nt2 = nodeType(c); + if (Strcmp(nt2,"template") == 0) nt2 = Getattr(c,"templatetype"); + if (Strcmp(nt1,"using") == 0) u1 = 1; + if (Strcmp(nt2,"using") == 0) u2 = 1; + + if ((Strcmp(nt1,nt2) != 0) && !(u1 || u2)) return c; + } + if (!(u1 || u2)) { + if ((!SwigType_isfunction(decl)) || (!SwigType_isfunction(ndecl))) { + /* Symbol table conflict */ + return c; + } + } + + /* Hmmm. Declarator seems to indicate that this is a function */ + /* Look at storage class to see if compatible */ + cstorage = Getattr(c,"storage"); + nstorage = Getattr(n,"storage"); + + /* If either one is declared as typedef, forget it. We're hosed */ + if (Cmp(cstorage,"typedef") == 0) { + return c; + } + if (Cmp(nstorage,"typedef") == 0) { + return c; + } + /* Okay. Walk down the list of symbols and see if we get a declarator match */ + cn = c; + pn = 0; + while (cn) { + decl = Getattr(cn,"decl"); + if (!(u1 || u2)) { + if (Cmp(ndecl,decl) == 0) { + /* Declarator conflict */ + return cn; + } + } + cl = cn; + cn = Getattr(cn,"sym:nextSibling"); + pn++; + } + /* Well, we made it this far. Guess we can drop the symbol in place */ + Setattr(n,"sym:symtab",current_symtab); + Setattr(n,"sym:name",symname); + Setattr(n,"sym:overname", NewStringf("__SWIG_%d", pn)); + Setattr(cl,"sym:nextSibling",n); + Setattr(n,"sym:previousSibling",cl); + Setattr(cl,"sym:overloaded",c); + Setattr(n,"sym:overloaded",c); + return n; + } + + /* No conflict. Just add it */ + Setattr(n,"sym:symtab",current_symtab); + Setattr(n,"sym:name",symname); + Setattr(n,"sym:overname", NewStringf("__SWIG_%d", pn)); + Setattr(current,symname,n); + return n; +} + +/* ----------------------------------------------------------------------------- + * symbol_lookup_qualified() + * + * Internal function to handle fully qualified symbol table lookups. This + * works from the symbol table supplied in symtab and unwinds its way out + * towards the global scope. + * + * This function operates in the C namespace, not the target namespace. + * ----------------------------------------------------------------------------- */ + +static Node * +symbol_lookup(String_or_char *name, Symtab *symtab) { + Node *n; + List *inherit; + Hash *sym = Getattr(symtab,"csymtab"); + + if (Getmark(symtab)) return 0; + Setmark(symtab,1); + + n = Getattr(sym,name); + if (n) { + Setmark(symtab,0); + return n; + } + inherit = Getattr(symtab,"inherit"); + if (inherit) { + int i,len; + len = Len(inherit); + for (i = 0; i < len; i++) { + n = symbol_lookup(name, Getitem(inherit,i)); + if (n) { + Setmark(symtab,0); + return n; + } + } + } + Setmark(symtab,0); + return 0; +} + +static Node * +symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, int local) { + /* This is a little funky, we search by fully qualified names */ + + if (!symtab) return 0; + if (!prefix) { + Node *n; + String *bname; + String *prefix; + bname = Swig_scopename_last(name); + prefix = Swig_scopename_prefix(name); + n = symbol_lookup_qualified(bname,symtab,prefix,local); + Delete(bname); + Delete(prefix); + return n; + } else { + String *qname; + Symtab *st; + Node *n = 0; + /* Make qualified name of current scope */ + qname = Swig_symbol_qualifiedscopename(symtab); + if (qname && Len(qname)) { + if (Len(prefix)) { + Append(qname,"::"); + Append(qname,prefix); + } + } else { + qname = NewString(prefix); + } + st = Getattr(symtabs,qname); + /* Found a scope match */ + if (st) { + if (!name) return st; + n = symbol_lookup(name, st); + } + Delete(qname); + if (!n) { + if (!local) { + Node *pn = parentNode(symtab); + if (pn) n = symbol_lookup_qualified(name,pn, prefix, local); + } else { + n = 0; + } + } + return n; + } +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_clookup() + * + * Look up a symbol in the symbol table. This uses the C name, not scripting + * names. Note: If we come across a using a directive, we follow it to + * to get the real node. + * ----------------------------------------------------------------------------- */ + +Node * +Swig_symbol_clookup(String_or_char *name, Symtab *n) { + Hash *hsym; + Node *s = 0; + + if (!n) { + hsym = current_symtab; + } else { + if (Strcmp(nodeType(n),"symboltable")) { + n = Getattr(n,"sym:symtab"); + } + assert(n); + if (n) { + hsym = n; + } + } + + if (Swig_scopename_check(name)) { + if (Strncmp(name,"::",2) == 0) { + String *nname = NewString(Char(name)+2); + if (Swig_scopename_check(nname)) { + s = symbol_lookup_qualified(nname,global_scope,0,0); + } + } else { + String *prefix = Swig_scopename_prefix(name); + if (prefix) { + s = symbol_lookup_qualified(name,hsym,0,0); + Delete(prefix); + if (!s) { + return 0; + } + } + } + } + if (!s) { + while (hsym) { + s = symbol_lookup(name,hsym); + if (s) break; + hsym = parentNode(hsym); + if (!hsym) break; + } + } + if (!s) { + return 0; + } + /* Check if s is a 'using' node */ + while (s && Strcmp(nodeType(s),"using") == 0) { + Node *ss; + ss = Swig_symbol_clookup(Getattr(s,"uname"), Getattr(s,"sym:symtab")); + if (!ss) { + Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", Getattr(s,"uname")); + } + s = ss; + } + return s; +} + +Node * +Swig_symbol_clookup_local(String_or_char *name, Symtab *n) { + Hash *h, *hsym; + Node *s = 0; + + if (!n) { + hsym = current_symtab; + h = ccurrent; + } else { + if (Strcmp(nodeType(n),"symboltable")) { + n = Getattr(n,"sym:symtab"); + } + assert(n); + hsym = n; + h = Getattr(n,"csymtab"); + } + + if (Swig_scopename_check(name)) { + if (Strncmp(name,"::",2) == 0) { + s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0); + } else { + s = symbol_lookup_qualified(name,hsym,0,0); + } + } + if (!s) { + s = symbol_lookup(name,hsym); + } + if (!s) return 0; + /* Check if s is a 'using' node */ + while (s && Strcmp(nodeType(s),"using") == 0) { + Node *ss = Swig_symbol_clookup_local(Getattr(s,"uname"), Getattr(s,"sym:symtab")); + if (!ss) { + Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", Getattr(s,"uname")); + } + s = ss; + } + return s; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_cscope() + * + * Look up a scope name. + * ----------------------------------------------------------------------------- */ + +Symtab * +Swig_symbol_cscope(String_or_char *name, Symtab *symtab) { + if (Strncmp(name,"::",2) == 0) return symbol_lookup_qualified(0, global_scope, name, 0); + return symbol_lookup_qualified(0,symtab,name,0); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_remove() + * + * Remove a symbol + * ----------------------------------------------------------------------------- */ + +void +Swig_symbol_remove(Node *n) { + Symtab *symtab; + String *symname; + Node *symprev; + Node *symnext; + symtab = Getattr(n,"sym:symtab"); /* Get symbol table object */ + symtab = Getattr(symtab,"symtab"); /* Get actual hash table of symbols */ + symname = Getattr(n,"sym:name"); + symprev = Getattr(n,"sym:previousSibling"); + symnext = Getattr(n,"sym:nextSibling"); + + /* If previous symbol, just fix the links */ + if (symprev) { + if (symnext) { + Setattr(symprev,"sym:nextSibling",symnext); + } else { + Delattr(symprev,"sym:nextSibling"); + } + } else { + /* If no previous symbol, see if there is a next symbol */ + if (symnext) { + Setattr(symtab,symname,symnext); + } else { + Delattr(symtab,symname); + } + } + Delattr(n,"sym:symtab"); + Delattr(n,"sym:previousSibling"); + Delattr(n,"sym:nextSibling"); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_qualified() + * + * Return the qualified name of a symbol + * ----------------------------------------------------------------------------- */ + +String * +Swig_symbol_qualified(Node *n) { + Hash *symtab; + if (Strcmp(nodeType(n),"symboltable") == 0) { + symtab = n; + } else { + symtab = Getattr(n,"sym:symtab"); + } + if (!symtab) return NewString(""); + return Swig_symbol_qualifiedscopename(symtab); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_isoverloaded() + * + * Check if a symbol is overloaded. Returns the first symbol if so. + * ----------------------------------------------------------------------------- */ + +Node * +Swig_symbol_isoverloaded(Node *n) { + return Getattr(n,"sym:overloaded"); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_type_qualify() + * + * Create a fully qualified type name + * ----------------------------------------------------------------------------- */ + +SwigType * +Swig_symbol_type_qualify(SwigType *t, Symtab *st) { + List *elements; + String *result; + int i,len; + + result = NewString(""); + elements = SwigType_split(t); + + len = Len(elements); + for (i = 0; i < len; i++) { + String *e = Getitem(elements,i); + if (SwigType_issimple(e)) { + Node *n = Swig_symbol_clookup(e,st); + if (n) { + String *name = Getattr(n,"name"); + Clear(e); + Append(e,name); + if (!Swig_scopename_check(name)) { + String *qname = Swig_symbol_qualified(n); + if (Len(qname)) { + Insert(e,0,"::"); + Insert(e,0,qname); + } + Delete(qname); + } + } else if (SwigType_istemplate(e)) { + String *tprefix, *tsuffix; + SwigType *qprefix; + List *targs; + String *tparm; + tprefix = SwigType_templateprefix(e); + tsuffix = SwigType_templatesuffix(e); + qprefix = Swig_symbol_type_qualify(tprefix,st); + targs = SwigType_parmlist(e); + Printf(qprefix,"<("); + for (tparm = Firstitem(targs); tparm;) { + String *qparm = Swig_symbol_type_qualify(tparm,st); + /* Printf(stdout,"qparm = '%s', tparm = '%s'\n", qparm, tparm);*/ + while (1) { + /* It is possible for an integer to show up here. If so, we need to evaluate it */ + { + Node *nn = Swig_symbol_clookup(qparm,st); + if ((nn) && (Strcmp(nodeType(nn),"cdecl") == 0)) { + String *nv = Getattr(nn,"value"); + if (nv) { + Clear(qparm); + Append(qparm,nv); + } else { + break; + } + } else if ((nn) && (Strcmp(nodeType(nn),"enumitem") == 0)) { + String *qn = Swig_symbol_qualified(nn); + if (Len(qn)) { + Append(qn,"::"); + Append(qn,Getattr(nn,"name")); + Clear(qparm); + Append(qparm,qn); + } + Delete(qn); + break; + } else { + break; + } + } + } + Append(qprefix,qparm); + tparm = Nextitem(targs); + if (tparm) { + Putc(',',qprefix); + } + Delete(qparm); + } + Append(qprefix,")>"); + Append(qprefix,tsuffix); + Clear(e); + Append(e,qprefix); + Delete(tprefix); + Delete(tsuffix); + Delete(qprefix); + } + if (Strncmp(e,"::",2) == 0) { + Delitem(e,0); + Delitem(e,0); + } + Append(result,e); + } else if (SwigType_isfunction(e)) { + List *parms = SwigType_parmlist(e); + String *s = NewString("f("); + String *p; + p = Firstitem(parms); + while (p) { + Append(s,Swig_symbol_type_qualify(p,st)); + p = Nextitem(parms); + if (p) { + Append(s,","); + } + } + Append(s,")."); + Append(result,s); + Delete(s); + } else { + Append(result,e); + } + } + Delete(elements); + return result; +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_typedef_reduce() + * + * Chase a typedef through symbol tables looking for a match. + * ----------------------------------------------------------------------------- */ + +SwigType *Swig_symbol_typedef_reduce(SwigType *ty, Symtab *tab) { + SwigType *prefix, *base; + Node *n; + + base = SwigType_base(ty); + prefix = SwigType_prefix(ty); + + n = Swig_symbol_clookup(base,tab); + if (!n) { + Delete(base); + Delete(prefix); + return Copy(ty); + } + if (Strcmp(nodeType(n),"using") == 0) { + String *uname = Getattr(n,"uname"); + if (uname) { + n = Swig_symbol_clookup(base,Getattr(n,"sym:symtab")); + if (!n) { + Delete(base); + Delete(prefix); + return Copy(ty); + } + } + } + if (Strcmp(nodeType(n),"cdecl") == 0) { + String *storage = Getattr(n,"storage"); + if (Strcmp(storage,"typedef") == 0) { + SwigType *decl; + SwigType *rt; + SwigType *nt = Copy(Getattr(n,"type")); + decl = Getattr(n,"decl"); + if (decl) { + SwigType_push(nt,decl); + } + SwigType_push(nt,prefix); + Delete(base); + Delete(prefix); + rt = Swig_symbol_typedef_reduce(nt, Getattr(n,"sym:symtab")); + Delete(nt); + return rt; + } + } + Delete(base); + Delete(prefix); + return Copy(ty); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_string_qualify() + * + * This function takes a string and looks for identifiers. Identifiers are + * then qualified according to scope rules. This function is used in a number + * of settings including expression evaluation, scoping of conversion operators, + * and so forth. + * ----------------------------------------------------------------------------- */ + +String * +Swig_symbol_string_qualify(String *s, Symtab *st) { + char *c; + String *id, *r; + int have_id = 0; + + id = NewString(""); + r = NewString(""); + c = Char(s); + while (*c) { + if (isalpha(*c) || (*c == '_') || (*c == ':')) { + Putc(*c,id); + have_id = 1; + } else { + if (have_id) { + String *qid = Swig_symbol_type_qualify(id,st); + Append(r,qid); + Clear(id); + Delete(qid); + have_id = 0; + } + Putc(*c,r); + } + c++; + } + if (have_id) { + String *qid = Swig_symbol_type_qualify(id,st); + Append(r,qid); + Delete(qid); + } + Delete(id); + return r; +} + diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 81566d21e..7df80420c 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -11,40 +11,19 @@ * ----------------------------------------------------------------------------- */ #include "swig.h" +#include <stdarg.h> +#include <assert.h> -static char cvsroot[] = "$Header$"; - -/* Hash table mapping tag names to handler functions */ -static Hash *rules = 0; -static int debug_emit = 0; - -/* ----------------------------------------------------------------------------- - * Swig_next() - * Swig_prev() - * - * Return next/prev node in a parse tree - * ----------------------------------------------------------------------------- */ - -DOH *Swig_next(DOH *obj) { - return Getnext(obj); -} - -DOH *Swig_prev(DOH *obj) { - return Getprev(obj); -} - -void Swig_debug_emit(int n) { - debug_emit = n; -} +char cvsroot_tree_c[] = "$Header$"; /* ----------------------------------------------------------------------------- - * Swig_dump_tags() + * Swig_print_tags() * * Dump the tag structure of a parse tree to standard output * ----------------------------------------------------------------------------- */ void -Swig_dump_tags(DOH *obj, DOH *root) { +Swig_print_tags(DOH *obj, DOH *root) { DOH *croot, *newroot; DOH *cobj; @@ -52,22 +31,21 @@ Swig_dump_tags(DOH *obj, DOH *root) { else croot = root; while (obj) { - Printf(stdout,"%s . %s (%s:%d)\n", croot, Getattr(obj,"tag"), Getfile(obj), Getline(obj)); - cobj = Getattr(obj,"child"); + Printf(stdout,"%s . %s (%s:%d)\n", croot, nodeType(obj), Getfile(obj), Getline(obj)); + cobj = firstChild(obj); if (cobj) { - newroot = NewStringf("%s . %s",croot,Getattr(obj,"tag")); - Swig_dump_tags(cobj,newroot); + newroot = NewStringf("%s . %s",croot,nodeType(obj)); + Swig_print_tags(cobj,newroot); Delete(newroot); } - obj = Swig_next(obj); + obj = nextSibling(obj); } if (!root) Delete(croot); } - /* ----------------------------------------------------------------------------- - * Swig_dump_tree() + * Swig_print_tree() * * Dump the tree structure of a parse tree to standard output * ----------------------------------------------------------------------------- */ @@ -85,429 +63,339 @@ static void print_indent(int l) { } } -void -Swig_dump_tree(DOH *obj) { - DOH *k; - DOH *cobj; - while (obj) { - print_indent(0); - Printf(stdout,"+++ %s ----------------------------------------\n", Getattr(obj,"tag")); - - k = Firstkey(obj); - while (k) { - if ((Cmp(k,"tag") == 0) || (Cmp(k,"child") == 0) || - (Cmp(k,"parent") == 0) || (Cmp(k,"next") == 0) || - (Cmp(k,"prev") == 0)) { - /* Do nothing */ - } else if (Cmp(k,"parms") == 0) { - print_indent(2); - Printf(stdout,"%-12s - %s\n", k, ParmList_protostr(Getattr(obj,k))); - } else { - DOH *o; - char *trunc = ""; - print_indent(2); +/* ----------------------------------------------------------------------------- + * Swig_dump_node(Node *n) + * ----------------------------------------------------------------------------- */ + +void +Swig_print_node(Node *obj) { + String *k; + Node *cobj; + + print_indent(0); + Printf(stdout,"+++ %s ----------------------------------------\n", nodeType(obj)); + k = Firstkey(obj); + while (k) { + if ((Cmp(k,"nodeType") == 0) || (Cmp(k,"firstChild") == 0) || (Cmp(k,"lastChild") == 0) || + (Cmp(k,"parentNode") == 0) || (Cmp(k,"nextSibling") == 0) || + (Cmp(k,"previousSibling") == 0) || (*(Char(k)) == '$')) { + /* Do nothing */ + } else if (Cmp(k,"parms") == 0) { + print_indent(2); + Printf(stdout,"%-12s - %s\n", k, ParmList_protostr(Getattr(obj,k))); + } else { + DOH *o; + char *trunc = ""; + print_indent(2); + if (DohIsString(Getattr(obj,k))) { o = Str(Getattr(obj,k)); if (Len(o) > 40) { trunc = "..."; } Printf(stdout,"%-12s - \"%(escape)-0.40s%s\"\n", k, o, trunc); Delete(o); + } else { + Printf(stdout,"%-12s - 0x%x\n", k, Getattr(obj,k)); } - k = Nextkey(obj); - } - cobj = Getattr(obj,"child"); - if (cobj) { - indent_level += 6; - Printf(stdout,"\n"); - Swig_dump_tree(cobj); - indent_level -= 6; - } else { - print_indent(1); - Printf(stdout,"\n"); } - obj = Swig_next(obj); + k = Nextkey(obj); } -} - - -/* ----------------------------------------------------------------------------- - * Swig_add_rule() - * - * Adds a new rule to the tree walking code. - * ----------------------------------------------------------------------------- */ - -void -Swig_add_rule(const String_or_char *name, int (*action)(DOH *node, void *clientdata)) -{ - if (!rules) rules = NewHash(); - if (action) - Setattr(rules,name,NewVoid((void *) action,0)); - else - Delattr(rules,name); - - if (debug_emit) { - Printf(stderr,"Swig_add_rule : '%s' -> %x\n", name, action); + cobj = firstChild(obj); + if (cobj) { + indent_level += 6; + Printf(stdout,"\n"); + Swig_print_tree(cobj); + indent_level -= 6; + } else { + print_indent(1); + Printf(stdout,"\n"); } } -/* ----------------------------------------------------------------------------- - * Swig_add_rules() - * - * Add a complete set of rules to the rule system - * ----------------------------------------------------------------------------- */ - -void -Swig_add_rules(SwigRule ruleset[]) { - int i = 0; - while (ruleset[i].name) { - Swig_add_rule(ruleset[i].name, ruleset[i].action); - i++; +void +Swig_print_tree(DOH *obj) { + while (obj) { + Swig_print_node(obj); + obj = nextSibling(obj); } } /* ----------------------------------------------------------------------------- - * Swig_clear_rules() + * appendChild() * - * Clears all of the existing rules + * Appends a new child to a node * ----------------------------------------------------------------------------- */ void -Swig_clear_rules() -{ - if (rules) Delete(rules); - rules = NewHash(); - if (debug_emit) { - Printf(stderr,"Swig_clear_rules :\n"); - } +appendChild(Node *node, Node *chd) { + Node *lc; -} - -/* ----------------------------------------------------------------------------- - * Swig_dump_rules() - * - * Print out debugging information for the rules - * ----------------------------------------------------------------------------- */ + if (!chd) return; -void -Swig_dump_rules() { - String *key; - Printf(stdout,"SWIG emit rules:::\n"); - if (!rules) { - Printf(stdout," No rules defined.\n"); - return; + lc = lastChild(node); + if (!lc) { + set_firstChild(node,chd); + } else { + set_nextSibling(lc,chd); + set_previousSibling(chd,lc); } - key = Firstkey(rules); - while (key) { - Printf(stdout," '%-15s' -> %x\n", key, GetVoid(rules,key)); - key = Nextkey(rules); + while (chd) { + lc = chd; + set_parentNode(chd,node); + chd = nextSibling(chd); } + set_lastChild(node,lc); } /* ----------------------------------------------------------------------------- - * Swig_tag_check() + * deleteNode() * - * Checks the tag name of an object taking into account namespace issues. - * For example, a check of "function" will match any object with a tag - * of the form "xxx:function" whereas a check of "c:function" will check - * for a more exact match. Returns 1 if a match is found, 0 otherwise + * Deletes a node. * ----------------------------------------------------------------------------- */ -int -Swig_tag_check(DOH *obj, const String_or_char *tagname) { - String *tag; - char *tc; - char *tnc; - tag = Getattr(obj,"tag"); - assert(tag); - - tnc = Char(tag); - tc = Char(tagname); - - while (tnc) { - if (strcmp(tc,tnc) == 0) return 1; - tnc = strchr(tnc,':'); - if (tnc) tnc++; - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * Swig_set_callback() - * - * Sets a parser callback function for a node. - * ----------------------------------------------------------------------------- */ void -Swig_set_callback(DOH *obj, void (*cb)(void *clientdata), void *clientdata) { - SetVoid(obj,"-callback-",(void *)cb); - if (clientdata) - SetVoid(obj,"-callbackarg-", clientdata); +deleteNode(Node *n) { + Node *parent; + Node *prev; + Node *next; + + parent = parentNode(n); + prev = previousSibling(n); + next = nextSibling(n); + if (prev) { + set_nextSibling(prev,next); + } else { + if (parent) { + set_firstChild(parent,next); + } + } + if (next) { + set_previousSibling(next,prev); + } else { + if (parent) { + set_lastChild(parent,prev); + } + } } /* ----------------------------------------------------------------------------- - * Swig_set_trace() + * copyNode() * - * Sets a tracing function on a parse tree node. Returns the old tracing - * function (if any). + * Copies a node, but only copies simple attributes (no lists, hashes). * ----------------------------------------------------------------------------- */ -void (*Swig_set_trace(DOH *obj, void (*cb)(DOH *, DOH *), DOH *arg))(DOH *, DOH *) { - void (*old)(DOH *,DOH *); - old = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-"); - SetVoid(obj,"-trace-", (void *) cb); - if (arg) - Setattr(obj,"-tracearg-", arg); - return old; +Node * +copyNode(Node *n) { + String *key; + DOH *v; + Node *c = NewHash(); + for (key = Firstkey(n); key; key = Nextkey(n)) { + v = Getattr(n,key); + if (DohIsString(v)) { + Setattr(c,key,Copy(v)); + } + } + Setfile(c,Getfile(n)); + Setline(c,Getline(n)); + return c; } /* ----------------------------------------------------------------------------- - * Swig_remove_trace() + * Swig_tag_nodes() * - * Removes the tracing function from a parse tree node + * Tags a collection of nodes with an attribute. Used by the parser to mark + * subtypes with extra information. * ----------------------------------------------------------------------------- */ void -Swig_remove_trace(DOH *obj) { - Delattr(obj,"-trace-"); - Delattr(obj,"-tracearg-"); +Swig_tag_nodes(Node *n, const String_or_char *attrname, DOH *value) { + while (n) { + Setattr(n,attrname,value); + Swig_tag_nodes(firstChild(n),attrname, value); + n = nextSibling(n); + } } - -/* ----------------------------------------------------------------------------- - * Swig_node_temporary() - * - * Sets a node as being temporary (deleted immediately after it is emitted) - * ----------------------------------------------------------------------------- */ - -void Swig_node_temporary(DOH *obj) { - SetInt(obj,"-temp-",1); +int +checkAttribute(Node *n, const String_or_char *name, const String_or_char *value) { + String *v; + v = Getattr(n,name); + if (!v) return 0; + if (Cmp(v,value) == 0) return 1; + return 0; } /* ----------------------------------------------------------------------------- - * Swig_node_ignore() - * - * Causes a node to be ignored + * Swig_require() * ----------------------------------------------------------------------------- */ -void Swig_node_ignore(DOH *obj) { - SetInt(obj,"-ignore-",1); +#define MAX_SWIG_STACK 256 +static Hash *attr_stack[MAX_SWIG_STACK]; +static Node **nodeptr_stack[MAX_SWIG_STACK]; +static Node *node_stack[MAX_SWIG_STACK]; +static int stackp = 0; +static int stack_direction = 0; + +static void set_direction(int n, int *x) { + if (n == 1) { + set_direction(0,&n); + } else { + if (&n < x) { + stack_direction = -1; /* Stack grows down */ + } else { + stack_direction = 1; /* Stack grows up */ + } + } } -/* ----------------------------------------------------------------------------- - * int Swig_emit() - * - * This function calls the handler function (if any) for an object. - * ----------------------------------------------------------------------------- */ - -int -Swig_emit(DOH *obj, void *clientdata) { - DOH *tag; - DOH *actionobj; - char *tc; - int (*action)(DOH *obj, void *clientdata); - void (*callback)(void *clientdata); - void (*tracefunc)(DOH *obj, DOH *arg); - int ret; - - assert(obj); - - if (!rules) { - Printf(stderr,"No rules defined in Swig_emit()!\n"); - return SWIG_ERROR; - } - if (obj) { - if (Getattr(obj,"-ignore-")) return SWIG_OK; - tag = Getattr(obj,"tag"); - assert(tag); - tc = Char(tag); - while(tc) { - actionobj = Getattr(rules,tc); - if (actionobj) { - if (debug_emit) { - Printf(stderr,"Swig_emit : Matched tag '%s' -> rule '%s'\n", tag, tc); - } - /* Check for user tracing -- traces occur before any handlers are called */ - tracefunc = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-"); - if (tracefunc) { - DOH *tobj = Getattr(obj,"-tracearg-"); - (*tracefunc)(obj,tobj); - } - action = (int (*)(DOH *, void *)) Data(actionobj); - ret = (*action)(obj,clientdata); - /* Check for a parser callback */ - callback = (void (*)(void *clientdata)) GetVoid(obj,"-callback-"); - if (callback) { - void *cbarg; - cbarg = GetVoid(obj,"-callbackarg-"); - (*callback)(cbarg); - Delattr(obj,"-callback-"); - Delattr(obj,"-callbackarg-"); - } - return ret; - } else { - tc = strchr(tc,':'); - if (tc) tc++; - } +int +Swig_require(Node **nptr, ...) { + va_list ap; + char *name; + DOH *obj; + DOH *frame = 0; + Node *n = *nptr; + va_start(ap, nptr); + name = va_arg(ap, char *); + while (name) { + int newref = 0; + int opt = 0; + if (*name == '*') { + newref = 1; + name++; + } else if (*name == '?') { + newref = 1; + opt = 1; + name++; } - actionobj = Getattr(rules,"*"); - if (actionobj) { - if (debug_emit) { - Printf(stderr,"Swig_emit : Matched tag '%s' -> rule '*'\n", tag); + obj = Getattr(n,name); + if (!opt && !obj) { + Printf(stderr,"%s:%d. Fatal error (Swig_require). Missing attribute '%s' in node '%s'.\n", + Getfile(n), Getline(n), name, nodeType(n)); + assert(obj); + } + if (!obj) obj = DohNone; + if (newref) { + if (!attr_stack[stackp]) { + attr_stack[stackp]= NewHash(); } - /* Check for user tracing -- traces occur before any handlers are called */ - tracefunc = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-"); - if (tracefunc) { - DOH *tobj = Getattr(obj,"-tracearg-"); - (*tracefunc)(obj,tobj); + frame = attr_stack[stackp]; + if (Setattr(frame,name,obj)) { + Printf(stderr,"Swig_require('%s'): Warning, attribute '%s' was already saved.\n", nodeType(n), name); } - action = (int (*)(DOH *, void *)) Data(actionobj); - ret = (*action)(obj,clientdata); - /* Check for a parser callback */ - callback = (void (*)(void *clientdata)) GetVoid(obj,"-callback-"); - if (callback) { - void *cbarg; - cbarg = GetVoid(obj,"-callbackarg-"); - (*callback)(cbarg); - Delattr(obj,"-callback-"); - Delattr(obj,"-callbackarg-"); + } + name = va_arg(ap, char *); + } + va_end(ap); + if (frame) { + /* This is a sanity check to make sure no one is saving data, but not restoring it */ + if (stackp > 0) { + int e = 0; + if (!stack_direction) set_direction(1,0); + + if (stack_direction < 0) { + if ((((char *) nptr) >= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1; + } else { + if ((((char *) nptr) <= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1; + } + if (e) { + Printf(stderr, +"Swig_require('%s'): Fatal memory management error. If you are seeing this\n\ +message. It means that the target language module is not managing its memory\n\ +correctly. A handler for '%s' probably forgot to call Swig_restore().\n\ +Please report this problem to swig-dev@cs.uchicago.edu.\n", nodeType(n), nodeType(node_stack[stackp-1])); + assert(0); } - return ret; - } - if (debug_emit) { - Printf(stderr,"Swig_emit : No rule defined for tag '%s'\n", tag); } + nodeptr_stack[stackp] = nptr; + node_stack[stackp] = n; + stackp++; } - return SWIG_NORULE; + return 1; } -/* ----------------------------------------------------------------------------- - * Swig_emit_all() - * - * Emit all of the nodes at this level. - * ----------------------------------------------------------------------------- */ int -Swig_emit_all(DOH *obj, void *clientdata) { - int ret; - while (obj) { - ret = Swig_emit(obj,clientdata); - if (ret < 0) return ret; - obj = Swig_next(obj); - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Swig_node_cut() - * - * This function cuts an object out of a parse tree. To do this, the object - * MUST be properly initialized with "next", "prev", and "parent" attributes. - * ----------------------------------------------------------------------------- */ - -void Swig_node_cut(DOH *obj) { - DOH *parent; - DOH *next; - DOH *prev; - - parent = Getattr(obj,"parent"); - assert(parent); - next = Getattr(obj,"next"); - prev = Getattr(obj,"prev"); - - DohIncref(obj); /* Make sure object doesn't go away */ - Delattr(obj,"parent"); /* Disassociate from my parent */ - - if (!next && !prev) { - /* Well, this is a single child. Guess we'll just tell the parent that their child is gone */ - Delattr(parent,"child"); - return; - } - - /* If no next node, then this must be at the end of a list */ - if (!next) { - Delattr(prev,"next"); /* Break the 'next' link in the previous node */ - Delattr(obj,"prev"); /* Break my link back to the previous object */ - return; - } - - /* No previous node. This must be the beginning of a list */ - if (!prev) { - Delattr(next,"prev"); /* Break the 'prev' link of the next node */ - Setattr(parent,"child",next); /* Update parent to point at next node */ - Delattr(obj,"next"); /* Break my link to the next object */ - return; +Swig_save(Node **nptr, ...) { + va_list ap; + char *name; + DOH *obj; + DOH *frame; + Node *n = *nptr; + + if ((stackp > 0) && (nodeptr_stack[stackp-1] == nptr)) { + frame = attr_stack[stackp-1]; + } else { + if (stackp > 0) { + int e = 0; + if (!stack_direction) set_direction(1,0); + if (stack_direction < 0) { + if ((((char *) nptr) >= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1; + } else { + if ((((char *) nptr) <= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1; + } + if (e) { + Printf(stderr, +"Swig_save('%s'): Fatal memory management error. If you are seeing this\n\ +message. It means that the target language module is not managing its memory\n\ +correctly. A handler for '%s' probably forgot to call Swig_restore().\n\ +Please report this problem to swig-dev@cs.uchicago.edu.\n", nodeType(n), nodeType(node_stack[stackp-1])); + assert(0); + } + } + attr_stack[stackp] = NewHash(); + nodeptr_stack[stackp] = nptr; + node_stack[stackp] = n; + frame = attr_stack[stackp]; + stackp++; } - - /* In the middle of a list someplace */ - Setattr(prev,"next",next); /* Update previous node to my next node */ - Setattr(next,"prev",prev); /* Update next node to my previous node */ - Delattr(obj,"next"); - Delattr(obj,"prev"); - return; -} - -/* ----------------------------------------------------------------------------- - * Swig_node_insert() - * - * Inserts a node after a given node. The node to be inserted should be - * isolated (no parent, no siblings, etc...). - * ----------------------------------------------------------------------------- */ - -void -Swig_node_insert(DOH *node, DOH *newnode) { - DOH *next; - next = Getattr(node,"next"); - - if (next) { - Setattr(newnode,"next", next); - Setattr(next,"prev", newnode); + va_start(ap, nptr); + name = va_arg(ap, char *); + while (name) { + if (*name == '*') { + name++; + } else if (*name == '?') { + name++; + } + obj = Getattr(n,name); + if (!obj) { + obj = DohNone; + } + if (Setattr(frame,name,obj)) { + Printf(stderr,"Swig_save('%s'): Warning, attribute '%s' was already saved.\n", nodeType(n), name); + } + name = va_arg(ap, char *); } - Setattr(node,"next",newnode); - Setattr(newnode,"prev", node); - Setattr(newnode,"parent", Getattr(node,"parent")); + va_end(ap); + return 1; } -/* ----------------------------------------------------------------------------- - * Swig_node_append_child() - * - * Appends a new child to a node - * ----------------------------------------------------------------------------- */ - -void -Swig_node_append_child(DOH *node, DOH *chd) { - DOH *c; - DOH *pc; - c = Getattr(node,"child"); - if (!c) { - Setattr(node,"child",chd); - Setattr(chd,"parent",node); - return; - } - while (c) { - pc = c; - c = Getnext(c); +void +Swig_restore(Node **nptr) { + String *key; + Hash *frame; + Node *n = *nptr; + assert(stackp > 0); + if (!(nptr==nodeptr_stack[stackp-1])) { + Printf(stderr, +"Swig_restore('%s'): Fatal memory management error. If you are seeing this\n\ +message. It means that the target language module is not managing its memory\n\ +correctly. A handler for '%s' probably forgot to call Swig_restore().\n\ +Please report this problem to swig-dev@cs.uchicago.edu.\n", nodeType(n), nodeType(node_stack[stackp-1])); + assert(0); } - Setattr(pc,"next",chd); - Setattr(chd,"prev",pc); - Setattr(chd,"parent",node); -} - -/* ----------------------------------------------------------------------------- - * Swig_count_nodes() - * - * Count number of nodes at this level - * ----------------------------------------------------------------------------- */ - -int Swig_count_nodes(DOH *node) { - int n = 0; - while (node) { - n++; - node = Getnext(node); + stackp--; + frame = attr_stack[stackp]; + nodeptr_stack[stackp] = 0; + node_stack[stackp] = 0; + for (key = Firstkey(frame); key; key = Nextkey(frame)) { + DOH *obj = Getattr(frame,key); + if (obj != DohNone) { + Setattr(n,key,obj); + } else { + Delattr(n,key); + } + Delattr(frame,key); } - return n; } - - - - - diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 3d68dd4fd..fbb5dddbd 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -9,10 +9,33 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_typemap_c[] = "$Header$"; #include "swig.h" +/* ----------------------------------------------------------------------------- + * Typemaps are stored in a collection of nested hash tables. Something like + * this: + * + * [ type ] + * +-------- [ name ] + * +-------- [ name ] + * + * Each hash table [ type ] or [ name ] then contains references to the + * different typemap methods. These are referenced by names such as + * "tmap:in", "tmap:out", "tmap:argout", and so forth. + * + * The object corresponding to a specific method has the following + * attributes: + * + * "type" - Typemap type + * "pname" - Parameter name + * "code" - Typemap code + * "typemap" - Descriptive text describing the actual map + * "locals" - Local variables (if any) + * + * ----------------------------------------------------------------------------- */ + #define MAX_SCOPE 32 static Hash *typemaps[MAX_SCOPE]; @@ -33,10 +56,15 @@ void Swig_typemap_init() { tm_scope = 0; } -static char *parm_key(String_or_char *pname) { - static char temp[512] = "-"; - strcpy(temp+1,Char(pname)); - return temp; +static String *tmop_name(const String_or_char *op) { + static Hash *names = 0; + String *s; + if (!names) names = NewHash(); + s = Getattr(names,op); + if (s) return s; + s = NewStringf("tmap:%s",op); + Setattr(names,op,s); + return s; } /* ----------------------------------------------------------------------------- @@ -45,14 +73,9 @@ static char *parm_key(String_or_char *pname) { * Create a new typemap scope * ----------------------------------------------------------------------------- */ -void Swig_typemap_new_scope(Hash *oldscope) { +void Swig_typemap_new_scope() { tm_scope++; - if (!oldscope) { - typemaps[tm_scope] = NewHash(); - } else { - typemaps[tm_scope] = oldscope; - DohIncref(oldscope); - } + typemaps[tm_scope] = NewHash(); } /* ----------------------------------------------------------------------------- @@ -64,12 +87,7 @@ void Swig_typemap_new_scope(Hash *oldscope) { Hash * Swig_typemap_pop_scope() { if (tm_scope > 0) { - if (Len(typemaps[tm_scope])) { - return typemaps[tm_scope--]; - } else { - Delete(typemaps[tm_scope--]); - return 0; - } + return typemaps[tm_scope--]; } return 0; } @@ -77,56 +95,96 @@ Swig_typemap_pop_scope() { /* ----------------------------------------------------------------------------- * Swig_typemap_register() * - * Add a new typemap + * Add a new multi-valued typemap * ----------------------------------------------------------------------------- */ void -Swig_typemap_register(const String_or_char *op, SwigType *type, String_or_char *pname, String_or_char *code, ParmList *locals) { - char *key; +Swig_typemap_register(const String_or_char *op, ParmList *parms, String_or_char *code, ParmList *locals, ParmList *kwargs) { Hash *tm; Hash *tm1; Hash *tm2; + Parm *np; + String *tmop; + SwigType *type; + String *pname; + + if (!parms) return; + tmop = tmop_name(op); + + /* Register the first type in the parameter list */ + + type = Getattr(parms,"type"); + pname = Getattr(parms,"name"); /* See if this type has been seen before */ tm = Getattr(typemaps[tm_scope],type); if (!tm) { tm = NewHash(); - Setattr(typemaps[tm_scope],Char(type),tm); + Setattr(typemaps[tm_scope],Copy(type),tm); Delete(tm); } - if ((pname) && Len(pname)) { + if (pname) { /* See if parameter has been seen before */ - key = parm_key(pname); - tm1 = Getattr(tm,key); + tm1 = Getattr(tm,pname); if (!tm1) { tm1 = NewHash(); - Setattr(tm,key,tm1); + Setattr(tm,NewString(pname),tm1); Delete(tm1); } tm = tm1; } - tm2 = Getattr(tm,op); - if (tm2) { - SwigType *tm_type; - String *tm_pname; - tm_type = Getattr(tm2,"type"); - tm_pname = Getattr(tm2,"pname"); - if (Cmp(tm_type,type) || Cmp(tm_pname,pname)) { - tm2 = 0; - } - } + + /* Now see if this typemap op has been seen before */ + tm2 = Getattr(tm,tmop); if (!tm2) { tm2 = NewHash(); - Setattr(tm,op,tm2); + Setattr(tm,tmop,tm2); Delete(tm2); } - Setattr(tm2,"code",NewString(code)); - Setattr(tm2,"type",NewString(type)); - Setattr(tm2,"typemap",NewStringf("typemap(%s) %s", op, SwigType_str(type,pname))); - if (pname) { - Setattr(tm2,"pname", NewString(pname)); + + /* For a multi-valued typemap, the typemap code and information + is really only stored in the last argument. However, to + make this work, we perform a really neat trick using + the typemap operator name. + + For example, consider this typemap + + %typemap(in) (int foo, int *bar, char *blah[]) { + ... + } + + To store it, we look at typemaps for the following: + + operator type-name + ---------------------------------------------- + "in" int foo + "in-int+foo:" int *bar + "in-int+foo:-p.int+bar: char *blah[] + + Notice how the operator expands to encode information about + previous arguments. + + */ + + np = nextSibling(parms); + if (np) { + /* Make an entirely new operator key */ + String *newop = NewStringf("%s-%s+%s:",op,type,pname); + /* Now reregister on the remaining arguments */ + Swig_typemap_register(newop,np,code,locals,kwargs); + + /* Setattr(tm2,newop,newop); */ + Delete(newop); + } else { + Setattr(tm2,"code",NewString(code)); + Setattr(tm2,"type",Copy(type)); + Setattr(tm2,"typemap",NewStringf("typemap(%s) %s", op, SwigType_str(type,pname))); + if (pname) { + Setattr(tm2,"pname", NewString(pname)); + } + Setattr(tm2,"locals", CopyParmList(locals)); + Setattr(tm2,"kwargs", CopyParmList(kwargs)); } - Setattr(tm2,"locals", CopyParmList(locals)); } /* ----------------------------------------------------------------------------- @@ -145,7 +203,7 @@ Swig_typemap_get(SwigType *type, String_or_char *name, int scope) { return 0; } if ((name) && Len(name)) { - tm1 = Getattr(tm, parm_key(name)); + tm1 = Getattr(tm, name); return tm1; } return tm; @@ -157,108 +215,264 @@ Swig_typemap_get(SwigType *type, String_or_char *name, int scope) { * Copy a typemap * ----------------------------------------------------------------------------- */ -void -Swig_typemap_copy(const String_or_char *op, SwigType *stype, String_or_char *sname, - SwigType *ttype, String_or_char *tname) { - - Hash *tm=0, *tm1; +int +Swig_typemap_copy(const String_or_char *op, ParmList *srcparms, ParmList *parms) { + Hash *tm = 0; + String *tmop; + Parm *p; + String *pname; + SwigType *ptype; int ts = tm_scope; + String *tmops, *newop; + if (ParmList_len(parms) != ParmList_len(srcparms)) return -1; + + tmop = tmop_name(op); while (ts >= 0) { - tm = Swig_typemap_get(stype,sname,ts); - if (tm) break; - tm = Swig_typemap_get(stype,0,ts); - if (tm) break; + p = srcparms; + tmops = NewString(tmop); + while (p) { + ptype = Getattr(p,"type"); + pname = Getattr(p,"name"); + + /* Lookup the type */ + tm = Swig_typemap_get(ptype,pname,ts); + if (!tm) break; + + tm = Getattr(tm,tmops); + if (!tm) break; + + /* Got a match. Look for next typemap */ + newop = NewStringf("%s-%s+%s:",tmops,ptype,pname); + Delete(tmops); + tmops = newop; + p = nextSibling(p); + } + Delete(tmops); + + if (!p && tm) { + + /* Got some kind of match */ + Swig_typemap_register(op,parms, Getattr(tm,"code"), Getattr(tm,"locals"),Getattr(tm,"kwargs")); + return 0; + } ts--; } - if (!tm) return; - tm1 = Getattr(tm,op); - if (!tm1) return; - Swig_typemap_register(op,ttype,tname, Getattr(tm1,"code"), Getattr(tm1,"locals")); + /* Not found */ + return -1; + } /* ----------------------------------------------------------------------------- * Swig_typemap_clear() * - * Delete a typemap + * Delete a multi-valued typemap * ----------------------------------------------------------------------------- */ void -Swig_typemap_clear(const String_or_char *op, SwigType *type, String_or_char *name) { - Hash *tm; +Swig_typemap_clear(const String_or_char *op, ParmList *parms) { + SwigType *type; + String *name; + Parm *p; + String *newop; + Hash *tm = 0; - tm = Swig_typemap_get(type,name,tm_scope); - if (tm) - Delattr(tm,op); + /* This might not work */ + newop = NewString(op); + p = parms; + while (p) { + type = Getattr(p,"type"); + name = Getattr(p,"name"); + tm = Swig_typemap_get(type,name,tm_scope); + if (!tm) return; + p = nextSibling(p); + if (p) + Printf(newop,"-%s+%s:", type,name); + } + if (tm) { + tm = Getattr(tm, tmop_name(newop)); + if (tm) { + Delattr(tm,"code"); + Delattr(tm,"locals"); + Delattr(tm,"kwargs"); + } + } + Delete(newop); } /* ----------------------------------------------------------------------------- * Swig_typemap_apply() * - * %apply directive. This function is nothing more than a glorified typemap - * copy. Note: this is *very* different than SWIG1.1 although the end result - * is very "similar." + * Multi-argument %apply directive. This is pretty horrible so I sure hope + * it works. * ----------------------------------------------------------------------------- */ -static void merge_attributes(Hash *target, Hash *source) { - String *key; - for (key = Firstkey(source); key; key = Nextkey(source)) { - /* if (Getattr(target,key)) continue; */ - Setattr(target,key,Getattr(source,key)); +static +int count_args(String *s) { + /* Count up number of arguments */ + int na = 0; + char *c = Char(s); + while (*c) { + if (*c == '+') na++; + c++; } + return na; } -void -Swig_typemap_apply(SwigType *tm_type, String_or_char *tmname, SwigType *type, String_or_char *pname) { - Hash *tm, *tm1, *am; - int ts = tm_scope; - char *key; +int +Swig_typemap_apply(ParmList *src, ParmList *dest) { + String *ssig, *dsig; + Parm *p, *np, *lastp, *dp, *lastdp = 0; + int narg = 0; + int ts = tm_scope; + SwigType *type = 0, *name; + Hash *tm, *sm; + int match = 0; - tm = Swig_typemap_get(type,pname,tm_scope); - if (!tm) { - tm = Getattr(typemaps[tm_scope],type); - if (!tm) { - tm = NewHash(); - Setattr(typemaps[tm_scope], Char(type), tm); - Delete(tm); + /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */ + + /* Create type signature of source */ + ssig = NewString(""); + dsig = NewString(""); + p = src; + dp = dest; + lastp = 0; + while (p) { + lastp = p; + lastdp = dp; + np = nextSibling(p); + if (np) { + Printf(ssig,"-%s+%s:", Getattr(p,"type"), Getattr(p,"name")); + Printf(dsig,"-%s+%s:", Getattr(dp,"type"), Getattr(dp,"name")); + narg++; } - if ((pname) && Len(pname)) { - key = parm_key(pname); + p = np; + dp = nextSibling(dp); + } + + /* make sure a typemap node exists for the last destination node */ + tm = Getattr(typemaps[tm_scope],Getattr(lastdp,"type")); + if (!tm) { + tm = NewHash(); + Setattr(typemaps[tm_scope],Getattr(lastdp,"type"),tm); + Delete(tm); + } + name = Getattr(lastdp,"name"); + if (name) { + Hash *tm1 = Getattr(tm,name); + if (!tm1) { tm1 = NewHash(); - Setattr(tm,key,tm1); + Setattr(tm,NewString(name),tm1); Delete(tm1); - tm = tm1; } + tm = tm1; } - /* tm contains the typemap table into which we are going to be copying */ + + /* This is a little nasty. We need to go searching for all possible typemaps in the + source and apply them to the target */ + + type = Getattr(lastp,"type"); + name = Getattr(lastp,"name"); + while (ts >= 0) { - am = Swig_typemap_get(tm_type, tmname,ts); - if (am) { - merge_attributes(tm,am); + + /* See if there is a matching typemap in this scope */ + sm = Swig_typemap_get(type,name,ts); + + if (sm) { + /* Got a typemap. Need to only merge attributes for methods that match our signature */ + String *key; + + match = 1; + for (key = Firstkey(sm); key; key = Nextkey(sm)) { + /* Check for a signature match with the source signature */ + if ((count_args(key) == narg) && (Strstr(key,ssig))) { + String *oldm; + /* A typemap we have to copy */ + String *nkey = Copy(key); + Replace(nkey,ssig,dsig,DOH_REPLACE_ANY); + + /* Make sure the typemap doesn't already exist in the target map */ + + oldm = Getattr(tm,nkey); + if (!oldm || (!Getattr(tm,"code"))) { + String *code; + ParmList *locals; + ParmList *kwargs; + Hash *sm1 = Getattr(sm,key); + + code = Getattr(sm1,"code"); + locals = Getattr(sm1,"locals"); + kwargs = Getattr(sm1,"kwargs"); + if (code) { + Replace(nkey,dsig,"", DOH_REPLACE_ANY); + Replace(nkey,"tmap:","", DOH_REPLACE_ANY); + Swig_typemap_register(nkey,dest,code,locals,kwargs); + } + } + Delete(nkey); + } + } } ts--; } + return match; } /* ----------------------------------------------------------------------------- * Swig_typemap_clear_apply() * - * %clear directive. Clears all typemaps for a type. + * %clear directive. Clears all typemaps for a type (in the current scope only). * ----------------------------------------------------------------------------- */ +/* Multi-argument %clear directive */ void -Swig_typemap_clear_apply(SwigType *type, String_or_char *name) { - Hash *tm; - - tm = Getattr(typemaps[tm_scope],type); - if (!tm) return; - if ((name) && (Len(name))) { - Delattr(tm,parm_key(name)); - } else { - Delattr(typemaps[tm_scope],type); +Swig_typemap_clear_apply(Parm *parms) { + String *tsig; + Parm *p, *np, *lastp; + int narg = 0; + Hash *tm; + String *name; + + /* Create a type signature of the parameters */ + tsig = NewString(""); + p = parms; + lastp = 0; + while (p) { + lastp = p; + np = nextSibling(p); + if (np) { + Printf(tsig,"-%s+%s:", Getattr(p,"type"), Getattr(p,"name")); + narg++; + } + p = np; + } + tm = Getattr(typemaps[tm_scope],Getattr(lastp,"type")); + if (!tm) { + Delete(tsig); + return; } + name = Getattr(lastp,"name"); + if (name) { + tm = Getattr(tm,name); + } + if (tm) { + /* Clear typemaps that match our signature */ + String *key, *key2; + for (key = Firstkey(tm); key; key = Nextkey(tm)) { + if (Strncmp(key,"tmap:",5) == 0) { + int na = count_args(key); + if ((na == narg) && Strstr(key,tsig)) { + Hash *h = Getattr(tm,key); + for (key2 = Firstkey(h); key2; key2 = Nextkey(h)) { + Delattr(h,key2); + } + } + } + } + } + Delete(tsig); } - /* Internal function to strip array dimensions. */ static SwigType *strip_arrays(SwigType *type) { SwigType *t; @@ -272,25 +486,30 @@ static SwigType *strip_arrays(SwigType *type) { return t; } + /* ----------------------------------------------------------------------------- - * Swig_typemap_search_op() + * Swig_typemap_search() * - * Search for a typemap match. + * Search for a typemap match. Tries to find the most specific typemap + * that includes a 'code' attribute. * ----------------------------------------------------------------------------- */ Hash * -Swig_typemap_search(const String_or_char *op, SwigType *type, String_or_char *name) { +Swig_typemap_search(const String_or_char *op, SwigType *type, String_or_char *name, SwigType **matchtype) { Hash *result = 0, *tm, *tm1, *tma; + Hash *backup = 0; SwigType *noarrays = 0; SwigType *primitive = 0; SwigType *ctype = 0; int ts; int isarray; - char *cname = 0; + String *cname = 0; + SwigType *unstripped = 0; + String *tmop = tmop_name(op); - if ((name) && Len(name)) cname = parm_key(name); - isarray = SwigType_isarray(type); + if ((name) && Len(name)) cname = name; ts = tm_scope; + while (ts >= 0) { ctype = type; while (ctype) { @@ -299,61 +518,455 @@ Swig_typemap_search(const String_or_char *op, SwigType *type, String_or_char *na if (tm && cname) { tm1 = Getattr(tm,cname); if (tm1) { - result = Getattr(tm1,op); /* See if there is a type-name match */ - if (result) goto ret_result; + result = Getattr(tm1,tmop); /* See if there is a type-name match */ + if (result && Getattr(result,"code")) goto ret_result; + if (result) backup = result; } } if (tm) { - result = Getattr(tm,op); /* See if there is simply a type match */ - if (result) goto ret_result; + result = Getattr(tm,tmop); /* See if there is simply a type match */ + if (result && Getattr(result,"code")) goto ret_result; + if (result) backup = result; } - + isarray = SwigType_isarray(ctype); if (isarray) { - /* If working with arrays, strip away all of the dimensions and replace with ANY. + /* If working with arrays, strip away all of the dimensions and replace with "ANY". See if that generates a match */ if (!noarrays) noarrays = strip_arrays(ctype); tma = Getattr(typemaps[ts],noarrays); if (tma && cname) { tm1 = Getattr(tma,cname); if (tm1) { - result = Getattr(tm1,op); /* type-name match */ - if (result) goto ret_result; + result = Getattr(tm1,tmop); /* type-name match */ + if (result && Getattr(result,"code")) goto ret_result; + if (result) backup = result; } } if (tma) { - result = Getattr(tma,op); /* type match */ - if (result) goto ret_result; + result = Getattr(tma,tmop); /* type match */ + if (result && Getattr(result,"code")) goto ret_result; + if (result) backup = result; } + Delete(noarrays); + noarrays = 0; } - /* No match so far. If this type had a typedef declaration, maybe there are - some typemaps for that */ + /* No match so far. If the type is unstripped, we'll strip its + qualifiers and check. Otherwise, we'll try to resolve a typedef */ + + if (!unstripped) { + unstripped = ctype; + ctype = SwigType_strip_qualifiers(ctype); + if (Strcmp(ctype,unstripped) != 0) continue; /* Types are different */ + Delete(ctype); + ctype = unstripped; + unstripped = 0; + } { - SwigType *nt = SwigType_typedef_resolve(ctype); - if (ctype != type) Delete(ctype); - ctype = nt; + String *octype; + if (unstripped) { + if (unstripped != type) { + Delete(ctype); + } + ctype = unstripped; + unstripped = 0; + } + octype = ctype; + ctype = SwigType_typedef_resolve(ctype); + if (octype != type) Delete(octype); } } - +#ifdef NEW + /* No match seems to be found at all. Try a SWIGTYPE substitution */ + if (!primitive) { + SwigType *base = SwigType_base(type); + primitive = SwigType_prefix(type); + if (Strstr(base,"enum ")) { + Append(primitive,"enum SWIGTYPE"); + } else { + Append(primitive,"SWIGTYPE"); + } + tm = Getattr(typemaps[ts],primitive); + if (tm && cname) { + tm1 = Getattr(tm, cname); + if (tm1) { + result = Getattr(tm1,tmop); + if (result) goto ret_result; + } + } + if (tm) { + result = Getattr(tm,tmop); + if (result) goto ret_result; + } + Delete(primitive); + primitive = 0; + } +#endif + /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */ if (!primitive) primitive = SwigType_default(type); tm = Getattr(typemaps[ts],primitive); - if (tm) { - result = Getattr(tm,op); + if (tm && cname) { + tm1 = Getattr(tm,cname); + if (tm1) { + result = Getattr(tm1,tmop); /* See if there is a type-name match */ + if (result) goto ret_result; + } + } + if (tm) { /* See if there is simply a type match */ + result = Getattr(tm,tmop); if (result) goto ret_result; } if (ctype != type) Delete(ctype); ts--; /* Hmmm. Nothing found in this scope. Guess we'll go try another scope */ } - + result = backup; + ret_result: if (noarrays) Delete(noarrays); if (primitive) Delete(primitive); + if ((unstripped) && (unstripped != type)) Delete(unstripped); + if (matchtype) { + *matchtype = Copy(ctype); + } if (type != ctype) Delete(ctype); return result; } +/* ----------------------------------------------------------------------------- + * Swig_typemap_search_multi() + * + * Search for a multi-valued typemap. + * ----------------------------------------------------------------------------- */ + +Hash * +Swig_typemap_search_multi(const String_or_char *op, ParmList *parms, int *nmatch) { + SwigType *type; + SwigType *mtype = 0; + String *name; + String *newop; + Hash *tm, *tm1; + + if (!parms) { + *nmatch = 0; + return 0; + } + type = Getattr(parms,"type"); + name = Getattr(parms,"name"); + + /* Try to find a match on the first type */ + tm = Swig_typemap_search(op, type, name, &mtype); + if (tm) { + if (mtype && SwigType_isarray(mtype)) { + Setattr(parms,"tmap:match", mtype); + } + Delete(mtype); + newop = NewStringf("%s-%s+%s:", op, type,name); + tm1 = Swig_typemap_search_multi(newop, nextSibling(parms), nmatch); + if (tm1) tm = tm1; + if (Getattr(tm,"code")) { + *(nmatch) = *nmatch + 1; + } else { + tm = 0; + } + Delete(newop); + } + return tm; +} + + +/* ----------------------------------------------------------------------------- + * typemap_replace_vars() + * + * Replaces typemap variables on a string. index is the $n variable. + * type and pname are the type and parameter name. + * ----------------------------------------------------------------------------- */ + +static +void replace_local_types(ParmList *p, String *name, String *rep) { + SwigType *t; + while (p) { + t = Getattr(p,"type"); + Replace(t,name,rep,DOH_REPLACE_ANY); + p = nextSibling(p); + } +} + +static +void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, String *pname, String *lname, int index) +{ + char var[512]; + char *varname; + SwigType *ftype; + + ftype = SwigType_typedef_resolve_all(type); + + if (!pname) pname = lname; + { + Parm *p; + int rep = 0; + p = locals; + while (p) { + if (Strchr(Getattr(p,"type"),'$')) rep = 1; + p = nextSibling(p); + } + if (!rep) locals = 0; + } + + sprintf(var,"$%d_",index); + varname = &var[strlen(var)]; + + /* If the original datatype was an array. We're going to go through and substitute + it's array dimensions */ + + if (SwigType_isarray(type)) { + String *size; + int ndim = SwigType_array_ndim(type); + int i; + size = NewString(""); + for (i = 0; i < ndim; i++) { + String *dim = SwigType_array_getdim(type,i); + if (index == 1) { + char t[32]; + sprintf(t,"$dim%d",i); + Replace(s,t,dim,DOH_REPLACE_ANY); + replace_local_types(locals,t,dim); + } + sprintf(varname,"dim%d",i); + Replace(s,var,dim,DOH_REPLACE_ANY); + replace_local_types(locals,var,dim); + if (Len(size)) Putc('*',size); + Append(size,dim); + Delete(dim); + } + sprintf(varname,"size"); + Replace(s,var,size,DOH_REPLACE_ANY); + replace_local_types(locals,var,size); + Delete(size); + } + + /* Parameter name substitution */ + if (index == 1) { + Replace(s,"$parmname",pname, DOH_REPLACE_ANY); + } + strcpy(varname,"name"); + Replace(s,var,pname,DOH_REPLACE_ANY); + + /* Type-related stuff */ + { + SwigType *star_type, *amp_type, *base_type; + SwigType *ltype, *star_ltype, *amp_ltype; + String *mangle, *star_mangle, *amp_mangle, *base_mangle; + String *descriptor, *star_descriptor, *amp_descriptor; + String *ts; + char *sc; + + sc = Char(s); + + if (strstr(sc,"type")) { + /* Given type : $type */ + ts = SwigType_str(type,0); + if (index == 1) { + Replace(s, "$type", ts, DOH_REPLACE_ANY); + replace_local_types(locals,"$type",type); + } + strcpy(varname,"type"); + Replace(s,var,ts,DOH_REPLACE_ANY); + replace_local_types(locals,var,type); + Delete(ts); + sc = Char(s); + } + if (strstr(sc,"ltype")) { + /* Local type: $ltype */ + ltype = SwigType_ltype(type); + ts = SwigType_str(ltype,0); + if (index == 1) { + Replace(s, "$ltype", ts, DOH_REPLACE_ANY); + replace_local_types(locals,"$ltype",ltype); + } + strcpy(varname,"ltype"); + Replace(s,var,ts,DOH_REPLACE_ANY); + replace_local_types(locals,var,ltype); + Delete(ts); + Delete(ltype); + sc = Char(s); + } + if (strstr(sc,"mangle") || strstr(sc,"descriptor")) { + /* Mangled type */ + + mangle = SwigType_manglestr(type); + if (index == 1) + Replace(s, "$mangle", mangle, DOH_REPLACE_ANY); + strcpy(varname,"mangle"); + Replace(s,var,mangle,DOH_REPLACE_ANY); + + descriptor = NewStringf("SWIGTYPE%s", mangle); + + if (index == 1) + if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY)) + SwigType_remember(type); + + strcpy(varname,"descriptor"); + if (Replace(s,var,descriptor,DOH_REPLACE_ANY)) + SwigType_remember(type); + + Delete(descriptor); + Delete(mangle); + } + + /* One pointer level removed */ + /* This creates variables of the form + $*n_type + $*n_ltype + */ + + if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype))) { + if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type))) { + star_type = Copy(ftype); + } else { + star_type = Copy(type); + } + if (!SwigType_isreference(star_type)) { + if (SwigType_isarray(star_type)) { + Delete(SwigType_pop(star_type)); + } else { + SwigType_del_pointer(star_type); + } + ts = SwigType_str(star_type,0); + if (index == 1) { + Replace(s, "$*type", ts, DOH_REPLACE_ANY); + replace_local_types(locals,"$*type",star_type); + } + sprintf(varname,"$*%d_type",index); + Replace(s,varname,ts,DOH_REPLACE_ANY); + replace_local_types(locals,varname,star_type); + Delete(ts); + } else { + Delete(SwigType_pop(star_type));; + } + star_ltype = SwigType_ltype(star_type); + ts = SwigType_str(star_ltype,0); + if (index == 1) { + Replace(s, "$*ltype", ts, DOH_REPLACE_ANY); + replace_local_types(locals,"$*ltype",star_ltype); + } + sprintf(varname,"$*%d_ltype",index); + Replace(s,varname,ts,DOH_REPLACE_ANY); + replace_local_types(locals,varname,star_ltype); + Delete(ts); + Delete(star_ltype); + + star_mangle = SwigType_manglestr(star_type); + if (index == 1) + Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY); + + sprintf(varname,"$*%d_mangle",index); + Replace(s,varname,star_mangle,DOH_REPLACE_ANY); + + star_descriptor = NewStringf("SWIGTYPE%s", star_mangle); + if (index == 1) + if (Replace(s, "$*descriptor", + star_descriptor, DOH_REPLACE_ANY)) + SwigType_remember(star_type); + sprintf(varname,"$*%d_descriptor",index); + if (Replace(s,varname,star_descriptor,DOH_REPLACE_ANY)) + SwigType_remember(star_type); + + Delete(star_descriptor); + Delete(star_mangle); + Delete(star_type); + } + else { + /* TODO: Signal error if one of the $* substitutions is + requested */ + } + /* One pointer level added */ + amp_type = Copy(type); + SwigType_add_pointer(amp_type); + ts = SwigType_str(amp_type,0); + if (index == 1) { + Replace(s, "$&type", ts, DOH_REPLACE_ANY); + replace_local_types(locals,"$&type",amp_type); + } + sprintf(varname,"$&%d_type",index); + Replace(s,varname,ts,DOH_REPLACE_ANY); + replace_local_types(locals,varname,amp_type); + Delete(ts); + + amp_ltype = SwigType_ltype(type); + SwigType_add_pointer(amp_ltype); + ts = SwigType_str(amp_ltype,0); + + if (index == 1) { + Replace(s, "$<ype", ts, DOH_REPLACE_ANY); + replace_local_types(locals, "$<ype", amp_ltype); + } + sprintf(varname,"$&%d_ltype",index); + Replace(s,varname,ts,DOH_REPLACE_ANY); + replace_local_types(locals,varname,amp_ltype); + Delete(ts); + Delete(amp_ltype); + + amp_mangle = SwigType_manglestr(amp_type); + if (index == 1) + Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY); + sprintf(varname,"$&%d_mangle",index); + Replace(s,varname,amp_mangle,DOH_REPLACE_ANY); + + amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle); + if (index == 1) + if (Replace(s, "$&descriptor", + amp_descriptor, DOH_REPLACE_ANY)) + SwigType_remember(amp_type); + sprintf(varname,"$&%d_descriptor",index); + if (Replace(s,varname,amp_descriptor,DOH_REPLACE_ANY)) + SwigType_remember(amp_type); + + Delete(amp_descriptor); + Delete(amp_mangle); + Delete(amp_type); + + /* Base type */ + if (SwigType_isarray(type)) { + SwigType *bt = Copy(type); + Delete(SwigType_pop_arrays(bt)); + base_type = SwigType_str(bt,0); + Delete(bt); + } else { + base_type = SwigType_base(type); + } + + if (index == 1) { + Replace(s,"$basetype", base_type, DOH_REPLACE_ANY); + replace_local_types(locals,"$basetype", base_type); + } + strcpy(varname,"basetype"); + Replace(s,var,base_type,DOH_REPLACE_ANY); + replace_local_types(locals,var,base_type); + + base_mangle = SwigType_manglestr(base_type); + if (index == 1) + Replace(s,"$basemangle", base_mangle, DOH_REPLACE_ANY); + strcpy(varname,"basemangle"); + Replace(s,var,base_mangle,DOH_REPLACE_ANY); + Delete(base_mangle); + Delete(base_type); + } + + /* Replace any $n. with (&n)-> */ + { + char temp[64]; + sprintf(var,"$%d.",index); + sprintf(temp,"(&$%d)->", index); + Replace(s,var,temp,DOH_REPLACE_ANY); + } + + /* Replace the bare $n variable */ + sprintf(var,"$%d",index); + Replace(s,var,lname,DOH_REPLACE_ANY); + Delete(ftype); +} /* ------------------------------------------------------------------------ * static typemap_locals() @@ -362,42 +975,50 @@ Swig_typemap_search(const String_or_char *op, SwigType *type, String_or_char *na * creates the local variables. * ------------------------------------------------------------------------ */ -static void typemap_locals(SwigType *t, String_or_char *pname, DOHString *s, ParmList *l, Wrapper *f) { +static void typemap_locals(DOHString *s, ParmList *l, Wrapper *f, int argnum) { Parm *p; char *new_name; - + p = l; while (p) { - SwigType *pt = Gettype(p); - String *pn = Getname(p); + SwigType *pt = Getattr(p,"type"); + String *pn = Getattr(p,"name"); + String *value = Getattr(p,"value"); if (pn) { if (Len(pn) > 0) { - DOHString *str; - SwigType *tt; + String *str; + int isglobal = 0; str = NewString(""); + + if (Strncmp(pn,"_global_",8) == 0) { + isglobal = 1; + } + /* If the user gave us $type as the name of the local variable, we'll use the passed datatype instead */ - if (Cmp(SwigType_base(pt),"$type")==0 || Cmp(SwigType_base(pt),"$basetype")==0) { - tt = t; + if ((argnum >= 0) && (!isglobal)) { + Printf(str,"%s%d",pn,argnum); } else { - tt = pt; + Printf(str,"%s",pn); } - Printf(str,"%s",pn); - /* Substitute parameter names */ - Replace(str,"$arg",pname, DOH_REPLACE_ANY); - if (Cmp(SwigType_base(pt),"$basetype")==0) { - /* use $basetype */ - new_name = Wrapper_new_localv(f,str,SwigType_base(tt),str,0); - } else { - new_name = Wrapper_new_localv(f,str, SwigType_str(tt,str), 0); + if (isglobal && Wrapper_check_local(f,str)) { + p = nextSibling(p); + continue; + } + if (value) { + new_name = Wrapper_new_localv(f,str, SwigType_str(pt,str), "=", value, NIL); + } else { + new_name = Wrapper_new_localv(f,str, SwigType_str(pt,str), NIL); + } + if (!isglobal) { + /* Substitute */ + Replace(s,pn,new_name,DOH_REPLACE_ID); } - /* Substitute */ - Replace(s,pn,new_name,DOH_REPLACE_ID); } } - p = Getnext(p); + p = nextSibling(p); } } @@ -407,43 +1028,39 @@ static void typemap_locals(SwigType *t, String_or_char *pname, DOHString *s, Par * Perform a typemap lookup (ala SWIG1.1) * ----------------------------------------------------------------------------- */ -char *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname, String_or_char *source, +String *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname, + String_or_char *lname, String_or_char *source, String_or_char *target, Wrapper *f) { Hash *tm; - String *s; + String *s = 0; + SwigType *mtype = 0; ParmList *locals; - - tm = Swig_typemap_search(op,type,pname); + tm = Swig_typemap_search(op,type,pname,&mtype); if (!tm) return 0; s = Getattr(tm,"code"); if (!s) return 0; + + /* Blocked */ + if (Cmp(s,"pass") == 0) return 0; + s = Copy(s); /* Make a local copy of the typemap code */ locals = Getattr(tm,"locals"); + if (locals) locals = CopyParmList(locals); - /* Replace array dimensions */ - if (locals && f) { - typemap_locals(type,pname,s,locals,f); + /* This is wrong. It replaces locals in place. Need to fix this */ + if (mtype && SwigType_isarray(mtype)) { + typemap_replace_vars(s,locals,mtype,pname,lname,1); + } else { + typemap_replace_vars(s,locals,type,pname,lname,1); } - /* If the original datatype was an array. We're going to go through and substitute - it's array dimensions */ - - if (SwigType_isarray(type)) { - char temp[10]; - int ndim = SwigType_array_ndim(type); - int i; - for (i = 0; i < ndim; i++) { - DOHString *dim = SwigType_array_getdim(type,i); - sprintf(temp,"$dim%d",i); - if (f) - Replace(Getattr(f,"locals"),temp,dim, DOH_REPLACE_ANY); - Replace(s,temp,dim,DOH_REPLACE_ANY); - } + if (locals && f) { + typemap_locals(s,locals,f,-1); } - + /* Now perform character replacements */ Replace(s,"$source",source,DOH_REPLACE_ANY); Replace(s,"$target",target,DOH_REPLACE_ANY); @@ -451,20 +1068,256 @@ char *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_ch String *tmname = Getattr(tm,"typemap"); if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); } - Replace(s,"$type",SwigType_str(type,0),DOH_REPLACE_ANY); + Replace(s,"$parmname",pname, DOH_REPLACE_ANY); + /* Replace(s,"$name",pname,DOH_REPLACE_ANY); */ + Delete(locals); + Delete(mtype); + return s; +} + +/* ----------------------------------------------------------------------------- + * Swig_typemap_lookup_new() + * + * Attach one or more typemaps to a node + * ----------------------------------------------------------------------------- */ + +String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f) +{ + SwigType *type; + SwigType *mtype = 0; + String *pname; + Hash *tm; + String *s = 0; + ParmList *locals; + ParmList *kw; + char temp[256]; + String *symname; + String *cname = 0; + String *clname = 0; + + type = Getattr(node,"type"); + if (!type) return 0; + + pname = Getattr(node,"name"); + tm = Swig_typemap_search(op,type,pname,&mtype); + if (!tm) return 0; + + s = Getattr(tm,"code"); + if (!s) return 0; + + /* Empty typemap. No match */ + if (Cmp(s,"pass") == 0) return 0; + + s = Copy(s); /* Make a local copy of the typemap code */ + + locals = Getattr(tm,"locals"); + if (locals) locals = CopyParmList(locals); + + if (pname) { + if (SwigType_istemplate(pname)) { + cname = SwigType_namestr(pname); + pname = cname; + } + } + if (SwigType_istemplate((char*)lname)) { + clname = SwigType_namestr((char *)lname); + lname = clname; + } + if (mtype && SwigType_isarray(mtype)) { + typemap_replace_vars(s,locals,mtype,pname,(char *) lname,1); + } else { + typemap_replace_vars(s,locals,type,pname,(char *) lname,1); + } + if (locals && f) { + typemap_locals(s,locals,f,-1); + } + { + String *tmname = Getattr(tm,"typemap"); + if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); + } + Replace(s,"$name",pname,DOH_REPLACE_ANY); + + symname = Getattr(node,"sym:name"); + if (symname) { + Replace(s,"$symname",symname, DOH_REPLACE_ANY); + } + + Setattr(node,tmop_name(op),s); + if (locals) { + sprintf(temp,"%s:locals", Char(op)); + Setattr(node,tmop_name(temp), locals); + Delete(locals); + } + + if (checkAttribute(tm,"type","SWIGTYPE")) { + sprintf(temp,"%s:SWIGTYPE", Char(op)); + Setattr(node,tmop_name(temp),"1"); + } + + /* Attach kwargs */ + kw = Getattr(tm,"kwargs"); + while (kw) { + sprintf(temp,"%s:%s",Char(op),Char(Getattr(kw,"name"))); + Setattr(node,tmop_name(temp), Copy(Getattr(kw,"value"))); + kw = nextSibling(kw); + } + + /* Look for warnings */ { - SwigType *ltype = Swig_clocal_type(type); - Replace(s,"$ltype",SwigType_str(ltype,0), DOH_REPLACE_ANY); - Delete(ltype); + String *w; + sprintf(temp,"%s:warning", Char(op)); + w = Getattr(node,tmop_name(temp)); + if (w) { + Swig_warning(0,Getfile(node),Getline(node),"%s\n", w); + } } - Replace(s,"$parmname",pname, DOH_REPLACE_ANY); - /* Print base type (without any pointers) */ - Replace(s,"$basetype",SwigType_base(type), DOH_REPLACE_ANY); - Replace(s,"$basemangle",SwigType_manglestr(SwigType_base(type)), DOH_REPLACE_ANY); - Replace(s,"$mangle",SwigType_manglestr(type), DOH_REPLACE_ANY); - Swig_temp_result(s); - return Char(s); + /* Look for code fragments */ + { + String *f; + sprintf(temp,"%s:fragment", Char(op)); + f = Getattr(node,tmop_name(temp)); + if (f) { + char *c, *tok; + String *t = Copy(f); + c = Char(t); + tok = strtok(c,","); + while (tok) { + Swig_fragment_emit(tok); + tok = strtok(NULL,","); + } + Delete(t); + } + } + + if (cname) Delete(cname); + if (clname) Delete(clname); + if (mtype) Delete(mtype); + return s; +} + +/* ----------------------------------------------------------------------------- + * Swig_typemap_attach_parms() + * + * Given a parmeter list, this function attaches all of the typemaps for a + * given typemap type + * ----------------------------------------------------------------------------- */ + +void +Swig_typemap_attach_parms(const String_or_char *op, ParmList *parms, Wrapper *f) { + Parm *p, *firstp; + Hash *tm; + int nmatch = 0; + int i; + String *s; + ParmList *locals; + int argnum = 0; + char temp[256]; + Parm *kw; + + p = parms; + while (p) { + argnum++; + nmatch = 0; + tm = Swig_typemap_search_multi(op,p,&nmatch); + if (!tm) { + p = nextSibling(p); + continue; + } + s = Getattr(tm,"code"); + if (!s) { + p = nextSibling(p); + continue; + } + + /* Empty typemap. No match */ + if (Cmp(s,"pass") == 0) { + p = nextSibling(p); + continue; + } + + s = Copy(s); + locals = Getattr(tm,"locals"); + if (locals) locals = CopyParmList(locals); + firstp = p; + for (i = 0; i < nmatch; i++) { + SwigType *type; + String *pname; + String *lname; + SwigType *mtype; + + type = Getattr(p,"type"); + pname = Getattr(p,"name"); + lname = Getattr(p,"lname"); + mtype = Getattr(p,"tmap:match"); + + if (mtype) { + typemap_replace_vars(s,locals, mtype,pname,lname,i+1); + Delattr(p,"tmap:match"); + } else { + typemap_replace_vars(s,locals, type,pname,lname,i+1); + } + if (checkAttribute(tm,"type","SWIGTYPE")) { + sprintf(temp,"%s:SWIGTYPE", Char(op)); + Setattr(p,tmop_name(temp),"1"); + } + p = nextSibling(p); + } + + if (locals && f) { + typemap_locals(s,locals,f,argnum); + } + + /* Replace the argument number */ + sprintf(temp,"%d",argnum); + Replace(s,"$argnum",temp, DOH_REPLACE_ANY); + + /* Attach attributes to object */ + Setattr(firstp,tmop_name(op),s); /* Code object */ + + if (locals) { + sprintf(temp,"%s:locals", Char(op)); + Setattr(firstp,tmop_name(temp), locals); + Delete(locals); + } + + /* Attach a link to the next parameter. Needed for multimaps */ + sprintf(temp,"%s:next",Char(op)); + Setattr(firstp,tmop_name(temp),p); + + /* Attach kwargs */ + kw = Getattr(tm,"kwargs"); + while (kw) { + sprintf(temp,"%s:%s",Char(op),Char(Getattr(kw,"name"))); + Setattr(firstp,tmop_name(temp), Copy(Getattr(kw,"value"))); + kw = nextSibling(kw); + } + { + String *w; + sprintf(temp,"%s:warning", Char(op)); + w = Getattr(firstp,tmop_name(temp)); + if (w) { + Swig_warning(0,Getfile(firstp), Getline(firstp), "%s\n", w); + } + } + /* Look for code fragments */ + { + String *f; + sprintf(temp,"%s:fragment", Char(op)); + f = Getattr(firstp,tmop_name(temp)); + if (f) { + char *c, *tok; + String *t = Copy(f); + c = Char(t); + tok = strtok(c,","); + while (tok) { + Swig_fragment_emit(tok); + tok = strtok(NULL,","); + } + Delete(t); + } + } + } } /* ----------------------------------------------------------------------------- @@ -483,37 +1336,4 @@ void Swig_typemap_debug() { } Printf(stdout,"-----------------------------------------------------------------------------\n"); } - - -/* ----------------------------------------------------------------------------- - * %except directive support. - * - * These functions technically don't really have anything to do with typemaps - * except that they have the same scoping rules. Therefore, it's easy enough to - * just use the hash table structure of the typemap code. - * ----------------------------------------------------------------------------- */ - -void Swig_except_register(String_or_char *code) { - String *s = NewString(code); - Setattr(typemaps[tm_scope],"*except*",s); - Delete(s); -} -char *Swig_except_lookup() { - String *s; - int ts = tm_scope; - while (ts >= 0) { - s = Getattr(typemaps[tm_scope],"*except*"); - if (s) { - s = Copy(s); - Swig_temp_result(s); - return Char(s); - } - ts--; - } - return 0; -} - -void Swig_except_clear() { - Delattr(typemaps[tm_scope],"*except*"); -} diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c new file mode 100644 index 000000000..65df2f882 --- /dev/null +++ b/Source/Swig/typesys.c @@ -0,0 +1,1609 @@ +/* ----------------------------------------------------------------------------- + * typesys.c + * + * SWIG type system management. These functions are used to manage + * the C++ type system including typenames, typedef, type scopes, + * inheritance, and namespaces. Generation of support code for the + * run-time type checker is also handled here. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_typesys_c[] = "$Header$"; + +#include "swig.h" + +/* ----------------------------------------------------------------------------- + * Synopsis + * + * The purpose of this module is to manage type names and scoping issues related + * to the C++ type system. The primary use is tracking typenames through typedef + * and inheritance. + * + * New typenames are introduced by typedef, class, and enum declarations. + * Each type is declared in a scope. This is either the global scope, a + * class, or a namespace. For example: + * + * typedef int A; // Typename A, in global scope + * namespace Foo { + * typedef int A; // Typename A, in scope Foo:: + * } + * class Bar { // Typename Bar, in global scope + * typedef int A; // Typename A, in scope Bar:: + * } + * + * To manage scopes, the type system is constructed as a tree of hash tables. Each + * hash table contains the following attributes: + * + * "name" - Scope name + * "qname" - Fully qualified typename + * "typetab" - Type table containing typenames and typedef information + * "symtab" - Hash table of symbols defined in a scope + * "inherit" - List of inherited scopes + * "parent" - Parent scope + * + * Typedef information is stored in the "typetab" hash table. For example, + * if you have these declarations: + * + * typedef int A; + * typedef A B; + * typedef B *C; + * + * typetab is built as follows: + * + * "A" : "int" + * "B" : "A" + * "C" : "p.B" + * + * To resolve a type back to its root type, one repeatedly expands on the type base. + * For example: + * + * C *[40] ---> a(40).p.C (string type representation, see stype.c) + * ---> a(40).p.p.B (C --> p.B) + * ---> a(40).p.p.A (B --> A) + * ---> a(40).p.p.int (A --> int) + * + * For inheritance, SWIG tries to resolve types back to the base class. For instance, if + * you have this: + * + * class Foo { + * public: + * typedef int Integer; + * }; + * + * class Bar : public Foo { + * void blah(Integer x); + * } + * + * The argument type of Bar::blah will be set to Foo::Integer. + * + * The scope-inheritance mechanism is used to manage C++ namespace aliases. + * For example, if you have this: + * + * namespace Foo { + * typedef int Integer; + * } + * + * namespace F = Foo; + * + * In this case, "F::" is defined as a scope that "inherits" from Foo. Internally, + * "F::" will merely be an empty scope that refers to Foo. SWIG will never + * place new type information into a namespace alias---attempts to do so + * will generate a warning message (in the parser) and will place information into + * Foo instead. + * + *----------------------------------------------------------------------------- */ + +static Typetab *current_scope = 0; /* Current type scope */ +static Hash *current_typetab = 0; /* Current type table */ +static Hash *current_symtab = 0; /* Current symbol table */ +static Typetab *global_scope = 0; /* The global scope */ +static Hash *scopes = 0; /* Hash table containing fully qualified scopes */ + +/* Performance optimization */ +static Hash *typedef_resolve_cache = 0; +static Hash *typedef_all_cache = 0; +static Hash *typedef_qualified_cache = 0; + +static void flush_cache() { + typedef_resolve_cache = 0; + typedef_all_cache = 0; + typedef_qualified_cache = 0; +} + +/* Initialize the scoping system */ + +void SwigType_typesystem_init() { + if (global_scope) Delete(global_scope); + if (scopes) Delete(scopes); + + current_scope = NewHash(); + global_scope = current_scope; + + Setattr(current_scope,"name",""); /* No name for global scope */ + current_typetab = NewHash(); + Setattr(current_scope,"typetab", current_typetab); + + current_symtab = 0; + scopes = NewHash(); + Setattr(scopes,"",current_scope); +} + +/* ----------------------------------------------------------------------------- + * SwigType_typedef() + * + * Defines a new typedef in the current scope. Returns -1 if the type name is + * already defined. + * ----------------------------------------------------------------------------- */ + +int SwigType_typedef(SwigType *type, String_or_char *name) { + Typetab *SwigType_find_scope(Typetab *, String *s); + if (Getattr(current_typetab, name)) return -1; /* Already defined */ + if (Strcmp(type,name) == 0) { /* Can't typedef a name to itself */ + return 0; + } + + /* Check if 'type' is already a scope. If so, we create an alias in the type + system for it. This is needed to make strange nested scoping problems work + correctly. */ + { + Typetab *t = SwigType_find_scope(current_scope,type); + if (t) { + SwigType_new_scope(name); + SwigType_inherit_scope(t); + SwigType_pop_scope(); + } + } + Setattr(current_typetab,name,type); + flush_cache(); + return 0; +} + + +/* ----------------------------------------------------------------------------- + * SwigType_typedef_class() + * + * Defines a class in the current scope. + * ----------------------------------------------------------------------------- */ + +int SwigType_typedef_class(String_or_char *name) { + String *cname; + /* Printf(stdout,"class : '%s'\n", name); */ + if (Getattr(current_typetab, name)) return -1; /* Already defined */ + cname = NewString(name); + Setmeta(cname,"class","1"); + Setattr(current_typetab,cname,cname); + flush_cache(); + return 0; +} + +/* ----------------------------------------------------------------------------- + * SwigType_scope_name() + * + * Returns the qualified scope name of a type table + * ----------------------------------------------------------------------------- */ + +String * +SwigType_scope_name(Typetab *ttab) { + String *qname = NewString(Getattr(ttab,"name")); + ttab = Getattr(ttab,"parent"); + while (ttab) { + String *pname = Getattr(ttab,"name"); + if (Len(pname)) { + Insert(qname,0,"::"); + Insert(qname,0,pname); + } + ttab = Getattr(ttab,"parent"); + } + return qname; +} +/* ----------------------------------------------------------------------------- + * SwigType_new_scope() + * + * Creates a new scope + * ----------------------------------------------------------------------------- */ + +void SwigType_new_scope(String_or_char *name) { + Typetab *s; + Hash *ttab; + String *qname; + + if (!name) { + name = "<unnamed>"; + } + s = NewHash(); + Setattr(s,"name", name); + Setattr(s,"parent", current_scope); + ttab = NewHash(); + Setattr(s,"typetab", ttab); + + /* Build fully qualified name and */ + qname = SwigType_scope_name(s); + Setattr(scopes,qname,s); + Setattr(s,"qname",qname); + Delete(qname); + + current_scope = s; + current_typetab = ttab; + current_symtab = 0; + flush_cache(); +} + +/* ----------------------------------------------------------------------------- + * SwigType_inherit_scope() + * + * Makes the current scope inherit from another scope. This is used for both + * C++ class inheritance, namespaces, and namespace aliases. + * ----------------------------------------------------------------------------- */ + +void +SwigType_inherit_scope(Typetab *scope) { + List *inherits; + int i, len; + inherits = Getattr(current_scope,"inherit"); + if (!inherits) { + inherits = NewList(); + Setattr(current_scope,"inherit", inherits); + } + assert(scope != current_scope); + + len = Len(inherits); + for (i = 0; i < len; i++) { + Node *n = Getitem(inherits,i); + if (n == scope) return; + } + Append(inherits,scope); +} + +/* ----------------------------------------------------------------------------- + * SwigType_scope_alias() + * + * Creates a scope-alias. + * ----------------------------------------------------------------------------- */ + +void +SwigType_scope_alias(String *aliasname, Typetab *ttab) { + String *q; + /* Printf(stdout,"alias: '%s' '%x'\n", aliasname, ttab);*/ + q = SwigType_scope_name(current_scope); + if (Len(q)) { + Append(q,"::"); + } + Append(q,aliasname); + Setattr(scopes,q,ttab); + flush_cache(); +} + +/* ----------------------------------------------------------------------------- + * SwigType_using_scope() + * + * Import another scope into this scope. + * ----------------------------------------------------------------------------- */ + +void +SwigType_using_scope(Typetab *scope) { + SwigType_inherit_scope(scope); + { + List *ulist; + int i, len; + ulist = Getattr(current_scope,"using"); + if (!ulist) { + ulist = NewList(); + Setattr(current_scope,"using", ulist); + } + assert(scope != current_scope); + len = Len(ulist); + for (i = 0; i < len; i++) { + Typetab *n = Getitem(ulist,i); + if (n == scope) return; + } + Append(ulist,scope); + } + flush_cache(); +} + +/* ----------------------------------------------------------------------------- + * SwigType_pop_scope() + * + * Pop off the last scope and perform a merge operation. Returns the hash + * table for the scope that was popped off. + * ----------------------------------------------------------------------------- */ + +Typetab *SwigType_pop_scope() { + Typetab *s, *s1; + s = Getattr(current_scope,"parent"); + if (!s) { + current_scope = 0; + current_typetab = 0; + current_symtab = 0; + return 0; + } + s1 = current_scope; + current_scope = s; + current_typetab = Getattr(s,"typetab"); + current_symtab = Getattr(s,"symtab"); + flush_cache(); + return s1; +} + +/* ----------------------------------------------------------------------------- + * SwigType_set_scope() + * + * Set the scope. Returns the old scope. + * ----------------------------------------------------------------------------- */ + +Typetab * +SwigType_set_scope(Typetab *t) { + Typetab *old = current_scope; + if (!t) t = global_scope; + current_scope = t; + current_typetab = Getattr(t,"typetab"); + current_symtab = Getattr(t,"symtab"); + flush_cache(); + return old; +} + +/* ----------------------------------------------------------------------------- + * SwigType_attach_symtab() + * + * Attaches a symbol table to a type scope + * ----------------------------------------------------------------------------- */ + +void +SwigType_attach_symtab(Symtab *sym) { + Setattr(current_scope,"symtab",sym); + current_symtab = sym; +} + +/* ----------------------------------------------------------------------------- + * SwigType_print_scope() + * + * Debugging function for printing out current scope + * ----------------------------------------------------------------------------- */ + +void SwigType_print_scope(Typetab *t) { + String *key; + Hash *ttab; + String *tkey; + + for (tkey = Firstkey(scopes); tkey; tkey = Nextkey(scopes)) { + t = Getattr(scopes,tkey); + ttab = Getattr(t,"typetab"); + + Printf(stdout,"Type scope '%s' (%x)\n", tkey, t); + { + List *inherit = Getattr(t,"inherit"); + if (inherit) { + Typetab *it; + for (it = Firstitem(inherit); it; it = Nextitem(inherit)) { + Printf(stdout," Inherits from '%s' (%x)\n", Getattr(it,"qname"), it); + } + } + } + Printf(stdout,"-------------------------------------------------------------\n"); + for (key = Firstkey(ttab); key; key = Nextkey(ttab)) { + Printf(stdout,"%40s -> %s\n", key, Getattr(ttab,key)); + } + } +} + +Typetab * +SwigType_find_scope(Typetab *s, String *nameprefix) { + Typetab *ss; + String *nnameprefix = 0; + static int check_parent = 1; + + /* Printf(stdout,"find_scope: %x(%s) '%s'\n", s, Getattr(s,"name"), nameprefix); */ + + if (SwigType_istemplate(nameprefix)) { + nnameprefix = SwigType_typedef_resolve_all(nameprefix); + nameprefix = nnameprefix; + } + + ss = s; + while (ss) { + String *full; + String *qname = Getattr(ss,"qname"); + if (qname) { + full = NewStringf("%s::%s", qname, nameprefix); + } else { + full = NewString(nameprefix); + } + if (Getattr(scopes,full)) { + s = Getattr(scopes,full); + } else { + s = 0; + } + Delete(full); + if (s) { + if (nnameprefix) Delete(nnameprefix); + return s; + } + if (!s) { + /* Check inheritance */ + List *inherit; + inherit = Getattr(ss,"using"); + if (inherit) { + Typetab *ttab; + int i, len; + len = Len(inherit); + for (i = 0; i < len; i++) { + int oldcp = check_parent; + ttab = Getitem(inherit,i); + check_parent = 0; + s = SwigType_find_scope(ttab,nameprefix); + check_parent = oldcp; + if (s) { + if (nnameprefix) Delete(nnameprefix); + return s; + } + } + } + } + if (!check_parent) break; + ss = Getattr(ss,"parent"); + } + if (nnameprefix) Delete(nnameprefix); + return 0; +} + +/* ----------------------------------------------------------------------------- + * SwigType_typedef_resolve() + * + * Resolves a typedef and returns a new type string. Returns 0 if there is no + * typedef mapping. base is a name without qualification. + * ----------------------------------------------------------------------------- */ + +static Typetab *resolved_scope = 0; + +/* Internal function */ +static SwigType * +typedef_resolve(Typetab *s, String *base) { + Hash *ttab; + SwigType *type; + List *inherit; + + if (!s) return 0; + /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */ + + if (Getmark(s)) return 0; + Setmark(s,1); + + ttab = Getattr(s,"typetab"); + type = Getattr(ttab,base); + if (type) { + resolved_scope = s; + Setmark(s,0); + return type; + } + /* Hmmm. Not found in my scope. It could be in an inherited scope */ + inherit = Getattr(s,"inherit"); + if (inherit) { + int i,len; + len = Len(inherit); + for (i = 0; i < len; i++) { + type = typedef_resolve(Getitem(inherit,i), base); + if (type) { + Setmark(s,0); + return type; + } + } + } + type = typedef_resolve(Getattr(s,"parent"), base); + Setmark(s,0); + return type; +} + +SwigType *SwigType_typedef_resolve(SwigType *t) { + String *base; + String *type = 0; + String *r = 0; + Typetab *s; + Hash *ttab; + String *namebase = 0; + String *nameprefix = 0; + int newtype = 0; + + resolved_scope = 0; + + if (!typedef_resolve_cache) { + typedef_resolve_cache = NewHash(); + } + /* + r = Getattr(typedef_resolve_cache,t); + if (r) { + if (r != DohNone) { + resolved_scope = Getmeta(r,"scope"); + return Copy(r); + } else { + return 0; + } + } +*/ + + base = SwigType_base(t); + + /* Printf(stdout,"base = '%s'\n", base); */ + + if (SwigType_issimple(base)) { + s = current_scope; + ttab = current_typetab; + if (Strncmp(base,"::",2) == 0) { + s = global_scope; + ttab = Getattr(s,"typetab"); + Delitem(base,0); + Delitem(base,0); + } + /* Do a quick check in the local scope */ + type = Getattr(ttab,base); + if (type) { + resolved_scope = s; + } + if (!type) { + /* Didn't find in this scope. We need to do a little more searching */ + if (Swig_scopename_check(base)) { + /* A qualified name. */ + nameprefix = Swig_scopename_prefix(base); + /* Printf(stdout,"nameprefix = '%s'\n", nameprefix);*/ + if (nameprefix) { + /* Name had a prefix on it. See if we can locate the proper scope for it */ + s = SwigType_find_scope(s,nameprefix); + /* Couldn't locate a scope for the type. */ + if (!s) { + Delete(base); + Delete(nameprefix); + r = 0; + goto return_result; + } + /* Try to locate the name starting in the scope */ + namebase = Swig_scopename_last(base); + /* Printf(stdout,"namebase = '%s'\n", namebase); */ + type = typedef_resolve(s,namebase); + /* Printf(stdout,"%s type = '%s'\n", Getattr(s,"name"), type); */ + if ((type) && (!Swig_scopename_check(type))) { + Typetab *rtab = resolved_scope; + String *qname = Getattr(resolved_scope,"qname"); + /* If qualified *and* the typename is defined from the resolved scope, we qualify */ + if ((qname) && typedef_resolve(resolved_scope,type)) { + type = Copy(type); + Insert(type,0,"::"); + Insert(type,0,qname); + newtype = 1; + } + resolved_scope = rtab; + } + } else { + /* Name is unqualified. */ + type = typedef_resolve(s,base); + } + } else { + /* Name is unqualified. */ + type = typedef_resolve(s,base); + } + } + + if (type && (Strcmp(base,type) == 0)) { + Delete(base); + r = 0; + goto return_result; + } + + /* If the type is a template, and no typedef was found, we need to check the + template arguments one by one to see if they can be resolved. */ + + if (!type && SwigType_istemplate(base)) { + List *tparms; + String *suffix; + int i,sz; + int rep = 0; + type = SwigType_templateprefix(base); + suffix = SwigType_templatesuffix(base); + Append(type,"<("); + tparms = SwigType_parmlist(base); + sz = Len(tparms); + for (i = 0; i < sz; i++) { + SwigType *tpr; + SwigType *tp = Getitem(tparms, i); + if (!rep) { + tpr = SwigType_typedef_resolve(tp); + } else { + tpr = 0; + } + if (tpr) { + Append(type,tpr); + rep = 1; + } else { + Append(type,tp); + } + if ((i+1) < sz) Append(type,","); + } + Append(type,")>"); + Append(type,suffix); + Delete(suffix); + Delete(tparms); + if (!rep) { + Delete(type); + type = 0; + } + } + if (namebase) Delete(namebase); + if (nameprefix) Delete(nameprefix); + } else { + if (SwigType_isfunction(base)) { + List *parms; + int i,sz; + int rep = 0; + type = NewString("f("); + parms = SwigType_parmlist(base); + sz = Len(parms); + for (i = 0; i < sz; i++) { + SwigType *tpr; + SwigType *tp = Getitem(parms, i); + if (!rep) { + tpr = SwigType_typedef_resolve(tp); + } else { + tpr = 0; + } + if (tpr) { + Append(type,tpr); + rep = 1; + } else { + Append(type,tp); + } + if ((i+1) < sz) Append(type,","); + } + Append(type,")."); + Delete(parms); + if (!rep) { + Delete(type); + type = 0; + } + } else if (SwigType_ismemberpointer(base)) { + String *rt; + String *mtype = SwigType_parm(base); + rt = SwigType_typedef_resolve(mtype); + if (rt) { + type = NewStringf("m(%s).", rt); + Delete(rt); + } + Delete(mtype); + } else { + type = 0; + } + } + r = SwigType_prefix(t); + if (!type) { + if (r && Len(r)) { + if ((Strstr(r,"f(") || (Strstr(r,"m(")))) { + SwigType *rt = SwigType_typedef_resolve(r); + if (rt) { + Delete(r); + Append(rt,base); + Delete(base); + r = rt; + goto return_result; + } + } + } + Delete(r); + Delete(base); + r = 0; + goto return_result; + } + Delete(base); + Append(r,type); + if (newtype) { + Delete(type); + } + + return_result: + if (!r) { + Setattr(typedef_resolve_cache,NewString(t),DohNone); + } else { + Setattr(typedef_resolve_cache,NewString(t),r); + Setmeta(r,"scope",resolved_scope); + r = Copy(r); + } + return r; +} + + +/* ----------------------------------------------------------------------------- + * SwigType_typedef_resolve_all() + * + * Fully resolve a type down to its most basic datatype + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_typedef_resolve_all(SwigType *t) { + SwigType *n; + SwigType *r; + + if (!typedef_all_cache) { + typedef_all_cache = NewHash(); + } + r = Getattr(typedef_all_cache,t); + if (r) { + return Copy(r); + } + r = NewString(t); + while ((n = SwigType_typedef_resolve(r))) { + Delete(r); + r = n; + } + { + SwigType *rr = Copy(r); + Setattr(typedef_all_cache,NewString(t),rr); + } + return r; +} + + +/* ----------------------------------------------------------------------------- + * SwigType_typedef_qualified() + * + * Given a type declaration, this function tries to fully qualify it according to + * typedef scope rules. + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_typedef_qualified(SwigType *t) +{ + List *elements; + String *result; + int i,len; + + if (!typedef_qualified_cache) typedef_qualified_cache = NewHash(); + result = Getattr(typedef_qualified_cache,t); + if (result) { + String *rc = Copy(result); + return rc; + } + result = NewString(""); + elements = SwigType_split(t); + len = Len(elements); + for (i = 0; i < len; i++) { + String *e = Getitem(elements,i); + if (SwigType_issimple(e)) { + if (!SwigType_istemplate(e)) { + String *isenum = 0; + if (SwigType_isenum(e)) { + isenum = e; + e = NewString(Char(e)+5); + } + resolved_scope = 0; + if (typedef_resolve(current_scope,e)) { + /* resolved_scope contains the scope that actually resolved the symbol */ + String *qname = Getattr(resolved_scope,"qname"); + if (qname) { + Insert(e,0,"::"); + Insert(e,0,qname); + if (isenum) { + Clear(isenum); + Printf(isenum, "enum %s", e); + Delete(e); + } + } + } else { + + if (Swig_scopename_check(e)) { + String *tqname; + String *qlast; + String *qname = Swig_scopename_prefix(e); + if (qname) { + qlast = Swig_scopename_last(e); + tqname = SwigType_typedef_qualified(qname); + Clear(e); + Printf(e,"%s::%s", tqname, qlast); + Delete(qname); + Delete(qlast); + Delete(tqname); + } + /* Automatic template instantiation might go here??? */ + + } + } + if (isenum) e = isenum; + + } else { + /* Template. We need to qualify template parameters as well as the template itself */ + String *tprefix, *qprefix; + String *tsuffix; + Parm *p; + List *parms = SwigType_parmlist(e); + tprefix = SwigType_templateprefix(e); + tsuffix = SwigType_templatesuffix(e); + qprefix = SwigType_typedef_qualified(tprefix); + Printf(qprefix,"<("); + p = Firstitem(parms); + while (p) { + String *qt = SwigType_typedef_qualified(p); + if ((Strcmp(qt,p) == 0)) { /* && (!Swig_scopename_check(qt))) { */ + /* No change in value. It is entirely possible that the parameter is an integer value. + If there is a symbol table associated with this scope, we're going to check for this */ + + if (current_symtab) { + Node *lastnode = 0; + String *value = Copy(p); + while (1) { + Node *n = Swig_symbol_clookup(value,current_symtab); + if (n == lastnode) break; + lastnode = n; + if (n) { + if (Strcmp(nodeType(n),"enumitem") == 0) { + /* An enum item. Generate a fully qualified name */ + String *qn = Swig_symbol_qualified(n); + if (Len(qn)) { + Append(qn,"::"); + Append(qn,Getattr(n,"name")); + Delete(value); + value = qn; + continue; + } else { + break; + } + } else if ((Strcmp(nodeType(n),"cdecl") == 0) && (Getattr(n,"value"))) { + Delete(value); + value = Copy(Getattr(n,"value")); + continue; + } + } + break; + } + Append(qprefix,value); + } else { + Append(qprefix,p); + } + } else { + Append(qprefix,qt); + } + Delete(qt); + p= Nextitem(parms); + if (p) { + Append(qprefix,","); + } + } + Append(qprefix,")>"); + Append(qprefix,tsuffix); + Delete(tsuffix); + Clear(e); + Append(e,qprefix); + Delete(tprefix); + Delete(qprefix); + } + if (Strncmp(e,"::",2) == 0) { + Delitem(e,0); + Delitem(e,0); + } + Append(result,e); + } else if (SwigType_isfunction(e)) { + List *parms = SwigType_parmlist(e); + String *s = NewString("f("); + String *p; + p = Firstitem(parms); + while (p) { + Append(s,SwigType_typedef_qualified(p)); + p = Nextitem(parms); + if (p) { + Append(s,","); + } + } + Append(s,")."); + Append(result,s); + Delete(s); + } else if (SwigType_isarray(e)) { + String *ndim; + String *dim = SwigType_parm(e); + ndim = Swig_symbol_string_qualify(dim,0); + Printf(result,"a(%s).",ndim); + Delete(dim); + Delete(ndim); + } else { + Append(result,e); + } + } + Delete(elements); + Setattr(typedef_qualified_cache,NewString(t),NewString(result)); + return result; +} + +/* ----------------------------------------------------------------------------- + * SwigType_istypedef() + * + * Checks a typename to see if it is a typedef. + * ----------------------------------------------------------------------------- */ + +int SwigType_istypedef(SwigType *t) { + String *type; + + type = SwigType_typedef_resolve(t); + if (type) { + Delete(type); + return 1; + } else { + return 0; + } +} + + +/* ----------------------------------------------------------------------------- + * SwigType_typedef_using() + * + * Processes a 'using' declaration to import types from one scope into another. + * Name is a qualified name like A::B. + * ----------------------------------------------------------------------------- */ + +int SwigType_typedef_using(String_or_char *name) { + String *base; + String *td; + String *prefix; + Typetab *s; + Typetab *tt = 0; + + String *defined_name = 0; + + /* Printf(stdout,"using %s\n", name);*/ + + if (!Swig_scopename_check(name)) return -1; /* Not properly qualified */ + base = Swig_scopename_last(name); + + /* See if the base is already defined in this scope */ + if (Getattr(current_typetab,base)) { + Delete(base); + return -1; + } + + /* See if the using name is a scope */ + /* tt = SwigType_find_scope(current_scope,name); + Printf(stdout,"tt = %x, name = '%s'\n", tt, name); */ + + /* We set up a typedef B --> A::B */ + Setattr(current_typetab,base,name); + + /* Find the scope name where the symbol is defined */ + td = SwigType_typedef_resolve(name); + /* Printf(stdout,"td = '%s' %x\n", td, resolved_scope); */ + if (resolved_scope) { + defined_name = Getattr(resolved_scope,"qname"); + if (defined_name) { + defined_name = Copy(defined_name); + Append(defined_name,"::"); + Append(defined_name,base); + } + } + if (td) Delete(td); + + /* Printf(stdout,"defined_name = '%s'\n", defined_name);*/ + tt = SwigType_find_scope(current_scope,defined_name); + + /* Figure out the scope the using directive refers to */ + { + prefix = Swig_scopename_prefix(name); + s = SwigType_find_scope(current_scope,prefix); + if (s) { + Hash *ttab = Getattr(s,"typetab"); + if (!Getattr(ttab,base) && defined_name) { + Setattr(ttab,base, defined_name); + } + } + } + + if (tt) { + /* Using directive had it's own scope. We need to do create a new scope for it */ + SwigType_new_scope(base); + SwigType_inherit_scope(tt); + SwigType_pop_scope(); + } + + if (defined_name) Delete(defined_name); + Delete(prefix); + Delete(base); + return 0; +} + +/* ----------------------------------------------------------------------------- + * SwigType_isclass() + * + * Determines if a type defines a class or not. A class is defined by + * its type-table entry maps to itself. Note: a pointer to a class is not + * a class. + * ----------------------------------------------------------------------------- */ + +int +SwigType_isclass(SwigType *t) { + SwigType *qty, *qtys; + int isclass = 0; + + qty = SwigType_typedef_resolve_all(t); + qtys = SwigType_strip_qualifiers(qty); + if (SwigType_issimple(qtys)) { + String *td = SwigType_typedef_resolve(qtys); + if (td) { + Delete(td); + } + if (resolved_scope) { + isclass = 1; + } + /* Hmmm. Not a class. If a template, it might be uninstantiated */ + if (SwigType_istemplate(qtys)) { + String *tp = SwigType_templateprefix(qtys); + isclass = SwigType_isclass(tp); + Delete(tp); + } + } + Delete(qty); + Delete(qtys); + return isclass; +} + +/* ----------------------------------------------------------------------------- + * SwigType_type() + * + * Returns an integer code describing the datatype. This is only used for + * compatibility with SWIG1.1 language modules and is likely to go away once + * everything is based on typemaps. + * ----------------------------------------------------------------------------- */ + +int SwigType_type(SwigType *t) +{ + char *c; + /* Check for the obvious stuff */ + c = Char(t); + + if (strncmp(c,"p.",2) == 0) { + if (SwigType_type(c+2) == T_CHAR) return T_STRING; + else return T_POINTER; + } + if (strncmp(c,"a(",2) == 0) return T_ARRAY; + if (strncmp(c,"r.",2) == 0) return T_REFERENCE; + if (strncmp(c,"m(",2) == 0) return T_MPOINTER; + if (strncmp(c,"q(",2) == 0) { + while(*c && (*c != '.')) c++; + if (*c) return SwigType_type(c+1); + return T_ERROR; + } + if (strncmp(c,"f(",2) == 0) return T_FUNCTION; + + /* Look for basic types */ + if (strcmp(c,"int") == 0) return T_INT; + if (strcmp(c,"long") == 0) return T_LONG; + if (strcmp(c,"short") == 0) return T_SHORT; + if (strcmp(c,"unsigned") == 0) return T_UINT; + if (strcmp(c,"unsigned short") == 0) return T_USHORT; + if (strcmp(c,"unsigned long") == 0) return T_ULONG; + if (strcmp(c,"unsigned int") == 0) return T_UINT; + if (strcmp(c,"char") == 0) return T_CHAR; + if (strcmp(c,"signed char") == 0) return T_SCHAR; + if (strcmp(c,"unsigned char") == 0) return T_UCHAR; + if (strcmp(c,"float") == 0) return T_FLOAT; + if (strcmp(c,"double") == 0) return T_DOUBLE; + if (strcmp(c,"void") == 0) return T_VOID; + if (strcmp(c,"bool") == 0) return T_BOOL; + if (strcmp(c,"long long") == 0) return T_LONGLONG; + if (strcmp(c,"unsigned long long") == 0) return T_ULONGLONG; + if (strncmp(c,"enum ",5) == 0) return T_INT; + + if (strcmp(c,"v(...)") == 0) return T_VARARGS; + /* Hmmm. Unknown type */ + if (SwigType_istypedef(t)) { + int r; + SwigType *nt = SwigType_typedef_resolve(t); + r = SwigType_type(nt); + Delete(nt); + return r; + } + return T_USER; +} + +/****************************************************************************** + *** * * * WARNING * * * *** + *** *** + *** Don't even think about modifying anything below this line unless you *** + *** are completely on top of *EVERY* subtle aspect of the C++ type system *** + *** and you are prepared to suffer endless hours of agony trying to *** + *** debug the SWIG run-time type checker after you break it. *** + ******************************************************************************/ + +/* ----------------------------------------------------------------------------- + * SwigType_remember() + * + * This function "remembers" a datatype that was used during wrapper code generation + * so that a type-checking table can be generated later on. It is up to the language + * modules to actually call this function--it is not done automatically. + * + * Type tracking is managed through two separate hash tables. The hash 'r_mangled' + * is mapping between mangled type names (used in the target language) and + * fully-resolved C datatypes used in the source input. The second hash 'r_resolved' + * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled + * names in the scripting languages. For example, consider the following set of + * typedef declarations: + * + * typedef double Real; + * typedef double Float; + * typedef double Point[3]; + * + * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and + * 'Point' were used in an interface file and "remembered" using this function. + * The hash tables would look like this: + * + * r_mangled { + * _p_double : [ p.double, a(3).double ] + * _p_Real : [ p.double ] + * _p_Float : [ p.double ] + * _Point : [ a(3).double ] + * + * r_resolved { + * p.double : [ _p_double, _p_Real, _p_Float ] + * a(3).double : [ _p_double, _Point ] + * } + * + * Together these two hash tables can be used to determine type-equivalency between + * mangled typenames. To do this, we view the two hash tables as a large graph and + * compute the transitive closure. + * ----------------------------------------------------------------------------- */ + +static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */ +static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */ +static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */ +static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */ +static Hash *r_remembered = 0; /* Hash of types we remembered already */ + +static void (*r_tracefunc)(SwigType *t, String *mangled, String *clientdata) = 0; + +void SwigType_remember_clientdata(SwigType *t, const String_or_char *clientdata) { + String *mt; + SwigType *lt; + Hash *h; + SwigType *fr; + SwigType *qr; + + if (!r_mangled) { + r_mangled = NewHash(); + r_resolved = NewHash(); + r_ltype = NewHash(); + r_clientdata = NewHash(); + r_remembered = NewHash(); + } + + { + String *last; + last = Getattr(r_remembered,t); + if (last && (Cmp(last,clientdata) == 0)) return; + } + + Setattr(r_remembered, Copy(t), clientdata ? NewString(clientdata) : (void *) ""); + + mt = SwigType_manglestr(t); /* Create mangled string */ + + if (r_tracefunc) { + (*r_tracefunc)(t,mt, (String *) clientdata); + } + + if (SwigType_istypedef(t)) + lt = Copy(t); + else + lt = SwigType_ltype(t); + Setattr(r_ltype, mt, lt); + fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */ + qr = SwigType_typedef_qualified(fr); + Delete(fr); + + /* Added to deal with possible table bug */ + fr = SwigType_strip_qualifiers(qr); + Delete(qr); + + /*Printf(stdout,"t = '%s'\n", t); + Printf(stdout,"fr= '%s'\n\n", fr); */ + + if (Strstr(t,"<") && !(Strstr(t,"<("))) { + Printf(stdout,"Bad template type passed to SwigType_remember: %s\n", t); + assert(0); + } + + h = Getattr(r_mangled,mt); + if (!h) { + h = NewHash(); + Setattr(r_mangled,mt,h); + Delete(h); + } + Setattr(h,fr,mt); + + h = Getattr(r_resolved, fr); + if (!h) { + h = NewHash(); + Setattr(r_resolved,fr,h); + Delete(h); + } + Setattr(h,mt,fr); + + if (clientdata) { + String *cd = Getattr(r_clientdata,fr); + if (cd) { + if (Strcmp(clientdata,cd) != 0) { + Printf(stderr,"*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr,0)); + Printf(stderr,"*** '%s' != '%s'\n", clientdata, cd); + assert(0); + } + } else { + Setattr(r_clientdata, fr, NewString(clientdata)); + } + } +} + +void +SwigType_remember(SwigType *ty) { + SwigType_remember_clientdata(ty,0); +} + +void (*SwigType_remember_trace(void (*tf)(SwigType *, String *, String *)))(SwigType *, String *, String *) { + void (*o)(SwigType *, String *, String *) = r_tracefunc; + r_tracefunc = tf; + return o; +} + +/* ----------------------------------------------------------------------------- + * SwigType_equivalent_mangle() + * + * Return a list of all of the mangled typenames that are equivalent to another + * mangled name. This works as follows: For each fully qualified C datatype + * in the r_mangled hash entry, we collect all of the mangled names from the + * r_resolved hash and combine them together in a list (removing duplicate entries). + * ----------------------------------------------------------------------------- */ + +List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) { + List *l; + Hash *h; + Hash *ch; + Hash *mh; + + if (found) { + h = found; + } else { + h = NewHash(); + } + if (checked) { + ch = checked; + } else { + ch = NewHash(); + } + if (Getattr(ch,ms)) goto check_exit; /* Already checked this type */ + Setattr(h,ms,"1"); + Setattr(ch, ms, "1"); + mh = Getattr(r_mangled,ms); + if (mh) { + String *key; + key = Firstkey(mh); + while (key) { + Hash *rh; + if (Getattr(ch,key)) { + key = Nextkey(mh); + continue; + } + Setattr(ch,key,"1"); + rh = Getattr(r_resolved,key); + if (rh) { + String *rkey; + rkey = Firstkey(rh); + while (rkey) { + Setattr(h,rkey,"1"); + SwigType_equivalent_mangle(rkey,ch,h); + rkey = Nextkey(rh); + } + } + key = Nextkey(mh); + } + } + check_exit: + if (!found) { + l = Keys(h); + Delete(h); + Delete(ch); + return l; + } else { + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * SwigType_clientdata_collect() + * + * Returns the clientdata field for a mangled type-string. + * ----------------------------------------------------------------------------- */ + +static +String *SwigType_clientdata_collect(String *ms, Hash *checked) { + Hash *ch; + Hash *mh; + String *clientdata = 0; + + if (checked) { + ch = checked; + } else { + ch = NewHash(); + } + if (Getattr(ch,ms)) goto check_exit; /* Already checked this type */ + Setattr(ch, ms, "1"); + mh = Getattr(r_mangled,ms); + if (mh) { + String *key; + key = Firstkey(mh); + while (key) { + Hash *rh; + Setattr(ch,key,"1"); + clientdata = Getattr(r_clientdata,key); + if (clientdata) goto check_exit; + rh = Getattr(r_resolved,key); + if (rh) { + String *rkey; + rkey = Firstkey(rh); + while (rkey) { + clientdata = SwigType_clientdata_collect(rkey,ch); + if (clientdata) goto check_exit; + rkey = Nextkey(rh); + } + } + key = Nextkey(mh); + } + } + check_exit: + if (!checked) { + Delete(ch); + } + return clientdata; +} + + + + +/* ----------------------------------------------------------------------------- + * SwigType_inherit() + * + * Record information about inheritance. We keep a hash table that keeps + * a mapping between base classes and all of the classes that are derived + * from them. + * + * subclass is a hash that maps base-classes to all of the classes derived from them. + * ----------------------------------------------------------------------------- */ + +static Hash *subclass = 0; +static Hash *conversions = 0; + +void +SwigType_inherit(String *derived, String *base, String *cast) { + Hash *h; + if (!subclass) subclass = NewHash(); + + /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */ + + if (SwigType_istemplate(derived)) { + derived = SwigType_typedef_qualified(SwigType_typedef_resolve_all(derived)); + } + if (SwigType_istemplate(base)) { + base = SwigType_typedef_qualified(SwigType_typedef_resolve_all(base)); + } + + /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast);*/ + + h = Getattr(subclass,base); + if (!h) { + h = NewHash(); + Setattr(subclass,base,h); + } + if (!Getattr(h,derived)) { + Setattr(h,derived, cast ? cast : (void *) ""); + } + +} + +/* ----------------------------------------------------------------------------- + * SwigType_issubtype() + * + * Determines if a t1 is a subtype of t2 + * ----------------------------------------------------------------------------- */ + +int +SwigType_issubtype(SwigType *t1, SwigType *t2) { + SwigType *ft1, *ft2; + String *b1, *b2; + Hash *h; + int r = 0; + + if (!subclass) return 0; + + ft1 = SwigType_typedef_resolve_all(t1); + ft2 = SwigType_typedef_resolve_all(t2); + b1 = SwigType_base(ft1); + b2 = SwigType_base(ft2); + + h = Getattr(subclass,b2); + if (h) { + if (Getattr(h,b1)) { + r = 1; + } + } + Delete(ft1); + Delete(ft2); + Delete(b1); + Delete(b2); + /* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */ + return r; +} + +/* ----------------------------------------------------------------------------- + * SwigType_inherit_equiv() + * + * Modify the type table to handle C++ inheritance + * ----------------------------------------------------------------------------- */ + +void SwigType_inherit_equiv(File *out) { + String *rkey, *bkey, *ckey; + String *prefix, *base; + Hash *sub; + Hash *rh; + List *rlist; + + if (!conversions) conversions = NewHash(); + if (!subclass) subclass = NewHash(); + + rkey = Firstkey(r_resolved); + while (rkey) { + /* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */ + base = SwigType_base(rkey); + /* Check to see whether the base is recorded in the subclass table */ + sub = Getattr(subclass,base); + Delete(base); + if (!sub) { + rkey = Nextkey(r_resolved); + continue; + } + + /* This type has subclasses. We now need to walk through these subtypes and generate pointer converion functions */ + + rh = Getattr(r_resolved, rkey); + rlist = NewList(); + for (ckey = Firstkey(rh); ckey; ckey = Nextkey(rh)) { + Append(rlist,ckey); + } + /* Printf(stdout,"rkey = '%s'\n", rkey); + Printf(stdout,"rh = %x '%s'\n", rh,rh); */ + + bkey = Firstkey(sub); + while (bkey) { + prefix= SwigType_prefix(rkey); + Append(prefix,bkey); + /* Printf(stdout,"set %x = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */ + Setattr(rh,SwigType_manglestr(prefix),prefix); + ckey = NewStringf("%s+%s",SwigType_manglestr(prefix), SwigType_manglestr(rkey)); + if (!Getattr(conversions,ckey)) { + String *convname = NewStringf("%sTo%s", SwigType_manglestr(prefix), SwigType_manglestr(rkey)); + Printf(out,"static void *%s(void *x) {\n", convname); + Printf(out," return (void *)((%s) %s ((%s) x));\n", SwigType_lstr(rkey,0), Getattr(sub,bkey), SwigType_lstr(prefix,0)); + Printf(out,"}\n"); + Setattr(conversions,ckey,convname); + Delete(ckey); + + /* This inserts conversions for typedefs */ + { + Hash *r = Getattr(r_resolved, prefix); + if (r) { + String *rrkey = Firstkey(r); + while (rrkey) { + String *rlkey; + String *rkeymangle; + + /* Make sure this name equivalence is not due to inheritance */ + if (Cmp(prefix, Getattr(r,rrkey)) == 0) { + rkeymangle = SwigType_manglestr(rkey); + ckey = NewStringf("%s+%s", rrkey, rkeymangle); + if (!Getattr(conversions, ckey)) { + Setattr(conversions, ckey, convname); + } + Delete(ckey); + for (rlkey = Firstitem(rlist); rlkey; rlkey = Nextitem(rlist)) { + ckey = NewStringf("%s+%s", rrkey, rlkey); + Setattr(conversions, ckey, convname); + Delete(ckey); + } + Delete(rkeymangle); + /* This is needed to pick up other alternative names for the same type. + Needed to make templates work */ + Setattr(rh,rrkey,Getattr(r,rrkey)); + } + rrkey = Nextkey(r); + } + } + } + Delete(convname); + } + Delete(prefix); + bkey = Nextkey(sub); + } + rkey = Nextkey(r_resolved); + } +} + +/* ----------------------------------------------------------------------------- + * SwigType_type_table() + * + * Generate the type-table for the type-checker. + * ----------------------------------------------------------------------------- */ + +void +SwigType_emit_type_table(File *f_forward, File *f_table) { + DOH *key; + String *types, *table; + int i = 0; + + if (!r_mangled) { + r_mangled = NewHash(); + r_resolved = NewHash(); + } + + Printf(f_table,"\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n"); + + SwigType_inherit_equiv(f_table); + + /* #define DEBUG 1 */ +#ifdef DEBUG + Printf(stdout,"---r_mangled---\n"); + Printf(stdout,"%s\n", r_mangled); + + Printf(stdout,"---r_resolved---\n"); + Printf(stdout,"%s\n", r_resolved); + + Printf(stdout,"---r_ltype---\n"); + Printf(stdout,"%s\n", r_ltype); + + Printf(stdout,"---subclass---\n"); + Printf(stdout,"%s\n", subclass); + + Printf(stdout,"---conversions---\n"); + Printf(stdout,"%s\n", conversions); + +#endif + table = NewString(""); + types = NewString(""); + Printf(table,"static swig_type_info *swig_types_initial[] = {\n"); + key = Firstkey(r_mangled); + Printf(f_forward,"\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n"); + while (key) { + List *el; + String *en; + String *cd; + + Printf(f_forward,"#define SWIGTYPE%s swig_types[%d] \n", key, i); + Printv(types,"static swig_type_info _swigt_", key, "[] = {", NIL); + + cd = SwigType_clientdata_collect(key,0); + if (!cd) cd = "0"; + Printv(types,"{\"", key, "\", 0, \"", SwigType_str(Getattr(r_ltype,key),0),"\", ", cd, "},", NIL); + el = SwigType_equivalent_mangle(key,0,0); + for (en = Firstitem(el); en; en = Nextitem(el)) { + String *ckey; + String *conv; + ckey = NewStringf("%s+%s", en, key); + conv = Getattr(conversions,ckey); + if (conv) { + Printf(types,"{\"%s\", %s},", en, conv); + } else { + Printf(types,"{\"%s\"},", en); + } + Delete(ckey); + } + Delete(el); + Printf(types,"{0}};\n"); + Printv(table, "_swigt_", key, ", \n", NIL); + key = Nextkey(r_mangled); + i++; + } + + Printf(table, "0\n};\n"); + Printf(f_forward,"static swig_type_info *swig_types[%d];\n", i+1); + Printf(f_forward,"\n/* -------- TYPES TABLE (END) -------- */\n\n"); + Printf(f_table,"%s\n", types); + Printf(f_table,"%s\n", table); + Printf(f_table,"\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n"); + Delete(types); + Delete(table); +} diff --git a/Source/Swig/warn.c b/Source/Swig/warn.c new file mode 100644 index 000000000..805f0a4dd --- /dev/null +++ b/Source/Swig/warn.c @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + * warn.c + * + * SWIG warning framework. This was added to warn developers about + * deprecated APIs and other features. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2001. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_warn_c[] = "$Header$"; + +#include "swig.h" + +static Hash *warnings = 0; + +/* ----------------------------------------------------------------------------- + * Swig_warn() + * + * Issue a warning + * ----------------------------------------------------------------------------- */ + +void +Swig_warn(const char *filename, int line, const char *msg) { + String *key; + if (!warnings) { + warnings = NewHash(); + } + key = NewStringf("%s:%d", filename,line); + if (!Getattr(warnings,key)) { + Printf(stderr,"swig-dev warning:%s:%d:%s\n", filename, line, msg); + Setattr(warnings,key,key); + } + Delete(key); +} + + + + + diff --git a/Source/Swig/wrapfunc.c b/Source/Swig/wrapfunc.c index f716fba39..182e3f2af 100644 --- a/Source/Swig/wrapfunc.c +++ b/Source/Swig/wrapfunc.c @@ -14,30 +14,41 @@ * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ -static char cvsroot[] = "$Header$"; +char cvsroot_wrapfunc_c[] = "$Header$"; #include "swig.h" #include <ctype.h> -#include "dohobj.h" +/* ----------------------------------------------------------------------------- + * NewWrapper() + * + * Create a new wrapper function object. + * ----------------------------------------------------------------------------- */ -typedef struct { - Hash *attr; /* Attributes */ - Hash *localh; /* Hash of local variable names */ - String *code; /* Code string */ -} WrapObj; +Wrapper * +NewWrapper() { + Wrapper *w; + w = (Wrapper *) malloc(sizeof(Wrapper)); + w->localh = NewHash(); + w->locals = NewString(""); + w->code = NewString(""); + w->def = NewString(""); + return w; +} /* ----------------------------------------------------------------------------- * DelWrapper() + * + * Delete a wrapper function object. * ----------------------------------------------------------------------------- */ -static void -DelWrapper(DOH *wo) { - WrapObj *w = (WrapObj *) ObjData(wo); +void +DelWrapper(Wrapper *w) { Delete(w->localh); + Delete(w->locals); Delete(w->code); - Delete(w->attr); - DohFree(w); + Delete(w->def); + free(w); } /* ----------------------------------------------------------------------------- @@ -108,6 +119,35 @@ Wrapper_pretty_print(String *str, File *f) { Printf(f,"%s",ts); Clear(ts); empty = 1; + } else if (c == '/') { + 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); @@ -122,39 +162,20 @@ Wrapper_pretty_print(String *str, File *f) { /* ----------------------------------------------------------------------------- - * Wrapper_str() + * Wrapper_print() * - * Create a string representation of the wrapper function. - * ----------------------------------------------------------------------------- */ - -static String * -Wrapper_str(DOH *wo) { - String *s, *s1; - WrapObj *w = (WrapObj *) ObjData(wo); - s = NewString(w->code); - s1 = NewString(""); - - /* Replace the first '{' with a brace followed by local variable definitions */ - Replace(s,"{", Getattr(w->attr,"locals"), DOH_REPLACE_FIRST); - Wrapper_pretty_print(s,s1); - Delete(s); - return s1; -} - -/* ----------------------------------------------------------------------------- - * Wrapper_dump() - * - * Serialize on out + * Print out a wrapper function. Does pretty printing as well. * ----------------------------------------------------------------------------- */ -static int -Wrapper_dump(DOH *wo, DOH *out) { - String *s; - int len; - s = Wrapper_str(wo); - len = Dump(s,out); - Delete(s); - return len; +void +Wrapper_print(Wrapper *w, File *f) { + String *str; + + str = NewString(""); + Printf(str,"%s\n", w->def); + Printf(str,"%s\n", w->locals); + Printf(str,"%s\n", w->code); + Wrapper_pretty_print(str,f); } /* ----------------------------------------------------------------------------- @@ -165,14 +186,13 @@ Wrapper_dump(DOH *wo, DOH *out) { * ----------------------------------------------------------------------------- */ int -Wrapper_add_local(Wrapper *wo, const String_or_char *name, const String_or_char *decl) { - WrapObj *w = (WrapObj *) ObjData(wo); +Wrapper_add_local(Wrapper *w, const String_or_char *name, const String_or_char *decl) { /* See if the local has already been declared */ if (Getattr(w->localh,name)) { return -1; } Setattr(w->localh,name,decl); - Printf(Getattr(w->attr,"locals"),"%s;\n", decl); + Printf(w->locals,"%s;\n", decl); return 0; } @@ -185,24 +205,23 @@ Wrapper_add_local(Wrapper *wo, const String_or_char *name, const String_or_char * ----------------------------------------------------------------------------- */ int -Wrapper_add_localv(Wrapper *wo, const String_or_char *name, ...) { +Wrapper_add_localv(Wrapper *w, const String_or_char *name, ...) { va_list ap; int ret; String *decl; DOH *obj; - WrapObj *w = (WrapObj *) ObjData(wo); decl = NewString(""); va_start(ap,name); obj = va_arg(ap,void *); while (obj) { - Printv(decl,obj,0); + Printv(decl,obj,NIL); Putc(' ', decl); obj = va_arg(ap, void *); } va_end(ap); - ret = Wrapper_add_local(wo,name,decl); + ret = Wrapper_add_local(w,name,decl); Delete(decl); return ret; } @@ -214,8 +233,7 @@ Wrapper_add_localv(Wrapper *wo, const String_or_char *name, ...) { * ----------------------------------------------------------------------------- */ int -Wrapper_check_local(Wrapper *wo, const String_or_char *name) { - WrapObj *w = (WrapObj *) ObjData(wo); +Wrapper_check_local(Wrapper *w, const String_or_char *name) { if (Getattr(w->localh,name)) { return 1; } @@ -230,22 +248,22 @@ Wrapper_check_local(Wrapper *wo, const String_or_char *name) { * ----------------------------------------------------------------------------- */ char * -Wrapper_new_local(Wrapper *wo, const String_or_char *name, const String_or_char *decl) { +Wrapper_new_local(Wrapper *w, const String_or_char *name, const String_or_char *decl) { int i; - char *ret; String *nname = NewString(name); String *ndecl = NewString(decl); - WrapObj *w = (WrapObj *) ObjData(wo); + char *ret; + i = 0; - while (Wrapper_check_local(wo,nname)) { + 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(Getattr(w->attr,"locals"),"%s;\n", ndecl); + Printf(w->locals,"%s;\n", ndecl); ret = Char(nname); Delete(nname); Delete(ndecl); @@ -262,205 +280,29 @@ Wrapper_new_local(Wrapper *wo, const String_or_char *name, const String_or_char * ----------------------------------------------------------------------------- */ char * -Wrapper_new_localv(Wrapper *wo, const String_or_char *name, ...) { +Wrapper_new_localv(Wrapper *w, const String_or_char *name, ...) { va_list ap; char *ret; String *decl; DOH *obj; - WrapObj *w = (WrapObj *) ObjData(wo); decl = NewString(""); va_start(ap,name); obj = va_arg(ap,void *); while (obj) { - Printv(decl,obj,0); + Printv(decl,obj,NIL); Putc(' ',decl); obj = va_arg(ap, void *); } va_end(ap); - ret = Wrapper_new_local(wo,name,decl); + ret = Wrapper_new_local(w,name,decl); Delete(decl); return ret; } -/* ----------------------------------------------------------------------------- - * Wrapper_Getattr() - * ----------------------------------------------------------------------------- */ -static DOH * -Wrapper_getattr(Wrapper *wo, DOH *k) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Getattr(w->attr,k); -} -/* ----------------------------------------------------------------------------- - * Wrapper_Delattr() - * ----------------------------------------------------------------------------- */ - -static int -Wrapper_delattr(Wrapper *wo, DOH *k) { - WrapObj *w = (WrapObj *) ObjData(wo); - Delattr(w->attr,k); - return 0; -} - -/* ----------------------------------------------------------------------------- - * Wrapper_Setattr() - * ----------------------------------------------------------------------------- */ - -static int -Wrapper_setattr(Wrapper *wo, DOH *k, DOH *obj) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Setattr(w->attr,k,obj); -} - -/* ----------------------------------------------------------------------------- - * Wrapper_firstkey() - * ----------------------------------------------------------------------------- */ - -static DOH * -Wrapper_firstkey(Wrapper *wo) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Firstkey(w->attr); -} - -/* ----------------------------------------------------------------------------- - * Wrapper_firstkey() - * ----------------------------------------------------------------------------- */ - -static DOH * -Wrapper_nextkey(Wrapper *wo) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Nextkey(w->attr); -} - -/* File methods. These simply operate on the code string */ - -static int -Wrapper_read(Wrapper *wo, void *buffer, int nbytes) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Read(w->code,buffer,nbytes); -} - -static int -Wrapper_write(Wrapper *wo, void *buffer, int nbytes) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Write(w->code,buffer,nbytes); -} - -static int -Wrapper_putc(Wrapper *wo, int ch) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Putc(ch, w->code); -} - -static int -Wrapper_getc(Wrapper *wo) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Getc(w->code); -} - -static int -Wrapper_ungetc(Wrapper *wo, int ch) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Ungetc(ch, w->code); -} - -static int -Wrapper_seek(Wrapper *wo, long offset, int whence) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Seek(w->code, offset, whence); -} - -static long -Wrapper_tell(Wrapper *wo) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Tell(w->code); -} - -/* String method */ - -static int Wrapper_replace(DOH *wo, DOH *tok, DOH *rep, int flags) { - WrapObj *w = (WrapObj *) ObjData(wo); - return Replace(w->code, tok, rep, flags); -} - -/* ----------------------------------------------------------------------------- - * type information - * ----------------------------------------------------------------------------- */ - -static DohHashMethods WrapperHashMethods = { - Wrapper_getattr, - Wrapper_setattr, - Wrapper_delattr, - Wrapper_firstkey, - Wrapper_nextkey, -}; - -static DohFileMethods WrapperFileMethods = { - Wrapper_read, - Wrapper_write, - Wrapper_putc, - Wrapper_getc, - Wrapper_ungetc, - Wrapper_seek, - Wrapper_tell, - 0, /* close */ -}; - -static DohStringMethods WrapperStringMethods = { - Wrapper_replace, - 0, -}; - -static DohObjInfo WrapperType = { - "Wrapper", /* objname */ - DelWrapper, /* doh_del */ - 0, /* doh_copy */ - 0, /* doh_clear */ - Wrapper_str, /* doh_str */ - 0, /* doh_data */ - 0, /* doh_dump */ - 0, /* doh_len */ - 0, /* doh_hash */ - 0, /* doh_cmp */ - 0, /* doh_setfile */ - 0, /* doh_getfile */ - 0, /* doh_setline */ - 0, /* doh_getline */ - &WrapperHashMethods, /* doh_mapping */ - 0, /* doh_sequence */ - &WrapperFileMethods, /* doh_file */ - &WrapperStringMethods, /* doh_string */ - 0, /* doh_positional */ - 0, -}; - -/* ----------------------------------------------------------------------------- - * NewWrapper() - * - * Create a new wrapper function object. - * ----------------------------------------------------------------------------- */ - -#define DOHTYPE_WRAPPER 0xa - -Wrapper * -NewWrapper() { - WrapObj *w; - static int init = 0; - if (!init) { - DohRegisterType(DOHTYPE_WRAPPER, &WrapperType); - init = 1; - } - w = (WrapObj *) DohMalloc(sizeof(WrapObj)); - w->localh = NewHash(); - w->code = NewString(""); - w->attr= NewHash(); - Setattr(w->attr,"locals","{\n"); - Setattr(w->attr,"wrapcode", w->code); - return DohObjMalloc(DOHTYPE_WRAPPER, w); -} |