]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wxSWIG/SWIG/scanner.cxx
Since I have made several changes to SWIG over the years to accomodate
[wxWidgets.git] / wxPython / wxSWIG / SWIG / scanner.cxx
diff --git a/wxPython/wxSWIG/SWIG/scanner.cxx b/wxPython/wxSWIG/SWIG/scanner.cxx
new file mode 100644 (file)
index 0000000..8f88562
--- /dev/null
@@ -0,0 +1,1381 @@
+/*******************************************************************************
+ * 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$
+ * scanner.c
+ *
+ * Dave Beazley
+ * January 1996
+ *
+ * Input scanner.   This scanner finds and returns tokens
+ * for the wrapper generator.   Since using lex/flex from
+ * C++ is so F'ed up, I've written this function to replace
+ * them entirely.     It's not as fast, but hopefully it will
+ * eliminate alot of compilation problems.
+ *
+ *************************************************************************/
+
+
+#include "internal.h"
+#include "parser.h"
+#include <string.h>
+#include <ctype.h>
+
+#define  YYBSIZE  8192
+
+struct InFile {
+  FILE   *f;
+  int    line_number;
+  char  *in_file;
+  int    extern_mode;  
+  int    force_extern;
+  struct InFile *prev;
+};
+
+// This structure is used for managing code fragments as
+// might be used by the %inline directive and handling of
+// nested structures.
+
+struct CodeFragment {
+  char          *text;
+  int            line_number;
+  CodeFragment  *next;
+};
+
+InFile  *in_head;
+
+FILE    *LEX_in = NULL;
+
+static String         header;
+static String         comment;
+       String         CCode;              // String containing C code
+static char           *yybuffer;
+static int            lex_pos = 0;
+static int            lex_len = 0;         
+static char           *inline_yybuffer = 0;
+static int            inline_lex_pos = 0;
+static int            inline_lex_len = 0;
+static int            inline_line_number = 0;
+static CodeFragment  *fragments = 0;      // Code fragments
+
+static 
+char           yytext[YYBSIZE];
+static int     yylen = 0;
+int            line_number = 1;
+int            column = 1;
+int            column_start = 1;
+char          *input_file;
+int            start_line = 0;
+static  int    comment_start;
+static  int    scan_init  = 0;
+static  int    num_brace = 0;
+static  int    last_brace = 0;
+static  int    in_define = 0;
+static  int    define_first_id = 0;   /* Set when looking for first identifier of a define */
+extern  int    Error;
+
+
+/**************************************************************
+ * scanner_init()
+ *
+ * Initialize buffers
+ **************************************************************/
+
+void scanner_init() {
+
+  yybuffer = (char *) malloc(YYBSIZE);
+  scan_init = 1;
+}
+
+/**************************************************************
+ * scanner_file(FILE *f)
+ *
+ * Start reading from new file 
+ **************************************************************/
+void scanner_file(FILE *f) {
+  InFile *in;
+
+  in = new InFile;
+  in->f = f;
+  in->in_file = input_file;
+  in->extern_mode = WrapExtern;        
+  in->force_extern = ForceExtern;
+  if (in_head) in_head->line_number = line_number+1;
+  if (!in_head) in->prev = 0;
+  else in->prev = in_head;
+  in_head = in;
+  LEX_in = f;
+  line_number = 1;
+}
+
+/**************************************************************
+ * scanner_close()
+ *
+ * Close current input file and go to next 
+ **************************************************************/
+
+void scanner_close() {
+
+  InFile *p;
+  static int lib_insert = 0;
+  fclose(LEX_in);
+  if (!in_head) return;
+  p = in_head->prev;
+  if (p != 0) {
+    LEX_in = p->f;
+    line_number = p->line_number;
+    input_file = p->in_file;
+    WrapExtern = p->extern_mode;
+    if (!WrapExtern) remove_symbol("SWIGEXTERN");
+    ForceExtern = p->force_extern;
+  } else {
+    LEX_in = NULL;
+  }
+  delete in_head;
+  in_head = p;
+
+  // if LEX_in is NULL it means we're done with the interface file. We're now
+  // going to grab all of the library files.
+
+  if ((!LEX_in) && (!lib_insert)) {
+    library_insert();
+    lib_insert = 1;
+  }
+
+}
+
+/**************************************************************
+ * char nextchar()
+ *
+ * gets next character from input.
+ * If we're in inlining mode, we actually retrieve a character
+ * from inline_yybuffer instead.
+ **************************************************************/
+
+char nextchar() {
+
+    char c = 0;
+
+    if (Inline) {
+      if (inline_lex_pos >= inline_lex_len) {
+       // Done with inlined code.  Check to see if we have any
+       // new code fragments.  If so, switch to them.
+       delete inline_yybuffer;
+       if (fragments) {
+         CodeFragment *f;
+         inline_yybuffer = fragments->text;
+         inline_lex_pos = 1;
+         inline_lex_len = strlen(fragments->text);
+         line_number = fragments->line_number;
+         f = fragments->next;
+         delete fragments;
+         fragments = f;
+         c = inline_yybuffer[0];
+       } else {
+         c = 0;
+         Inline = 0;
+         line_number = inline_line_number;       // Restore old line number
+       }
+      } else {
+       inline_lex_pos++;
+       c = inline_yybuffer[inline_lex_pos-1];
+      }
+    }
+    if (!Inline) {
+      if (lex_pos >= lex_len) {
+       if (!LEX_in) {
+         SWIG_exit(1);
+       }
+       while(fgets(yybuffer, YYBSIZE, LEX_in) == NULL) {
+         scanner_close();        // Close current input file
+         if (!LEX_in) return 0;  // No more, we're outta here
+       }
+       lex_len = strlen(yybuffer);
+       lex_pos = 0;
+      }
+      
+      lex_pos++;
+      c = yybuffer[lex_pos-1];
+    }
+      
+    if (yylen >= YYBSIZE) {
+      fprintf(stderr,"** FATAL ERROR.  Buffer overflow in scanner.cxx.\nReport this to swig@cs.utah.edu.\n");
+      SWIG_exit(1);
+    }
+    yytext[yylen] = c;
+    yylen++;
+    if (c == '\n') {
+      line_number++;
+      column = 1;
+    } else {
+      column++;
+    }
+    return(c);
+}
+
+void retract(int n) {
+  int i, j, c;
+  
+  for (i = 0; i < n; i++) {
+    if (Inline) {
+      inline_lex_pos--;
+      if (inline_lex_pos < 0) {
+       fprintf(stderr,"Internal scanner error. inline_lex_pos < 0\n");
+       SWIG_exit(1);
+      }
+    }
+    else lex_pos--;
+    yylen--;
+    column--;
+    if (yylen >= 0) {
+      if (yytext[yylen] == '\n') {
+       line_number--;
+       // Figure out what column we're in
+       c = yylen-1;
+       j = 1;
+       while (c >= 0){
+         if (yytext[c] == '\n') break;
+         j++;
+         c--;
+       }
+       column = j;
+      }
+    }
+  }
+  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) {
+
+  if (Inline) {
+
+    // Already processing a code fragment, simply hang on
+    // to this one for later.
+
+    CodeFragment *f,*f1;
+
+    // Add a new code fragment to our list
+    f = new CodeFragment;
+    f->text = copy_string(text);
+    f->line_number = line;
+    f->next = 0;
+    if (!fragments) fragments = f;
+    else {
+      f1 = fragments;
+      while (f1->next) f1 = f1->next;
+      f1->next = f;
+    }
+  } else {
+
+    // Switch our scanner over to process text from a string.
+    // Save current line number and other information however.
+
+    inline_yybuffer = copy_string(text);
+    inline_lex_len = strlen(text);
+    inline_lex_pos = 0;
+    inline_line_number = line_number;       // Make copy of old line number
+    line_number = line;
+    Inline = 1;
+  }
+}
+
+/**************************************************************
+ * yycomment(char *, int line)
+ *
+ * Inserts a comment into a documentation entry.    
+ **************************************************************/
+
+void yycomment(char *s, int line, int col) {
+  comment_handler->add_comment(s,line,col,input_file);
+}
+
+/**************************************************************
+ * void skip_brace(void)
+ *
+ * Found a {.
+ * Skip all characters until we find a matching closed }.
+ *
+ * This function is used to skip over inlined C code and other
+ * garbage found in interface files.
+ ***************************************************************/
+
+void skip_brace(void) {
+
+  char c;
+  CCode = "{";
+  while (num_brace > last_brace) {
+    if ((c = nextchar()) == 0) {
+      fprintf(stderr,"%s : Line %d.  Missing '}'. Reached end of input.\n",
+             input_file, line_number);
+      FatalError();
+      return;
+    }
+    CCode << c;
+    if (c == '{') num_brace++;
+    if (c == '}') num_brace--;
+    yylen = 0;
+  }
+}
+
+
+/**************************************************************
+ * void skip_template(void)
+ *
+ * Found a <.
+ * Skip all characters until we find a matching closed >.
+ *
+ * This function is used to skip over C++ templated types
+ * and objective-C protocols.
+ ***************************************************************/
+
+void skip_template(void) {
+
+  char c;
+  CCode = "<";
+  int  num_lt = 1;
+  while (num_lt > 0) {
+    if ((c = nextchar()) == 0) {
+      fprintf(stderr,"%s : Line %d.  Missing '>'. Reached end of input.\n",
+             input_file, line_number);
+      FatalError();
+      return;
+    }
+    CCode << c;
+    if (c == '<') num_lt++;
+    if (c == '>') num_lt--;
+    yylen = 0;
+  }
+}
+
+/**************************************************************
+ * void skip_to_end(void)
+ *
+ * Skips to the @end directive in a Objective-C definition
+ **************************************************************/
+
+void skip_to_end(void) {
+  char c;
+  int  state = 0;
+  yylen = 0;
+  while ((c = nextchar())){
+    switch(state) {
+    case 0:
+      if (c == '@') state = 1;
+      else yylen = 0;
+      break;
+    case 1:
+      if (isspace(c)) {
+       if (strncmp(yytext,"@end",4) == 0) return; 
+       else {
+         yylen = 0;
+         state = 0;
+       }
+      } else {
+       state = 1;
+      }
+      break;
+    }
+  }
+  fprintf(stderr,"%s : EOF. Missing @end. Reached end of input.\n",
+         input_file);
+  FatalError();
+  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) {
+      fprintf(stderr,"%s : Line %d.  Missing semicolon. Reached end of input.\n",
+             input_file, line_number);
+      FatalError();
+      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) {
+       fprintf(stderr,"%s : Line %d.  Missing '}'. Reached end of input.\n",
+               input_file, line_number);
+       FatalError();
+       return;
+      }
+      if (c == '{') num_brace++;
+      if (c == '}') num_brace--;
+      yylen = 0;
+    }
+  }
+}
+
+/**************************************************************
+ * void skip_define(void)
+ *
+ * Skips to the end of a #define statement.
+ *
+ **************************************************************/
+
+void skip_define(void) {
+  char c;
+  while (in_define) {
+    if ((c = nextchar()) == 0) return;
+    if (c == '\\') in_define = 2;
+    if (c == '\n') {
+      if (in_define == 2) {
+       in_define = 1;
+      } else if (in_define == 1) {
+       in_define = 0;
+      }
+    }
+    yylen = 0;
+  }
+}
+
+/**************************************************************
+ * int skip_cond(int inthen)
+ *
+ * Skips the false portion of an #ifdef directive.   Looks
+ * for either a matching #else or #endif 
+ *
+ * inthen is 0 or 1 depending on whether or not we're
+ * handling the "then" or "else" part of a conditional.
+ *
+ * Returns 1 if the else part of the #if-#endif block was
+ * reached.  Returns 0 otherwise.  Returns -1 on error.
+ **************************************************************/
+
+int skip_cond(int inthen) {
+  int    level = 0;         /* Used to handled nested if-then-else */
+  int    state = 0;
+  char   c;
+  int    start_line;
+  char  *file;
+  
+  file = copy_string(input_file);
+  start_line = line_number;
+  yylen = 0;
+
+  while(1) {
+    switch(state) {
+    case 0 :
+      if ((c = nextchar()) == 0) {
+       fprintf(stderr,"%s : Line %d.  Unterminated #if-else directive.\n", file, start_line);
+       FatalError();
+       return -1;     /* Error */
+      }
+      if ((c == '#') || (c == '%')) {
+       state = 1;
+      } else if (isspace(c)) {
+       yylen =0;
+       state = 0;
+      } else {
+       /* Some non-whitespace character. Look for line end */
+       yylen = 0;
+       state = 3;
+      }
+      break;
+    case 1:
+      /* Beginning of a C preprocessor statement */
+      if ((c = nextchar()) == 0) {
+       fprintf(stderr,"%s : Line %d.  Unterminated #if-else directive.\n", file, start_line);
+       FatalError();
+       return -1;     /* Error */
+      }
+      if (c == '\n') {
+       state = 0;
+       yylen = 0;
+      }
+      else if (isspace(c)) {
+       state = 1;
+       yylen--;
+      } else {
+       state = 2;
+      }
+      break;
+    case 2:
+      /* CPP directive */
+      if ((c = nextchar()) == 0)  {
+       fprintf(stderr,"%s : Line %d.  Unterminated #if-else directive.\n", file, start_line);
+       FatalError();
+       return -1;     /* Error */
+      }
+      if ((c == ' ') || (c == '\t') || (c=='\n')) {
+       yytext[yylen-1] = 0;
+       if ((strcmp(yytext,"#ifdef") == 0) || (strcmp(yytext,"%ifdef") == 0)) {
+         level++;
+         state = 0;
+       } else if ((strcmp(yytext,"#ifndef") == 0) || (strcmp(yytext,"%ifndef") == 0)) {
+         level++;
+         state = 0;
+       } else if ((strcmp(yytext,"#if") == 0) || (strcmp(yytext,"%if") == 0)) {
+         level++;
+         state = 0;
+       } else if ((strcmp(yytext,"#else") == 0) || (strcmp(yytext,"%else") == 0)) {
+         if (level == 0) {    /* Found matching else.  exit */
+           if (!inthen) {
+             /* Hmmm.  We've got an "extra #else" directive here */
+             fprintf(stderr,"%s : Line %d.  Misplaced #else.\n", input_file, line_number);
+             FatalError();
+             yylen = 0;
+             state = 0;
+           } else {
+             yylen = 0;
+             delete file;
+             return 1;
+           }
+         } else {
+           yylen = 0;
+           state = 0;
+         }
+       } else if ((strcmp(yytext,"#endif") == 0) || (strcmp(yytext,"%endif") == 0)) {
+         if (level <= 0) {    /* Found matching endif. exit */
+           yylen = 0;
+           delete file;
+           return 0;
+         } else {
+           state = 0;
+           yylen = 0;
+           level--;
+         }
+       } else if ((strcmp(yytext,"#elif") == 0) || (strcmp(yytext,"%elif") == 0)) {
+         if (level <= 0) {
+           // If we come across this, we pop it back onto the input queue and return
+           retract(6);
+           delete file;
+           return 0;
+         } else {
+           yylen = 0;
+           state = 0;
+         }
+       } else {
+         yylen = 0;
+         state = 0;
+       }
+      }
+      break;
+    case 3:
+      /* Non-white space.  Look for line break */
+      if ((c = nextchar()) == 0) {
+       fprintf(stderr,"%s : Line %d.  Unterminated #if directive.\n", file, start_line);
+       FatalError();
+       return -1;     /* Error */
+      }
+      if (c == '\n') {
+       yylen = 0;
+       state = 0;
+      } else {
+       yylen = 0;
+       state = 3;
+      }
+      break;
+    }
+  }
+}
+      
+/**************************************************************
+ * 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;
+           if (in_define == 1) {
+             in_define = 0;
+             return(ENDDEF);
+           } else if (in_define == 2) {
+             in_define = 1;
+           }
+         } else if (isspace(c)) {
+           state = 0;
+           yylen = 0;
+         }
+             
+         /* 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) {
+             fprintf(stderr,"%s : Line %d. Error. Extraneous '}' (Ignored)\n",
+                     input_file, line_number);
+             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 == '&') return (AND);
+         else if (c == '|') return (OR);
+         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 == '\\') {
+           if (in_define == 1) {
+             in_define = 2;
+             state = 0;
+           } else 
+             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 (isdigit(c)) state = 8;  // A numerical value
+         else if ((isalpha(c)) || (c == '_') || (c == '$')) state = 7;
+         else state = 99;
+         break;
+       case 1:  /*  Comment block */
+         if ((c = nextchar()) == 0) return(0);
+         if (c == '/') {
+           comment_start = line_number;
+           column_start = column;
+           comment = "  ";
+           state = 10;        // C++ style comment
+         } else if (c == '*') {
+           comment_start = line_number;
+           column_start = column;
+           comment = "  ";
+           state = 11;   // C style comment
+         } else {
+           retract(1);
+           return(SLASH);
+         }
+         break;
+       case 10:  /* C++ style comment */
+         if ((c = nextchar()) == 0) {
+           fprintf(stderr,"%s : EOF. Unterminated comment detected.\n",input_file);
+           FatalError();
+           return 0;
+         }
+         if (c == '\n') {
+           comment << c;
+           // Add the comment to documentation
+           yycomment(comment.get(),comment_start, column_start);
+           yylen = 0;
+           state = 0;
+           if (in_define == 1) {
+             in_define = 0;
+             return(ENDDEF);
+           }
+         } else {
+           state = 10;
+           comment << c;
+           yylen = 0;
+         }
+         break;
+       case 11: /* C style comment block */
+         if ((c = nextchar()) == 0) {
+           fprintf(stderr,"%s : EOF. Unterminated comment detected.\n", input_file);
+           FatalError();
+           return 0;
+         }
+         if (c == '*') {
+           state = 12;
+         } else {
+           comment << c;
+           yylen = 0;
+           state = 11;
+         }
+         break;
+       case 12: /* Still in C style comment */
+         if ((c = nextchar()) == 0) {
+           fprintf(stderr,"%s : EOF. Unterminated comment detected.\n", input_file);
+           FatalError();
+           return 0;
+         }
+         if (c == '*') {
+           comment << c;
+           state = 12;
+         } else if (c == '/') {
+           comment << "  \n";
+           yycomment(comment.get(),comment_start,column_start);
+           yylen = 0;
+           state = 0;
+         } else {
+           comment << '*' << c;
+           yylen = 0;
+           state = 11;
+         }
+         break;
+
+       case 2: /* Processing a string */
+         if ((c = nextchar()) == 0) {
+           fprintf(stderr,"%s : EOF. Unterminated string detected.\n", input_file);
+           FatalError();
+           return 0;
+         }
+         if (c == '\"') {
+           yytext[yylen-1] = 0;
+           yylval.id = copy_string(yytext+1);
+           return(STRING);
+         } else if (c == '\\') {
+           state = 21;             /* Possibly an escape sequence. */
+           break;
+         } else state = 2;
+         break;
+       case 21: /* An escape sequence. get next character, then go
+                   back to processing strings */
+
+         if ((c = nextchar()) == 0) return 0;
+         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);
+         } else if ((c == ' ') || (c == '\t')) {  // Ignore white space after # symbol
+           yytext[yylen] = 0;
+           yylen--;
+           state = 3;
+         } else {
+           yytext[yylen] = 0;
+           state = 31;
+         }
+         break;
+       case 31:
+         if ((c = nextchar()) == 0) return 0;
+         if ((c == ' ') || (c == '\t') || (c=='\n')) {
+           retract(1);
+           yytext[yylen] = 0;
+           if (strcmp(yytext,"#define") == 0) {
+             in_define = 1;
+             define_first_id = 1;
+             return(DEFINE);
+           } else if (strcmp(yytext,"#ifdef") == 0) {
+             return(IFDEF);
+           } else if (strcmp(yytext,"#ifndef") == 0) {
+             return(IFNDEF);
+           } else if (strcmp(yytext,"#else") == 0) {
+             return(ELSE);
+           } else if (strcmp(yytext,"#endif") == 0) {
+             return(ENDIF);
+           } else if (strcmp(yytext,"#undef") == 0) {
+             return(UNDEF);
+           } else if (strcmp(yytext,"#if") == 0) {
+             return(IF);
+           } else if (strcmp(yytext,"#elif") == 0) {
+             return(ELIF);
+           } else {
+             /* Some kind of "unknown CPP directive.  Skip to end of the line */
+             state = 32;
+           }
+         }
+         break;
+       case 32:
+         if ((c = nextchar()) == 0) return 0;
+         if (c == '\n') {
+           retract(1);
+           yytext[yylen] = 0;
+           yylval.id = yytext;
+           return(POUND);
+         }
+         state = 32;
+         break;
+
+       case 4: /* A wrapper generator directive (maybe) */
+         if (( c= nextchar()) == 0) return 0;
+         if (c == '{') {
+           state = 40;   /* Include block */
+           header = "";
+           start_line = line_number;
+         }
+         else if ((isalpha(c)) || (c == '_')) state = 7;
+         else {
+           retract(1);
+           state = 99;
+         }
+         break;
+         
+       case 40: /* Process an include block */
+         if ((c = nextchar()) == 0) {
+           fprintf(stderr,"%s : EOF. Unterminated include block detected.\n", input_file);
+           FatalError();
+           return 0;
+         }
+         yylen = 0;
+         if (c == '%') state = 41;
+         else {
+           header << c;
+           yylen = 0;
+           state = 40;
+         }
+         break;
+       case 41: /* Still processing include block */
+         if ((c = nextchar()) == 0) {
+           fprintf(stderr,"%s : EOF. Unterminated include block detected.\n", input_file);
+           FatalError();
+           return 0;
+         }
+         if (c == '}') {
+           yylval.id = header.get();
+           return(HBLOCK);
+         } else {
+           header << '%';
+           header << c;
+           yylen = 0;
+           state = 40;
+         }
+         break;
+
+       case 5: /* Maybe a double colon */
+
+         if (( c= nextchar()) == 0) return 0;
+         if ( c == ':') return DCOLON;
+         else {
+           retract(1);
+           return COLON;
+         }
+
+
+       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 == '$'))
+           //              || (c == '.') || (c == '-'))
+           state = 7;
+         else if (c == '(') {
+           /* We might just be in a CPP macro definition.  Better check */
+           if ((in_define) && (define_first_id)) {
+             /* Yep.  We're going to ignore the rest of it */
+             skip_define();
+             define_first_id = 0;
+             return (MACRO);
+           } else {
+             retract(1);
+             define_first_id = 0;
+             return(ID);
+           }
+         } else {
+           retract(1);
+           define_first_id = 0;
+           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')) {
+             yytext[yylen] = 0;
+            yylval.id = copy_string(yytext);
+            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);
+             yytext[yylen] = 0;
+             yylval.id = copy_string(yytext);
+             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')) {
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_FLOAT);
+         } else {
+           retract(1);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           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;
+           yylval.id = copy_string(yytext);
+           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);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           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);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           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);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           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')) {
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_FLOAT);
+         } else {
+           retract(1);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_FLOAT);
+         }
+         /* Parse a character constant. ie. 'a' */
+         break;
+
+       case 87 :
+         /* A long integer of some sort */
+         if ((c = nextchar()) == 0) return (0);
+         if ((c == 'u') || (c == 'U')) {
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_ULONG);
+         } else {
+           retract(1);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_LONG);
+         } 
+
+       case 88:
+         /* An unsigned integer of some sort */
+         if ((c = nextchar()) == 0) return (0);
+         if ((c == 'l') || (c == 'L')) {
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_ULONG);
+         } else {
+           retract(1);
+           yytext[yylen] = 0;
+           yylval.id = copy_string(yytext);
+           return(NUM_UNSIGNED);
+         } 
+
+       case 9:
+         if ((c = nextchar()) == 0) return (0);
+         if (c == '\'') {
+           yytext[yylen-1] = 0;
+           yylval.id = copy_string(yytext+1);
+           return(CHARCONST);
+         }
+         break;
+
+       case 100:
+         if ((c = nextchar()) == 0) return (0);
+         if (isdigit(c)) state = 81;
+         else {
+           retract(1);
+           return(PERIOD);
+         }
+         break;
+       default:
+         if (!Error) {
+           fprintf(stderr,"%s : Line %d ::Illegal character '%c'=%d.\n",input_file, line_number,c,c);
+           FatalError();
+         }
+         state = 0;    
+         Error = 1;    
+         return(ILLEGAL);
+       }
+    }
+}
+
+static int check_typedef = 0;
+
+void scanner_check_typedef() {
+  check_typedef = 1;
+}
+
+void scanner_ignore_typedef() {
+  check_typedef = 0;
+}
+
+
+/**************************************************************
+ * int yylex()
+ *
+ * Gets the lexene and returns tokens.
+ *************************************************************/
+
+extern "C" int yylex(void) {
+    
+    int   l;
+
+    if (!scan_init) {
+      scanner_init();
+      //      if (LEX_in == NULL) LEX_in = stdin;
+      //      scanner_file(LEX_in);
+    }
+    
+    l = yylook();
+
+    /* We got some sort of non-white space object.  We set the start_line 
+       variable unless it has already been set */
+
+    if (!start_line) {
+      start_line = line_number;
+    }
+
+    /* Copy the lexene */
+
+    yytext[yylen] = 0;
+
+    /* Hack to support ignoring of CPP macros */
+
+    if (l != DEFINE) {
+      define_first_id = 0;
+    }
+
+    switch(l) {
+
+      case ID:
+
+       /* Look for keywords now */
+
+       if (strcmp(yytext,"int") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_INT;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_INT);
+       }
+       if (strcmp(yytext,"double") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_DOUBLE;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_DOUBLE);
+       }
+       if (strcmp(yytext,"void") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_VOID;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_VOID);
+       }
+       if (strcmp(yytext,"char") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_CHAR;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_CHAR);
+       }
+       if (strcmp(yytext,"short") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_SHORT;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_SHORT);
+       }
+       if (strcmp(yytext,"long") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_LONG;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_LONG);
+       }
+       if (strcmp(yytext,"float") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_FLOAT;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_FLOAT);
+       }
+       if (strcmp(yytext,"signed") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_SINT;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_SIGNED);
+       }
+       if (strcmp(yytext,"unsigned") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_UINT;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_UNSIGNED);
+       }
+       if (strcmp(yytext,"bool") == 0) {
+         yylval.type = new DataType;
+         yylval.type->type = T_BOOL;
+         strcpy(yylval.type->name,yytext);
+         return(TYPE_BOOL);
+       }
+       // C++ keywords
+       
+       if (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) return(OPERATOR);
+         if (strcmp(yytext,"throw") == 0) return(THROW);
+         if (strcmp(yytext,"inline") == 0) return(yylex());
+         if (strcmp(yytext,"template") == 0) return(TEMPLATE);
+       }
+
+       // Objective-C keywords
+        if (ObjC) {
+         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);
+       }
+
+       // Misc keywords
+
+       if (strcmp(yytext,"static") == 0) return(STATIC);
+       if (strcmp(yytext,"extern") == 0) return(EXTERN);
+       if (strcmp(yytext,"const") == 0) return(CONST);
+       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,"defined") == 0) return(DEFINED);
+
+       // Ignored keywords 
+
+       if (strcmp(yytext,"volatile") == 0) return(yylex());
+
+       // SWIG directives
+
+       if (strcmp(yytext,"%module") == 0) return(MODULE);
+       if (strcmp(yytext,"%init") == 0)  return(INIT);
+       if (strcmp(yytext,"%wrapper") == 0) return(WRAPPER);
+       if (strcmp(yytext,"%readonly") == 0) return(READONLY);
+       if (strcmp(yytext,"%readwrite") == 0) return(READWRITE);
+       if (strcmp(yytext,"%name") == 0) return(NAME);
+        if (strcmp(yytext,"%rename") == 0) return(RENAME);
+       if (strcmp(yytext,"%include") == 0) return(INCLUDE);
+       if (strcmp(yytext,"%extern") == 0) return(WEXTERN);
+        if (strcmp(yytext,"%checkout") == 0) return(CHECKOUT);
+       if (strcmp(yytext,"%val") == 0) return(CVALUE);
+       if (strcmp(yytext,"%out") == 0) return(COUT);
+
+       if (strcmp(yytext,"%section") == 0) {
+         yylval.ivalue = line_number;
+         return(SECTION);
+       }
+       if (strcmp(yytext,"%subsection") == 0) {
+         yylval.ivalue = line_number;
+         return(SUBSECTION);
+       }
+       if (strcmp(yytext,"%subsubsection") == 0) {
+         yylval.ivalue = line_number;
+         return (SUBSUBSECTION);
+       }
+       if (strcmp(yytext,"%title") == 0) {
+         yylval.ivalue = line_number;
+         return(TITLE);
+       } 
+       if (strcmp(yytext,"%style") == 0) return(STYLE);
+       if (strcmp(yytext,"%localstyle") == 0) return(LOCALSTYLE);
+       if (strcmp(yytext,"%typedef") == 0) {
+         yylval.ivalue = 1;
+         return(TYPEDEF);
+       }
+       if (strcmp(yytext,"typedef") == 0) {
+         yylval.ivalue = 0;
+         return(TYPEDEF);
+       }
+       if (strcmp(yytext,"%alpha") == 0) return(ALPHA_MODE);
+       if (strcmp(yytext,"%raw") == 0) return(RAW_MODE);
+       if (strcmp(yytext,"%text") == 0) return(TEXT);
+       if (strcmp(yytext,"%native") == 0) return(NATIVE);
+       if (strcmp(yytext,"%disabledoc") == 0) return(DOC_DISABLE);
+       if (strcmp(yytext,"%enabledoc") == 0) return(DOC_ENABLE);
+       if (strcmp(yytext,"%ifdef") == 0) return(IFDEF);
+       if (strcmp(yytext,"%else") == 0) return(ELSE);
+       if (strcmp(yytext,"%ifndef") == 0) return(IFNDEF);
+       if (strcmp(yytext,"%endif") == 0) return(ENDIF);
+       if (strcmp(yytext,"%if") == 0) return(IF);
+       if (strcmp(yytext,"%elif") == 0) return(ELIF);
+       if (strcmp(yytext,"%pragma") == 0) return(PRAGMA);
+       if (strcmp(yytext,"%addmethods") == 0) return(ADDMETHODS);
+       if (strcmp(yytext,"%inline") == 0) return(INLINE);
+       if (strcmp(yytext,"%typemap") == 0) return(TYPEMAP);
+       if (strcmp(yytext,"%except") == 0) return(EXCEPT);
+       if (strcmp(yytext,"%import") == 0) return(IMPORT);
+       if (strcmp(yytext,"%echo") == 0) return(ECHO);
+        if (strcmp(yytext,"%new") == 0) return(NEW);
+       if (strcmp(yytext,"%apply") == 0) return(APPLY);
+       if (strcmp(yytext,"%clear") == 0) return(CLEAR);
+        if (strcmp(yytext,"%doconly") == 0) return(DOCONLY);
+       // Have an unknown identifier, as a last step, we'll
+       // do a typedef lookup on it.
+
+       if (check_typedef) {
+         if (DataType::is_typedef(yytext)) {
+           yylval.type = new DataType;
+           yylval.type->type = T_USER;
+           strcpy(yylval.type->name,yytext);
+           yylval.type->typedef_resolve();
+           return(TYPE_TYPEDEF);
+         }
+       }
+
+       yylval.id = copy_string(yytext);
+       return(ID);
+      default:
+       return(l);
+    }
+}
+
+// --------------------------------------------------------------
+// scanner_clear_start()
+//
+// Clears the start of a declaration
+// --------------------------------------------------------------
+
+void scanner_clear_start() {
+  start_line = 0;
+}