special cases and other things in wxPython, and since I plan on making several more, I've decided to put the SWIG sources in wxPython's CVS instead of relying on maintaining patches. This effectivly becomes a fork of an obsolete version of SWIG, :-( but since SWIG 1.3 still doesn't have some things I rely on in 1.1, not to mention that my custom patches would all have to be redone, I felt that this is the easier road to take. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15307 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			4158 lines
		
	
	
		
			116 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			4158 lines
		
	
	
		
			116 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
%{
 | 
						|
/*******************************************************************************
 | 
						|
 * 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$
 | 
						|
 *
 | 
						|
 * parser.y
 | 
						|
 *
 | 
						|
 * YACC parser for parsing function declarations.
 | 
						|
 *
 | 
						|
 * *** DISCLAIMER ***
 | 
						|
 *
 | 
						|
 * This is the most ugly, incredibly henious, and completely unintelligible
 | 
						|
 * file in SWIG.  While it started out simple, it has grown into a
 | 
						|
 * monster that is almost unmaintainable.   A complete parser rewrite is
 | 
						|
 * currently in progress that should make this file about 1/4 the size
 | 
						|
 * that it is now.   Needless to say, don't modify this file or even look
 | 
						|
 * at it for that matter!
 | 
						|
 ***********************************************************************/
 | 
						|
 | 
						|
#define yylex yylex
 | 
						|
 | 
						|
extern "C" int yylex();
 | 
						|
void   yyerror (char *s);       
 | 
						|
    
 | 
						|
extern int  line_number;
 | 
						|
extern int  start_line;
 | 
						|
extern void skip_brace(void);
 | 
						|
extern void skip_define(void);
 | 
						|
extern void skip_decl(void);
 | 
						|
extern int  skip_cond(int);
 | 
						|
extern void skip_to_end(void);
 | 
						|
extern void skip_template(void);
 | 
						|
extern void scanner_check_typedef(void);
 | 
						|
extern void scanner_ignore_typedef(void);
 | 
						|
extern void scanner_clear_start(void);
 | 
						|
extern void start_inline(char *, int);
 | 
						|
extern void format_string(char *);
 | 
						|
extern void swig_pragma(char *, char *);
 | 
						|
 | 
						|
#include "internal.h"
 | 
						|
 | 
						|
#ifdef NEED_ALLOC
 | 
						|
void *alloca(unsigned n) {
 | 
						|
  return((void *) malloc(n));
 | 
						|
}
 | 
						|
#else
 | 
						|
// This redefinition is apparently needed on a number of machines,
 | 
						|
// particularly HPUX
 | 
						|
#undef  alloca
 | 
						|
#define alloca  malloc
 | 
						|
#endif
 | 
						|
 | 
						|
// Initialization flags.   These indicate whether or not certain
 | 
						|
// features have been initialized.  These were added to allow
 | 
						|
// interface files without the block (required in previous
 | 
						|
// versions).
 | 
						|
 | 
						|
static int     module_init = 0;    /* Indicates whether the %module name was given */
 | 
						|
static int     title_init = 0;     /* Indicates whether %title directive has been given */
 | 
						|
static int     doc_init = 0;    
 | 
						|
 | 
						|
static int     lang_init = 0;      /* Indicates if the language has been initialized */
 | 
						|
 | 
						|
static int            i;
 | 
						|
       int            Error = 0;
 | 
						|
static char           temp_name[128];
 | 
						|
static DataType      *temp_typeptr, temp_type;
 | 
						|
static char           yy_rename[256];
 | 
						|
static int            Rename_true = 0;
 | 
						|
static DataType      *Active_type = 0;         // Used to support variable lists
 | 
						|
static int            Active_extern = 0;       // Whether or not list is external
 | 
						|
static int            Active_static = 0;
 | 
						|
static DataType       *Active_typedef = 0;     // Used for typedef lists
 | 
						|
static int            InArray = 0;             // Used when an array declaration is found 
 | 
						|
static int            in_then = 0;
 | 
						|
static int            in_else = 0;       
 | 
						|
static int            allow = 1;               // Used during conditional compilation
 | 
						|
static int            doc_scope = 0;           // Documentation scoping
 | 
						|
static String         ArrayString;             // Array type attached to parameter names
 | 
						|
static String         ArrayBackup;             // Array backup string
 | 
						|
static char           *DefArg = 0;             // Default argument hack
 | 
						|
static char           *ConstChar = 0;          // Used to store raw character constants
 | 
						|
static ParmList       *tm_parm = 0;            // Parameter list used to hold typemap parameters
 | 
						|
static Hash            name_hash;              // Hash table containing renamings
 | 
						|
       char           *objc_construct = "new"; // Objective-C constructor
 | 
						|
       char           *objc_destruct = "free"; // Objective-C destructor
 | 
						|
 | 
						|
/* Some macros for building constants */
 | 
						|
 | 
						|
#define E_BINARY(TARGET, SRC1, SRC2, OP)  \
 | 
						|
        TARGET = new char[strlen(SRC1) + strlen(SRC2) +strlen(OP)+1];\
 | 
						|
	sprintf(TARGET,"%s%s%s",SRC1,OP,SRC2);
 | 
						|
 | 
						|
/* C++ modes */
 | 
						|
 | 
						|
#define  CPLUS_PUBLIC    1
 | 
						|
#define  CPLUS_PRIVATE   2
 | 
						|
#define  CPLUS_PROTECTED 3
 | 
						|
 | 
						|
int     cplus_mode;
 | 
						|
 | 
						|
// Declarations of some functions for handling C++ 
 | 
						|
 | 
						|
extern void cplus_open_class(char *name, char *rname, char *ctype);
 | 
						|
extern void cplus_member_func(char *, char *, DataType *, ParmList *, int);
 | 
						|
extern void cplus_constructor(char *, char *, ParmList *);
 | 
						|
extern void cplus_destructor(char *, char *);
 | 
						|
extern void cplus_variable(char *, char *, DataType *);
 | 
						|
extern void cplus_static_func(char *, char *, DataType *, ParmList *);
 | 
						|
extern void cplus_declare_const(char *, char *, DataType *, char *);
 | 
						|
extern void cplus_class_close(char *);
 | 
						|
extern void cplus_inherit(int, char **);
 | 
						|
extern void cplus_cleanup(void);
 | 
						|
extern void cplus_static_var(char *, char *, DataType *);
 | 
						|
extern void cplus_register_type(char *);
 | 
						|
extern void cplus_register_scope(Hash *);
 | 
						|
extern void cplus_inherit_scope(int, char **);
 | 
						|
extern void cplus_add_pragma(char *, char *, char *);
 | 
						|
extern DocEntry *cplus_set_class(char *);
 | 
						|
extern void cplus_unset_class();
 | 
						|
extern void cplus_abort();
 | 
						|
  
 | 
						|
// ----------------------------------------------------------------------
 | 
						|
// static init_language()
 | 
						|
//
 | 
						|
// Initialize the target language.
 | 
						|
// Does nothing if this function has already been called.
 | 
						|
// ----------------------------------------------------------------------
 | 
						|
 | 
						|
static void init_language() {
 | 
						|
  if (!lang_init) {
 | 
						|
    lang->initialize();
 | 
						|
    
 | 
						|
    // Initialize the documentation system
 | 
						|
 | 
						|
    if (!doctitle) {
 | 
						|
      doctitle = new DocTitle(title,0);
 | 
						|
    }
 | 
						|
    if (!doc_init)
 | 
						|
      doctitle->usage = title;
 | 
						|
 | 
						|
    doc_stack[0] = doctitle;
 | 
						|
    doc_stack_top = 0;
 | 
						|
    
 | 
						|
    int oldignore = IgnoreDoc;
 | 
						|
    IgnoreDoc = 1;
 | 
						|
    if (ConfigFile) {
 | 
						|
      include_file(ConfigFile);
 | 
						|
    }
 | 
						|
    IgnoreDoc = oldignore;
 | 
						|
  }
 | 
						|
  lang_init = 1;
 | 
						|
  title_init = 1;
 | 
						|
}
 | 
						|
 | 
						|
// ----------------------------------------------------------------------
 | 
						|
// int promote(int t1, int t2)
 | 
						|
//
 | 
						|
// Promote types (for constant expressions)
 | 
						|
// ----------------------------------------------------------------------
 | 
						|
 | 
						|
int promote(int t1, int t2) {
 | 
						|
 | 
						|
  if ((t1 == T_ERROR) || (t2 == T_ERROR)) return T_ERROR;
 | 
						|
  if ((t1 == T_DOUBLE) || (t2 == T_DOUBLE)) return T_DOUBLE;
 | 
						|
  if ((t1 == T_FLOAT) || (t2 == T_FLOAT)) return T_FLOAT;
 | 
						|
  if ((t1 == T_ULONG) || (t2 == T_ULONG)) return T_ULONG;
 | 
						|
  if ((t1 == T_LONG) || (t2 == T_LONG)) return T_LONG;
 | 
						|
  if ((t1 == T_UINT) || (t2 == T_UINT)) return T_UINT;
 | 
						|
  if ((t1 == T_INT) || (t2 == T_INT)) return T_INT;
 | 
						|
  if ((t1 == T_USHORT) || (t2 == T_USHORT)) return T_SHORT;
 | 
						|
  if ((t1 == T_SHORT) || (t2 == T_SHORT)) return T_SHORT;
 | 
						|
  if ((t1 == T_UCHAR) || (t2 == T_UCHAR)) return T_UCHAR;
 | 
						|
  if (t1 != t2) {
 | 
						|
    fprintf(stderr,"%s : Line %d. Type mismatch in constant expression\n",
 | 
						|
	    input_file, line_number);
 | 
						|
    FatalError();
 | 
						|
  }
 | 
						|
  return t1;
 | 
						|
}
 | 
						|
 | 
						|
/* Generate the scripting name of an object.  Takes %name directive into 
 | 
						|
   account among other things */
 | 
						|
 | 
						|
static char *make_name(char *name) {
 | 
						|
  // Check to see if the name is in the hash
 | 
						|
  char *nn = (char *) name_hash.lookup(name);
 | 
						|
  if (nn) return nn;        // Yep, return it.
 | 
						|
 | 
						|
  if (Rename_true) {
 | 
						|
    Rename_true = 0;
 | 
						|
    return yy_rename;
 | 
						|
  } else {
 | 
						|
    // Now check to see if the name contains a $
 | 
						|
    if (strchr(name,'$')) {
 | 
						|
      static String temp;
 | 
						|
      temp = "";
 | 
						|
      temp << name;
 | 
						|
      temp.replace("$","_S_");
 | 
						|
      return temp;
 | 
						|
    } else {
 | 
						|
      return name;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* Return the parent of a documentation entry.   If wrapping externally, this is 0 */
 | 
						|
 | 
						|
static DocEntry *doc_parent() {
 | 
						|
  if (!WrapExtern) 
 | 
						|
    return doc_stack[doc_stack_top];
 | 
						|
  else
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
// ----------------------------------------------------------------------
 | 
						|
// create_function(int ext, char *name, DataType *t, ParmList *l)
 | 
						|
//
 | 
						|
// Creates a function and manages documentation creation.  Really
 | 
						|
// only used internally to the parser.
 | 
						|
// ----------------------------------------------------------------------
 | 
						|
 | 
						|
void create_function(int ext, char *name, DataType *t, ParmList *l) {
 | 
						|
  if (Active_static) return;     // Static declaration. Ignore
 | 
						|
 | 
						|
  init_language();
 | 
						|
  if (WrapExtern) return;        // External wrapper file. Ignore
 | 
						|
 | 
						|
  char *iname = make_name(name);
 | 
						|
 | 
						|
  // Check if symbol already exists
 | 
						|
 | 
						|
  if (add_symbol(iname, t, (char *) 0)) {
 | 
						|
    fprintf(stderr,"%s : Line %d. Function %s multiply defined (2nd definition ignored).\n",
 | 
						|
	    input_file, line_number, iname);
 | 
						|
  } else {
 | 
						|
    Stat_func++;
 | 
						|
    if (Verbose) {
 | 
						|
      fprintf(stderr,"Wrapping function : ");
 | 
						|
      emit_extern_func(name, t, l, 0, stderr);
 | 
						|
    }
 | 
						|
 | 
						|
    // If extern, make an extern declaration in the SWIG wrapper file
 | 
						|
 | 
						|
    if (ext) 
 | 
						|
      emit_extern_func(name, t, l, ext, f_header);
 | 
						|
    else if (ForceExtern) {
 | 
						|
      emit_extern_func(name, t, l, 1, f_header);
 | 
						|
    }
 | 
						|
 | 
						|
    // If this function has been declared inline, produce a function
 | 
						|
 | 
						|
    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
    lang->create_function(name, iname, t, l);
 | 
						|
    l->check_defined();
 | 
						|
    t->check_defined();
 | 
						|
  }
 | 
						|
  scanner_clear_start();
 | 
						|
}
 | 
						|
 | 
						|
// -------------------------------------------------------------------
 | 
						|
// create_variable(int ext, char *name, DataType *t)
 | 
						|
//
 | 
						|
// Create a link to a global variable.
 | 
						|
// -------------------------------------------------------------------
 | 
						|
 | 
						|
void create_variable(int ext, char *name, DataType *t) {
 | 
						|
 | 
						|
  if (WrapExtern) return;        // External wrapper file. Ignore
 | 
						|
  int oldstatus = Status;
 | 
						|
 | 
						|
  if (Active_static) return;  // If static ignore
 | 
						|
				   
 | 
						|
  init_language();
 | 
						|
 | 
						|
  char *iname = make_name(name);
 | 
						|
  if (add_symbol(iname, t, (char *) 0)) {
 | 
						|
    fprintf(stderr,"%s : Line %d. Variable %s multiply defined (2nd definition ignored).\n",
 | 
						|
	    input_file, line_number, iname);
 | 
						|
  } else {
 | 
						|
    Stat_var++;
 | 
						|
    if (Verbose) {
 | 
						|
      fprintf(stderr,"Wrapping variable : ");
 | 
						|
      emit_extern_var(name, t, 0, stderr);
 | 
						|
    }
 | 
						|
 | 
						|
    // If externed, output an external declaration
 | 
						|
 | 
						|
    if (ext) 
 | 
						|
      emit_extern_var(name, t, ext, f_header);
 | 
						|
    else if (ForceExtern) {
 | 
						|
      emit_extern_var(name, t, 1, f_header);
 | 
						|
    }
 | 
						|
 | 
						|
    // If variable datatype is read-only, we'll force it to be readonly
 | 
						|
    if (t->status & STAT_READONLY) Status = Status | STAT_READONLY;
 | 
						|
 | 
						|
    // Now dump it out
 | 
						|
    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
    lang->link_variable(name, iname, t);
 | 
						|
    t->check_defined();
 | 
						|
    Status = oldstatus;
 | 
						|
  }
 | 
						|
  scanner_clear_start();
 | 
						|
}
 | 
						|
 | 
						|
// ------------------------------------------------------------------
 | 
						|
// create_constant(char *name, DataType *type, char *value)
 | 
						|
//
 | 
						|
// Creates a new constant.
 | 
						|
// -------------------------------------------------------------------
 | 
						|
 | 
						|
void create_constant(char *name, DataType *type, char *value) {
 | 
						|
 | 
						|
  if (Active_static) return;
 | 
						|
  if (WrapExtern) return;        // External wrapper file. Ignore
 | 
						|
  init_language();
 | 
						|
 | 
						|
  if (Rename_true) {
 | 
						|
    fprintf(stderr,"%s : Line %d. %%name directive ignored with #define\n",
 | 
						|
	    input_file, line_number);
 | 
						|
    Rename_true = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((type->type == T_CHAR) && (!type->is_pointer))
 | 
						|
    type->is_pointer++;
 | 
						|
  
 | 
						|
  if (!value) value = copy_string(name);
 | 
						|
  sprintf(temp_name,"const:%s", name);
 | 
						|
  if (add_symbol(temp_name, type, value)) {
 | 
						|
    fprintf(stderr,"%s : Line %d. Constant %s multiply defined. (2nd definition ignored)\n",
 | 
						|
	    input_file, line_number, name);
 | 
						|
  } else {
 | 
						|
    // Update symbols value if already defined.
 | 
						|
    update_symbol(name, type, value);
 | 
						|
 | 
						|
    if (!WrapExtern) {    // Only wrap the constant if not in %extern mode
 | 
						|
      Stat_const++;
 | 
						|
      if (Verbose) 
 | 
						|
	fprintf(stderr,"Creating constant %s = %s\n", name, value);
 | 
						|
 | 
						|
      doc_entry = new DocDecl(name,doc_stack[doc_stack_top]);	   
 | 
						|
      lang->declare_const(name, name, type, value);
 | 
						|
      type->check_defined();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  scanner_clear_start();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Print out array brackets */
 | 
						|
void print_array() {
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < InArray; i++)
 | 
						|
    fprintf(stderr,"[]");
 | 
						|
}
 | 
						|
 | 
						|
/* manipulate small stack for managing if-then-else */
 | 
						|
 | 
						|
static int then_data[100];
 | 
						|
static int else_data[100];
 | 
						|
static int allow_data[100];
 | 
						|
static int te_index = 0;
 | 
						|
static int prev_allow = 1;
 | 
						|
 | 
						|
void if_push() {
 | 
						|
  then_data[te_index] = in_then;
 | 
						|
  else_data[te_index] = in_else;
 | 
						|
  allow_data[te_index] = allow;
 | 
						|
  prev_allow = allow;
 | 
						|
  te_index++;
 | 
						|
  if (te_index >= 100) {
 | 
						|
    fprintf(stderr,"SWIG.  Internal parser error. if-then-else stack overflow.\n");
 | 
						|
    SWIG_exit(1);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void if_pop() {
 | 
						|
  if (te_index > 0) {
 | 
						|
    te_index--;
 | 
						|
    in_then = then_data[te_index];
 | 
						|
    in_else = else_data[te_index];
 | 
						|
    allow = allow_data[te_index];
 | 
						|
    if (te_index > 0) {
 | 
						|
      prev_allow = allow_data[te_index-1];
 | 
						|
    } else {
 | 
						|
      prev_allow = 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Structures for handling code fragments built for nested classes
 | 
						|
 | 
						|
struct Nested {
 | 
						|
  String   code;         // Associated code fragment
 | 
						|
  int      line;         // line number where it starts
 | 
						|
  char     *name;        // Name associated with this nested class
 | 
						|
  DataType *type;        // Datatype associated with the name
 | 
						|
  Nested   *next;        // Next code fragment in list
 | 
						|
};
 | 
						|
 | 
						|
// 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 void dump_nested(char *parent) {
 | 
						|
  Nested *n,*n1;
 | 
						|
  n = nested_list;
 | 
						|
  int oldstatus = Status;
 | 
						|
 | 
						|
  Status = STAT_READONLY;
 | 
						|
  while (n) {
 | 
						|
    // Token replace the name of the parent class
 | 
						|
    n->code.replace("$classname",parent);
 | 
						|
 | 
						|
    // Fix up the name of the datatype (for building typedefs and other stuff)
 | 
						|
    sprintf(n->type->name,"%s_%s",parent,n->name);
 | 
						|
    
 | 
						|
    // Add the appropriate declaration to the C++ processor
 | 
						|
    doc_entry = new DocDecl(n->name,doc_stack[doc_stack_top]);
 | 
						|
    cplus_variable(n->name,(char *) 0, n->type);
 | 
						|
 | 
						|
    // Dump the code to the scanner
 | 
						|
    if (Verbose)
 | 
						|
      fprintf(stderr,"Splitting from %s : (line %d) \n%s\n", parent,n->line, n->code.get());
 | 
						|
 | 
						|
    fprintf(f_header,"\n%s\n", n->code.get());
 | 
						|
    start_inline(n->code.get(),n->line);
 | 
						|
 | 
						|
    n1 = n->next;
 | 
						|
    delete n;
 | 
						|
    n = n1;
 | 
						|
  }
 | 
						|
  nested_list = 0;
 | 
						|
  Status = oldstatus;
 | 
						|
}    
 | 
						|
 | 
						|
%}
 | 
						|
 | 
						|
/* The type of each node in the parse tree
 | 
						|
   must be one of the elements of the union
 | 
						|
   given below.  This is used to derive the
 | 
						|
   C++ declaration for "yylval" that appears
 | 
						|
   in parser.tab.h. */
 | 
						|
 | 
						|
%union {         
 | 
						|
  char        *id;
 | 
						|
  struct Declaration {
 | 
						|
    char *id;
 | 
						|
    int   is_pointer;
 | 
						|
    int   is_reference;
 | 
						|
  } decl;
 | 
						|
  struct InitList {
 | 
						|
    char **names;
 | 
						|
    int    count;
 | 
						|
  } ilist;
 | 
						|
  struct DocList {
 | 
						|
    char **names;
 | 
						|
    char **values;
 | 
						|
    int  count;
 | 
						|
  } dlist;
 | 
						|
  struct Define {
 | 
						|
    char *id;
 | 
						|
    int   type;
 | 
						|
  } dtype;
 | 
						|
  DataType     *type;
 | 
						|
  Parm         *p;
 | 
						|
  TMParm       *tmparm;
 | 
						|
  ParmList     *pl;
 | 
						|
  int           ivalue;
 | 
						|
};
 | 
						|
 | 
						|
%token <id> ID 
 | 
						|
%token <id> HBLOCK WRAPPER POUND 
 | 
						|
%token <id> STRING
 | 
						|
%token <id> NUM_INT NUM_FLOAT CHARCONST NUM_UNSIGNED NUM_LONG NUM_ULONG
 | 
						|
%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
 | 
						|
%token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE DEFINE PERIOD
 | 
						|
%token CONST STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
 | 
						|
%token WEXTERN ILLEGAL
 | 
						|
%token READONLY READWRITE NAME RENAME INCLUDE CHECKOUT ADDMETHODS PRAGMA 
 | 
						|
%token CVALUE COUT
 | 
						|
%token ENUM ENDDEF MACRO 
 | 
						|
%token CLASS PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND OPERATOR THROW TEMPLATE
 | 
						|
%token NATIVE INLINE
 | 
						|
%token IFDEF IFNDEF ENDIF ELSE UNDEF IF DEFINED ELIF
 | 
						|
%token RAW_MODE ALPHA_MODE TEXT DOC_DISABLE DOC_ENABLE STYLE LOCALSTYLE
 | 
						|
%token TYPEMAP EXCEPT IMPORT ECHO NEW APPLY CLEAR DOCONLY
 | 
						|
%token <ivalue> TITLE SECTION SUBSECTION SUBSUBSECTION 
 | 
						|
%token LESSTHAN GREATERTHAN
 | 
						|
%token <id> USERDIRECTIVE
 | 
						|
 | 
						|
/* Objective C tokens */
 | 
						|
 | 
						|
%token OC_INTERFACE OC_END OC_PUBLIC OC_PRIVATE OC_PROTECTED OC_CLASS OC_IMPLEMENT OC_PROTOCOL
 | 
						|
 | 
						|
%left  OR
 | 
						|
%left  XOR
 | 
						|
%left  AND
 | 
						|
%left  LSHIFT RSHIFT 
 | 
						|
%left  PLUS MINUS 
 | 
						|
%left  STAR SLASH
 | 
						|
%left  UMINUS NOT LNOT
 | 
						|
%left  DCOLON
 | 
						|
 | 
						|
%type <ivalue>   extern array array2 parm_specifier parm_specifier_list;
 | 
						|
%type <pl>       parms ptail;
 | 
						|
%type <p>        parm parm_type;
 | 
						|
%type <tmparm>   typemap_parm tm_list tm_tail;
 | 
						|
%type <id>       pname cpptype base_specifier access_specifier typemap_name tm_method idstring;
 | 
						|
%type <type>     type opt_signed opt_unsigned strict_type;
 | 
						|
%type <decl>     declaration nested_decl;
 | 
						|
%type <ivalue>   stars cpp_const_expr;
 | 
						|
%type <ilist>    initlist base_list inherit;
 | 
						|
%type <dtype>    definetype definetail def_args;
 | 
						|
%type <dtype>    etype;
 | 
						|
%type <dtype>    expr;
 | 
						|
%type <id>       ename stylearg objc_inherit;
 | 
						|
%type <dlist>    stylelist styletail;
 | 
						|
%type <type>     objc_ret_type objc_arg_type; 
 | 
						|
%type <id>       objc_protolist objc_separator;
 | 
						|
%type <pl>       objc_args;
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
/* The productions of the grammar with their
 | 
						|
   associated semantic actions. */
 | 
						|
 | 
						|
program        : { 
 | 
						|
                    {
 | 
						|
		      int ii;
 | 
						|
		      for (ii = 0; ii < 256; ii++) {
 | 
						|
			handler_stack[ii] = 0;
 | 
						|
		      }
 | 
						|
		      handler_stack[0] = comment_handler;
 | 
						|
		    }
 | 
						|
                    doc_stack[0] = doctitle;
 | 
						|
                 } command {
 | 
						|
		   CommentHandler::cleanup();
 | 
						|
                   cplus_cleanup();
 | 
						|
		   doc_entry = doctitle;
 | 
						|
		   if (lang_init) {
 | 
						|
		     lang->close();
 | 
						|
		   }
 | 
						|
		   if (te_index) {
 | 
						|
		     fprintf(stderr,"%s : EOF.  Missing #endif detected.\n", input_file);
 | 
						|
		     FatalError();
 | 
						|
		   }
 | 
						|
               }
 | 
						|
               ;
 | 
						|
    
 | 
						|
command        : command statement { 
 | 
						|
		     scanner_clear_start();
 | 
						|
                     Error = 0;
 | 
						|
                }
 | 
						|
               | empty {
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
statement      : INCLUDE idstring {
 | 
						|
                  if (allow) {
 | 
						|
//		    init_language();
 | 
						|
		    doc_entry = 0;
 | 
						|
		    // comment_handler->clear();
 | 
						|
		    include_file($2);
 | 
						|
		  }
 | 
						|
                }
 | 
						|
 | 
						|
/* %extern directive */
 | 
						|
 | 
						|
               | WEXTERN idstring {
 | 
						|
		 if (allow) {
 | 
						|
		   int oldextern = WrapExtern;
 | 
						|
//		   init_language();
 | 
						|
		   doc_entry = 0;
 | 
						|
		   // comment_handler->clear();
 | 
						|
		   WrapExtern = 1;
 | 
						|
		   if (include_file($2) >= 0) {
 | 
						|
		     add_symbol("SWIGEXTERN",0,0);
 | 
						|
		   } else {
 | 
						|
		     WrapExtern = oldextern;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* %import directive.  Like %extern but calls out to a language module */
 | 
						|
 | 
						|
                | IMPORT idstring {
 | 
						|
		  if (allow) {
 | 
						|
		    int oldextern = WrapExtern;
 | 
						|
		    init_language();
 | 
						|
		    doc_entry = 0;
 | 
						|
		    WrapExtern = 1;
 | 
						|
		    if (include_file($2) >= 0) {
 | 
						|
		      add_symbol("SWIGEXTERN",0,0);
 | 
						|
		      lang->import($2);
 | 
						|
		    } else {
 | 
						|
		      WrapExtern = oldextern;
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
                }
 | 
						|
 | 
						|
/* %checkout directive.  Like %include, but simply copies the file into the
 | 
						|
   current directory */
 | 
						|
 | 
						|
                | CHECKOUT idstring {
 | 
						|
                  if (allow) {
 | 
						|
                     if ((checkout_file($2,$2)) == 0) {
 | 
						|
                       fprintf(stderr,"%s checked out from the SWIG library.\n",$2);
 | 
						|
                      }
 | 
						|
                  }
 | 
						|
                }
 | 
						|
 | 
						|
/* An unknown C preprocessor statement.  Just throw it away */
 | 
						|
 | 
						|
                | POUND {
 | 
						|
		 if (allow) {
 | 
						|
                  doc_entry = 0;
 | 
						|
		  if (Verbose) {
 | 
						|
		    fprintf(stderr,"%s : Line %d.  CPP %s ignored.\n", input_file, line_number,$1);
 | 
						|
		  }
 | 
						|
		 }
 | 
						|
		}
 | 
						|
 | 
						|
/* A variable declaration */
 | 
						|
 | 
						|
                | extern type declaration array2 def_args {
 | 
						|
		  if (allow) {
 | 
						|
		    init_language();
 | 
						|
		    if (Active_type) delete Active_type;
 | 
						|
		    Active_type = new DataType($2);
 | 
						|
		    Active_extern = $1;
 | 
						|
		    $2->is_pointer += $3.is_pointer;
 | 
						|
		    if ($4 > 0) {
 | 
						|
		      $2->is_pointer++;
 | 
						|
		      $2->status = STAT_READONLY;
 | 
						|
                      $2->arraystr = copy_string(ArrayString);
 | 
						|
		    }
 | 
						|
		    if ($3.is_reference) {
 | 
						|
		      fprintf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
 | 
						|
		      FatalError();
 | 
						|
		    } else {
 | 
						|
		      if ($2->qualifier) {
 | 
						|
			if ((strcmp($2->qualifier,"const") == 0)) {
 | 
						|
			  if ($5.type != T_ERROR)
 | 
						|
			    create_constant($3.id, $2, $5.id);
 | 
						|
			} else 
 | 
						|
			  create_variable($1,$3.id,$2);
 | 
						|
		      } else
 | 
						|
			create_variable($1,$3.id,$2);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  delete $2;
 | 
						|
                } stail { } 
 | 
						|
 | 
						|
/* Global variable that smells like a function pointer */
 | 
						|
 | 
						|
                | extern strict_type LPAREN STAR { 
 | 
						|
                   skip_decl();
 | 
						|
		   fprintf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
 | 
						|
			   input_file, line_number);
 | 
						|
		}
 | 
						|
 | 
						|
/* A static variable declaration (Ignored) */
 | 
						|
 | 
						|
   	        | STATIC type declaration array2 def_args {
 | 
						|
		  if (Verbose) {
 | 
						|
		    fprintf(stderr,"static variable %s ignored.\n",$3.id);
 | 
						|
		  }
 | 
						|
		  Active_static = 1;
 | 
						|
		  delete $2;
 | 
						|
		} stail {
 | 
						|
		  Active_static = 0;
 | 
						|
		}
 | 
						|
 | 
						|
/* Global variable that smells like a function pointer */
 | 
						|
 | 
						|
                | STATIC strict_type LPAREN STAR { 
 | 
						|
                   skip_decl();
 | 
						|
		   fprintf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
 | 
						|
			   input_file, line_number);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
/* A function declaration */
 | 
						|
 | 
						|
                | extern type declaration LPAREN parms RPAREN cpp_const {
 | 
						|
		  if (allow) {
 | 
						|
		    init_language();
 | 
						|
		    if (Active_type) delete Active_type;
 | 
						|
		    Active_type = new DataType($2);
 | 
						|
		    Active_extern = $1;
 | 
						|
		    $2->is_pointer += $3.is_pointer;
 | 
						|
		    $2->is_reference = $3.is_reference;
 | 
						|
		    create_function($1, $3.id, $2, $5);
 | 
						|
		  }
 | 
						|
		  delete $2;
 | 
						|
		  delete $5;
 | 
						|
		} stail { } 
 | 
						|
               
 | 
						|
/* A function declaration with code after it */
 | 
						|
 | 
						|
                | extern type declaration LPAREN parms RPAREN func_end {
 | 
						|
		  if (allow) {
 | 
						|
		    init_language();
 | 
						|
		    $2->is_pointer += $3.is_pointer;
 | 
						|
		    $2->is_reference = $3.is_reference;
 | 
						|
		    create_function($1, $3.id, $2, $5);
 | 
						|
		  }
 | 
						|
		  delete $2;
 | 
						|
		  delete $5;
 | 
						|
		};
 | 
						|
 | 
						|
/* A function declared without any return datatype */
 | 
						|
 | 
						|
                | extern declaration LPAREN parms RPAREN cpp_const { 
 | 
						|
		  if (allow) {
 | 
						|
                    init_language();
 | 
						|
		    DataType *t = new DataType(T_INT);
 | 
						|
                    t->is_pointer += $2.is_pointer;
 | 
						|
		    t->is_reference = $2.is_reference;
 | 
						|
		    create_function($1,$2.id,t,$4);
 | 
						|
		    delete t;
 | 
						|
		  }
 | 
						|
                } stail { };
 | 
						|
 | 
						|
/* A static function declaration code after it */
 | 
						|
 | 
						|
                | STATIC type declaration LPAREN parms RPAREN func_end {
 | 
						|
		  if ((allow) && (Inline)) {
 | 
						|
		    if (strlen(CCode.get())) {
 | 
						|
		      init_language();
 | 
						|
		      $2->is_pointer += $3.is_pointer;
 | 
						|
		      $2->is_reference = $3.is_reference;
 | 
						|
		      create_function(0, $3.id, $2, $5);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  delete $2;
 | 
						|
		  delete $5;
 | 
						|
		};
 | 
						|
 | 
						|
/* A function with an explicit inline directive. Not safe to use inside a %inline block */
 | 
						|
 | 
						|
                | INLINE type declaration LPAREN parms RPAREN func_end {
 | 
						|
		  if (allow) {
 | 
						|
		    init_language();
 | 
						|
		    $2->is_pointer += $3.is_pointer;
 | 
						|
		    $2->is_reference = $3.is_reference;
 | 
						|
		    if (Inline) {
 | 
						|
		      fprintf(stderr,"%s : Line %d. Repeated %%inline directive.\n",input_file,line_number);
 | 
						|
		      FatalError();
 | 
						|
		    } else {
 | 
						|
		      if (strlen(CCode.get())) {
 | 
						|
			fprintf(f_header,"static ");
 | 
						|
			emit_extern_func($3.id,$2,$5,3,f_header);
 | 
						|
			fprintf(f_header,"%s\n",CCode.get());
 | 
						|
		      }
 | 
						|
		      create_function(0, $3.id, $2, $5);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  delete $2;
 | 
						|
		  delete $5;
 | 
						|
		};
 | 
						|
 | 
						|
/* A static function declaration (ignored) */
 | 
						|
 | 
						|
                | STATIC type declaration LPAREN parms RPAREN cpp_const {
 | 
						|
		  if (allow) {
 | 
						|
		    if (Verbose) {
 | 
						|
		      fprintf(stderr,"static function %s ignored.\n", $3.id);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  Active_static = 1;
 | 
						|
		  delete $2;
 | 
						|
		  delete $5;
 | 
						|
		} stail {
 | 
						|
		  Active_static = 0;
 | 
						|
		 }
 | 
						|
 | 
						|
/* Enable Read-only mode */
 | 
						|
 | 
						|
               | READONLY {
 | 
						|
		  if (allow)
 | 
						|
		    Status = Status | STAT_READONLY;
 | 
						|
	       }
 | 
						|
 | 
						|
/* Enable Read-write mode */
 | 
						|
 | 
						|
	       | READWRITE {
 | 
						|
		 if (allow)
 | 
						|
		   Status = Status & ~STAT_READONLY;
 | 
						|
	       }
 | 
						|
 | 
						|
/* New %name directive */
 | 
						|
               | NAME LPAREN ID RPAREN {
 | 
						|
		 if (allow) {
 | 
						|
                     strcpy(yy_rename,$3);
 | 
						|
                     Rename_true = 1;
 | 
						|
		 }
 | 
						|
               }
 | 
						|
 | 
						|
/* %rename directive */
 | 
						|
               | RENAME ID ID SEMI { 
 | 
						|
		 if (name_hash.lookup($2)) {
 | 
						|
		   name_hash.remove($2);
 | 
						|
		 }
 | 
						|
		 name_hash.add($2,copy_string($3));
 | 
						|
	       }
 | 
						|
          
 | 
						|
/* %new directive */
 | 
						|
 | 
						|
               | NEW {
 | 
						|
                     NewObject = 1;
 | 
						|
                } statement {
 | 
						|
                     NewObject = 0;
 | 
						|
               }
 | 
						|
 | 
						|
/* Empty name directive.  No longer allowed  */
 | 
						|
 | 
						|
               | NAME LPAREN RPAREN {
 | 
						|
		 if (allow) {
 | 
						|
		   fprintf(stderr,"%s : Lind %d. Empty %%name() is no longer supported.\n",
 | 
						|
			   input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
	       } cpp {
 | 
						|
		 Rename_true = 0;
 | 
						|
	       }
 | 
						|
 | 
						|
/* A native wrapper function */
 | 
						|
 | 
						|
               | NATIVE LPAREN ID RPAREN extern ID SEMI {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   init_language();
 | 
						|
		   if (add_symbol($3,(DataType *) 0, (char *) 0)) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n",
 | 
						|
			     input_file, line_number, $3);
 | 
						|
		   } else {
 | 
						|
		     doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 | 
						|
		     lang->add_native($3,$6);
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
               | NATIVE LPAREN ID RPAREN extern type declaration LPAREN parms RPAREN SEMI {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   init_language();
 | 
						|
		   $6->is_pointer += $7.is_pointer;
 | 
						|
		   if (add_symbol($3,(DataType *) 0, (char *) 0)) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n",
 | 
						|
			     input_file, line_number, $3);
 | 
						|
		   } else {
 | 
						|
		     if ($5) {
 | 
						|
		       emit_extern_func($7.id, $6, $9, $5, f_header);
 | 
						|
		     }
 | 
						|
		     doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 | 
						|
		     lang->add_native($3,$7.id);
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
		 delete $6;
 | 
						|
		 delete $9;
 | 
						|
	       }
 | 
						|
 | 
						|
/* %title directive */
 | 
						|
 | 
						|
               | TITLE STRING styletail {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   if (!title_init) {
 | 
						|
		     title_init = 1;
 | 
						|
		     doc_init = 1;
 | 
						|
		     if (!comment_handler) {
 | 
						|
		       comment_handler = new CommentHandler();
 | 
						|
		     }
 | 
						|
		     { 
 | 
						|
		       int ii;
 | 
						|
		       for (ii = 0; ii < $3.count; ii++) {
 | 
						|
			 comment_handler->style($3.names[ii],$3.values[ii]);
 | 
						|
		       }
 | 
						|
		     }
 | 
						|
		     // Create a new title for documentation 
 | 
						|
		     {
 | 
						|
		       int temp = line_number;
 | 
						|
		       line_number = $1;
 | 
						|
		       if (!doctitle)
 | 
						|
			 doctitle = new DocTitle($2,0);
 | 
						|
		       else {
 | 
						|
			 doctitle->name = copy_string(title);
 | 
						|
			 doctitle->line_number = $1;
 | 
						|
			 doctitle->end_line = $1;
 | 
						|
		       }
 | 
						|
		       line_number = temp;
 | 
						|
		     }
 | 
						|
		     doctitle->usage = $2;
 | 
						|
		     doc_entry = doctitle;
 | 
						|
		     doc_stack[0] = doc_entry;
 | 
						|
		     doc_stack_top = 0;
 | 
						|
		     handler_stack[0] = comment_handler;
 | 
						|
		     { 
 | 
						|
		       int ii;
 | 
						|
		       for (ii = 0; ii < $3.count; ii++) {
 | 
						|
			 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 | 
						|
		       }
 | 
						|
		     }
 | 
						|
 | 
						|
		   } else {
 | 
						|
		     // Ignore it
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       } 
 | 
						|
 | 
						|
 | 
						|
/* %section directive */
 | 
						|
 | 
						|
               | SECTION STRING styletail {
 | 
						|
		 if (allow && (!WrapExtern) && (!IgnoreDoc)) {
 | 
						|
		   // Copy old comment handler
 | 
						|
		   // if (handler_stack[1]) delete handler_stack[1];
 | 
						|
		   handler_stack[1] = new CommentHandler(handler_stack[0]);  
 | 
						|
		   comment_handler = handler_stack[1];
 | 
						|
		   { 
 | 
						|
		     int ii;
 | 
						|
		     for (ii = 0; ii < $3.count; ii++) {
 | 
						|
		       comment_handler->style($3.names[ii],$3.values[ii]);
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		   {
 | 
						|
		     int temp = line_number;
 | 
						|
		     line_number = $1;
 | 
						|
		     doc_entry = new DocSection($2,doc_stack[0]);
 | 
						|
		     line_number = temp;
 | 
						|
		   }
 | 
						|
		   doc_stack_top = 1;
 | 
						|
		   doc_stack[1] = doc_entry;
 | 
						|
		   { 
 | 
						|
		     int ii;
 | 
						|
		     for (ii = 0; ii < $3.count; ii++) {
 | 
						|
		       doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* %subsection directive */
 | 
						|
               | SUBSECTION STRING styletail {
 | 
						|
		 if (allow && (!WrapExtern) && (!IgnoreDoc)) {
 | 
						|
		   if (doc_stack_top < 1) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Can't apply %%subsection here.\n", input_file,line_number);
 | 
						|
		     FatalError();
 | 
						|
		   } else {
 | 
						|
 | 
						|
		     // Copy old comment handler
 | 
						|
		     // if (handler_stack[2]) delete handler_stack[2];
 | 
						|
		     handler_stack[2] = new CommentHandler(handler_stack[1]);
 | 
						|
		     comment_handler = handler_stack[2];
 | 
						|
		     { 
 | 
						|
		       int ii;
 | 
						|
		       for (ii = 0; ii < $3.count; ii++) {
 | 
						|
			 comment_handler->style($3.names[ii],$3.values[ii]);
 | 
						|
		       }
 | 
						|
		     }
 | 
						|
		     {
 | 
						|
		       int temp = line_number;
 | 
						|
		       line_number = $1;
 | 
						|
		       doc_entry = new DocSection($2,doc_stack[1]);
 | 
						|
		       line_number = temp;
 | 
						|
		     }
 | 
						|
		     doc_stack_top = 2;
 | 
						|
		     doc_stack[2] = doc_entry;
 | 
						|
		     { 
 | 
						|
		       int ii;
 | 
						|
		       for (ii = 0; ii < $3.count; ii++) {
 | 
						|
			 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 | 
						|
		       }
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* %subsubsection directive */
 | 
						|
               | SUBSUBSECTION STRING styletail {
 | 
						|
		 if (allow && (!WrapExtern) && (!IgnoreDoc)) {
 | 
						|
		   if (doc_stack_top < 2) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Can't apply %%subsubsection here.\n", input_file,line_number);
 | 
						|
		     FatalError();
 | 
						|
		   } else {
 | 
						|
 | 
						|
		     // Copy old comment handler
 | 
						|
 | 
						|
		     // if (handler_stack[3]) delete handler_stack[3];
 | 
						|
		     handler_stack[3] = new CommentHandler(handler_stack[2]);
 | 
						|
		     comment_handler = handler_stack[3];
 | 
						|
		     { 
 | 
						|
		       int ii;
 | 
						|
		       for (ii = 0; ii < $3.count; ii++) {
 | 
						|
			 comment_handler->style($3.names[ii],$3.values[ii]);
 | 
						|
		       }
 | 
						|
		     }
 | 
						|
		     {
 | 
						|
		       int temp = line_number;
 | 
						|
		       line_number = $1;
 | 
						|
		       doc_entry = new DocSection($2,doc_stack[2]);
 | 
						|
		       line_number = temp;
 | 
						|
		     }
 | 
						|
		     doc_stack_top = 3;
 | 
						|
		     doc_stack[3] = doc_entry;
 | 
						|
		     { 
 | 
						|
		       int ii;
 | 
						|
		       for (ii = 0; ii < $3.count; ii++) {
 | 
						|
			 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 | 
						|
		       }
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* %alpha directive (obsolete) */
 | 
						|
               | ALPHA_MODE {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   fprintf(stderr,"%%alpha directive is obsolete.  Use '%%style sort' instead.\n");
 | 
						|
		   handler_stack[0]->style("sort",0);
 | 
						|
		   doc_stack[0]->style("sort",0);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
/* %raw directive (obsolete) */
 | 
						|
               | RAW_MODE {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   fprintf(stderr,"%%raw directive is obsolete. Use '%%style nosort' instead.\n");
 | 
						|
		   handler_stack[0]->style("nosort",0);
 | 
						|
		   doc_stack[0]->style("nosort",0);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
               | doc_enable { }
 | 
						|
 | 
						|
/* %text directive */
 | 
						|
 | 
						|
               | TEXT HBLOCK {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   $2[strlen($2) - 1] = 0;
 | 
						|
		   doc_entry = new DocText($2,doc_stack[doc_stack_top]);
 | 
						|
		   doc_entry = 0;
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
             
 | 
						|
 | 
						|
               | typedef_decl { }
 | 
						|
 | 
						|
/* Code insertion block */
 | 
						|
 | 
						|
               | HBLOCK {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   init_language();
 | 
						|
		   $1[strlen($1) - 1] = 0;
 | 
						|
//		   fprintf(f_header,"#line %d \"%s\"\n", start_line, input_file);
 | 
						|
		   fprintf(f_header, "%s\n", $1);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* Super-secret undocumented for people who really know what's going on feature */
 | 
						|
 | 
						|
               | WRAPPER HBLOCK {
 | 
						|
                 if (allow && (!WrapExtern)) {
 | 
						|
		   init_language();
 | 
						|
		   $2[strlen($2) - 1] = 0;
 | 
						|
		   fprintf(f_wrappers,"%s\n",$2);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* Initialization code */
 | 
						|
 | 
						|
               | INIT HBLOCK {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   init_language();
 | 
						|
		   $2[strlen($2) -1] = 0;
 | 
						|
		   fprintf(f_init,"%s\n", $2);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* Inline block */
 | 
						|
               | INLINE HBLOCK {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   init_language();
 | 
						|
		   $2[strlen($2) - 1] = 0;
 | 
						|
		   fprintf(f_header, "%s\n", $2);
 | 
						|
		   start_inline($2,start_line);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* Echo mode */
 | 
						|
               | ECHO HBLOCK {
 | 
						|
		 if (allow && (!WrapExtern)) {
 | 
						|
		   fprintf(stderr,"%s\n", $2);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
               | ECHO STRING {
 | 
						|
                 if (allow && (!WrapExtern)) {
 | 
						|
                   fprintf(stderr,"%s\n", $2);
 | 
						|
                 }
 | 
						|
               }
 | 
						|
 | 
						|
/* Disable code generation */
 | 
						|
               | DOCONLY {
 | 
						|
                   DocOnly = 1;
 | 
						|
               }
 | 
						|
       
 | 
						|
/* Init directive--to avoid errors in other modules */
 | 
						|
 | 
						|
               | INIT ID initlist {
 | 
						|
		 if (allow) {
 | 
						|
		   if (!module_init) {
 | 
						|
		     lang->set_init($2);
 | 
						|
		     module_init = 1;
 | 
						|
		     init_language();
 | 
						|
		   } else {
 | 
						|
		     if (Verbose)
 | 
						|
		       fprintf(stderr,"%s : Line %d. %%init %s ignored.\n",
 | 
						|
			       input_file, line_number, $2);
 | 
						|
		   }
 | 
						|
		   if ($3.count > 0) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Warning. Init list no longer supported.\n",
 | 
						|
			     input_file,line_number);
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
		 for (i = 0; i < $3.count; i++)
 | 
						|
		   if ($3.names[i]) delete [] $3.names[i];
 | 
						|
		 delete [] $3.names;
 | 
						|
	       }
 | 
						|
/* Module directive */
 | 
						|
 | 
						|
               | MODULE ID initlist {
 | 
						|
		 if (allow) {
 | 
						|
		   if ($3.count)
 | 
						|
		     lang->set_module($2,$3.names);
 | 
						|
		   else
 | 
						|
		     lang->set_module($2,0);
 | 
						|
		   module_init = 1;
 | 
						|
		   init_language();
 | 
						|
		 }
 | 
						|
		 for (i = 0; i < $3.count; i++)
 | 
						|
		   if ($3.names[i]) delete [] $3.names[i];
 | 
						|
		 delete [] $3.names;
 | 
						|
	       }
 | 
						|
 | 
						|
/* #define directive */
 | 
						|
 | 
						|
               | DEFINE ID definetail {
 | 
						|
		 if (allow) {
 | 
						|
		   if (($3.type != T_ERROR) && ($3.type != T_SYMBOL)) {
 | 
						|
		     init_language();
 | 
						|
		     temp_typeptr = new DataType($3.type);
 | 
						|
		     create_constant($2, temp_typeptr, $3.id);
 | 
						|
		     delete temp_typeptr;
 | 
						|
		   } else if ($3.type == T_SYMBOL) {
 | 
						|
		     // Add a symbol to the SWIG symbol table
 | 
						|
		     if (add_symbol($2,(DataType *) 0, (char *) 0)) {
 | 
						|
		       fprintf(stderr,"%s : Line %d. Warning. Symbol %s already defined.\n", 
 | 
						|
			       input_file,line_number, $2);
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* A CPP Macro.   Ignore (hopefully) */
 | 
						|
 | 
						|
               | DEFINE MACRO {
 | 
						|
		 if (Verbose) {
 | 
						|
		   fprintf(stderr,"%s : Line %d.  CPP Macro ignored.\n", input_file, line_number);
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* An undef directive */
 | 
						|
               | UNDEF ID {
 | 
						|
		 remove_symbol($2);
 | 
						|
	       }
 | 
						|
 | 
						|
/* Enumerations */
 | 
						|
 | 
						|
               | extern ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE SEMI { 
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   if ($3) {
 | 
						|
		     temp_type.type = T_INT;
 | 
						|
		     temp_type.is_pointer = 0;
 | 
						|
		     temp_type.implicit_ptr = 0;
 | 
						|
		     sprintf(temp_type.name,"int");
 | 
						|
		     temp_type.typedef_add($3,1);
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* A typdef'd enum.  Pretty common in C headers */
 | 
						|
 | 
						|
               | TYPEDEF ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE ID {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   temp_type.type = T_INT;
 | 
						|
		   temp_type.is_pointer = 0;
 | 
						|
		   temp_type.implicit_ptr = 0;
 | 
						|
		   sprintf(temp_type.name,"int");
 | 
						|
		   Active_typedef = new DataType(&temp_type);
 | 
						|
		   temp_type.typedef_add($8,1);
 | 
						|
		 }
 | 
						|
	       } typedeflist { }
 | 
						|
 | 
						|
/* -----------------------------------------------------------------
 | 
						|
   typemap support.
 | 
						|
 | 
						|
   These constructs are used to support type-maps.
 | 
						|
   ----------------------------------------------------------------- */
 | 
						|
 | 
						|
/* Create a new typemap */
 | 
						|
 | 
						|
               | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
 | 
						|
		   TMParm *p;
 | 
						|
                   skip_brace();
 | 
						|
		   p = $7;
 | 
						|
		   while (p) {
 | 
						|
		     typemap_register($5,$3,p->p->t,p->p->name,CCode,p->args);
 | 
						|
		     p = p->next;
 | 
						|
                   }
 | 
						|
		   delete $3;
 | 
						|
		   delete $5;
 | 
						|
	       }
 | 
						|
 | 
						|
/* Create a new typemap in current language */
 | 
						|
               | TYPEMAP LPAREN tm_method RPAREN tm_list LBRACE {
 | 
						|
		 if (!typemap_lang) {
 | 
						|
		   fprintf(stderr,"SWIG internal error. No typemap_lang specified.\n");
 | 
						|
		   fprintf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
 | 
						|
		   FatalError();
 | 
						|
		 } else {
 | 
						|
		   TMParm *p;
 | 
						|
		   skip_brace();
 | 
						|
		   p = $5;
 | 
						|
		   while (p) {
 | 
						|
		     typemap_register($3,typemap_lang,p->p->t,p->p->name,CCode,p->args);
 | 
						|
		     p = p->next;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
		 delete $3;
 | 
						|
	       }
 | 
						|
 | 
						|
/* Clear a typemap */
 | 
						|
 | 
						|
               | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list SEMI {
 | 
						|
		 TMParm *p;
 | 
						|
		 p = $7;
 | 
						|
		 while (p) {
 | 
						|
                   typemap_clear($5,$3,p->p->t,p->p->name);
 | 
						|
		   p = p->next;
 | 
						|
		 }
 | 
						|
		 delete $3;
 | 
						|
		 delete $5;
 | 
						|
	       }
 | 
						|
/* Clear a typemap in current language */
 | 
						|
 | 
						|
               | TYPEMAP LPAREN tm_method RPAREN tm_list SEMI {
 | 
						|
		 if (!typemap_lang) {
 | 
						|
		   fprintf(stderr,"SWIG internal error. No typemap_lang specified.\n");
 | 
						|
		   fprintf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
 | 
						|
		   FatalError();
 | 
						|
		 } else {
 | 
						|
		   TMParm *p;
 | 
						|
		   p = $5;
 | 
						|
		   while (p) {
 | 
						|
		     typemap_clear($3,typemap_lang,p->p->t,p->p->name);
 | 
						|
		     p = p->next;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
		 delete $3;
 | 
						|
	       }
 | 
						|
 | 
						|
/* Copy a typemap */
 | 
						|
 | 
						|
               | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
 | 
						|
                   TMParm *p;
 | 
						|
		   p = $7;
 | 
						|
		   while (p) {
 | 
						|
		     typemap_copy($5,$3,$9->p->t,$9->p->name,p->p->t,p->p->name);
 | 
						|
		     p = p->next;
 | 
						|
		   }
 | 
						|
		   delete $3;
 | 
						|
		   delete $5;
 | 
						|
		   delete $9->p;
 | 
						|
		   delete $9;
 | 
						|
	       }
 | 
						|
 | 
						|
/* Copy typemap in current language */
 | 
						|
 | 
						|
               | TYPEMAP LPAREN tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
 | 
						|
		 if (!typemap_lang) {
 | 
						|
		   fprintf(stderr,"SWIG internal error. No typemap_lang specified.\n");
 | 
						|
		   fprintf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
 | 
						|
		   FatalError();
 | 
						|
		 } else {
 | 
						|
                   TMParm *p;
 | 
						|
		   p = $5;
 | 
						|
		   while (p) {
 | 
						|
		     typemap_copy($3,typemap_lang,$7->p->t,$7->p->name,p->p->t,p->p->name);
 | 
						|
		     p = p->next;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
		 delete $3;
 | 
						|
		 delete $7->p;
 | 
						|
		 delete $7;
 | 
						|
	       }
 | 
						|
/* -----------------------------------------------------------------
 | 
						|
   apply and clear support (for typemaps)
 | 
						|
   ----------------------------------------------------------------- */
 | 
						|
 | 
						|
               | APPLY typemap_parm LBRACE tm_list RBRACE {
 | 
						|
		 TMParm *p;
 | 
						|
		 p = $4;
 | 
						|
		 while(p) {
 | 
						|
		   typemap_apply($2->p->t,$2->p->name,p->p->t,p->p->name);
 | 
						|
		   p = p->next;
 | 
						|
		 }
 | 
						|
		 delete $4;
 | 
						|
		 delete $2->args;
 | 
						|
		 delete $2;
 | 
						|
               }
 | 
						|
	       | CLEAR tm_list SEMI {
 | 
						|
		 TMParm *p;
 | 
						|
		 p = $2;
 | 
						|
		 while (p) {
 | 
						|
		   typemap_clear_apply(p->p->t, p->p->name);
 | 
						|
		   p = p->next;
 | 
						|
		 }
 | 
						|
               }
 | 
						|
 | 
						|
 | 
						|
/* -----------------------------------------------------------------
 | 
						|
   exception support
 | 
						|
 | 
						|
   These constructs are used to define exceptions
 | 
						|
   ----------------------------------------------------------------- */
 | 
						|
 | 
						|
/* An exception definition */
 | 
						|
               | EXCEPT LPAREN ID RPAREN LBRACE {
 | 
						|
                    skip_brace();
 | 
						|
                    fragment_register("except",$3, CCode);
 | 
						|
		    delete $3;
 | 
						|
	       }
 | 
						|
 | 
						|
/* A Generic Exception (no language specified */
 | 
						|
               | EXCEPT LBRACE {
 | 
						|
                    skip_brace();
 | 
						|
                    fragment_register("except",typemap_lang, CCode);
 | 
						|
               }
 | 
						|
 | 
						|
/* Clear an exception */
 | 
						|
 | 
						|
               | EXCEPT LPAREN ID RPAREN SEMI {
 | 
						|
                     fragment_clear("except",$3);
 | 
						|
               }
 | 
						|
 | 
						|
/* Generic clear */
 | 
						|
               | EXCEPT SEMI {
 | 
						|
                     fragment_clear("except",typemap_lang);
 | 
						|
	       }
 | 
						|
   
 | 
						|
/* Miscellaenous stuff */
 | 
						|
 | 
						|
               | SEMI { }
 | 
						|
               | cpp { }
 | 
						|
               | objective_c { }
 | 
						|
               | error {
 | 
						|
		 if (!Error) {
 | 
						|
		   {
 | 
						|
		     static int last_error_line = -1;
 | 
						|
		     if (last_error_line != line_number) {
 | 
						|
		       fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 | 
						|
		       FatalError();
 | 
						|
		       last_error_line = line_number;
 | 
						|
                       // Try to make some kind of recovery.
 | 
						|
		       skip_decl();
 | 
						|
		     }
 | 
						|
		     Error = 1;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* A an extern C type declaration.  Does nothing, but is ignored */
 | 
						|
 | 
						|
               | EXTERN STRING LBRACE command RBRACE { }
 | 
						|
               | cond_compile { }
 | 
						|
 | 
						|
/* Officially, this directive doesn't exist yet */
 | 
						|
 | 
						|
               | pragma { }
 | 
						|
 | 
						|
/* %style directive.   This applies to all current styles */
 | 
						|
 | 
						|
               | STYLE stylelist {
 | 
						|
		 { 
 | 
						|
		   int ii,jj;
 | 
						|
		   for (ii = 0; ii < $2.count; ii++) {
 | 
						|
		     comment_handler->style($2.names[ii],$2.values[ii]);
 | 
						|
		     for (jj = 0; jj < doc_stack_top; jj++) 
 | 
						|
		       doc_stack[jj]->style($2.names[ii],$2.values[ii]);
 | 
						|
		     if (doctitle)
 | 
						|
		       doctitle->style($2.names[ii],$2.values[ii]);
 | 
						|
		     doc->style($2.names[ii],$2.values[ii]);
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* %localstyle directive.   This applies only to the current style */
 | 
						|
 | 
						|
               | LOCALSTYLE stylelist {
 | 
						|
		 { 
 | 
						|
		   int ii;
 | 
						|
		   for (ii = 0; ii < $2.count; ii++) {
 | 
						|
		     comment_handler = new CommentHandler(comment_handler);
 | 
						|
		     handler_stack[doc_stack_top] = comment_handler;
 | 
						|
		     comment_handler->style($2.names[ii],$2.values[ii]);
 | 
						|
		     doc_stack[doc_stack_top]->style($2.names[ii],$2.values[ii]);
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* User defined directive */
 | 
						|
               | user_directive{ }
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
/* Dcumentation disable/enable */
 | 
						|
 | 
						|
doc_enable     : DOC_DISABLE {
 | 
						|
		 if (allow) {
 | 
						|
		   if (IgnoreDoc) {
 | 
						|
		     /* Already in a disabled documentation */
 | 
						|
		     doc_scope++;
 | 
						|
		   } else {
 | 
						|
		     if (Verbose)
 | 
						|
		       fprintf(stderr,"%s : Line %d. Documentation disabled.\n", input_file, line_number);
 | 
						|
		     IgnoreDoc = 1;
 | 
						|
		     doc_scope = 1;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
/* %enabledoc directive */
 | 
						|
               | DOC_ENABLE {
 | 
						|
		 if (allow) {
 | 
						|
		   if (IgnoreDoc) {
 | 
						|
		     if (doc_scope > 1) {
 | 
						|
		       doc_scope--;
 | 
						|
		     } else {
 | 
						|
		       if (Verbose)
 | 
						|
			 fprintf(stderr,"%s : Line %d. Documentation enabled.\n", input_file, line_number);
 | 
						|
		       IgnoreDoc = 0;
 | 
						|
		       doc_scope = 0;
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Note : This really needs to be re-done */
 | 
						|
 | 
						|
/* A typedef with pointers */
 | 
						|
typedef_decl   : TYPEDEF type declaration {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   /* Add a new typedef */
 | 
						|
		   Active_typedef = new DataType($2);
 | 
						|
		   $2->is_pointer += $3.is_pointer;
 | 
						|
		   $2->typedef_add($3.id);
 | 
						|
		   /* If this is %typedef, add it to the header */
 | 
						|
		   if ($1) 
 | 
						|
		     fprintf(f_header,"typedef %s %s;\n", $2->print_full(), $3.id);
 | 
						|
		   cplus_register_type($3.id);
 | 
						|
		 }
 | 
						|
	       } typedeflist { };
 | 
						|
 | 
						|
/* A rudimentary typedef involving function pointers */
 | 
						|
 | 
						|
               | TYPEDEF type LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   /* Typedef'd pointer */
 | 
						|
		   if ($1) {
 | 
						|
		     sprintf(temp_name,"(*%s)",$5);
 | 
						|
		     fprintf(f_header,"typedef ");
 | 
						|
		     emit_extern_func(temp_name, $2,$8,0,f_header);
 | 
						|
		   }
 | 
						|
		   strcpy($2->name,"<function ptr>");
 | 
						|
		   $2->type = T_USER;
 | 
						|
		   $2->is_pointer = 1;
 | 
						|
		   $2->typedef_add($5,1);
 | 
						|
		   cplus_register_type($5);
 | 
						|
		 }
 | 
						|
		 delete $2;
 | 
						|
		 delete $5;
 | 
						|
		 delete $8;
 | 
						|
	       }
 | 
						|
 | 
						|
/* A typedef involving function pointers again */
 | 
						|
 | 
						|
               | TYPEDEF type stars LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   if ($1) {
 | 
						|
		     $2->is_pointer += $3;
 | 
						|
		     sprintf(temp_name,"(*%s)",$6);
 | 
						|
		     fprintf(f_header,"typedef ");
 | 
						|
		     emit_extern_func(temp_name, $2,$9,0,f_header);
 | 
						|
		   }
 | 
						|
 | 
						|
		   /* Typedef'd pointer */
 | 
						|
		   strcpy($2->name,"<function ptr>");
 | 
						|
		   $2->type = T_USER;
 | 
						|
		   $2->is_pointer = 1;
 | 
						|
		   $2->typedef_add($6,1);
 | 
						|
		   cplus_register_type($6);
 | 
						|
		 }
 | 
						|
		 delete $2;
 | 
						|
		 delete $6;
 | 
						|
		 delete $9;
 | 
						|
	       }
 | 
						|
 | 
						|
/* A typedef involving arrays */
 | 
						|
 | 
						|
               | TYPEDEF type declaration array {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   Active_typedef = new DataType($2);
 | 
						|
		   // This datatype is going to be readonly
 | 
						|
			
 | 
						|
		   $2->status = STAT_READONLY | STAT_REPLACETYPE;
 | 
						|
		   $2->is_pointer += $3.is_pointer;
 | 
						|
		   // Turn this into a "pointer" corresponding to the array
 | 
						|
		   $2->is_pointer++;
 | 
						|
		   $2->arraystr = copy_string(ArrayString);
 | 
						|
		   $2->typedef_add($3.id);
 | 
						|
		   fprintf(stderr,"%s : Line %d. Warning. Array type %s will be read-only without a typemap\n",input_file,line_number, $3.id);
 | 
						|
		   cplus_register_type($3.id);
 | 
						|
 | 
						|
		 }
 | 
						|
	       } typedeflist { }
 | 
						|
               ;
 | 
						|
 | 
						|
/* ------------------------------------------------------------------------
 | 
						|
   Typedef list
 | 
						|
   
 | 
						|
   The following rules are used to manage typedef lists.  Only a temporary
 | 
						|
   hack until the SWIG 2.0 parser gets online.
 | 
						|
 | 
						|
   Active_typedef contains the datatype of the last typedef (if applicable)
 | 
						|
   ------------------------------------------------------------------------ */
 | 
						|
             
 | 
						|
 | 
						|
typedeflist   : COMMA declaration typedeflist {
 | 
						|
                if (allow) {
 | 
						|
		  if (Active_typedef) {
 | 
						|
		    DataType *t;
 | 
						|
		    t = new DataType(Active_typedef);
 | 
						|
		    t->is_pointer += $2.is_pointer;
 | 
						|
		    t->typedef_add($2.id);
 | 
						|
		    cplus_register_type($2.id);
 | 
						|
		    delete t;
 | 
						|
		  }
 | 
						|
		}
 | 
						|
              }
 | 
						|
              | COMMA declaration array {
 | 
						|
		    DataType *t;
 | 
						|
		    t = new DataType(Active_typedef);
 | 
						|
		    t->status = STAT_READONLY | STAT_REPLACETYPE;
 | 
						|
		    t->is_pointer += $2.is_pointer + 1;
 | 
						|
		    t->arraystr = copy_string(ArrayString);
 | 
						|
		    t->typedef_add($2.id);
 | 
						|
		    cplus_register_type($2.id);
 | 
						|
		    delete t;
 | 
						|
    		    fprintf(stderr,"%s : Line %d. Warning. Array type %s will be read-only without a typemap.\n",input_file,line_number, $2.id);
 | 
						|
	      }
 | 
						|
              | empty { }
 | 
						|
              ;
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------
 | 
						|
   Conditional Compilation
 | 
						|
 | 
						|
   SWIG supports the following constructs
 | 
						|
           #ifdef
 | 
						|
	   #ifndef
 | 
						|
	   #else
 | 
						|
	   #endif
 | 
						|
	   #if defined(ID)
 | 
						|
	   #if ! defined(ID)
 | 
						|
	   #elif
 | 
						|
	  
 | 
						|
   #if, and #elif are a little weak in this implementation
 | 
						|
   ---------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
 | 
						|
/* #ifdef directive */
 | 
						|
cond_compile   : IFDEF ID {
 | 
						|
		 /* Push old if-then-else status */
 | 
						|
		 if_push();
 | 
						|
		 /* Look a symbol up in the symbol table */
 | 
						|
		 if (lookup_symbol($2)) {
 | 
						|
		   in_then = 1;
 | 
						|
		   in_else = 0;
 | 
						|
		   allow = 1 & prev_allow;
 | 
						|
		 } else {
 | 
						|
		   /* Condition is false.   Skip over whatever is in this block */
 | 
						|
		   in_else = skip_cond(1);
 | 
						|
		   if (in_else == -1) {
 | 
						|
		     /* Unrecoverable error */
 | 
						|
		     SWIG_exit(1);
 | 
						|
		   }
 | 
						|
		   if (!in_else) {
 | 
						|
		     if_pop();        // Pop out. Reached end of block
 | 
						|
		   } else {
 | 
						|
		     allow = prev_allow;
 | 
						|
		     in_then = 0;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
                }
 | 
						|
 | 
						|
/* #ifndef directive */
 | 
						|
 | 
						|
               | IFNDEF ID {
 | 
						|
		 if_push();
 | 
						|
		 if (lookup_symbol($2)) {
 | 
						|
		   /* Condition is false.   Skip over whatever is in this block */
 | 
						|
		   in_else = skip_cond(1);
 | 
						|
		   if (in_else == -1) {
 | 
						|
		     /* Unrecoverable error */
 | 
						|
		     SWIG_exit(1);
 | 
						|
		   }
 | 
						|
		   if (!in_else) {
 | 
						|
		     if_pop();        // Pop out. Reached end of block
 | 
						|
		   } else {
 | 
						|
		     allow = prev_allow;
 | 
						|
		     in_then = 0;
 | 
						|
		   }
 | 
						|
		 } else {
 | 
						|
		   in_then = 1;
 | 
						|
		   in_else = 0;		   
 | 
						|
		   allow = 1 & prev_allow;
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* #else directive */
 | 
						|
               | ELSE {
 | 
						|
		 if ((!in_then) || (in_else)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Misplaced else\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 } else {
 | 
						|
		   in_then = 0;
 | 
						|
		   in_else = 1;
 | 
						|
		   if (allow) {
 | 
						|
		     allow = 0;
 | 
						|
		     /* Skip over rest of the conditional */
 | 
						|
		     skip_cond(0);
 | 
						|
		     if_pop();
 | 
						|
		   } else {
 | 
						|
		     allow = 1;
 | 
						|
		   }
 | 
						|
		   allow = allow & prev_allow;
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
/* #endif directive */
 | 
						|
               | ENDIF {
 | 
						|
		 if ((!in_then) && (!in_else)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Misplaced endif\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 } else {
 | 
						|
		   if_pop();
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* #if */
 | 
						|
               | IF cpp_const_expr {
 | 
						|
		 /* Push old if-then-else status */
 | 
						|
		 if_push();
 | 
						|
		 if ($2) {
 | 
						|
		   in_then = 1;
 | 
						|
		   in_else = 0;
 | 
						|
		   allow = 1 & prev_allow;
 | 
						|
		 } else {
 | 
						|
		   /* Condition is false.   Skip over whatever is in this block */
 | 
						|
		   in_else = skip_cond(1);
 | 
						|
		   if (in_else == -1) {
 | 
						|
		     /* Unrecoverable error */
 | 
						|
		     SWIG_exit(1);
 | 
						|
		   }
 | 
						|
		   if (!in_else) {
 | 
						|
		     if_pop();        // Pop out. Reached end of block
 | 
						|
		   } else {
 | 
						|
		     allow = prev_allow;
 | 
						|
		     in_then = 0;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
 | 
						|
/* #elif.  We treat this identical to an #if.  Abit of a hack, but what
 | 
						|
   the hell. */
 | 
						|
 | 
						|
               | ELIF cpp_const_expr {
 | 
						|
		 /* have to pop old if clause off */
 | 
						|
		 if_pop();
 | 
						|
 | 
						|
		 /* Push old if-then-else status */
 | 
						|
		 if_push();
 | 
						|
		 if ($2) {
 | 
						|
		   in_then = 1;
 | 
						|
		   in_else = 0;
 | 
						|
		   allow = 1 & prev_allow;
 | 
						|
		 } else {
 | 
						|
		   /* Condition is false.   Skip over whatever is in this block */
 | 
						|
		   in_else = skip_cond(1);
 | 
						|
		   if (in_else == -1) {
 | 
						|
		     /* Unrecoverable error */
 | 
						|
		     SWIG_exit(1);
 | 
						|
		   }
 | 
						|
		   if (!in_else) {
 | 
						|
		     if_pop();        // Pop out. Reached end of block
 | 
						|
		   } else {
 | 
						|
		     allow = prev_allow;
 | 
						|
		     in_then = 0;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* C preprocessor expression (only used for conditional compilation */
 | 
						|
 | 
						|
cpp_const_expr : DEFINED LPAREN ID RPAREN {
 | 
						|
 | 
						|
                 /* Look ID up in the symbol table */
 | 
						|
                    if (lookup_symbol($3)) {
 | 
						|
		      $$ = 1;
 | 
						|
		    } else {
 | 
						|
		      $$ = 0;
 | 
						|
		    }
 | 
						|
               }
 | 
						|
               | DEFINED ID {
 | 
						|
		 if (lookup_symbol($2)) {
 | 
						|
		   $$ = 1;
 | 
						|
		 } else {
 | 
						|
		   $$ = 0;
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
               | LNOT cpp_const_expr {
 | 
						|
                      if ($2) $$ = 0;
 | 
						|
		      else $$ = 1;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
pragma         : PRAGMA LPAREN ID COMMA ID stylearg RPAREN {
 | 
						|
		 if (allow && (!WrapExtern))
 | 
						|
		   lang->pragma($3,$5,$6);
 | 
						|
		   fprintf(stderr,"%s : Line %d. Warning. '%%pragma(lang,opt=value)' syntax is obsolete.\n",
 | 
						|
			   input_file,line_number);
 | 
						|
		   fprintf(stderr,"        Use '%%pragma(lang) opt=value' instead.\n");
 | 
						|
	       }
 | 
						|
 | 
						|
               | PRAGMA ID stylearg {
 | 
						|
                 if (allow && (!WrapExtern)) 
 | 
						|
		   swig_pragma($2,$3);
 | 
						|
    	       }
 | 
						|
               | PRAGMA LPAREN ID RPAREN ID stylearg {
 | 
						|
		 if (allow && (!WrapExtern))
 | 
						|
		   lang->pragma($3,$5,$6);
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Allow lists of variables and functions to be built up */
 | 
						|
 | 
						|
stail          : SEMI { }
 | 
						|
               | COMMA declaration array2 def_args {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   temp_typeptr = new DataType(Active_type);
 | 
						|
		   temp_typeptr->is_pointer += $2.is_pointer;
 | 
						|
		   if ($3 > 0) {
 | 
						|
		     temp_typeptr->is_pointer++;
 | 
						|
		     temp_typeptr->status = STAT_READONLY;
 | 
						|
		     temp_typeptr->arraystr = copy_string(ArrayString);
 | 
						|
		   }
 | 
						|
		   if ($2.is_reference) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
 | 
						|
		     FatalError();
 | 
						|
		   } else {
 | 
						|
		     if (temp_typeptr->qualifier) {
 | 
						|
		       if ((strcmp(temp_typeptr->qualifier,"const") == 0)) {
 | 
						|
			 /* Okay.  This is really some sort of C++ constant here. */
 | 
						|
			 if ($4.type != T_ERROR)
 | 
						|
			   create_constant($2.id, temp_typeptr, $4.id);
 | 
						|
		       } else 
 | 
						|
			 create_variable(Active_extern,$2.id, temp_typeptr);
 | 
						|
		     } else
 | 
						|
		       create_variable(Active_extern, $2.id, temp_typeptr);
 | 
						|
		   }
 | 
						|
		   delete temp_typeptr;
 | 
						|
		 }
 | 
						|
	       } stail { } 
 | 
						|
               | COMMA declaration LPAREN parms RPAREN cpp_const {
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   temp_typeptr = new DataType(Active_type);
 | 
						|
		   temp_typeptr->is_pointer += $2.is_pointer;
 | 
						|
		   temp_typeptr->is_reference = $2.is_reference;
 | 
						|
		   create_function(Active_extern, $2.id, temp_typeptr, $4);
 | 
						|
		   delete temp_typeptr;
 | 
						|
		 }
 | 
						|
		 delete $4;
 | 
						|
	       } stail { }
 | 
						|
              ;
 | 
						|
 | 
						|
definetail     : definetype ENDDEF {
 | 
						|
                   $$ = $1;
 | 
						|
                 } 
 | 
						|
               | ENDDEF {
 | 
						|
                   $$.type = T_SYMBOL;
 | 
						|
	       }
 | 
						|
               | error ENDDEF {
 | 
						|
		 if (Verbose) 
 | 
						|
		   fprintf(stderr,"%s : Line %d.  Warning. Unable to parse #define (ignored)\n", input_file, line_number);
 | 
						|
		 $$.type = T_ERROR;
 | 
						|
	       }
 | 
						|
 | 
						|
               ;
 | 
						|
 | 
						|
extern         : EXTERN { $$ = 1; }
 | 
						|
               | empty {$$ = 0; }
 | 
						|
               | EXTERN STRING {
 | 
						|
		 if (strcmp($2,"C") == 0) {
 | 
						|
		   $$ = 2;
 | 
						|
		 } else {
 | 
						|
		   fprintf(stderr,"%s : Line %d.  Unrecognized extern type \"%s\" (ignored).\n", input_file, line_number, $2);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* End of a function declaration.  Allows C++ "const" directive and inline code */
 | 
						|
 | 
						|
func_end       : cpp_const LBRACE { skip_brace(); }
 | 
						|
/*               | LBRACE { skip_brace(); } */
 | 
						|
               ;
 | 
						|
 | 
						|
/* ------------------------------------------------------------------------------
 | 
						|
   Function parameter lists
 | 
						|
 | 
						|
   ------------------------------------------------------------------------------ */
 | 
						|
 | 
						|
parms          : parm ptail {
 | 
						|
                 if (($1->t->type != T_VOID) || ($1->t->is_pointer))
 | 
						|
		   $2->insert($1,0);
 | 
						|
		 $$ = $2;
 | 
						|
		 delete $1;
 | 
						|
		}
 | 
						|
               | empty { $$ = new ParmList;}
 | 
						|
               ;
 | 
						|
 | 
						|
ptail          : COMMA parm ptail {
 | 
						|
		 $3->insert($2,0);
 | 
						|
		 $$ = $3;
 | 
						|
		 delete $2;
 | 
						|
                }
 | 
						|
               | empty { $$ = new ParmList;}
 | 
						|
               ;
 | 
						|
 | 
						|
parm           : parm_type {
 | 
						|
                  $$ = $1;
 | 
						|
		  if (typemap_check("ignore",typemap_lang,$$->t,$$->name))
 | 
						|
		    $$->ignore = 1;
 | 
						|
               }
 | 
						|
               | parm_specifier_list parm_type {
 | 
						|
                  $$ = $2;
 | 
						|
                  $$->call_type = $$->call_type | $1;
 | 
						|
		  if (InArray && ($$->call_type & CALL_VALUE)) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Error. Can't use %%val with an array.\n", input_file, line_number);
 | 
						|
		     FatalError();
 | 
						|
		  }
 | 
						|
		  if (!$$->t->is_pointer) {
 | 
						|
		     fprintf(stderr,"%s : Line %d. Error. Can't use %%val or %%out with a non-pointer argument.\n", input_file, line_number);
 | 
						|
		     FatalError();
 | 
						|
		  } else {
 | 
						|
		    $$->t->is_pointer--;
 | 
						|
		  }
 | 
						|
		}
 | 
						|
 | 
						|
parm_type      : type pname {
 | 
						|
		    if (InArray) {
 | 
						|
		      $1->is_pointer++;
 | 
						|
		      if (Verbose) {
 | 
						|
			fprintf(stderr,"%s : Line %d. Warning. Array %s", input_file, line_number, $1->print_type());
 | 
						|
			print_array();
 | 
						|
			fprintf(stderr," has been converted to %s.\n", $1->print_type());
 | 
						|
		      }
 | 
						|
		      // Add array string to the type
 | 
						|
		      $1->arraystr = copy_string(ArrayString.get());
 | 
						|
		    } 
 | 
						|
		    $$ = new Parm($1,$2);
 | 
						|
		    $$->call_type = 0;
 | 
						|
		    $$->defvalue = DefArg;
 | 
						|
		    if (($1->type == T_USER) && !($1->is_pointer)) {
 | 
						|
		      if (Verbose)
 | 
						|
			fprintf(stderr,"%s : Line %d. Warning : Parameter of type '%s'\nhas been remapped to '%s *' and will be called using *((%s *) ptr).\n",
 | 
						|
				input_file, line_number, $1->name, $1->name, $1->name);
 | 
						|
 | 
						|
		      $$->call_type = CALL_REFERENCE;
 | 
						|
		      $$->t->is_pointer++;
 | 
						|
		    }
 | 
						|
		    delete $1;
 | 
						|
		    delete $2;
 | 
						|
                 }
 | 
						|
 | 
						|
                | type stars pname {
 | 
						|
		   $$ = new Parm($1,$3);
 | 
						|
		   $$->t->is_pointer += $2;
 | 
						|
		   $$->call_type = 0;
 | 
						|
		   $$->defvalue = DefArg;
 | 
						|
		   if (InArray) {
 | 
						|
		     $$->t->is_pointer++;
 | 
						|
		     if (Verbose) {
 | 
						|
		       fprintf(stderr,"%s : Line %d. Warning. Array %s", input_file, line_number, $$->t->print_type());
 | 
						|
		       print_array();
 | 
						|
		       fprintf(stderr," has been converted to %s.\n", $$->t->print_type());
 | 
						|
		     }
 | 
						|
		     // Add array string to the type
 | 
						|
		     $$->t->arraystr = copy_string(ArrayString.get());
 | 
						|
		    }
 | 
						|
		   delete $1;
 | 
						|
		   delete $3;
 | 
						|
		}
 | 
						|
 | 
						|
                | type AND pname {
 | 
						|
		  $$ = new Parm($1,$3);
 | 
						|
		  $$->t->is_reference = 1;
 | 
						|
		  $$->call_type = 0;
 | 
						|
		  $$->t->is_pointer++;
 | 
						|
		  $$->defvalue = DefArg;
 | 
						|
		  if (!CPlusPlus) {
 | 
						|
			fprintf(stderr,"%s : Line %d. Warning.  Use of C++ Reference detected.  Use the -c++ option.\n", input_file, line_number);
 | 
						|
		  }
 | 
						|
		  delete $1;
 | 
						|
		  delete $3;
 | 
						|
		}
 | 
						|
                | type LPAREN stars pname RPAREN LPAREN parms RPAREN {
 | 
						|
                  fprintf(stderr,"%s : Line %d. Error. Function pointer not allowed (remap with typedef).\n", input_file, line_number);
 | 
						|
		  FatalError();
 | 
						|
		  $$ = new Parm($1,$4);
 | 
						|
		  $$->t->type = T_ERROR;
 | 
						|
		  $$->name = copy_string($4);
 | 
						|
		  strcpy($$->t->name,"<function ptr>");
 | 
						|
		  delete $1;
 | 
						|
		  delete $4;
 | 
						|
		  delete $7;
 | 
						|
		}
 | 
						|
                | PERIOD PERIOD PERIOD {
 | 
						|
                  fprintf(stderr,"%s : Line %d. Variable length arguments not supported (ignored).\n", input_file, line_number);
 | 
						|
		  $$ = new Parm(new DataType(T_INT),"varargs");
 | 
						|
		  $$->t->type = T_ERROR;
 | 
						|
		  $$->name = copy_string("varargs");
 | 
						|
		  strcpy($$->t->name,"<varargs>");
 | 
						|
		  FatalError();
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
pname          : ID def_args {
 | 
						|
                    $$ = $1; 
 | 
						|
                    InArray = 0;
 | 
						|
		    if ($2.type == T_CHAR)
 | 
						|
		      DefArg = copy_string(ConstChar);
 | 
						|
		    else
 | 
						|
		      DefArg = copy_string($2.id);
 | 
						|
                    if ($2.id) delete $2.id;
 | 
						|
                }
 | 
						|
               | ID array {
 | 
						|
                    $$ = $1; 
 | 
						|
                    InArray = $2; 
 | 
						|
                    DefArg = 0;
 | 
						|
               }
 | 
						|
               | array {
 | 
						|
                         $$ = new char[1];
 | 
						|
                         $$[0] = 0;
 | 
						|
                         InArray = $1;
 | 
						|
                         DefArg = 0;
 | 
						|
               }
 | 
						|
               | empty { $$ = new char[1];
 | 
						|
	                 $$[0] = 0;
 | 
						|
                         InArray = 0;
 | 
						|
                         DefArg = 0;
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 | 
						|
def_args       : EQUAL definetype { $$ = $2; }
 | 
						|
               | EQUAL AND ID {
 | 
						|
		 $$.id = new char[strlen($3)+2];
 | 
						|
		 $$.id[0] = '&';
 | 
						|
		 strcpy(&$$.id[1], $3);
 | 
						|
		 $$.type = T_USER;
 | 
						|
	       }
 | 
						|
               | EQUAL LBRACE {
 | 
						|
		 skip_brace();
 | 
						|
		 $$.id = 0; $$.type = T_INT;
 | 
						|
	       }
 | 
						|
               | COLON NUM_INT {
 | 
						|
               }
 | 
						|
               | empty {$$.id = 0; $$.type = T_INT;}
 | 
						|
               ;
 | 
						|
 | 
						|
parm_specifier : CVALUE { $$ = CALL_VALUE; }
 | 
						|
               | COUT { $$ = CALL_OUTPUT; }
 | 
						|
               ;
 | 
						|
                
 | 
						|
parm_specifier_list : parm_specifier_list parm_specifier {
 | 
						|
                 $$ = $1 | $2;
 | 
						|
               }
 | 
						|
               | parm_specifier {
 | 
						|
                 $$ = $1;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Declaration must be an identifier, possibly preceded by a * for pointer types  */
 | 
						|
 | 
						|
declaration    : ID { $$.id = $1;
 | 
						|
                      $$.is_pointer = 0;
 | 
						|
		      $$.is_reference = 0;
 | 
						|
                }
 | 
						|
               | stars ID {
 | 
						|
                      $$.id = $2;
 | 
						|
		      $$.is_pointer = $1;
 | 
						|
		      $$.is_reference = 0;
 | 
						|
	       }
 | 
						|
               | AND ID {
 | 
						|
		      $$.id = $2;
 | 
						|
		      $$.is_pointer = 1;
 | 
						|
		      $$.is_reference = 1;
 | 
						|
		      if (!CPlusPlus) {
 | 
						|
			fprintf(stderr,"%s : Line %d. Warning.  Use of C++ Reference detected.  Use the -c++ option.\n", input_file, line_number);
 | 
						|
		      }
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
stars :          STAR empty { $$ = 1; }
 | 
						|
               | STAR stars { $$ = $2 + 1;}
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
array :        LBRACKET  RBRACKET array2 {
 | 
						|
		 $$ = $3 + 1;
 | 
						|
		 "[]" >> ArrayString;
 | 
						|
              }
 | 
						|
              | LBRACKET expr RBRACKET array2 {
 | 
						|
                 $$ = $4 + 1;
 | 
						|
		 "]" >> ArrayString;
 | 
						|
		 $2.id >> ArrayString;
 | 
						|
		 "[" >> ArrayString;
 | 
						|
              }
 | 
						|
	      ;
 | 
						|
array2 :       array {
 | 
						|
                 $$ = $1;
 | 
						|
              }
 | 
						|
              | empty { $$ = 0;
 | 
						|
                        ArrayString = "";
 | 
						|
              }
 | 
						|
	      ;
 | 
						|
 | 
						|
/* Data type must be a built in type or an identifier for user-defined types
 | 
						|
   This type can be preceded by a modifier. */
 | 
						|
 | 
						|
type           : TYPE_INT {
 | 
						|
                   $$ = $1;
 | 
						|
               }
 | 
						|
               | TYPE_SHORT opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_LONG opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_CHAR {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_BOOL {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_FLOAT {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_DOUBLE {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_VOID {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_SIGNED opt_signed {
 | 
						|
                   if ($2) $$ = $2;
 | 
						|
		   else $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_UNSIGNED opt_unsigned {
 | 
						|
                   if ($2) $$ = $2;
 | 
						|
		   else $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_TYPEDEF objc_protolist {
 | 
						|
		 $$ = $1;
 | 
						|
		 if (strlen($2) > 0) {
 | 
						|
		    if ((strlen($2) + strlen($$->name)) >= MAX_NAME) {
 | 
						|
		      fprintf(stderr,"%s : Line %d. Fatal error. Type-name is too long!\n", 
 | 
						|
			      input_file, line_number);
 | 
						|
		    } else {
 | 
						|
		      strcat($$->name,$2);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
	       }
 | 
						|
               | ID objc_protolist {
 | 
						|
		  $$ = new DataType;
 | 
						|
		  strcpy($$->name,$1);
 | 
						|
		  $$->type = T_USER;
 | 
						|
		  /* Do a typedef lookup */
 | 
						|
		  $$->typedef_resolve();
 | 
						|
		  if (strlen($2) > 0) {
 | 
						|
		    if ((strlen($2) + strlen($$->name)) >= MAX_NAME) {
 | 
						|
		      fprintf(stderr,"%s : Line %d. Fatal error. Type-name is too long!\n", 
 | 
						|
			      input_file, line_number);
 | 
						|
		    } else {
 | 
						|
		      strcat($$->name,$2);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
	       }
 | 
						|
               | CONST type {
 | 
						|
		  $$ = $2;
 | 
						|
                  $$->qualifier = new char[6];
 | 
						|
		  strcpy($$->qualifier,"const");
 | 
						|
     	       }
 | 
						|
               | cpptype ID {
 | 
						|
                  $$ = new DataType;
 | 
						|
		  sprintf($$->name,"%s %s",$1, $2);
 | 
						|
		  $$->type = T_USER;
 | 
						|
	       }
 | 
						|
               | ID DCOLON ID {
 | 
						|
                  $$ = new DataType;
 | 
						|
                  sprintf($$->name,"%s::%s",$1,$3);
 | 
						|
                  $$->type = T_USER;
 | 
						|
		  $$->typedef_resolve();
 | 
						|
               }
 | 
						|
/* This declaration causes a shift-reduce conflict.  Unresolved for now */
 | 
						|
 | 
						|
 | 
						|
               | DCOLON ID {
 | 
						|
                  $$ = new DataType;
 | 
						|
                  sprintf($$->name,"%s", $2);
 | 
						|
                  $$->type = T_USER;
 | 
						|
                  $$->typedef_resolve(1);
 | 
						|
               }
 | 
						|
               | ENUM ID {
 | 
						|
                  $$ = new DataType;
 | 
						|
                  sprintf($$->name,"enum %s", $2);
 | 
						|
                  $$->type = T_INT;
 | 
						|
                  $$->typedef_resolve(1);
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 | 
						|
/* type specification without ID symbol.   Used in some cases to prevent shift-reduce conflicts */
 | 
						|
 | 
						|
strict_type    : TYPE_INT {
 | 
						|
                   $$ = $1;
 | 
						|
               }
 | 
						|
               | TYPE_SHORT opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_LONG opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_CHAR {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_BOOL {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_FLOAT {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_DOUBLE {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_VOID {
 | 
						|
                   $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_SIGNED opt_signed {
 | 
						|
                   if ($2) $$ = $2;
 | 
						|
		   else $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_UNSIGNED opt_unsigned {
 | 
						|
                   if ($2) $$ = $2;
 | 
						|
		   else $$ = $1;
 | 
						|
	       }
 | 
						|
               | TYPE_TYPEDEF objc_protolist {
 | 
						|
		   $$ = $1;
 | 
						|
		   strcat($$->name,$2);
 | 
						|
	       }
 | 
						|
               | CONST type {
 | 
						|
		  $$ = $2;
 | 
						|
                  $$->qualifier = new char[6];
 | 
						|
		  strcpy($$->qualifier,"const");
 | 
						|
     	       }
 | 
						|
               | cpptype ID {
 | 
						|
                  $$ = new DataType;
 | 
						|
		  sprintf($$->name,"%s %s",$1, $2);
 | 
						|
		  $$->type = T_USER;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Optional signed types */
 | 
						|
 | 
						|
opt_signed     : empty {
 | 
						|
                   $$ = (DataType *) 0;
 | 
						|
               }
 | 
						|
               | TYPE_INT {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_INT;
 | 
						|
		   sprintf(temp_name,"signed %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               | TYPE_SHORT opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_SHORT;
 | 
						|
		   sprintf(temp_name,"signed %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               | TYPE_LONG opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_LONG;
 | 
						|
		   sprintf(temp_name,"signed %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               | TYPE_CHAR {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_SCHAR;
 | 
						|
		   sprintf(temp_name,"signed %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Optional unsigned types */
 | 
						|
 | 
						|
opt_unsigned   : empty {
 | 
						|
                   $$ = (DataType *) 0;
 | 
						|
               }
 | 
						|
               | TYPE_INT {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_UINT;
 | 
						|
		   sprintf(temp_name,"unsigned %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               | TYPE_SHORT opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_USHORT;
 | 
						|
		   sprintf(temp_name,"unsigned %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               | TYPE_LONG opt_int {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_ULONG;
 | 
						|
		   sprintf(temp_name,"unsigned %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               | TYPE_CHAR {
 | 
						|
                   $$ = $1;
 | 
						|
		   $$->type = T_UCHAR;
 | 
						|
		   sprintf(temp_name,"unsigned %s",$1->name);
 | 
						|
		   strcpy($$->name,temp_name);
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
opt_int        : TYPE_INT { }
 | 
						|
               | empty { }
 | 
						|
               ;
 | 
						|
 | 
						|
definetype     : { scanner_check_typedef(); } expr {
 | 
						|
                   $$ = $2;
 | 
						|
		   scanner_ignore_typedef();
 | 
						|
		   if (ConstChar) delete ConstChar;
 | 
						|
		   ConstChar = 0;
 | 
						|
                }
 | 
						|
                | STRING {
 | 
						|
                   $$.id = $1;
 | 
						|
                   $$.type = T_CHAR;
 | 
						|
		   if (ConstChar) delete ConstChar;
 | 
						|
		   ConstChar = new char[strlen($1)+3];
 | 
						|
		   sprintf(ConstChar,"\"%s\"",$1);
 | 
						|
		}
 | 
						|
                | CHARCONST {
 | 
						|
                   $$.id = $1;
 | 
						|
		   $$.type = T_CHAR;
 | 
						|
		   if (ConstChar) delete ConstChar;
 | 
						|
		   ConstChar = new char[strlen($1)+3];
 | 
						|
		   sprintf(ConstChar,"'%s'",$1);
 | 
						|
		 }
 | 
						|
                ;	       
 | 
						|
 | 
						|
 | 
						|
/* Initialization function links */
 | 
						|
 | 
						|
initlist       : initlist COMMA ID {
 | 
						|
                 $$ = $1;
 | 
						|
		 $$.names[$$.count] = copy_string($3);
 | 
						|
		 $$.count++;
 | 
						|
		 $$.names[$$.count] = (char *) 0;
 | 
						|
                }
 | 
						|
               | empty {
 | 
						|
                 $$.names = new char *[NI_NAMES];
 | 
						|
		 $$.count = 0;
 | 
						|
		 for (i = 0; i < NI_NAMES; i++) 
 | 
						|
		   $$.names[i] = (char *) 0;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Some stuff for handling enums */
 | 
						|
 | 
						|
ename          :  ID { $$ = $1; } 
 | 
						|
               |  empty { $$ = (char *) 0;}
 | 
						|
               ;
 | 
						|
 | 
						|
/* SWIG enum list.   
 | 
						|
*/
 | 
						|
 | 
						|
enumlist       :  enumlist COMMA edecl {}
 | 
						|
               |  edecl {}
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
edecl          :  ID {
 | 
						|
		   temp_typeptr = new DataType(T_INT);
 | 
						|
		   create_constant($1, temp_typeptr, $1);
 | 
						|
		   delete temp_typeptr;
 | 
						|
		 } 
 | 
						|
                 | ID EQUAL { scanner_check_typedef();} etype {
 | 
						|
		   temp_typeptr = new DataType($4.type);
 | 
						|
// Use enum name instead of value
 | 
						|
// OLD		   create_constant($1, temp_typeptr, $4.id);
 | 
						|
                   create_constant($1, temp_typeptr, $1);
 | 
						|
		   delete temp_typeptr;
 | 
						|
                 }
 | 
						|
                 | cond_compile edecl { }
 | 
						|
                 | empty { }
 | 
						|
                 ;
 | 
						|
		   
 | 
						|
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)) {
 | 
						|
		     fprintf(stderr,"%s : Lind %d. Type error. Expecting an int\n",
 | 
						|
			     input_file, line_number);
 | 
						|
		     FatalError();
 | 
						|
		   }
 | 
						|
 | 
						|
                }
 | 
						|
                | CHARCONST {
 | 
						|
                   $$.id = $1;
 | 
						|
		   $$.type = T_CHAR;
 | 
						|
		 }
 | 
						|
                ;	       
 | 
						|
 | 
						|
/* 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           :  NUM_INT { 
 | 
						|
                  $$.id = $1;
 | 
						|
                  $$.type = T_INT;
 | 
						|
                 }
 | 
						|
               |  NUM_FLOAT {
 | 
						|
                  $$.id = $1;
 | 
						|
                  $$.type = T_DOUBLE;
 | 
						|
               }
 | 
						|
               |  NUM_UNSIGNED {
 | 
						|
                  $$.id = $1;
 | 
						|
		  $$.type = T_UINT;
 | 
						|
	       }
 | 
						|
               |  NUM_LONG {
 | 
						|
                  $$.id = $1;
 | 
						|
		  $$.type = T_LONG;
 | 
						|
	       } 
 | 
						|
               |  NUM_ULONG {
 | 
						|
                  $$.id = $1;
 | 
						|
		  $$.type = T_ULONG;
 | 
						|
	       }
 | 
						|
               |  SIZEOF LPAREN type RPAREN {
 | 
						|
	          $$.id = new char[strlen($3->name)+9];
 | 
						|
		  sprintf($$.id,"sizeof(%s)", $3->name);
 | 
						|
		  $$.type = T_INT;
 | 
						|
	       }
 | 
						|
               |  LPAREN strict_type RPAREN expr %prec UMINUS {
 | 
						|
		  $$.id = new char[strlen($4.id)+strlen($2->name)+3];
 | 
						|
		  sprintf($$.id,"(%s)%s",$2->name,$4.id);
 | 
						|
		  $$.type = $2->type;
 | 
						|
	       } 
 | 
						|
               | ID {
 | 
						|
		 $$.id = lookup_symvalue($1);
 | 
						|
		 if ($$.id == (char *) 0)
 | 
						|
		   $$.id = $1;
 | 
						|
		 else {
 | 
						|
		   $$.id = new char[strlen($$.id)+3];
 | 
						|
		   sprintf($$.id,"(%s)",lookup_symvalue($1));
 | 
						|
		 }
 | 
						|
		 temp_typeptr = lookup_symtype($1);
 | 
						|
		 if (temp_typeptr) $$.type = temp_typeptr->type;
 | 
						|
		 else $$.type = T_INT;
 | 
						|
               }
 | 
						|
               | ID DCOLON ID {
 | 
						|
                  $$.id = new char[strlen($1)+strlen($3)+3];
 | 
						|
		  sprintf($$.id,"%s::%s",$1,$3);
 | 
						|
                  $$.type = T_INT;
 | 
						|
		  delete $1;
 | 
						|
		  delete $3;
 | 
						|
               }
 | 
						|
               | expr PLUS expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"+");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
	       }
 | 
						|
               | expr MINUS expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"-");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
	       }
 | 
						|
               | expr STAR expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"*");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               | expr SLASH expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"/");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               | expr AND expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"&");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               | expr OR expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"|");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 $$.type = T_INT;
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               | expr XOR expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"^");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 $$.type = T_INT;
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               | expr LSHIFT expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,"<<");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 $$.type = T_INT;
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               | expr RSHIFT expr {
 | 
						|
	         E_BINARY($$.id,$1.id,$3.id,">>");
 | 
						|
		 $$.type = promote($1.type,$3.type);
 | 
						|
		 if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 $$.type = T_INT;
 | 
						|
		 delete $1.id;
 | 
						|
		 delete $3.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               |  MINUS expr %prec UMINUS {
 | 
						|
	          $$.id = new char[strlen($2.id)+2];
 | 
						|
		  sprintf($$.id,"-%s",$2.id);
 | 
						|
		  $$.type = $2.type;
 | 
						|
		 delete $2.id;
 | 
						|
 | 
						|
	       }
 | 
						|
               |  NOT expr {
 | 
						|
	          $$.id = new char[strlen($2.id)+2];
 | 
						|
		  sprintf($$.id,"~%s",$2.id);
 | 
						|
		  if ($2.type == T_DOUBLE) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 | 
						|
		   FatalError();
 | 
						|
		  }
 | 
						|
		  $$.type = $2.type;
 | 
						|
		  delete $2.id;
 | 
						|
	       }
 | 
						|
               |  LPAREN expr RPAREN {
 | 
						|
	          $$.id = new char[strlen($2.id)+3];
 | 
						|
	          sprintf($$.id,"(%s)", $2.id);
 | 
						|
		  $$.type = $2.type;
 | 
						|
		  delete $2.id;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
/****************************************************************/
 | 
						|
/* C++ Support                                                  */
 | 
						|
/****************************************************************/
 | 
						|
 | 
						|
cpp          : cpp_class { }
 | 
						|
             | cpp_other {}
 | 
						|
             ;
 | 
						|
  
 | 
						|
cpp_class    : 
 | 
						|
 | 
						|
/* A class/struct/union  definition */
 | 
						|
             extern cpptype ID inherit LBRACE {
 | 
						|
	       char *iname;
 | 
						|
	       if (allow) {
 | 
						|
		 init_language();
 | 
						|
		 DataType::new_scope();
 | 
						|
 | 
						|
		 sprintf(temp_name,"CPP_CLASS:%s\n",$3);
 | 
						|
		 if (add_symbol(temp_name, (DataType *) 0, (char *) 0)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $3);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 if ((!CPlusPlus) && (strcmp($2,"class") == 0))
 | 
						|
		   fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 | 
						|
 | 
						|
		 iname = make_name($3);
 | 
						|
		 doc_entry = new DocClass(iname, doc_parent());
 | 
						|
		 if (iname == $3) 
 | 
						|
		   cplus_open_class($3, 0, $2);
 | 
						|
		 else
 | 
						|
		   cplus_open_class($3, iname, $2);
 | 
						|
		 if (strcmp($2,"class") == 0)
 | 
						|
		   cplus_mode = CPLUS_PRIVATE;
 | 
						|
		 else
 | 
						|
		   cplus_mode = CPLUS_PUBLIC;
 | 
						|
		 doc_stack_top++;
 | 
						|
		 doc_stack[doc_stack_top] = doc_entry;
 | 
						|
		 scanner_clear_start();
 | 
						|
		 nested_list = 0;
 | 
						|
		 // Merge in scope from base classes
 | 
						|
		 cplus_inherit_scope($4.count,$4.names);
 | 
						|
	       }
 | 
						|
              } cpp_members RBRACE {
 | 
						|
		if (allow) {
 | 
						|
		  if ($4.names) {
 | 
						|
		    if (strcmp($2,"union") != 0)
 | 
						|
		      cplus_inherit($4.count, $4.names);
 | 
						|
		    else {
 | 
						|
		      fprintf(stderr,"%s : Line %d.  Inheritance not allowed for unions.\n",input_file, line_number);
 | 
						|
		      FatalError();
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  // Clean up the inheritance list
 | 
						|
		  if ($4.names) {
 | 
						|
		    int j;
 | 
						|
		    for (j = 0; j < $4.count; j++) {
 | 
						|
		      if ($4.names[j]) delete [] $4.names[j];
 | 
						|
		    }
 | 
						|
		    delete [] $4.names;
 | 
						|
		  }
 | 
						|
 | 
						|
		  // Dumped nested declarations (if applicable)
 | 
						|
		  dump_nested($3);
 | 
						|
 | 
						|
		  // Save and collapse current scope
 | 
						|
		  cplus_register_scope(DataType::collapse_scope($3));
 | 
						|
 | 
						|
		  // Restore the original doc entry for this class
 | 
						|
		  doc_entry = doc_stack[doc_stack_top];
 | 
						|
		  cplus_class_close((char *) 0); 
 | 
						|
		  doc_entry = 0;
 | 
						|
		  // Bump the documentation stack back down
 | 
						|
		  doc_stack_top--;
 | 
						|
		  cplus_mode = CPLUS_PUBLIC;
 | 
						|
		}
 | 
						|
	      }
 | 
						|
 | 
						|
/* Class with a typedef */
 | 
						|
		
 | 
						|
             | TYPEDEF cpptype ID inherit LBRACE {
 | 
						|
	       if (allow) {
 | 
						|
		 char *iname;
 | 
						|
		 init_language();
 | 
						|
		 DataType::new_scope();
 | 
						|
 | 
						|
		 sprintf(temp_name,"CPP_CLASS:%s\n",$3);
 | 
						|
		 if (add_symbol(temp_name, (DataType *) 0, (char *) 0)) {
 | 
						|
		   fprintf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $3);
 | 
						|
		   FatalError();
 | 
						|
		 }
 | 
						|
		 if ((!CPlusPlus) && (strcmp($2,"class") == 0))
 | 
						|
		   fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 | 
						|
		 
 | 
						|
		 iname = make_name($3);
 | 
						|
		 doc_entry = new DocClass(iname, doc_parent());
 | 
						|
		 if ($3 == iname) 
 | 
						|
		   cplus_open_class($3, 0, $2);
 | 
						|
		 else
 | 
						|
		   cplus_open_class($3, iname, $2);
 | 
						|
		 if (strcmp($2,"class") == 0)
 | 
						|
		   cplus_mode = CPLUS_PRIVATE;
 | 
						|
		 else
 | 
						|
		   cplus_mode = CPLUS_PUBLIC;
 | 
						|
		 // Create a documentation entry for the class
 | 
						|
		 doc_stack_top++;
 | 
						|
		 doc_stack[doc_stack_top] = doc_entry;
 | 
						|
		 scanner_clear_start();
 | 
						|
		 nested_list = 0;
 | 
						|
 | 
						|
		 // Merge in scope from base classes
 | 
						|
		 cplus_inherit_scope($4.count,$4.names);
 | 
						|
 | 
						|
	       }
 | 
						|
              } cpp_members RBRACE declaration {
 | 
						|
		if (allow) {
 | 
						|
		  if ($4.names) {
 | 
						|
		    if (strcmp($2,"union") != 0)
 | 
						|
		      cplus_inherit($4.count, $4.names);
 | 
						|
		    else {
 | 
						|
		      fprintf(stderr,"%s : Line %d.  Inheritance not allowed for unions.\n",input_file, line_number);
 | 
						|
		      FatalError();
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  // Create a datatype for correctly processing the typedef
 | 
						|
		  Active_typedef = new DataType();
 | 
						|
		  Active_typedef->type = T_USER;
 | 
						|
		  sprintf(Active_typedef->name,"%s %s", $2,$3);
 | 
						|
		  Active_typedef->is_pointer = 0;
 | 
						|
		  Active_typedef->implicit_ptr = 0;
 | 
						|
 | 
						|
		  // Clean up the inheritance list
 | 
						|
		  if ($4.names) {
 | 
						|
		    int j;
 | 
						|
		    for (j = 0; j < $4.count; j++) {
 | 
						|
		      if ($4.names[j]) delete [] $4.names[j];
 | 
						|
		    }
 | 
						|
		    delete [] $4.names;
 | 
						|
		  }
 | 
						|
 | 
						|
		  if ($9.is_pointer > 0) {
 | 
						|
		    fprintf(stderr,"%s : Line %d.  typedef struct { } *id not supported properly. Winging it...\n", input_file, line_number);
 | 
						|
 | 
						|
		  }
 | 
						|
		  // Create dump nested class code
 | 
						|
		  if ($9.is_pointer > 0) {
 | 
						|
		    dump_nested($3);
 | 
						|
		  } else {
 | 
						|
		    dump_nested($9.id);
 | 
						|
		  }
 | 
						|
		    
 | 
						|
		  // Collapse any datatypes created in the the class
 | 
						|
 | 
						|
		  cplus_register_scope(DataType::collapse_scope($3));
 | 
						|
 | 
						|
		  doc_entry = doc_stack[doc_stack_top];
 | 
						|
		  if ($9.is_pointer > 0) {
 | 
						|
		    cplus_class_close($3);
 | 
						|
		  } else {
 | 
						|
		    cplus_class_close($9.id); 
 | 
						|
		  }
 | 
						|
		  doc_stack_top--;
 | 
						|
		  doc_entry = 0;
 | 
						|
 | 
						|
		  // Create a typedef in global scope
 | 
						|
 | 
						|
		  if ($9.is_pointer == 0)
 | 
						|
		    Active_typedef->typedef_add($9.id);
 | 
						|
		  else {
 | 
						|
		    DataType *t = new DataType(Active_typedef);
 | 
						|
		    t->is_pointer += $9.is_pointer;
 | 
						|
		    t->typedef_add($9.id);
 | 
						|
		    cplus_register_type($9.id);
 | 
						|
		    delete t;
 | 
						|
		  }
 | 
						|
		  cplus_mode = CPLUS_PUBLIC;
 | 
						|
		}
 | 
						|
	      } typedeflist { };
 | 
						|
 | 
						|
/* An unnamed struct with a typedef */
 | 
						|
 | 
						|
             | TYPEDEF cpptype LBRACE {
 | 
						|
	       char *iname;
 | 
						|
	       if (allow) {
 | 
						|
		 init_language();
 | 
						|
		 DataType::new_scope();
 | 
						|
		 if ((!CPlusPlus) && (strcmp($2,"class") == 0))
 | 
						|
		   fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 | 
						|
		 
 | 
						|
		 iname = make_name("");
 | 
						|
		 doc_entry = new DocClass(iname,doc_parent());
 | 
						|
		 if (strlen(iname))
 | 
						|
		   cplus_open_class("", iname, $2);
 | 
						|
		 else
 | 
						|
		   cplus_open_class("",0,$2);
 | 
						|
		 if (strcmp($2,"class") == 0)
 | 
						|
		   cplus_mode = CPLUS_PRIVATE;
 | 
						|
		 else
 | 
						|
		   cplus_mode = CPLUS_PUBLIC;
 | 
						|
		 doc_stack_top++;
 | 
						|
		 doc_stack[doc_stack_top] = doc_entry;
 | 
						|
		 scanner_clear_start();
 | 
						|
		 nested_list = 0;
 | 
						|
	       }
 | 
						|
              } cpp_members RBRACE declaration {
 | 
						|
		if (allow) {
 | 
						|
		  if ($7.is_pointer > 0) {
 | 
						|
		    fprintf(stderr,"%s : Line %d. typedef %s {} *%s not supported correctly. Will be ignored.\n", input_file, line_number, $2, $7.id);
 | 
						|
		    cplus_abort();
 | 
						|
		  } else {
 | 
						|
		    sprintf(temp_name,"CPP_CLASS:%s\n",$7.id);
 | 
						|
		    if (add_symbol(temp_name, (DataType *) 0, (char *) 0)) {
 | 
						|
		      fprintf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $7.id);
 | 
						|
		      FatalError();
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  // Create a datatype for correctly processing the typedef
 | 
						|
		  Active_typedef = new DataType();
 | 
						|
		  Active_typedef->type = T_USER;
 | 
						|
		  sprintf(Active_typedef->name,"%s",$7.id);
 | 
						|
		  Active_typedef->is_pointer = 0;
 | 
						|
		  Active_typedef->implicit_ptr = 0;
 | 
						|
		  
 | 
						|
		  // Dump nested classes
 | 
						|
		  if ($7.is_pointer == 0)  
 | 
						|
		    dump_nested($7.id);
 | 
						|
 | 
						|
		  // Go back to previous scope
 | 
						|
 | 
						|
		  cplus_register_scope(DataType::collapse_scope((char *) 0));
 | 
						|
		  
 | 
						|
		  doc_entry = doc_stack[doc_stack_top];
 | 
						|
		  // Change name of doc_entry
 | 
						|
		  doc_entry->name = copy_string($7.id);
 | 
						|
		  if ($7.is_pointer == 0) 
 | 
						|
		    cplus_class_close($7.id); 
 | 
						|
		  doc_entry = 0;
 | 
						|
		  doc_stack_top--;
 | 
						|
		  cplus_mode = CPLUS_PUBLIC;
 | 
						|
		}
 | 
						|
	      } typedeflist { }
 | 
						|
             ;
 | 
						|
 | 
						|
cpp_other    :/* A dummy class name */
 | 
						|
 | 
						|
             extern cpptype ID SEMI {
 | 
						|
	       char *iname;
 | 
						|
		 if (allow) {
 | 
						|
		   init_language();
 | 
						|
		   iname = make_name($3);
 | 
						|
		   lang->cpp_class_decl($3,iname,$2);
 | 
						|
		 }
 | 
						|
	     }   
 | 
						|
 | 
						|
/* A static C++ member function (declared out of scope)  */
 | 
						|
            
 | 
						|
              | extern type declaration DCOLON ID LPAREN parms RPAREN SEMI {
 | 
						|
	       if (allow) {
 | 
						|
		 init_language();
 | 
						|
		 if (!CPlusPlus) 
 | 
						|
		   fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 | 
						|
		 
 | 
						|
		 $2->is_pointer += $3.is_pointer;
 | 
						|
		 $2->is_reference = $3.is_reference;
 | 
						|
		 // Fix up the function name
 | 
						|
		 sprintf(temp_name,"%s::%s",$3.id,$5);
 | 
						|
		 if (!Rename_true) {
 | 
						|
		   Rename_true = 1;
 | 
						|
		   sprintf(yy_rename,"%s_%s",$3.id,$5);
 | 
						|
		 }
 | 
						|
		 create_function($1, temp_name, $2, $7);
 | 
						|
	       }
 | 
						|
	       delete $2;
 | 
						|
	       delete $7;
 | 
						|
	      }
 | 
						|
 
 | 
						|
/* A static C++ member data */
 | 
						|
             | extern type declaration DCOLON ID SEMI {
 | 
						|
	       if (allow) {
 | 
						|
		 init_language();
 | 
						|
		 if (!CPlusPlus) 
 | 
						|
		   fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 | 
						|
 | 
						|
		 $2->is_pointer += $3.is_pointer;
 | 
						|
		 // Fix up the function name
 | 
						|
		 sprintf(temp_name,"%s::%s",$3.id,$5);
 | 
						|
		 if (!Rename_true) {
 | 
						|
		   Rename_true = 1;
 | 
						|
		   sprintf(yy_rename,"%s_%s",$3.id,$5);
 | 
						|
		 }
 | 
						|
		 create_variable($1,temp_name, $2);
 | 
						|
	       }
 | 
						|
	       delete $2;
 | 
						|
	     }
 | 
						|
 | 
						|
/* Operator overloading catch */
 | 
						|
 | 
						|
             | extern type declaration DCOLON OPERATOR {
 | 
						|
	       fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
 | 
						|
		skip_decl();
 | 
						|
		delete $2;
 | 
						|
	     } 
 | 
						|
 | 
						|
 | 
						|
/* Template catch */
 | 
						|
             | TEMPLATE {
 | 
						|
	       fprintf(stderr,"%s : Line %d. Templates not currently supported (ignored).\n",
 | 
						|
		       input_file, line_number);
 | 
						|
	       skip_decl();
 | 
						|
	     }
 | 
						|
 | 
						|
/* %addmethods directive used outside of a class definition */
 | 
						|
 | 
						|
             | ADDMETHODS ID LBRACE {
 | 
						|
	       cplus_mode = CPLUS_PUBLIC;
 | 
						|
               doc_entry = cplus_set_class($2);
 | 
						|
	       if (!doc_entry) {
 | 
						|
		 doc_entry = new DocClass($2,doc_parent());
 | 
						|
	       };
 | 
						|
	       doc_stack_top++;
 | 
						|
	       doc_stack[doc_stack_top] = doc_entry;
 | 
						|
	       scanner_clear_start();
 | 
						|
	       AddMethods = 1;
 | 
						|
	     } added_members RBRACE {
 | 
						|
	       cplus_unset_class();
 | 
						|
	       doc_entry = 0;
 | 
						|
	       doc_stack_top--;
 | 
						|
	       AddMethods = 0;
 | 
						|
	     }
 | 
						|
             ;
 | 
						|
 | 
						|
added_members : cpp_member cpp_members { }
 | 
						|
              | objc_method objc_methods { } 
 | 
						|
              | empty { }
 | 
						|
              ;
 | 
						|
      
 | 
						|
cpp_members  : cpp_member cpp_members {}
 | 
						|
             | ADDMETHODS LBRACE {
 | 
						|
	           AddMethods = 1;
 | 
						|
	     } cpp_members RBRACE {
 | 
						|
	           AddMethods = 0;
 | 
						|
	     } cpp_members { }
 | 
						|
	     | error {
 | 
						|
	       skip_decl();
 | 
						|
		   {
 | 
						|
		     static int last_error_line = -1;
 | 
						|
		     if (last_error_line != line_number) {
 | 
						|
		       fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 | 
						|
		       FatalError();
 | 
						|
		       last_error_line = line_number;
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
	     } cpp_members { }
 | 
						|
             | empty { }
 | 
						|
             ;
 | 
						|
 | 
						|
cpp_member   :  type declaration LPAREN parms RPAREN cpp_end {
 | 
						|
                char *iname;
 | 
						|
                if (allow) {
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    Stat_func++;
 | 
						|
		    $1->is_pointer += $2.is_pointer;
 | 
						|
		    $1->is_reference = $2.is_reference;
 | 
						|
		    if (Verbose) {
 | 
						|
		      fprintf(stderr,"Wrapping member function : %s\n",$2.id);
 | 
						|
		    }
 | 
						|
		    iname = make_name($2.id);
 | 
						|
		    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $2.id) iname = 0;
 | 
						|
		    cplus_member_func($2.id, iname, $1,$4,0);
 | 
						|
		  }
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
		delete $1;
 | 
						|
		delete $4;
 | 
						|
              }
 | 
						|
 
 | 
						|
/* Virtual member function */
 | 
						|
                      
 | 
						|
             |  VIRTUAL type declaration LPAREN parms RPAREN cpp_vend {
 | 
						|
	       char *iname;
 | 
						|
	       if (allow) {
 | 
						|
		 init_language();
 | 
						|
		 if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		   Stat_func++;
 | 
						|
		   $2->is_pointer += $3.is_pointer;
 | 
						|
		   $2->is_reference = $3.is_reference;
 | 
						|
		   if (Verbose) {
 | 
						|
		     fprintf(stderr,"Wrapping virtual member function : %s\n",$3.id);
 | 
						|
		   }
 | 
						|
		   iname = make_name($3.id);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $3.id) iname = 0;
 | 
						|
		   cplus_member_func($3.id,iname,$2,$5,1);
 | 
						|
		 }
 | 
						|
		 scanner_clear_start();
 | 
						|
	       }
 | 
						|
	       delete $2;
 | 
						|
	       delete $5;
 | 
						|
	     }
 | 
						|
 | 
						|
/* Possibly a constructor */
 | 
						|
              | ID LPAREN parms RPAREN ctor_end {
 | 
						|
		char *iname;
 | 
						|
		if (allow) {
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    Stat_func++;
 | 
						|
		    if (Verbose) {
 | 
						|
		      fprintf(stderr,"Wrapping C++ constructor %s\n", $1);
 | 
						|
		    }
 | 
						|
		    iname = make_name($1);
 | 
						|
		    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $1) iname = 0;
 | 
						|
		    cplus_constructor($1,iname, $3);
 | 
						|
		  }
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
		delete $3;
 | 
						|
	      }
 | 
						|
 | 
						|
/* A destructor (hopefully) */
 | 
						|
 | 
						|
              | NOT ID LPAREN parms RPAREN cpp_end {
 | 
						|
		char *iname;
 | 
						|
		if (allow) {
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    Stat_func++;
 | 
						|
		    if (Verbose) {
 | 
						|
		      fprintf(stderr,"Wrapping C++ destructor %s\n", $2);
 | 
						|
		    }
 | 
						|
		    iname = make_name($2);
 | 
						|
		    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $2) iname = 0;
 | 
						|
		    cplus_destructor($2,iname);
 | 
						|
		  }
 | 
						|
		}
 | 
						|
		scanner_clear_start();
 | 
						|
	      }
 | 
						|
 | 
						|
/* A virtual destructor */
 | 
						|
 | 
						|
              | VIRTUAL NOT ID LPAREN RPAREN cpp_end {
 | 
						|
 	        char *iname;
 | 
						|
		if (allow) {
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    Stat_func++;
 | 
						|
		    if (Verbose) {
 | 
						|
		      fprintf(stderr,"Wrapping C++ destructor %s\n", $3);
 | 
						|
		    }
 | 
						|
		    iname = make_name($3);
 | 
						|
		    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $3) iname = 0;
 | 
						|
		    cplus_destructor($3,iname);
 | 
						|
		  }
 | 
						|
		}
 | 
						|
		scanner_clear_start();
 | 
						|
	      }
 | 
						|
 | 
						|
/* Member data */
 | 
						|
 | 
						|
              | type declaration def_args {
 | 
						|
		if (allow) {
 | 
						|
		  char *iname;
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    if (Active_type) delete Active_type;
 | 
						|
		    Active_type = new DataType($1);
 | 
						|
		    $1->is_pointer += $2.is_pointer;
 | 
						|
		    $1->is_reference = $2.is_reference;
 | 
						|
		    if ($1->qualifier) {
 | 
						|
		      if ((strcmp($1->qualifier,"const") == 0) && ($1->is_pointer == 0)) {
 | 
						|
			// Okay.  This is really some sort of C++ constant here.
 | 
						|
	  	          if ($3.type != T_ERROR) {
 | 
						|
			    iname = make_name($2.id);
 | 
						|
			    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
			    if (iname == $2.id) iname = 0;
 | 
						|
			    cplus_declare_const($2.id,iname, $1, $3.id);
 | 
						|
			  }
 | 
						|
		      } else {
 | 
						|
			int oldstatus = Status;
 | 
						|
			char *tm;
 | 
						|
			if ($1->status & STAT_READONLY) {
 | 
						|
			  if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 | 
						|
			    Status = Status | STAT_READONLY;
 | 
						|
			}
 | 
						|
			iname = make_name($2.id);
 | 
						|
			doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
			if (iname == $2.id) iname = 0;
 | 
						|
			cplus_variable($2.id,iname,$1);
 | 
						|
			Status = oldstatus;
 | 
						|
		      }
 | 
						|
		    } else {
 | 
						|
		      char *tm = 0;
 | 
						|
		      int oldstatus = Status;
 | 
						|
		      if ($1->status & STAT_READONLY) {
 | 
						|
			if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 | 
						|
			  Status = Status | STAT_READONLY;
 | 
						|
		      }
 | 
						|
		      iname = make_name($2.id);
 | 
						|
		      doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		      if (iname == $2.id) iname = 0;
 | 
						|
		      cplus_variable($2.id,iname,$1);
 | 
						|
		      Status = oldstatus;
 | 
						|
		      if (Verbose) {
 | 
						|
			fprintf(stderr,"Wrapping member data %s\n", $2.id);
 | 
						|
		      }
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
		delete $1;
 | 
						|
	      } cpp_tail { }
 | 
						|
 | 
						|
              | type declaration array def_args {
 | 
						|
		char *iname;
 | 
						|
		if (allow) {
 | 
						|
		  int oldstatus = Status;
 | 
						|
		  char *tm = 0;
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    if (Active_type) delete Active_type;
 | 
						|
		    Active_type = new DataType($1);
 | 
						|
		    $1->is_pointer += $2.is_pointer + 1;
 | 
						|
		    $1->is_reference = $2.is_reference;
 | 
						|
		    $1->arraystr = copy_string(ArrayString);
 | 
						|
		    if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 | 
						|
		      Status = STAT_READONLY;
 | 
						|
 | 
						|
		    iname = make_name($2.id);
 | 
						|
		    doc_entry = new DocDecl(iname, doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $2.id) iname = 0;
 | 
						|
		    cplus_variable($2.id,iname,$1);
 | 
						|
		    Status = oldstatus;
 | 
						|
		    if (!tm)
 | 
						|
		      fprintf(stderr,"%s : Line %d. Warning. Array member will be read-only.\n",input_file,line_number);
 | 
						|
		  }
 | 
						|
		scanner_clear_start();
 | 
						|
		}
 | 
						|
		delete $1;
 | 
						|
	      }
 | 
						|
  
 | 
						|
 | 
						|
/* Static Member data */
 | 
						|
 | 
						|
              | STATIC type declaration {
 | 
						|
		char *iname;
 | 
						|
		if (allow) {
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    $2->is_pointer += $3.is_pointer;
 | 
						|
		    iname = make_name($3.id);
 | 
						|
		    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $3.id) iname = 0;
 | 
						|
		    cplus_static_var($3.id,iname,$2);
 | 
						|
		    if (Active_type) delete Active_type;
 | 
						|
		    Active_type = new DataType($2);
 | 
						|
		    if (Verbose) {
 | 
						|
		      fprintf(stderr,"Wrapping static member data %s\n", $3.id);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
		delete $2;
 | 
						|
	      } cpp_tail { }
 | 
						|
 | 
						|
/* Static member function */
 | 
						|
 | 
						|
              | STATIC type declaration LPAREN parms RPAREN cpp_end {
 | 
						|
		char *iname;
 | 
						|
		if (allow) {
 | 
						|
		  $2->is_pointer += $3.is_pointer;
 | 
						|
		  $2->is_reference = $3.is_reference;
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		    iname = make_name($3.id);
 | 
						|
		    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		    if (iname == $3.id) iname = 0;
 | 
						|
		    cplus_static_func($3.id, iname, $2, $5);
 | 
						|
		    if (Verbose)
 | 
						|
		      fprintf(stderr,"Wrapping static member function %s\n",$3.id);
 | 
						|
		  }
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
		delete $2;
 | 
						|
		delete $5;
 | 
						|
	      }
 | 
						|
/* Turn on public: mode */
 | 
						|
 | 
						|
              | PUBLIC COLON {
 | 
						|
		if (allow) {
 | 
						|
		  cplus_mode = CPLUS_PUBLIC;
 | 
						|
		  if (Verbose)
 | 
						|
		    fprintf(stderr,"Public mode\n");
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
	      }
 | 
						|
 | 
						|
/* Turn on private: mode */
 | 
						|
 | 
						|
              | PRIVATE COLON {
 | 
						|
		if (allow) {
 | 
						|
		  cplus_mode = CPLUS_PRIVATE;
 | 
						|
		  if (Verbose)
 | 
						|
		    fprintf(stderr,"Private mode\n");
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
	      }
 | 
						|
 | 
						|
/* Turn on protected mode */
 | 
						|
 | 
						|
              | PROTECTED COLON {
 | 
						|
		if (allow) {
 | 
						|
		  cplus_mode = CPLUS_PROTECTED;
 | 
						|
		  if (Verbose)
 | 
						|
		    fprintf(stderr,"Protected mode\n");
 | 
						|
		  scanner_clear_start();
 | 
						|
		}
 | 
						|
	      }
 | 
						|
 | 
						|
/* This is the new style rename */
 | 
						|
 | 
						|
             | NAME LPAREN ID RPAREN {
 | 
						|
	       if (allow) {
 | 
						|
		 strcpy(yy_rename,$3);
 | 
						|
		 Rename_true = 1;
 | 
						|
	       }
 | 
						|
	     } 
 | 
						|
 | 
						|
/* New mode */
 | 
						|
             | NEW {
 | 
						|
                 NewObject = 1;
 | 
						|
             } cpp_member {
 | 
						|
                 NewObject = 0;
 | 
						|
             }
 | 
						|
 | 
						|
/* C++ Enum */
 | 
						|
              | ENUM ename LBRACE {scanner_clear_start();} cpp_enumlist RBRACE SEMI {
 | 
						|
 | 
						|
		 // if ename was supplied.  Install it as a new integer datatype.
 | 
						|
 | 
						|
		if (allow) {
 | 
						|
		  init_language();
 | 
						|
		  if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		   if ($2) {
 | 
						|
		     cplus_register_type($2);
 | 
						|
		     temp_type.type = T_INT;
 | 
						|
		     temp_type.is_pointer = 0;
 | 
						|
		     temp_type.implicit_ptr = 0;
 | 
						|
		     sprintf(temp_type.name,"int");
 | 
						|
		     temp_type.typedef_add($2,1); 
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       }
 | 
						|
	      }
 | 
						|
              | READONLY {
 | 
						|
		if (allow)
 | 
						|
		  Status = Status | STAT_READONLY;
 | 
						|
		scanner_clear_start();
 | 
						|
              }
 | 
						|
              | READWRITE {
 | 
						|
		if (allow) 
 | 
						|
		  Status = Status & ~(STAT_READONLY);
 | 
						|
		scanner_clear_start();
 | 
						|
	      }
 | 
						|
/* A friend :   Illegal */
 | 
						|
              | FRIEND {
 | 
						|
		if (allow)
 | 
						|
		  fprintf(stderr,"%s : Line %d. Friends are not allowed--members only! (ignored)\n", input_file, line_number);
 | 
						|
		skip_decl();
 | 
						|
		scanner_clear_start();
 | 
						|
	      }  
 | 
						|
 | 
						|
/* An operator: Illegal */
 | 
						|
              | type type_extra OPERATOR {
 | 
						|
		if (allow)
 | 
						|
		  fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
 | 
						|
		skip_decl();
 | 
						|
		scanner_clear_start();
 | 
						|
	      }
 | 
						|
              | cond_compile { 
 | 
						|
		scanner_clear_start();
 | 
						|
	      }
 | 
						|
 | 
						|
/* A typedef inside a class */
 | 
						|
              | typedef_decl { }
 | 
						|
 | 
						|
/* Pragma directive */
 | 
						|
 | 
						|
              | cpp_pragma {
 | 
						|
	      		scanner_clear_start();
 | 
						|
	      }
 | 
						|
 | 
						|
 | 
						|
cpp_pragma    : PRAGMA ID stylearg {
 | 
						|
                 if (allow && (!WrapExtern)) { }
 | 
						|
    	       }
 | 
						|
               | PRAGMA LPAREN ID RPAREN ID stylearg {
 | 
						|
		 if (allow && (!WrapExtern))
 | 
						|
                   cplus_add_pragma($3,$5,$6);
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------
 | 
						|
   Nested structure.    This is a big ugly "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 */
 | 
						|
 | 
						|
              | cpptype ID LBRACE { start_line = line_number; skip_brace(); 
 | 
						|
	      } nested_decl SEMI { 
 | 
						|
 | 
						|
		if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		  cplus_register_type($2);
 | 
						|
		  if ($5.id) {
 | 
						|
		    if (strcmp($1,"class") == 0) {
 | 
						|
		      fprintf(stderr,"%s : Line %d.  Warning. Nested classes not currently supported (ignored).\n", input_file, line_number);
 | 
						|
		      /* Generate some code for a new class */
 | 
						|
		    } else {
 | 
						|
		      Nested *n = new Nested;
 | 
						|
		      n->code << "typedef " << $1 << " " 
 | 
						|
			      << CCode.get() << " $classname_" << $5.id << ";\n";
 | 
						|
		      n->name = copy_string($5.id);
 | 
						|
		      n->line = start_line;
 | 
						|
		      n->type = new DataType;
 | 
						|
		      n->type->type = T_USER;
 | 
						|
		      n->type->is_pointer = $5.is_pointer;
 | 
						|
		      n->type->is_reference = $5.is_reference;
 | 
						|
		      n->next = 0;
 | 
						|
		      add_nested(n);
 | 
						|
		    }
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	      }
 | 
						|
/* An unnamed structure definition */
 | 
						|
              | cpptype LBRACE { start_line = line_number; skip_brace();
 | 
						|
              } declaration SEMI { 
 | 
						|
		if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		  if (strcmp($1,"class") == 0) {
 | 
						|
		    fprintf(stderr,"%s : Line %d.  Warning. Nested classes not currently supported (ignored)\n", input_file, line_number);
 | 
						|
		    /* Generate some code for a new class */
 | 
						|
		  } else {
 | 
						|
		    /* Generate some code for a new class */
 | 
						|
 | 
						|
		    Nested *n = new Nested;
 | 
						|
		    n->code << "typedef " << $1 << " " 
 | 
						|
			    << CCode.get() << " $classname_" << $4.id << ";\n";
 | 
						|
		    n->name = copy_string($4.id);
 | 
						|
		    n->line = start_line;
 | 
						|
		    n->type = new DataType;
 | 
						|
		    n->type->type = T_USER;
 | 
						|
		    n->type->is_pointer = $4.is_pointer;
 | 
						|
		    n->type->is_reference = $4.is_reference;
 | 
						|
		    n->next = 0;
 | 
						|
		    add_nested(n);
 | 
						|
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	      }
 | 
						|
/* An empty class declaration */
 | 
						|
              | cpptype ID SEMI {
 | 
						|
  		    if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
                       cplus_register_type($2);
 | 
						|
                    }
 | 
						|
              }
 | 
						|
 | 
						|
/* Other miscellaneous errors */
 | 
						|
              | type stars LPAREN { 
 | 
						|
                     skip_decl();
 | 
						|
                     fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
 | 
						|
		     
 | 
						|
	      }
 | 
						|
              | strict_type LPAREN STAR {
 | 
						|
                     skip_decl();
 | 
						|
                     fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
 | 
						|
		     
 | 
						|
	      }
 | 
						|
              | ID LPAREN STAR { 
 | 
						|
                     skip_decl();
 | 
						|
                     fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
 | 
						|
		     
 | 
						|
	      }
 | 
						|
              | doc_enable { }
 | 
						|
              | SEMI { }
 | 
						|
              ;
 | 
						|
 | 
						|
nested_decl   : declaration { $$ = $1;}
 | 
						|
              | empty { $$.id = 0; }
 | 
						|
              ;
 | 
						|
 | 
						|
type_extra    : stars {}
 | 
						|
              | AND {}
 | 
						|
              | empty {}
 | 
						|
              ; 
 | 
						|
 | 
						|
cpp_tail      : SEMI { }
 | 
						|
               | COMMA declaration def_args {
 | 
						|
		 if (allow) {
 | 
						|
		   int oldstatus = Status;
 | 
						|
		   char *tm;
 | 
						|
 | 
						|
		   init_language();
 | 
						|
		   if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		     temp_typeptr = new DataType(Active_type);
 | 
						|
		     temp_typeptr->is_pointer += $2.is_pointer;
 | 
						|
		     if (Verbose) {
 | 
						|
		       fprintf(stderr,"Wrapping member variable : %s\n",$2.id);
 | 
						|
		     }
 | 
						|
		     Stat_var++;
 | 
						|
		     doc_entry = new DocDecl($2.id,doc_stack[doc_stack_top]);
 | 
						|
		     if (temp_typeptr->status & STAT_READONLY) {
 | 
						|
		       if (!(tm = typemap_lookup("memberin",typemap_lang,temp_typeptr,$2.id,"",""))) 
 | 
						|
			 Status = Status | STAT_READONLY;
 | 
						|
		     }
 | 
						|
		     cplus_variable($2.id,(char *) 0,temp_typeptr);		
 | 
						|
		     Status = oldstatus;
 | 
						|
		     delete temp_typeptr;
 | 
						|
		   }
 | 
						|
		   scanner_clear_start();
 | 
						|
		 }
 | 
						|
	       } cpp_tail { } 
 | 
						|
               | COMMA declaration array def_args {
 | 
						|
		 if (allow) {
 | 
						|
		   int oldstatus = Status;
 | 
						|
		   char *tm;
 | 
						|
 | 
						|
		   init_language();
 | 
						|
		   if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		     temp_typeptr = new DataType(Active_type);
 | 
						|
		     temp_typeptr->is_pointer += $2.is_pointer;
 | 
						|
		     if (Verbose) {
 | 
						|
		       fprintf(stderr,"Wrapping member variable : %s\n",$2.id);
 | 
						|
		     }
 | 
						|
		     Stat_var++;
 | 
						|
		     if (!(tm = typemap_lookup("memberin",typemap_lang,temp_typeptr,$2.id,"",""))) 
 | 
						|
		       Status = Status | STAT_READONLY;
 | 
						|
		     doc_entry = new DocDecl($2.id,doc_stack[doc_stack_top]);
 | 
						|
		     if (temp_typeptr->status & STAT_READONLY) Status = Status | STAT_READONLY;
 | 
						|
		     cplus_variable($2.id,(char *) 0,temp_typeptr);		
 | 
						|
		     Status = oldstatus;
 | 
						|
		     if (!tm)
 | 
						|
		       fprintf(stderr,"%s : Line %d. Warning. Array member will be read-only.\n",input_file,line_number);
 | 
						|
		     delete temp_typeptr;
 | 
						|
		   }
 | 
						|
		   scanner_clear_start();
 | 
						|
		 }
 | 
						|
	       } cpp_tail { } 
 | 
						|
               ;
 | 
						|
 | 
						|
cpp_end        : cpp_const SEMI { 
 | 
						|
                    CCode = "";
 | 
						|
               } 
 | 
						|
               | cpp_const LBRACE { skip_brace(); }
 | 
						|
               ;
 | 
						|
 | 
						|
cpp_vend       : cpp_const SEMI { CCode = ""; }
 | 
						|
               | cpp_const EQUAL definetype SEMI { CCode = ""; }
 | 
						|
               | cpp_const LBRACE { skip_brace(); }
 | 
						|
               ;
 | 
						|
 | 
						|
cpp_enumlist   :  cpp_enumlist COMMA cpp_edecl {}
 | 
						|
               |  cpp_edecl {}
 | 
						|
               ;
 | 
						|
 | 
						|
cpp_edecl      :  ID {
 | 
						|
                    if (allow) {
 | 
						|
		      if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
			if (Verbose) {
 | 
						|
			  fprintf(stderr,"Creating enum value %s\n", $1);
 | 
						|
			}
 | 
						|
			Stat_const++;
 | 
						|
			temp_typeptr = new DataType(T_INT);
 | 
						|
			doc_entry = new DocDecl($1,doc_stack[doc_stack_top]);
 | 
						|
			cplus_declare_const($1, (char *) 0, temp_typeptr, (char *) 0);
 | 
						|
			delete temp_typeptr;
 | 
						|
			scanner_clear_start();
 | 
						|
		      }
 | 
						|
		    }
 | 
						|
                  }
 | 
						|
                 | ID EQUAL etype {
 | 
						|
		   if (allow) {
 | 
						|
		     if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		       if (Verbose) {
 | 
						|
			 fprintf(stderr, "Creating enum value %s = %s\n", $1, $3.id);
 | 
						|
		       }
 | 
						|
		       Stat_const++;
 | 
						|
		       temp_typeptr = new DataType(T_INT);
 | 
						|
		       doc_entry = new DocDecl($1,doc_stack[doc_stack_top]);
 | 
						|
		       cplus_declare_const($1,(char *) 0, temp_typeptr,(char *) 0);
 | 
						|
// OLD : Bug with value     cplus_declare_const($1,(char *) 0, temp_typeptr,$3.id);
 | 
						|
		       delete temp_typeptr;
 | 
						|
		       scanner_clear_start();
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
                 | NAME LPAREN ID RPAREN ID {
 | 
						|
		   if (allow) {
 | 
						|
		     if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		       if (Verbose) {
 | 
						|
			 fprintf(stderr,"Creating enum value %s\n", $5);
 | 
						|
		       }
 | 
						|
		       Stat_const++;
 | 
						|
		       temp_typeptr = new DataType(T_INT);
 | 
						|
		       doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 | 
						|
		       cplus_declare_const($5, $3, temp_typeptr, (char *) 0);
 | 
						|
		       delete temp_typeptr;
 | 
						|
		       scanner_clear_start();
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
                 | NAME LPAREN ID RPAREN ID EQUAL etype {
 | 
						|
		   if (allow) {
 | 
						|
		     if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		       if (Verbose) {
 | 
						|
			 fprintf(stderr, "Creating enum value %s = %s\n", $5, $7.id);
 | 
						|
		       }
 | 
						|
		       Stat_const++;
 | 
						|
		       temp_typeptr = new DataType(T_INT);
 | 
						|
		       doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 | 
						|
		       cplus_declare_const($5,$3, temp_typeptr, (char *) 0);
 | 
						|
// Old : bug with value	       cplus_declare_const($5,$3, temp_typeptr,$7.id);
 | 
						|
		       delete temp_typeptr;
 | 
						|
		       scanner_clear_start();
 | 
						|
		     }
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
                 | cond_compile cpp_edecl { }
 | 
						|
                 | empty { }
 | 
						|
                 ;
 | 
						|
 | 
						|
inherit        : COLON base_list {
 | 
						|
		   $$ = $2;
 | 
						|
                }
 | 
						|
                | empty {
 | 
						|
                   $$.names = (char **) 0;
 | 
						|
		   $$.count = 0;
 | 
						|
                }
 | 
						|
                ;
 | 
						|
 | 
						|
base_list      : base_specifier { 
 | 
						|
                   int i;
 | 
						|
                   $$.names = new char *[NI_NAMES];
 | 
						|
		   $$.count = 0;
 | 
						|
		   for (i = 0; i < NI_NAMES; i++){
 | 
						|
		     $$.names[i] = (char *) 0;
 | 
						|
		   }
 | 
						|
                   if ($1) {
 | 
						|
                       $$.names[$$.count] = copy_string($1);
 | 
						|
                       $$.count++;
 | 
						|
		   }
 | 
						|
               }
 | 
						|
 | 
						|
               | base_list COMMA base_specifier { 
 | 
						|
                   $$ = $1;
 | 
						|
                   if ($3) {
 | 
						|
		     $$.names[$$.count] = copy_string($3);
 | 
						|
		     $$.count++;
 | 
						|
		   }
 | 
						|
               }
 | 
						|
               ;
 | 
						|
                                 
 | 
						|
base_specifier : ID {     
 | 
						|
                  fprintf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
 | 
						|
			  input_file,line_number,$1);
 | 
						|
		  $$ = (char *) 0;
 | 
						|
               }
 | 
						|
               | VIRTUAL ID { 
 | 
						|
                  fprintf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
 | 
						|
			  input_file,line_number,$2);
 | 
						|
		  $$ = (char *) 0;
 | 
						|
	       }
 | 
						|
	       | VIRTUAL access_specifier ID {
 | 
						|
		 if (strcmp($2,"public") == 0) {
 | 
						|
		   $$ = $3;
 | 
						|
		 } else {
 | 
						|
		   fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
 | 
						|
			   input_file,line_number,$2);
 | 
						|
		   $$ = (char *) 0;
 | 
						|
		 }
 | 
						|
               }
 | 
						|
               | access_specifier ID {
 | 
						|
		 if (strcmp($1,"public") == 0) {
 | 
						|
		   $$ = $2;
 | 
						|
		 } else {
 | 
						|
		   fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
 | 
						|
			   input_file,line_number,$1);
 | 
						|
		   $$ = (char *) 0;
 | 
						|
		 }
 | 
						|
	       }                          
 | 
						|
               | access_specifier VIRTUAL ID {
 | 
						|
                 if (strcmp($1,"public") == 0) {
 | 
						|
		   $$ = $3;
 | 
						|
		 } else {
 | 
						|
		   fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
 | 
						|
			   input_file,line_number,$1);
 | 
						|
		   $$ = (char *) 0;
 | 
						|
		 }
 | 
						|
               }
 | 
						|
               ;                               
 | 
						|
 | 
						|
access_specifier :  PUBLIC { $$ = "public"; }
 | 
						|
               | PRIVATE { $$ = "private"; }
 | 
						|
               | PROTECTED { $$ = "protected"; }
 | 
						|
               ;
 | 
						|
              
 | 
						|
  
 | 
						|
cpptype        : CLASS { $$ = "class"; }
 | 
						|
               | STRUCT { $$ = "struct"; }
 | 
						|
               | UNION {$$ = "union"; }
 | 
						|
               ;
 | 
						|
 | 
						|
cpp_const      : CONST {} 
 | 
						|
               | THROW LPAREN parms RPAREN { delete $3;}
 | 
						|
               | empty {}
 | 
						|
               ;
 | 
						|
 | 
						|
/* Constructor initializer */
 | 
						|
 | 
						|
ctor_end       : cpp_const ctor_initializer SEMI { 
 | 
						|
                    CCode = "";
 | 
						|
               } 
 | 
						|
               | cpp_const ctor_initializer LBRACE { skip_brace(); }
 | 
						|
               ;
 | 
						|
 | 
						|
ctor_initializer : COLON mem_initializer_list {}
 | 
						|
               | empty {}
 | 
						|
               ;
 | 
						|
 | 
						|
mem_initializer_list : mem_initializer { }
 | 
						|
               | mem_initializer_list COMMA mem_initializer { }
 | 
						|
               ;
 | 
						|
 | 
						|
mem_initializer : ID LPAREN expr_list RPAREN { }
 | 
						|
               | ID LPAREN RPAREN { }
 | 
						|
                ;
 | 
						|
 
 | 
						|
expr_list      : expr { }
 | 
						|
               | expr_list COMMA expr { }
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
/**************************************************************/
 | 
						|
/* Objective-C parsing                                        */
 | 
						|
/**************************************************************/
 | 
						|
 | 
						|
objective_c    : OC_INTERFACE ID objc_inherit { 
 | 
						|
                   ObjCClass = 1;
 | 
						|
                   init_language();
 | 
						|
		   cplus_mode = CPLUS_PROTECTED;
 | 
						|
		   sprintf(temp_name,"CPP_CLASS:%s\n",$2);
 | 
						|
		   if (add_symbol(temp_name,(DataType *) 0, (char *) 0)) {
 | 
						|
		     fprintf(stderr,"%s : Line %d.  @interface %s is multiple defined.\n",
 | 
						|
			     input_file,line_number,$2);
 | 
						|
		     FatalError();
 | 
						|
		   }
 | 
						|
		   // Create a new documentation entry
 | 
						|
		   doc_entry = new DocClass($2,doc_parent());
 | 
						|
		   doc_stack_top++;
 | 
						|
		   doc_stack[doc_stack_top] = doc_entry;
 | 
						|
		   scanner_clear_start();
 | 
						|
		   cplus_open_class($2, (char *) 0, "");     // Open up a new C++ class
 | 
						|
                } LBRACE objc_data RBRACE objc_methods OC_END { 
 | 
						|
		  if ($3) {
 | 
						|
		      char *inames[1];
 | 
						|
		      inames[0] = $3;
 | 
						|
		      cplus_inherit(1,inames);
 | 
						|
		  }
 | 
						|
		  // Restore original doc entry for this class
 | 
						|
		  doc_entry = doc_stack[doc_stack_top];
 | 
						|
		  cplus_class_close($2);
 | 
						|
		  doc_entry = 0;
 | 
						|
		  doc_stack_top--;
 | 
						|
		  cplus_mode = CPLUS_PUBLIC;
 | 
						|
		  ObjCClass = 0;
 | 
						|
		  delete $2;
 | 
						|
		  delete $3;
 | 
						|
                }
 | 
						|
/* An obj-c category declaration */
 | 
						|
               | OC_INTERFACE ID LPAREN ID RPAREN objc_protolist {
 | 
						|
                 ObjCClass = 1;
 | 
						|
		 init_language();
 | 
						|
                 cplus_mode = CPLUS_PROTECTED;
 | 
						|
                 doc_entry = cplus_set_class($2);
 | 
						|
		 if (!doc_entry) {
 | 
						|
		   doc_entry = new DocClass($2,doc_parent());
 | 
						|
		 }
 | 
						|
		 doc_stack_top++;
 | 
						|
		 doc_stack[doc_stack_top] = doc_entry;
 | 
						|
		 scanner_clear_start();
 | 
						|
	       } objc_methods OC_END {
 | 
						|
                 cplus_unset_class();
 | 
						|
                 doc_entry = 0;
 | 
						|
                 doc_stack_top--;
 | 
						|
               }
 | 
						|
               | OC_IMPLEMENT { skip_to_end(); }
 | 
						|
               | OC_PROTOCOL { skip_to_end(); }
 | 
						|
               | OC_CLASS ID initlist SEMI {
 | 
						|
		 char *iname = make_name($2);
 | 
						|
                 init_language();
 | 
						|
                 lang->cpp_class_decl($2,iname,"");
 | 
						|
		 for (int i = 0; i <$3.count; i++) {
 | 
						|
		   if ($3.names[i]) {
 | 
						|
		     iname = make_name($3.names[i]);
 | 
						|
		     lang->cpp_class_decl($3.names[i],iname,"");
 | 
						|
		     delete [] $3.names[i];
 | 
						|
		   }
 | 
						|
		 } 
 | 
						|
		 delete [] $3.names;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_inherit   : COLON ID objc_protolist { $$ = $2;}
 | 
						|
               | objc_protolist empty { $$ = 0; }
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
objc_protolist : LESSTHAN { skip_template(); 
 | 
						|
                   CCode.strip();           // Strip whitespace
 | 
						|
		   CCode.replace("<","< ");
 | 
						|
		   CCode.replace(">"," >");
 | 
						|
                   $$ = CCode.get();
 | 
						|
                 }
 | 
						|
               | empty {
 | 
						|
                   $$ = "";
 | 
						|
               }
 | 
						|
               ;
 | 
						|
                 
 | 
						|
objc_data      : objc_vars objc_data { }
 | 
						|
               | OC_PUBLIC { 
 | 
						|
                    cplus_mode = CPLUS_PUBLIC;
 | 
						|
                 } objc_data { }
 | 
						|
               | OC_PRIVATE {
 | 
						|
                    cplus_mode = CPLUS_PRIVATE;
 | 
						|
                 } objc_data { }
 | 
						|
               | OC_PROTECTED { 
 | 
						|
                    cplus_mode = CPLUS_PROTECTED;
 | 
						|
                 } objc_data { }
 | 
						|
               | error {
 | 
						|
		 if (!Error) {
 | 
						|
		   skip_decl();
 | 
						|
		   {
 | 
						|
		     static int last_error_line = -1;
 | 
						|
		     if (last_error_line != line_number) {
 | 
						|
		       fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 | 
						|
		       FatalError();
 | 
						|
		       last_error_line = line_number;
 | 
						|
		     }
 | 
						|
		     Error = 1;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       } objc_data { }
 | 
						|
               | empty { }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_vars      : objc_var objc_vartail SEMI {
 | 
						|
  
 | 
						|
                }
 | 
						|
               ;
 | 
						|
 | 
						|
/* An objective-C member variable */
 | 
						|
 | 
						|
objc_var       : type declaration { 
 | 
						|
                 if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		   int oldstatus = Status;
 | 
						|
		   char *tm;
 | 
						|
		   char *iname;
 | 
						|
		   if (Active_type) delete Active_type;
 | 
						|
		   Active_type = new DataType($1);
 | 
						|
		   $1->is_pointer += $2.is_pointer;
 | 
						|
		   $1->is_reference = $2.is_reference;
 | 
						|
		   if ($1->status & STAT_READONLY) {
 | 
						|
		     if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 | 
						|
		       Status = Status | STAT_READONLY;
 | 
						|
		   }
 | 
						|
		   iname = make_name($2.id);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $2.id) iname = 0;
 | 
						|
		   cplus_variable($2.id,iname,$1);
 | 
						|
		   Status = oldstatus; 
 | 
						|
		 }
 | 
						|
		 scanner_clear_start();
 | 
						|
		 delete $1;
 | 
						|
               }
 | 
						|
               | type declaration array { 
 | 
						|
		 if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		   int oldstatus = Status;
 | 
						|
		   char *tm, *iname;
 | 
						|
		   if (Active_type) delete Active_type;
 | 
						|
		   Active_type = new DataType($1);
 | 
						|
		   $1->is_pointer += $2.is_pointer;
 | 
						|
		   $1->is_reference = $2.is_reference;
 | 
						|
		   $1->arraystr = copy_string(ArrayString);
 | 
						|
		   if ($1->status & STAT_READONLY) {
 | 
						|
		     if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 | 
						|
		       Status = Status | STAT_READONLY;
 | 
						|
		   }
 | 
						|
		   iname = make_name($2.id);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $2.id) iname = 0;
 | 
						|
		   cplus_variable($2.id,iname,$1);
 | 
						|
		   Status = oldstatus; 
 | 
						|
		 }
 | 
						|
		 scanner_clear_start();
 | 
						|
		 delete $1;
 | 
						|
	       }
 | 
						|
               | NAME LPAREN ID RPAREN {
 | 
						|
                    strcpy(yy_rename,$3);
 | 
						|
                    Rename_true = 1;
 | 
						|
	       } objc_var { };
 | 
						|
 | 
						|
objc_vartail   : COMMA declaration objc_vartail { 
 | 
						|
                 if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		   int oldstatus = Status;
 | 
						|
		   char *tm, *iname;
 | 
						|
		   DataType *t = new DataType (Active_type);
 | 
						|
		   t->is_pointer += $2.is_pointer;
 | 
						|
		   t->is_reference = $2.is_reference;
 | 
						|
		   if (t->status & STAT_READONLY) {
 | 
						|
		     if (!(tm = typemap_lookup("memberin",typemap_lang,t,$2.id,"",""))) 
 | 
						|
		       Status = Status | STAT_READONLY;
 | 
						|
		   }
 | 
						|
		   iname = make_name($2.id);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $2.id) iname = 0;
 | 
						|
		   cplus_variable($2.id,iname,t);
 | 
						|
		   Status = oldstatus; 
 | 
						|
		   delete t;
 | 
						|
		 }
 | 
						|
		 scanner_clear_start();
 | 
						|
               }
 | 
						|
               | COMMA declaration array objc_vartail {
 | 
						|
		 char *iname;
 | 
						|
                 if (cplus_mode == CPLUS_PUBLIC) {
 | 
						|
		   int oldstatus = Status;
 | 
						|
		   char *tm;
 | 
						|
		   DataType *t = new DataType (Active_type);
 | 
						|
		   t->is_pointer += $2.is_pointer;
 | 
						|
		   t->is_reference = $2.is_reference;
 | 
						|
		   t->arraystr = copy_string(ArrayString);
 | 
						|
		   if (t->status & STAT_READONLY) {
 | 
						|
		     if (!(tm = typemap_lookup("memberin",typemap_lang,t,$2.id,"",""))) 
 | 
						|
		       Status = Status | STAT_READONLY;
 | 
						|
		   }
 | 
						|
		   iname = make_name($2.id);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $2.id) iname = 0;
 | 
						|
		   cplus_variable($2.id,iname,t);
 | 
						|
		   Status = oldstatus; 
 | 
						|
		   delete t;
 | 
						|
		 }
 | 
						|
		 scanner_clear_start();
 | 
						|
               }
 | 
						|
               | empty { }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_methods   : objc_method objc_methods { };
 | 
						|
               | ADDMETHODS LBRACE {
 | 
						|
                   AddMethods = 1;
 | 
						|
	       } objc_methods RBRACE {
 | 
						|
                   AddMethods = 0;
 | 
						|
               }
 | 
						|
               | NAME LPAREN ID RPAREN {
 | 
						|
                     strcpy(yy_rename,$3);
 | 
						|
                     Rename_true = 1;
 | 
						|
	       } objc_methods { }
 | 
						|
               | error {
 | 
						|
                 skip_decl();		                
 | 
						|
		 if (!Error) {
 | 
						|
		   {
 | 
						|
		     static int last_error_line = -1;
 | 
						|
		     if (last_error_line != line_number) {
 | 
						|
		       fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 | 
						|
		       FatalError();
 | 
						|
		       last_error_line = line_number;
 | 
						|
		     }
 | 
						|
		     Error = 1;
 | 
						|
		   }
 | 
						|
		 }
 | 
						|
	       } objc_methods { }
 | 
						|
               | empty { }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_method    : MINUS objc_ret_type ID objc_args objc_end {
 | 
						|
                 char *iname;
 | 
						|
                 // An objective-C instance function
 | 
						|
                 // This is like a C++ member function
 | 
						|
 | 
						|
		 if (strcmp($3,objc_destruct) == 0) {
 | 
						|
		   // This is an objective C destructor
 | 
						|
                   doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 | 
						|
                   cplus_destructor($3,(char *) 0);
 | 
						|
		 } else {
 | 
						|
		   iname = make_name($3);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $3) iname = 0;
 | 
						|
		   cplus_member_func($3,iname,$2,$4,0);
 | 
						|
		   scanner_clear_start();
 | 
						|
		   delete $2;
 | 
						|
		   delete $3;
 | 
						|
		   delete $4;
 | 
						|
		 }
 | 
						|
               }
 | 
						|
               | PLUS objc_ret_type ID objc_args objc_end { 
 | 
						|
                 char *iname;
 | 
						|
                 // An objective-C class function
 | 
						|
                 // This is like a c++ static member function
 | 
						|
                 if (strcmp($3,objc_construct) == 0) {
 | 
						|
		   // This is an objective C constructor
 | 
						|
		   doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 | 
						|
                   cplus_constructor($3,0,$4);
 | 
						|
		 } else {
 | 
						|
		   iname = make_name($3);
 | 
						|
		   doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 | 
						|
		   if (iname == $3) iname = 0;
 | 
						|
		   cplus_static_func($3,iname,$2,$4);
 | 
						|
		 }
 | 
						|
                 scanner_clear_start();
 | 
						|
                 delete $2;
 | 
						|
                 delete $3;
 | 
						|
                 delete $4;
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_end       : SEMI { CCode = ""; }
 | 
						|
               | LBRACE { skip_brace(); }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_ret_type  : LPAREN type RPAREN { 
 | 
						|
                  $$ = $2;
 | 
						|
                }
 | 
						|
               | LPAREN type stars RPAREN { 
 | 
						|
                  $$ = $2;
 | 
						|
                  $$->is_pointer += $3;
 | 
						|
               }
 | 
						|
               | empty {       /* Empty type means "id" type */
 | 
						|
                  $$ = new DataType(T_VOID);
 | 
						|
		  sprintf($$->name,"id");
 | 
						|
                  $$->is_pointer = 1;
 | 
						|
                  $$->implicit_ptr = 1;
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_arg_type  : LPAREN parm RPAREN { 
 | 
						|
                  $$ = new DataType($2->t);
 | 
						|
                  delete $2;
 | 
						|
                 }
 | 
						|
               | empty { 
 | 
						|
                  $$ = new DataType(T_VOID);
 | 
						|
		  sprintf($$->name,"id");
 | 
						|
                  $$->is_pointer = 1;
 | 
						|
                  $$->implicit_ptr = 1;
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 
 | 
						|
objc_args      : objc_args objc_separator objc_arg_type ID { 
 | 
						|
                   Parm *p= new Parm($3,$4);
 | 
						|
		   p->objc_separator = $2;
 | 
						|
                   $$ = $1;
 | 
						|
                   $$->append(p);
 | 
						|
               }
 | 
						|
               | empty { 
 | 
						|
                 $$ = new ParmList;
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 | 
						|
objc_separator : COLON { $$ = copy_string(":"); }
 | 
						|
               | ID COLON { $$ = new char[strlen($1)+2]; 
 | 
						|
                    strcpy($$,$1);
 | 
						|
		    strcat($$,":");
 | 
						|
		    delete $1;
 | 
						|
	        }
 | 
						|
               ;
 | 
						|
 | 
						|
/* Miscellaneous stuff */
 | 
						|
 | 
						|
/* Documentation style list */
 | 
						|
 | 
						|
stylelist      : ID stylearg styletail {
 | 
						|
                    $$ = $3;
 | 
						|
		    $$.names[$$.count] = copy_string($1);
 | 
						|
		    $$.values[$$.count] = copy_string($2);
 | 
						|
		    format_string($$.values[$$.count]);
 | 
						|
		    $$.count++;
 | 
						|
                 }
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
styletail      : styletail COMMA ID stylearg {
 | 
						|
                    $$ = $1;
 | 
						|
		    $$.names[$$.count] = copy_string($3);
 | 
						|
		    $$.values[$$.count] = copy_string($4);
 | 
						|
		    format_string($$.values[$$.count]);
 | 
						|
		    $$.count++;
 | 
						|
                 }
 | 
						|
               | empty {
 | 
						|
                    $$.names = new char *[NI_NAMES];
 | 
						|
		    $$.values = new char *[NI_NAMES];
 | 
						|
		    $$.count = 0;
 | 
						|
	       }
 | 
						|
               ;
 | 
						|
 | 
						|
stylearg       : EQUAL NUM_INT {
 | 
						|
                     $$ = $2;
 | 
						|
                 }
 | 
						|
               | EQUAL STRING {
 | 
						|
                     $$ = $2;
 | 
						|
	       }
 | 
						|
               | empty { 
 | 
						|
                     $$ = 0;
 | 
						|
                }
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
/* --------------------------------------------------------------
 | 
						|
 * Type-map parameters 
 | 
						|
 * -------------------------------------------------------------- */
 | 
						|
 | 
						|
tm_method      : ID {
 | 
						|
                 $$ = $1;
 | 
						|
               } 
 | 
						|
               | CONST {
 | 
						|
                 $$ = copy_string("const");
 | 
						|
               }
 | 
						|
               ;
 | 
						|
 | 
						|
tm_list        : typemap_parm tm_tail {
 | 
						|
                 $$ = $1;
 | 
						|
                 $$->next = $2;
 | 
						|
		}
 | 
						|
               ;
 | 
						|
 | 
						|
tm_tail        : COMMA typemap_parm tm_tail {
 | 
						|
                 $$ = $2;
 | 
						|
                 $$->next = $3;
 | 
						|
                }
 | 
						|
               | empty { $$ = 0;}
 | 
						|
               ;
 | 
						|
 | 
						|
typemap_parm   : type typemap_name {
 | 
						|
		    if (InArray) {
 | 
						|
		      $1->is_pointer++;
 | 
						|
		      $1->arraystr = copy_string(ArrayString);
 | 
						|
		    }
 | 
						|
		    $$ = new TMParm;
 | 
						|
                    $$->p = new Parm($1,$2);
 | 
						|
		    $$->p->call_type = 0;
 | 
						|
		    $$->args = tm_parm;
 | 
						|
		    delete $1;
 | 
						|
		    delete $2;
 | 
						|
                 }
 | 
						|
 | 
						|
                | type stars typemap_name {
 | 
						|
		  $$ = new TMParm;
 | 
						|
		   $$->p = new Parm($1,$3);
 | 
						|
		   $$->p->t->is_pointer += $2;
 | 
						|
		   $$->p->call_type = 0;
 | 
						|
		   if (InArray) {
 | 
						|
		     $$->p->t->is_pointer++;
 | 
						|
		     $$->p->t->arraystr = copy_string(ArrayString);
 | 
						|
		    }
 | 
						|
		   $$->args = tm_parm;
 | 
						|
		   delete $1;
 | 
						|
		   delete $3;
 | 
						|
		}
 | 
						|
 | 
						|
                | type AND typemap_name {
 | 
						|
                  $$ = new TMParm;
 | 
						|
		  $$->p = new Parm($1,$3);
 | 
						|
		  $$->p->t->is_reference = 1;
 | 
						|
		  $$->p->call_type = 0;
 | 
						|
		  $$->p->t->is_pointer++;
 | 
						|
		  if (!CPlusPlus) {
 | 
						|
			fprintf(stderr,"%s : Line %d. Warning.  Use of C++ Reference detected.  Use the -c++ option.\n", input_file, line_number);
 | 
						|
		  }
 | 
						|
		  $$->args = tm_parm;
 | 
						|
		  delete $1;
 | 
						|
		  delete $3;
 | 
						|
		}
 | 
						|
                | type LPAREN stars typemap_name RPAREN LPAREN parms RPAREN {
 | 
						|
                  fprintf(stderr,"%s : Line %d. Error. Function pointer not allowed (remap with typedef).\n", input_file, line_number);
 | 
						|
		  FatalError();
 | 
						|
                  $$ = new TMParm;
 | 
						|
		  $$->p = new Parm($1,$4);
 | 
						|
		  $$->p->t->type = T_ERROR;
 | 
						|
		  $$->p->name = copy_string($4);
 | 
						|
		  strcpy($$->p->t->name,"<function ptr>");
 | 
						|
		  $$->args = tm_parm;
 | 
						|
		  delete $1;
 | 
						|
		  delete $4;
 | 
						|
		  delete $7;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
typemap_name    : ID typemap_args {
 | 
						|
                    $$ = $1; 
 | 
						|
                    InArray = 0;
 | 
						|
                }
 | 
						|
                | ID array  { 
 | 
						|
                    ArrayBackup = "";
 | 
						|
		    ArrayBackup << ArrayString;
 | 
						|
                  } typemap_args {
 | 
						|
                    $$ = $1;
 | 
						|
                    InArray = $2;
 | 
						|
                    ArrayString = "";
 | 
						|
		    ArrayString << ArrayBackup;
 | 
						|
                }
 | 
						|
                | array { 
 | 
						|
                    ArrayBackup = "";
 | 
						|
		    ArrayBackup << ArrayString;
 | 
						|
		} typemap_args {
 | 
						|
		    $$ = new char[1];
 | 
						|
		    $$[0] = 0;
 | 
						|
		    InArray = $1;
 | 
						|
                    ArrayString = "";
 | 
						|
                    ArrayString << ArrayBackup;
 | 
						|
		}
 | 
						|
                | typemap_args { $$ = new char[1];
 | 
						|
  	                  $$[0] = 0;
 | 
						|
                          InArray = 0;
 | 
						|
                }
 | 
						|
                ;
 | 
						|
 | 
						|
typemap_args    : LPAREN parms RPAREN {
 | 
						|
                  tm_parm = $2;
 | 
						|
                }
 | 
						|
                | empty {
 | 
						|
                  tm_parm = 0;
 | 
						|
                }
 | 
						|
                ;
 | 
						|
 | 
						|
idstring       : ID {$$ = $1;}
 | 
						|
               | STRING { $$ = $1;}
 | 
						|
               ;
 | 
						|
 | 
						|
 | 
						|
/* User defined directive */
 | 
						|
 | 
						|
user_directive : USERDIRECTIVE LPAREN parms RPAREN uservalue { }
 | 
						|
               | USERDIRECTIVE uservalue { }
 | 
						|
               ;
 | 
						|
 | 
						|
uservalue      : ID SEMI { }
 | 
						|
               | STRING SEMI { }
 | 
						|
               | LBRACE RBRACE { }
 | 
						|
               ;
 | 
						|
 
 | 
						|
                     
 | 
						|
                          
 | 
						|
/* Parsing of expressions, but only for throw away code */
 | 
						|
 | 
						|
/* Might need someday 
 | 
						|
dummyexpr      :  NUM_INT { }
 | 
						|
               |  NUM_FLOAT { }
 | 
						|
               |  NUM_UNSIGNED { }
 | 
						|
               |  NUM_LONG { } 
 | 
						|
               |  NUM_ULONG { }
 | 
						|
               |  SIZEOF LPAREN type RPAREN { }
 | 
						|
               |  ID { }
 | 
						|
               |  dummyexpr PLUS dummyexpr {	       }
 | 
						|
               |  dummyexpr MINUS dummyexpr {	       }
 | 
						|
               |  dummyexpr STAR dummyexpr {	       }
 | 
						|
               |  dummyexpr SLASH dummyexpr {	       }
 | 
						|
               |  dummyexpr AND dummyexpr {	       }
 | 
						|
               |  dummyexpr OR dummyexpr {	       }
 | 
						|
               |  dummyexpr XOR dummyexpr {	       }
 | 
						|
               |  dummyexpr LSHIFT dummyexpr {	       }
 | 
						|
               |  dummyexpr RSHIFT dummyexpr {	       }
 | 
						|
               |  MINUS dummyexpr %prec UMINUS {	       }
 | 
						|
               |  NOT dummyexpr {	       }
 | 
						|
               |  LPAREN dummyexpr RPAREN {	       }
 | 
						|
               ;
 | 
						|
 | 
						|
	       */
 | 
						|
 | 
						|
 | 
						|
empty          :   ;
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
void error_recover() {
 | 
						|
  int c;
 | 
						|
  c = yylex();
 | 
						|
  while ((c > 0) && (c != SEMI)) 
 | 
						|
    c = yylex();
 | 
						|
}
 | 
						|
 | 
						|
/* Called by the parser (yyparse) when an error is found.*/
 | 
						|
void yyerror (char *) {
 | 
						|
  //  Fprintf(stderr,"%s : Line %d. Syntax error.\n", input_file, line_number);
 | 
						|
  //  error_recover();
 | 
						|
}
 | 
						|
 |