%{ /* ----------------------------------------------------------------------------- * parser.yxx * * YACC parser for SWIG1.1. This grammar is a broken subset of C/C++. * This file is in the process of being deprecated. * * Author(s) : David Beazley (beazley@cs.uchicago.edu) * * Copyright (C) 1998-2000. The University of Chicago * Copyright (C) 1995-1998. The University of Utah and The Regents of the * University of California. * * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ #define yylex yylex static char cvsroot[] = "$Header$"; 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" extern "C" { #include "preprocessor.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 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 = 0; 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 DOHString *ArrayString = 0; // Array type attached to parameter names static DOHString *ArrayBackup = 0; 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 DOHHash *name_hash = 0; // Hash table containing renamings char *objc_construct = (char *) "new"; // Objective-C constructor char *objc_destruct = (char *) "free"; // Objective-C destructor static DOHHash *symbols = 0; /* 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(void *); extern void cplus_inherit_scope(int, char **); extern void cplus_add_pragma(char *, char *, char *); extern void cplus_set_class(char *); extern void cplus_unset_class(); extern void cplus_abort(); void parser_init() { ArrayString = NewString(""); temp_type = NewDataType(0); } // ---------------------------------------------------------------------- // 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(); } lang_init = 1; } /* Add a symbol to the symbol table. Return -1 if it already exists */ int add_symbol(char *name) { if (!symbols) symbols = NewHash(); if (Getattr(symbols,name)) return -1; Setattr(symbols,name,name); return 0; } // ---------------------------------------------------------------------- // 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 if (!name_hash) name_hash = NewHash(); char *nn = GetChar(name_hash,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 DOHString *temp = 0; if (!temp) temp= NewString(""); Clear(temp); Append(temp,name); Replace(temp,"$","_S_",DOH_REPLACE_ANY); return Char(temp); } else { return name; } } } // ---------------------------------------------------------------------- // 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)) { fprintf(stderr,"%s : Line %d. Function %s multiply defined (2nd definition ignored).\n", input_file, line_number, iname); } else { // 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 lang->create_function(name, iname, t, l); } 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)) { fprintf(stderr,"%s : Line %d. Variable %s multiply defined (2nd definition ignored).\n", input_file, line_number, iname); } else { // 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 lang->link_variable(name, iname, t); 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)) { fprintf(stderr,"%s : Line %d. Constant %s multiply defined. (2nd definition ignored)\n", input_file, line_number, name); } else { if (!WrapExtern) { // Only wrap the constant if not in %extern mode lang->declare_const(name, name, type, value); } } scanner_clear_start(); } /* Print out array brackets */ void print_array() { int i; for (i = 0; i < InArray; i++) fprintf(stderr,"[]"); } // Structures for handling code fragments built for nested classes struct Nested { DOHString *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 Replace(n->code, "$classname", parent, DOH_REPLACE_ANY); // 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 cplus_variable(n->name,(char *) 0, n->type); // Dump the code to the scanner fprintf(f_header,"\n%s\n", Char(n->code)); start_inline(Char(n->code),n->line); n1 = n->next; Delete(n->code); 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; struct { char *filename; int line; int flag; } loc; DataType *type; Parm *p; TMParm *tmparm; ParmList *pl; int ivalue; }; %token ID %token HBLOCK WRAPPER POUND %token STRING %token INCLUDE IMPORT WEXTERN SWIGMACRO %token NUM_INT NUM_FLOAT CHARCONST NUM_UNSIGNED NUM_LONG NUM_ULONG %token TYPEDEF %token 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 ILLEGAL CONSTANT %token READONLY READWRITE NAME RENAME 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 RAW_MODE ALPHA_MODE TEXT DOC_DISABLE DOC_ENABLE STYLE LOCALSTYLE %token TYPEMAP EXCEPT ECHO NEW APPLY CLEAR DOCONLY %token TITLE SECTION SUBSECTION SUBSUBSECTION %token LESSTHAN GREATERTHAN %token 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 extern array array2; %type parms ptail; %type

parm parm_type; %type typemap_parm tm_list tm_tail; %type pname cpptype base_specifier access_specifier typemap_name tm_method; %type type opt_signed opt_unsigned strict_type; %type declaration nested_decl; %type stars; %type initlist base_list inherit; %type definetype def_args; %type etype; %type expr; %type ename stylearg objc_inherit; %type stylelist styletail; %type objc_ret_type objc_arg_type; %type objc_protolist objc_separator; %type objc_args; %% /* The productions of the grammar with their associated semantic actions. */ program : command { cplus_cleanup(); if (lang_init) { lang->close(); } } ; command : command statement { scanner_clear_start(); Error = 0; } | empty { } ; statement : INCLUDE STRING LBRACE { $1.filename = copy_string(input_file); $1.line = line_number; input_file = copy_string($2); line_number = 0; } command RBRACE { input_file = $1.filename; line_number = $1.line; } /* %extern directive */ | WEXTERN STRING LBRACE { $1.flag = WrapExtern; WrapExtern = 1; $1.filename = copy_string(input_file); $1.line = line_number; input_file = copy_string($2); line_number = 0; } command RBRACE { input_file = $1.filename; line_number = $1.line; WrapExtern = $1.flag; } /* %import directive. Like %extern but calls out to a language module */ | IMPORT STRING LBRACE { $1.flag = WrapExtern; WrapExtern = 1; $1.filename = copy_string(input_file); $1.line = line_number; input_file = copy_string($2); line_number = 0; lang->import($2); } command RBRACE { input_file = $1.filename; line_number = $1.line; WrapExtern = $1.flag; } | SWIGMACRO ID COMMA STRING COMMA NUM_INT LBRACE { $1.filename = copy_string(input_file); $1.line = line_number; input_file = copy_string($4); line_number = atoi($6) - 1; } command RBRACE { input_file = $1.filename; line_number = $1.line; } /* An unknown C preprocessor statement. Just throw it away */ | POUND { } /* A variable declaration */ | extern type declaration array2 def_args { init_language(); if (Active_type) DelDataType(Active_type); Active_type = CopyDataType($2); Active_extern = $1; $2->is_pointer += $3.is_pointer; if ($4 > 0) { $2->is_pointer++; $2->status = STAT_READONLY; DataType_set_arraystr($2,Char(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 (DataType_qualifier($2)) { if ((strcmp(DataType_qualifier($2),"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); } DelDataType($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 { Active_static = 1; DelDataType($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 { init_language(); if (Active_type) DelDataType(Active_type); Active_type = CopyDataType($2); Active_extern = $1; $2->is_pointer += $3.is_pointer; $2->is_reference = $3.is_reference; create_function($1, $3.id, $2, $5); DelDataType($2); DelParmList($5); } stail { } /* A function declaration with code after it */ | extern type declaration LPAREN parms RPAREN func_end { init_language(); $2->is_pointer += $3.is_pointer; $2->is_reference = $3.is_reference; create_function($1, $3.id, $2, $5); DelDataType($2); DelParmList($5); }; /* A function declared without any return datatype */ | extern declaration LPAREN parms RPAREN cpp_const { init_language(); DataType *t = NewDataType(T_INT); t->is_pointer += $2.is_pointer; t->is_reference = $2.is_reference; create_function($1,$2.id,t,$4); DelDataType(t); } stail { }; /* A static function declaration code after it */ | STATIC type declaration LPAREN parms RPAREN func_end { if (Inline) { if (strlen(Char(CCode))) { init_language(); $2->is_pointer += $3.is_pointer; $2->is_reference = $3.is_reference; create_function(0, $3.id, $2, $5); } } DelDataType($2); DelParmList($5); }; /* A function with an explicit inline directive. Not safe to use inside a %inline block */ | INLINE type declaration LPAREN parms RPAREN func_end { 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(Char(CCode))) { fprintf(f_header,"static "); emit_extern_func($3.id,$2,$5,3,f_header); fprintf(f_header,"%s\n",Char(CCode)); } create_function(0, $3.id, $2, $5); } DelDataType($2); DelParmList($5); }; /* A static function declaration (ignored) */ | STATIC type declaration LPAREN parms RPAREN cpp_const { Active_static = 1; DelDataType($2); DelParmList($5); } stail { Active_static = 0; } /* Enable Read-only mode */ | READONLY { Status = Status | STAT_READONLY; } /* Enable Read-write mode */ | READWRITE { Status = Status & ~STAT_READONLY; } /* New %name directive */ | NAME LPAREN ID RPAREN { strcpy(yy_rename,$3); Rename_true = 1; } /* %rename directive */ | RENAME ID ID SEMI { if (!name_hash) name_hash = NewHash(); Setattr(name_hash,$2,$3); } /* %new directive */ | NEW { NewObject = 1; } statement { NewObject = 0; } /* Empty name directive. No longer allowed */ | NAME LPAREN RPAREN { 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 (!WrapExtern) { init_language(); if (add_symbol($3)) { fprintf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n", input_file, line_number, $3); } else { lang->add_native($3,$6,0,0); } } } | NATIVE LPAREN ID RPAREN extern type declaration LPAREN parms RPAREN SEMI { if (!WrapExtern) { init_language(); $6->is_pointer += $7.is_pointer; if (add_symbol($3)) { 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); } lang->add_native($3,$7.id,$6,$9); } } DelDataType($6); DelParmList($9); } /* %title directive */ | TITLE STRING styletail { } /* %section directive */ | SECTION STRING styletail { } /* %subsection directive */ | SUBSECTION STRING styletail { } /* %subsubsection directive */ | SUBSUBSECTION STRING styletail { } | doc_enable { } /* %text directive */ | TEXT HBLOCK { } | typedef_decl { } /* Code insertion block */ | HBLOCK { if (!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 (!WrapExtern) { init_language(); $2[strlen($2) - 1] = 0; fprintf(f_wrappers,"%s\n",$2); } } /* Initialization code */ | INIT HBLOCK { if (!WrapExtern) { init_language(); $2[strlen($2) -1] = 0; fprintf(f_init,"%s\n", $2); } } /* Inline block */ | INLINE HBLOCK { if (!WrapExtern) { init_language(); $2[strlen($2) - 1] = 0; fprintf(f_header, "%s\n", $2); { /* Need to run through the preprocessor */ DOH *cpps; DOH *s = NewString($2); Setline(s,start_line); Setfile(s,input_file); Seek(s,0,SEEK_SET); cpps = Preprocessor_parse(s); start_inline(Char(cpps), start_line); Delete(s); Delete(cpps); } } } /* Echo mode */ | ECHO HBLOCK { if (!WrapExtern) { fprintf(stderr,"%s\n", $2); } } | ECHO STRING { if (!WrapExtern) { fprintf(stderr,"%s\n", $2); } } /* Disable code generation */ | DOCONLY { } /* Init directive--to avoid errors in other modules */ | INIT ID initlist { if (!module_init) { lang->set_init($2); module_init = 1; init_language(); } 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 ($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; } /* constant directive */ | CONSTANT ID definetype SEMI { if (($3.type != T_ERROR) && ($3.type != T_SYMBOL)) { init_language(); temp_typeptr = NewDataType($3.type); create_constant($2, temp_typeptr, $3.id); DelDataType(temp_typeptr); } else if ($3.type == T_SYMBOL) { // Add a symbol to the SWIG symbol table if (add_symbol($2)) { fprintf(stderr,"%s : Line %d. Warning. Symbol %s already defined.\n", input_file,line_number, $2); } } } /* Enumerations */ | extern ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE SEMI { init_language(); if ($3) { temp_type->type = T_INT; temp_type->is_pointer = 0; temp_type->implicit_ptr = 0; sprintf(temp_type->name,"int"); DataType_typedef_add(temp_type,$3,1); lang->add_typedef(temp_type,$3); } } /* A typdef'd enum. Pretty common in C headers */ | TYPEDEF ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE ID { init_language(); temp_type->type = T_INT; temp_type->is_pointer = 0; temp_type->implicit_ptr = 0; sprintf(temp_type->name,"int"); Active_typedef = CopyDataType(temp_type); DataType_typedef_add(temp_type,$8,1); lang->add_typedef(temp_type,$8); } 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,Parm_Gettype(p->p),Parm_Getname(p->p),Char(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,Parm_Gettype(p->p),Parm_Getname(p->p),Char(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,Parm_Gettype(p->p),Parm_Getname(p->p)); 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,Parm_Gettype(p->p),Parm_Getname(p->p)); 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,Parm_Gettype($9->p),Parm_Getname($9->p),Parm_Gettype(p->p),Parm_Getname(p->p)); p = p->next; } delete $3; delete $5; DelParm($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,Parm_Gettype($7->p),Parm_Getname($7->p),Parm_Gettype(p->p),Parm_Getname(p->p)); p = p->next; } } delete $3; DelParm($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(Parm_Gettype($2->p),Parm_Getname($2->p),Parm_Gettype(p->p),Parm_Getname(p->p)); p = p->next; } delete $4; DelParmList($2->args); delete $2; } | CLEAR tm_list SEMI { TMParm *p; p = $2; while (p) { typemap_clear_apply(Parm_Gettype(p->p), Parm_Getname(p->p)); p = p->next; } } /* ----------------------------------------------------------------- exception support These constructs are used to define exceptions ----------------------------------------------------------------- */ /* An exception definition */ | EXCEPT LPAREN ID RPAREN LBRACE { skip_brace(); fragment_register((char *)"except",$3, Char(CCode)); delete $3; } /* A Generic Exception (no language specified */ | EXCEPT LBRACE { skip_brace(); fragment_register((char *) "except",typemap_lang, Char(CCode)); } /* Clear an exception */ | EXCEPT LPAREN ID RPAREN SEMI { fragment_clear((char *) "except",$3); } /* Generic clear */ | EXCEPT SEMI { fragment_clear((char *) "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 { } /* Officially, this directive doesn't exist yet */ | pragma { } /* %style directive. This applies to all current styles */ | STYLE stylelist { } /* %localstyle directive. This applies only to the current style */ | LOCALSTYLE stylelist { } /* User defined directive */ | user_directive{ } ; /* Dcumentation disable/enable */ doc_enable : DOC_DISABLE { } /* %enabledoc directive */ | DOC_ENABLE { } ; /* Note : This really needs to be re-done */ /* A typedef with pointers */ typedef_decl : TYPEDEF type declaration { init_language(); /* Add a new typedef */ Active_typedef = CopyDataType($2); $2->is_pointer += $3.is_pointer; DataType_typedef_add($2, $3.id,0); lang->add_typedef($2,$3.id); /* If this is %typedef, add it to the header */ if ($1) fprintf(f_header,"typedef %s %s;\n", DataType_print_full($2), $3.id); cplus_register_type($3.id); } typedeflist { }; /* A rudimentary typedef involving function pointers */ | TYPEDEF type LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI { 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,""); $2->type = T_USER; $2->is_pointer = 1; DataType_typedef_add($2,$5,1); lang->add_typedef($2,$5); cplus_register_type($5); DelDataType($2); delete $5; DelParmList($8); } /* A typedef involving function pointers again */ | TYPEDEF type stars LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI { 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,""); $2->type = T_USER; $2->is_pointer = 1; DataType_typedef_add($2,$6,1); lang->add_typedef($2,$6); cplus_register_type($6); DelDataType($2); delete $6; DelParmList($9); } /* A typedef involving arrays */ | TYPEDEF type declaration array { init_language(); Active_typedef = CopyDataType($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++; DataType_set_arraystr($2,Char(ArrayString)); DataType_typedef_add($2,$3.id,0); lang->add_typedef($2,$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 (Active_typedef) { DataType *t; t = CopyDataType(Active_typedef); t->is_pointer += $2.is_pointer; DataType_typedef_add(t,$2.id,0); lang->add_typedef(t,$2.id); cplus_register_type($2.id); DelDataType(t); } } | COMMA declaration array { DataType *t; t = CopyDataType(Active_typedef); t->status = STAT_READONLY | STAT_REPLACETYPE; t->is_pointer += $2.is_pointer + 1; DataType_set_arraystr(t,Char(ArrayString)); DataType_typedef_add(t,$2.id,0); lang->add_typedef(t,$2.id); cplus_register_type($2.id); DelDataType(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 { } ; pragma : PRAGMA LPAREN ID COMMA ID stylearg RPAREN { if (!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 (!WrapExtern) swig_pragma($2,$3); } | PRAGMA LPAREN ID RPAREN ID stylearg { if (!WrapExtern) lang->pragma($3,$5,$6); } ; /* Allow lists of variables and functions to be built up */ stail : SEMI { } | COMMA declaration array2 def_args { init_language(); temp_typeptr = CopyDataType(Active_type); temp_typeptr->is_pointer += $2.is_pointer; if ($3 > 0) { temp_typeptr->is_pointer++; temp_typeptr->status = STAT_READONLY; DataType_set_arraystr(temp_typeptr,Char(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 (DataType_qualifier(temp_typeptr)) { if ((strcmp(DataType_qualifier(temp_typeptr),"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); } DelDataType(temp_typeptr); } stail { } | COMMA declaration LPAREN parms RPAREN cpp_const { init_language(); temp_typeptr = CopyDataType(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); DelDataType(temp_typeptr); DelParmList($4); } stail { } ; 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 { DataType *pt = Parm_Gettype($1); if ((pt->type != T_VOID) || (pt->is_pointer)) ParmList_insert($2,$1,0); $$ = $2; DelParm($1); } | empty { $$ = NewParmList(); } ; ptail : COMMA parm ptail { ParmList_insert($3,$2,0); $$ = $3; DelParm($2); } | empty { $$ = NewParmList(); } ; parm : parm_type { $$ = $1; if (typemap_check((char *)"ignore",typemap_lang,Parm_Gettype($$),Parm_Getname($$))) $$->ignore = 1; } parm_type : type pname { if (InArray) { $1->is_pointer++; // Add array string to the type DataType_set_arraystr($1, Char(ArrayString)); } $$ = NewParm($1,$2); Parm_Setvalue($$,DefArg); DelDataType($1); delete $2; } | type stars pname { $$ = NewParm($1,$3); Parm_Gettype($$)->is_pointer+=$2; Parm_Setvalue($$,DefArg); if (InArray) { Parm_Gettype($$)->is_pointer++; // Add array string to the type DataType_set_arraystr(Parm_Gettype($$), Char(ArrayString)); } DelDataType($1); delete $3; } | type AND pname { $$ = NewParm($1,$3); DataType *pt = Parm_Gettype($$); pt->is_reference = 1; pt->is_pointer++; Parm_Setvalue($$,DefArg); if (!CPlusPlus) { fprintf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number); } DelDataType($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(); $$ = NewParm($1,$4); DataType *pt = Parm_Gettype($$); pt->type = T_ERROR; Parm_Setname($$,$4); strcpy(pt->name,""); DelDataType($1); delete $4; DelParmList($7); } | PERIOD PERIOD PERIOD { fprintf(stderr,"%s : Line %d. Variable length arguments not supported (ignored).\n", input_file, line_number); $$ = NewParm(NewDataType(T_INT),(char *) "varargs"); DataType *pt = Parm_Gettype($$); pt->type = T_ERROR; Parm_Setname($$,(char*)"varargs"); strcpy(pt->name,""); FatalError(); } ; pname : ID def_args { $$ = $1; InArray = 0; if ($2.type == T_CHAR) DefArg = Swig_copy_string(ConstChar); else DefArg = Swig_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;} ; /* 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; Insert(ArrayString,0,"[]"); } | LBRACKET expr RBRACKET array2 { $$ = $4 + 1; Insert(ArrayString,0,"]"); Insert(ArrayString,0,$2.id); Insert(ArrayString,0,"["); } ; array2 : array { $$ = $1; } | empty { $$ = 0; Clear(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 { $$ = NewDataType(0); strcpy($$->name,$1); $$->type = T_USER; /* Do a typedef lookup */ DataType_typedef_resolve($$,0); 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; DataType_set_qualifier($$,(char*)"const"); } | cpptype ID { $$ = NewDataType(0); sprintf($$->name,"%s %s",$1, $2); $$->type = T_USER; } | ID DCOLON ID { $$ = NewDataType(0); sprintf($$->name,"%s::%s",$1,$3); $$->type = T_USER; DataType_typedef_resolve($$,0); } /* This declaration causes a shift-reduce conflict. Unresolved for now */ | DCOLON ID { $$ = NewDataType(0); sprintf($$->name,"%s", $2); $$->type = T_USER; DataType_typedef_resolve($$,1); } | ENUM ID { $$ = NewDataType(0); sprintf($$->name,"enum %s", $2); $$->type = T_INT; DataType_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; DataType_set_qualifier($$,(char*)"const"); } | cpptype ID { $$ = NewDataType(0); 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 = NewDataType(T_INT); create_constant($1, temp_typeptr, $1); DelDataType(temp_typeptr); } | ID EQUAL { scanner_check_typedef();} etype { temp_typeptr = NewDataType($4.type); // Use enum name instead of value // OLD create_constant($1, temp_typeptr, $4.id); if ($4.type == T_CHAR) create_constant($1,temp_typeptr, $4.id); else create_constant($1, temp_typeptr, $1); DelDataType(temp_typeptr); scanner_ignore_typedef(); } | 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_INT; } ; /* Arithmetic expressions. Used for constants and other cool stuff. Really, we're not doing anything except string concatenation, but this does allow us to parse many constant declarations. */ expr : 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 = $1; $$.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; init_language(); DataType_new_scope(0); sprintf(temp_name,"CPP_CLASS:%s\n",$3); if (add_symbol(temp_name)) { 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); 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; scanner_clear_start(); nested_list = 0; // Merge in scope from base classes cplus_inherit_scope($4.count,$4.names); } cpp_members RBRACE { 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)); cplus_class_close((char *) 0); cplus_mode = CPLUS_PUBLIC; } /* Class with a typedef */ | TYPEDEF cpptype ID inherit LBRACE { char *iname; init_language(); DataType_new_scope(0); sprintf(temp_name,"CPP_CLASS:%s\n",$3); if (add_symbol(temp_name)) { 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); 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; scanner_clear_start(); nested_list = 0; // Merge in scope from base classes cplus_inherit_scope($4.count,$4.names); } cpp_members RBRACE declaration { 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 = NewDataType(0); 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)); if ($9.is_pointer > 0) { cplus_class_close($3); } else { cplus_class_close($9.id); } // Create a typedef in global scope if ($9.is_pointer == 0) { DataType_typedef_add(Active_typedef,$9.id,0); lang->add_typedef(Active_typedef,$9.id); } else { DataType *t = CopyDataType(Active_typedef); t->is_pointer += $9.is_pointer; DataType_typedef_add(t,$9.id,0); lang->add_typedef(t,$9.id); cplus_register_type($9.id); DelDataType(t); } cplus_mode = CPLUS_PUBLIC; } typedeflist { }; /* An unnamed struct with a typedef */ | TYPEDEF cpptype LBRACE { char *iname; init_language(); DataType_new_scope(0); 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((char*)""); if (strlen(iname)) cplus_open_class((char *)"", iname, $2); else cplus_open_class((char *) "",0,$2); if (strcmp($2,"class") == 0) cplus_mode = CPLUS_PRIVATE; else cplus_mode = CPLUS_PUBLIC; scanner_clear_start(); nested_list = 0; } cpp_members RBRACE declaration { 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)) { 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 = NewDataType(0); 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)); if ($7.is_pointer == 0) cplus_class_close($7.id); cplus_mode = CPLUS_PUBLIC; } typedeflist { } ; cpp_other :/* A dummy class name */ extern cpptype ID SEMI { char *iname; 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 { 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); DelDataType($2); DelParmList($7); } /* A static C++ member data */ | extern type declaration DCOLON ID SEMI { 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); DelDataType($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(); DelDataType($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; cplus_set_class($2); scanner_clear_start(); AddMethods = 1; } added_members RBRACE { cplus_unset_class(); 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; init_language(); if (cplus_mode == CPLUS_PUBLIC) { $1->is_pointer += $2.is_pointer; $1->is_reference = $2.is_reference; iname = make_name($2.id); if (iname == $2.id) iname = 0; cplus_member_func($2.id, iname, $1,$4,0); } scanner_clear_start(); DelDataType($1); DelParmList($4); } /* Virtual member function */ | VIRTUAL type declaration LPAREN parms RPAREN cpp_vend { char *iname; init_language(); if (cplus_mode == CPLUS_PUBLIC) { $2->is_pointer += $3.is_pointer; $2->is_reference = $3.is_reference; iname = make_name($3.id); if (iname == $3.id) iname = 0; cplus_member_func($3.id,iname,$2,$5,1); } scanner_clear_start(); DelDataType($2); DelParmList($5); } /* Possibly a constructor */ | ID LPAREN parms RPAREN ctor_end { char *iname; init_language(); if (cplus_mode == CPLUS_PUBLIC) { iname = make_name($1); if (iname == $1) iname = 0; cplus_constructor($1,iname, $3); } scanner_clear_start(); DelParmList($3); } /* A destructor (hopefully) */ | NOT ID LPAREN parms RPAREN cpp_end { char *iname; init_language(); if (cplus_mode == CPLUS_PUBLIC) { iname = make_name($2); if (iname == $2) iname = 0; cplus_destructor($2,iname); } scanner_clear_start(); DelParmList($4); } /* A virtual destructor */ | VIRTUAL NOT ID LPAREN RPAREN cpp_end { char *iname; init_language(); if (cplus_mode == CPLUS_PUBLIC) { iname = make_name($3); if (iname == $3) iname = 0; cplus_destructor($3,iname); } scanner_clear_start(); } /* Member data */ | type declaration def_args { char *iname; init_language(); if (cplus_mode == CPLUS_PUBLIC) { if (Active_type) DelDataType(Active_type); Active_type = CopyDataType($1); $1->is_pointer += $2.is_pointer; $1->is_reference = $2.is_reference; if (DataType_qualifier($1)) { if ((strcmp(DataType_qualifier($1),"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); 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((char*)"memberin",typemap_lang,$1,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } iname = make_name($2.id); 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((char*)"memberin",typemap_lang,$1,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } iname = make_name($2.id); if (iname == $2.id) iname = 0; cplus_variable($2.id,iname,$1); Status = oldstatus; } } scanner_clear_start(); DelDataType($1); } cpp_tail { } | type declaration array def_args { char *iname; int oldstatus = Status; char *tm = 0; init_language(); if (cplus_mode == CPLUS_PUBLIC) { if (Active_type) DelDataType(Active_type); Active_type = CopyDataType($1); $1->is_pointer += $2.is_pointer + 1; $1->is_reference = $2.is_reference; DataType_set_arraystr($1,Char(ArrayString)); if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,$1,$2.id,(char*)"",(char*)""))) Status = STAT_READONLY; iname = make_name($2.id); 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(); DelDataType($1); } /* Static Member data */ | STATIC type declaration { char *iname; init_language(); if (cplus_mode == CPLUS_PUBLIC) { $2->is_pointer += $3.is_pointer; iname = make_name($3.id); if (iname == $3.id) iname = 0; cplus_static_var($3.id,iname,$2); if (Active_type) DelDataType(Active_type); Active_type = CopyDataType($2); } scanner_clear_start(); DelDataType($2); } cpp_tail { } /* Static member function */ | STATIC type declaration LPAREN parms RPAREN cpp_end { char *iname; $2->is_pointer += $3.is_pointer; $2->is_reference = $3.is_reference; if (cplus_mode == CPLUS_PUBLIC) { iname = make_name($3.id); if (iname == $3.id) iname = 0; cplus_static_func($3.id, iname, $2, $5); } scanner_clear_start(); DelDataType($2); DelParmList($5); } /* Turn on public: mode */ | PUBLIC COLON { cplus_mode = CPLUS_PUBLIC; scanner_clear_start(); } /* Turn on private: mode */ | PRIVATE COLON { cplus_mode = CPLUS_PRIVATE; scanner_clear_start(); } /* Turn on protected mode */ | PROTECTED COLON { cplus_mode = CPLUS_PROTECTED; scanner_clear_start(); } /* This is the new style rename */ | NAME LPAREN ID RPAREN { 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. 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"); DataType_typedef_add(temp_type,$2,1); lang->add_typedef(temp_type,$2); } } } | READONLY { Status = Status | STAT_READONLY; scanner_clear_start(); } | READWRITE { Status = Status & ~(STAT_READONLY); scanner_clear_start(); } /* A friend : Illegal */ | FRIEND { 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 { fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number); skip_decl(); scanner_clear_start(); } /* A typedef inside a class */ | typedef_decl { } /* Pragma directive */ | cpp_pragma { scanner_clear_start(); } cpp_pragma : PRAGMA ID stylearg { if (!WrapExtern) { } } | PRAGMA LPAREN ID RPAREN ID stylearg { if (!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 = NewString(""); Printv(n->code, "typedef ", $1, " ", Char(CCode), " $classname_", $5.id, ";\n", 0); n->name = copy_string($5.id); n->line = start_line; n->type = NewDataType(0); 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 = NewString(""); Printv(n->code, "typedef ", $1, " " , Char(CCode), " $classname_", $4.id, ";\n",0); n->name = copy_string($4.id); n->line = start_line; n->type = NewDataType(0); 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 { int oldstatus = Status; char *tm; init_language(); if (cplus_mode == CPLUS_PUBLIC) { temp_typeptr = CopyDataType(Active_type); temp_typeptr->is_pointer += $2.is_pointer; if (temp_typeptr->status & STAT_READONLY) { if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,temp_typeptr,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } cplus_variable($2.id,(char *) 0,temp_typeptr); Status = oldstatus; DelDataType(temp_typeptr); } scanner_clear_start(); } cpp_tail { } | COMMA declaration array def_args { int oldstatus = Status; char *tm; init_language(); if (cplus_mode == CPLUS_PUBLIC) { temp_typeptr = CopyDataType(Active_type); temp_typeptr->is_pointer += $2.is_pointer; if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,temp_typeptr,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; 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); DelDataType(temp_typeptr); } scanner_clear_start(); } cpp_tail { } ; cpp_end : cpp_const SEMI { Clear(CCode); } | cpp_const LBRACE { skip_brace(); } ; cpp_vend : cpp_const SEMI { Clear(CCode); } | cpp_const EQUAL definetype SEMI { Clear(CCode); } | cpp_const LBRACE { skip_brace(); } ; cpp_enumlist : cpp_enumlist COMMA cpp_edecl {} | cpp_edecl {} ; cpp_edecl : ID { if (cplus_mode == CPLUS_PUBLIC) { temp_typeptr = NewDataType(T_INT); cplus_declare_const($1, (char *) 0, temp_typeptr, (char *) 0); DelDataType(temp_typeptr); scanner_clear_start(); } } | ID EQUAL etype { if (cplus_mode == CPLUS_PUBLIC) { temp_typeptr = NewDataType(T_INT); cplus_declare_const($1,(char *) 0, temp_typeptr,(char *) 0); // OLD : Bug with value cplus_declare_const($1,(char *) 0, temp_typeptr,$3.id); DelDataType(temp_typeptr); scanner_clear_start(); } } | NAME LPAREN ID RPAREN ID { if (cplus_mode == CPLUS_PUBLIC) { temp_typeptr = NewDataType(T_INT); cplus_declare_const($5, $3, temp_typeptr, (char *) 0); DelDataType(temp_typeptr); scanner_clear_start(); } } | NAME LPAREN ID RPAREN ID EQUAL etype { if (cplus_mode == CPLUS_PUBLIC) { temp_typeptr = NewDataType(T_INT); cplus_declare_const($5,$3, temp_typeptr, (char *) 0); // Old : bug with value cplus_declare_const($5,$3, temp_typeptr,$7.id); DelDataType(temp_typeptr); scanner_clear_start(); } } | 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 { $$ = (char*)"public"; } | PRIVATE { $$ = (char*)"private"; } | PROTECTED { $$ = (char*)"protected"; } ; cpptype : CLASS { $$ = (char*)"class"; } | STRUCT { $$ = (char*)"struct"; } | UNION {$$ = (char*)"union"; } ; cpp_const : CONST {} | THROW LPAREN parms RPAREN { DelParmList($3);} | empty {} ; /* Constructor initializer */ ctor_end : cpp_const ctor_initializer SEMI { Clear(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)) { fprintf(stderr,"%s : Line %d. @interface %s is multiple defined.\n", input_file,line_number,$2); FatalError(); } scanner_clear_start(); cplus_open_class($2, (char *) 0, (char*)""); // 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); } cplus_class_close($2); 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; cplus_set_class($2); scanner_clear_start(); } objc_methods OC_END { cplus_unset_class(); } | 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,(char*)""); 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,(char*)""); 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(">"," >"); */ $$ = Char(CCode); } | empty { $$ = (char*)""; } ; 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) DelDataType(Active_type); Active_type = CopyDataType($1); $1->is_pointer += $2.is_pointer; $1->is_reference = $2.is_reference; if ($1->status & STAT_READONLY) { if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,$1,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } iname = make_name($2.id); if (iname == $2.id) iname = 0; cplus_variable($2.id,iname,$1); Status = oldstatus; } scanner_clear_start(); DelDataType($1); } | type declaration array { if (cplus_mode == CPLUS_PUBLIC) { int oldstatus = Status; char *tm, *iname; if (Active_type) DelDataType(Active_type); Active_type = CopyDataType($1); $1->is_pointer += $2.is_pointer; $1->is_reference = $2.is_reference; DataType_set_arraystr($1, Char(ArrayString)); if ($1->status & STAT_READONLY) { if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,$1,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } iname = make_name($2.id); if (iname == $2.id) iname = 0; cplus_variable($2.id,iname,$1); Status = oldstatus; } scanner_clear_start(); DelDataType($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 = CopyDataType (Active_type); t->is_pointer += $2.is_pointer; t->is_reference = $2.is_reference; if (t->status & STAT_READONLY) { if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,t,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } iname = make_name($2.id); if (iname == $2.id) iname = 0; cplus_variable($2.id,iname,t); Status = oldstatus; DelDataType(t); } scanner_clear_start(); } | COMMA declaration array objc_vartail { char *iname; if (cplus_mode == CPLUS_PUBLIC) { int oldstatus = Status; char *tm; DataType *t = CopyDataType (Active_type); t->is_pointer += $2.is_pointer; t->is_reference = $2.is_reference; DataType_set_arraystr(t,Char(ArrayString)); if (t->status & STAT_READONLY) { if (!(tm = typemap_lookup((char*)"memberin",typemap_lang,t,$2.id,(char*)"",(char*)""))) Status = Status | STAT_READONLY; } iname = make_name($2.id); if (iname == $2.id) iname = 0; cplus_variable($2.id,iname,t); Status = oldstatus; DelDataType(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 cplus_destructor($3,(char *) 0); } else { iname = make_name($3); if (iname == $3) iname = 0; cplus_member_func($3,iname,$2,$4,0); scanner_clear_start(); DelDataType($2); delete $3; DelParmList($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 cplus_constructor($3,0,$4); } else { iname = make_name($3); if (iname == $3) iname = 0; cplus_static_func($3,iname,$2,$4); } scanner_clear_start(); DelDataType($2); delete $3; DelParmList($4); } ; objc_end : SEMI { Clear(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 */ $$ = NewDataType(T_VOID); sprintf($$->name,"id"); $$->is_pointer = 1; $$->implicit_ptr = 1; } ; objc_arg_type : LPAREN parm RPAREN { $$ = CopyDataType(Parm_Gettype($2)); DelParm($2); } | empty { $$ = NewDataType(T_VOID); sprintf($$->name,"id"); $$->is_pointer = 1; $$->implicit_ptr = 1; } ; objc_args : objc_args objc_separator objc_arg_type ID { Parm *p= NewParm($3,$4); /* p->objc_separator = $2; */ $$ = $1; ParmList_append($$,p); } | empty { $$ = NewParmList(); } ; objc_separator : COLON { $$ = copy_string((char*)":"); } | 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((char*)"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++; DataType_set_arraystr($1,Char(ArrayString)); } $$ = new TMParm; $$->p = NewParm($1,$2); $$->args = tm_parm; DelDataType($1); delete $2; } | type stars typemap_name { $$ = new TMParm; $$->p = NewParm($1,$3); DataType *pt = Parm_Gettype($$->p); pt->is_pointer += $2; if (InArray) { pt->is_pointer++; DataType_set_arraystr(pt,Char(ArrayString)); } $$->args = tm_parm; DelDataType($1); delete $3; } | type AND typemap_name { $$ = new TMParm; $$->p = NewParm($1,$3); DataType *pt = Parm_Gettype($$->p); pt->is_reference = 1; pt->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; DelDataType($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 = NewParm($1,$4); DataType *pt = Parm_Gettype($$->p); pt->type = T_ERROR; Parm_Setname($$->p,$4); strcpy(pt->name,""); $$->args = tm_parm; DelDataType($1); delete $4; DelParmList($7); } ; typemap_name : ID typemap_args { $$ = $1; InArray = 0; } | ID array { ArrayBackup = Copy(ArrayString); } typemap_args { $$ = $1; InArray = $2; Clear(ArrayString); Append(ArrayString,ArrayBackup); Delete(ArrayBackup); } | array { ArrayBackup = Copy(ArrayString); } typemap_args { $$ = new char[1]; $$[0] = 0; InArray = $1; Clear(ArrayString); Append(ArrayString,ArrayBackup); Delete(ArrayBackup); } | typemap_args { $$ = new char[1]; $$[0] = 0; InArray = 0; } ; typemap_args : LPAREN parms RPAREN { tm_parm = $2; } | empty { tm_parm = 0; } ; /* 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(); }