2 /*******************************************************************************
 
   3  * Simplified Wrapper and Interface Generator  (SWIG)
 
   5  * Author : David Beazley
 
   7  * Department of Computer Science        
 
   8  * University of Chicago
 
  11  * beazley@cs.uchicago.edu
 
  13  * Please read the file LICENSE for the copyright and terms by which SWIG
 
  14  * can be used and distributed.
 
  15  *******************************************************************************/
 
  16 /***********************************************************************
 
  21  * YACC parser for parsing function declarations.
 
  25  * This is the most ugly, incredibly henious, and completely unintelligible
 
  26  * file in SWIG.  While it started out simple, it has grown into a
 
  27  * monster that is almost unmaintainable.   A complete parser rewrite is
 
  28  * currently in progress that should make this file about 1/4 the size
 
  29  * that it is now.   Needless to say, don't modify this file or even look
 
  30  * at it for that matter!
 
  31  ***********************************************************************/
 
  35 extern "C" int yylex();
 
  36 void   yyerror (char *s);       
 
  38 extern int  line_number;
 
  39 extern int  start_line;
 
  40 extern void skip_brace(void);
 
  41 extern void skip_define(void);
 
  42 extern void skip_decl(void);
 
  43 extern int  skip_cond(int);
 
  44 extern void skip_to_end(void);
 
  45 extern void skip_template(void);
 
  46 extern void scanner_check_typedef(void);
 
  47 extern void scanner_ignore_typedef(void);
 
  48 extern void scanner_clear_start(void);
 
  49 extern void start_inline(char *, int);
 
  50 extern void format_string(char *);
 
  51 extern void swig_pragma(char *, char *);
 
  56 void *alloca(unsigned n) {
 
  57   return((void *) malloc(n));
 
  60 // This redefinition is apparently needed on a number of machines,
 
  66 // Initialization flags.   These indicate whether or not certain
 
  67 // features have been initialized.  These were added to allow
 
  68 // interface files without the block (required in previous
 
  71 static int     module_init = 0;    /* Indicates whether the %module name was given */
 
  72 static int     title_init = 0;     /* Indicates whether %title directive has been given */
 
  73 static int     doc_init = 0;    
 
  75 static int     lang_init = 0;      /* Indicates if the language has been initialized */
 
  79 static char           temp_name[128];
 
  80 static DataType      *temp_typeptr, temp_type;
 
  81 static char           yy_rename[256];
 
  82 static int            Rename_true = 0;
 
  83 static DataType      *Active_type = 0;         // Used to support variable lists
 
  84 static int            Active_extern = 0;       // Whether or not list is external
 
  85 static int            Active_static = 0;
 
  86 static DataType       *Active_typedef = 0;     // Used for typedef lists
 
  87 static int            InArray = 0;             // Used when an array declaration is found 
 
  88 static int            in_then = 0;
 
  89 static int            in_else = 0;       
 
  90 static int            allow = 1;               // Used during conditional compilation
 
  91 static int            doc_scope = 0;           // Documentation scoping
 
  92 static String         ArrayString;             // Array type attached to parameter names
 
  93 static String         ArrayBackup;             // Array backup string
 
  94 static char           *DefArg = 0;             // Default argument hack
 
  95 static char           *ConstChar = 0;          // Used to store raw character constants
 
  96 static ParmList       *tm_parm = 0;            // Parameter list used to hold typemap parameters
 
  97 static Hash            name_hash;              // Hash table containing renamings
 
  98        char           *objc_construct = "new"; // Objective-C constructor
 
  99        char           *objc_destruct = "free"; // Objective-C destructor
 
 101 /* Some macros for building constants */
 
 103 #define E_BINARY(TARGET, SRC1, SRC2, OP)  \
 
 104         TARGET = new char[strlen(SRC1) + strlen(SRC2) +strlen(OP)+1];\
 
 105         sprintf(TARGET,"%s%s%s",SRC1,OP,SRC2);
 
 109 #define  CPLUS_PUBLIC    1
 
 110 #define  CPLUS_PRIVATE   2
 
 111 #define  CPLUS_PROTECTED 3
 
 115 // Declarations of some functions for handling C++ 
 
 117 extern void cplus_open_class(char *name, char *rname, char *ctype);
 
 118 extern void cplus_member_func(char *, char *, DataType *, ParmList *, int);
 
 119 extern void cplus_constructor(char *, char *, ParmList *);
 
 120 extern void cplus_destructor(char *, char *);
 
 121 extern void cplus_variable(char *, char *, DataType *);
 
 122 extern void cplus_static_func(char *, char *, DataType *, ParmList *);
 
 123 extern void cplus_declare_const(char *, char *, DataType *, char *);
 
 124 extern void cplus_class_close(char *);
 
 125 extern void cplus_inherit(int, char **);
 
 126 extern void cplus_cleanup(void);
 
 127 extern void cplus_static_var(char *, char *, DataType *);
 
 128 extern void cplus_register_type(char *);
 
 129 extern void cplus_register_scope(Hash *);
 
 130 extern void cplus_inherit_scope(int, char **);
 
 131 extern void cplus_add_pragma(char *, char *, char *);
 
 132 extern DocEntry *cplus_set_class(char *);
 
 133 extern void cplus_unset_class();
 
 134 extern void cplus_abort();
 
 136 // ----------------------------------------------------------------------
 
 137 // static init_language()
 
 139 // Initialize the target language.
 
 140 // Does nothing if this function has already been called.
 
 141 // ----------------------------------------------------------------------
 
 143 static void init_language() {
 
 147     // Initialize the documentation system
 
 150       doctitle = new DocTitle(title,0);
 
 153       doctitle->usage = title;
 
 155     doc_stack[0] = doctitle;
 
 158     int oldignore = IgnoreDoc;
 
 161       include_file(ConfigFile);
 
 163     IgnoreDoc = oldignore;
 
 169 // ----------------------------------------------------------------------
 
 170 // int promote(int t1, int t2)
 
 172 // Promote types (for constant expressions)
 
 173 // ----------------------------------------------------------------------
 
 175 int promote(int t1, int t2) {
 
 177   if ((t1 == T_ERROR) || (t2 == T_ERROR)) return T_ERROR;
 
 178   if ((t1 == T_DOUBLE) || (t2 == T_DOUBLE)) return T_DOUBLE;
 
 179   if ((t1 == T_FLOAT) || (t2 == T_FLOAT)) return T_FLOAT;
 
 180   if ((t1 == T_ULONG) || (t2 == T_ULONG)) return T_ULONG;
 
 181   if ((t1 == T_LONG) || (t2 == T_LONG)) return T_LONG;
 
 182   if ((t1 == T_UINT) || (t2 == T_UINT)) return T_UINT;
 
 183   if ((t1 == T_INT) || (t2 == T_INT)) return T_INT;
 
 184   if ((t1 == T_USHORT) || (t2 == T_USHORT)) return T_SHORT;
 
 185   if ((t1 == T_SHORT) || (t2 == T_SHORT)) return T_SHORT;
 
 186   if ((t1 == T_UCHAR) || (t2 == T_UCHAR)) return T_UCHAR;
 
 188     fprintf(stderr,"%s : Line %d. Type mismatch in constant expression\n",
 
 189             input_file, line_number);
 
 195 /* Generate the scripting name of an object.  Takes %name directive into 
 
 196    account among other things */
 
 198 static char *make_name(char *name) {
 
 199   // Check to see if the name is in the hash
 
 200   char *nn = (char *) name_hash.lookup(name);
 
 201   if (nn) return nn;        // Yep, return it.
 
 207     // Now check to see if the name contains a $
 
 208     if (strchr(name,'$')) {
 
 212       temp.replace("$","_S_");
 
 220 /* Return the parent of a documentation entry.   If wrapping externally, this is 0 */
 
 222 static DocEntry *doc_parent() {
 
 224     return doc_stack[doc_stack_top];
 
 229 // ----------------------------------------------------------------------
 
 230 // create_function(int ext, char *name, DataType *t, ParmList *l)
 
 232 // Creates a function and manages documentation creation.  Really
 
 233 // only used internally to the parser.
 
 234 // ----------------------------------------------------------------------
 
 236 void create_function(int ext, char *name, DataType *t, ParmList *l) {
 
 237   if (Active_static) return;     // Static declaration. Ignore
 
 240   if (WrapExtern) return;        // External wrapper file. Ignore
 
 242   char *iname = make_name(name);
 
 244   // Check if symbol already exists
 
 246   if (add_symbol(iname, t, (char *) 0)) {
 
 247     fprintf(stderr,"%s : Line %d. Function %s multiply defined (2nd definition ignored).\n",
 
 248             input_file, line_number, iname);
 
 252       fprintf(stderr,"Wrapping function : ");
 
 253       emit_extern_func(name, t, l, 0, stderr);
 
 256     // If extern, make an extern declaration in the SWIG wrapper file
 
 259       emit_extern_func(name, t, l, ext, f_header);
 
 260     else if (ForceExtern) {
 
 261       emit_extern_func(name, t, l, 1, f_header);
 
 264     // If this function has been declared inline, produce a function
 
 266     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
 267     lang->create_function(name, iname, t, l);
 
 271   scanner_clear_start();
 
 274 // -------------------------------------------------------------------
 
 275 // create_variable(int ext, char *name, DataType *t)
 
 277 // Create a link to a global variable.
 
 278 // -------------------------------------------------------------------
 
 280 void create_variable(int ext, char *name, DataType *t) {
 
 282   if (WrapExtern) return;        // External wrapper file. Ignore
 
 283   int oldstatus = Status;
 
 285   if (Active_static) return;  // If static ignore
 
 289   char *iname = make_name(name);
 
 290   if (add_symbol(iname, t, (char *) 0)) {
 
 291     fprintf(stderr,"%s : Line %d. Variable %s multiply defined (2nd definition ignored).\n",
 
 292             input_file, line_number, iname);
 
 296       fprintf(stderr,"Wrapping variable : ");
 
 297       emit_extern_var(name, t, 0, stderr);
 
 300     // If externed, output an external declaration
 
 303       emit_extern_var(name, t, ext, f_header);
 
 304     else if (ForceExtern) {
 
 305       emit_extern_var(name, t, 1, f_header);
 
 308     // If variable datatype is read-only, we'll force it to be readonly
 
 309     if (t->status & STAT_READONLY) Status = Status | STAT_READONLY;
 
 312     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
 313     lang->link_variable(name, iname, t);
 
 317   scanner_clear_start();
 
 320 // ------------------------------------------------------------------
 
 321 // create_constant(char *name, DataType *type, char *value)
 
 323 // Creates a new constant.
 
 324 // -------------------------------------------------------------------
 
 326 void create_constant(char *name, DataType *type, char *value) {
 
 328   if (Active_static) return;
 
 329   if (WrapExtern) return;        // External wrapper file. Ignore
 
 333     fprintf(stderr,"%s : Line %d. %%name directive ignored with #define\n",
 
 334             input_file, line_number);
 
 338   if ((type->type == T_CHAR) && (!type->is_pointer))
 
 341   if (!value) value = copy_string(name);
 
 342   sprintf(temp_name,"const:%s", name);
 
 343   if (add_symbol(temp_name, type, value)) {
 
 344     fprintf(stderr,"%s : Line %d. Constant %s multiply defined. (2nd definition ignored)\n",
 
 345             input_file, line_number, name);
 
 347     // Update symbols value if already defined.
 
 348     update_symbol(name, type, value);
 
 350     if (!WrapExtern) {    // Only wrap the constant if not in %extern mode
 
 353         fprintf(stderr,"Creating constant %s = %s\n", name, value);
 
 355       doc_entry = new DocDecl(name,doc_stack[doc_stack_top]);      
 
 356       lang->declare_const(name, name, type, value);
 
 357       type->check_defined();
 
 360   scanner_clear_start();
 
 364 /* Print out array brackets */
 
 367   for (i = 0; i < InArray; i++)
 
 368     fprintf(stderr,"[]");
 
 371 /* manipulate small stack for managing if-then-else */
 
 373 static int then_data[100];
 
 374 static int else_data[100];
 
 375 static int allow_data[100];
 
 376 static int te_index = 0;
 
 377 static int prev_allow = 1;
 
 380   then_data[te_index] = in_then;
 
 381   else_data[te_index] = in_else;
 
 382   allow_data[te_index] = allow;
 
 385   if (te_index >= 100) {
 
 386     fprintf(stderr,"SWIG.  Internal parser error. if-then-else stack overflow.\n");
 
 394     in_then = then_data[te_index];
 
 395     in_else = else_data[te_index];
 
 396     allow = allow_data[te_index];
 
 398       prev_allow = allow_data[te_index-1];
 
 405 // Structures for handling code fragments built for nested classes
 
 408   String   code;         // Associated code fragment
 
 409   int      line;         // line number where it starts
 
 410   char     *name;        // Name associated with this nested class
 
 411   DataType *type;        // Datatype associated with the name
 
 412   Nested   *next;        // Next code fragment in list
 
 415 // Some internal variables for saving nested class information
 
 417 static Nested      *nested_list = 0;
 
 419 // Add a function to the nested list
 
 421 static void add_nested(Nested *n) {
 
 423   if (!nested_list) nested_list = n;
 
 426     while (n1->next) n1 = n1->next;
 
 431 // Dump all of the nested class declarations to the inline processor
 
 432 // However.  We need to do a few name replacements and other munging
 
 433 // first.  This function must be called before closing a class!
 
 435 static void dump_nested(char *parent) {
 
 438   int oldstatus = Status;
 
 440   Status = STAT_READONLY;
 
 442     // Token replace the name of the parent class
 
 443     n->code.replace("$classname",parent);
 
 445     // Fix up the name of the datatype (for building typedefs and other stuff)
 
 446     sprintf(n->type->name,"%s_%s",parent,n->name);
 
 448     // Add the appropriate declaration to the C++ processor
 
 449     doc_entry = new DocDecl(n->name,doc_stack[doc_stack_top]);
 
 450     cplus_variable(n->name,(char *) 0, n->type);
 
 452     // Dump the code to the scanner
 
 454       fprintf(stderr,"Splitting from %s : (line %d) \n%s\n", parent,n->line, n->code.get());
 
 456     fprintf(f_header,"\n%s\n", n->code.get());
 
 457     start_inline(n->code.get(),n->line);
 
 469 /* The type of each node in the parse tree
 
 470    must be one of the elements of the union
 
 471    given below.  This is used to derive the
 
 472    C++ declaration for "yylval" that appears
 
 503 %token <id> HBLOCK WRAPPER POUND 
 
 505 %token <id> NUM_INT NUM_FLOAT CHARCONST NUM_UNSIGNED NUM_LONG NUM_ULONG
 
 506 %token <ivalue> TYPEDEF
 
 507 %token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_TYPEDEF
 
 508 %token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE DEFINE PERIOD
 
 509 %token CONST STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
 
 510 %token WEXTERN ILLEGAL
 
 511 %token READONLY READWRITE NAME RENAME INCLUDE CHECKOUT ADDMETHODS PRAGMA 
 
 513 %token ENUM ENDDEF MACRO 
 
 514 %token CLASS PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND OPERATOR THROW TEMPLATE
 
 516 %token IFDEF IFNDEF ENDIF ELSE UNDEF IF DEFINED ELIF
 
 517 %token RAW_MODE ALPHA_MODE TEXT DOC_DISABLE DOC_ENABLE STYLE LOCALSTYLE
 
 518 %token TYPEMAP EXCEPT IMPORT ECHO NEW APPLY CLEAR DOCONLY
 
 519 %token <ivalue> TITLE SECTION SUBSECTION SUBSUBSECTION 
 
 520 %token LESSTHAN GREATERTHAN
 
 521 %token <id> USERDIRECTIVE
 
 523 /* Objective C tokens */
 
 525 %token OC_INTERFACE OC_END OC_PUBLIC OC_PRIVATE OC_PROTECTED OC_CLASS OC_IMPLEMENT OC_PROTOCOL
 
 533 %left  UMINUS NOT LNOT
 
 536 %type <ivalue>   extern array array2 parm_specifier parm_specifier_list;
 
 537 %type <pl>       parms ptail;
 
 538 %type <p>        parm parm_type;
 
 539 %type <tmparm>   typemap_parm tm_list tm_tail;
 
 540 %type <id>       pname cpptype base_specifier access_specifier typemap_name tm_method idstring;
 
 541 %type <type>     type opt_signed opt_unsigned strict_type;
 
 542 %type <decl>     declaration nested_decl;
 
 543 %type <ivalue>   stars cpp_const_expr;
 
 544 %type <ilist>    initlist base_list inherit;
 
 545 %type <dtype>    definetype definetail def_args;
 
 548 %type <id>       ename stylearg objc_inherit;
 
 549 %type <dlist>    stylelist styletail;
 
 550 %type <type>     objc_ret_type objc_arg_type; 
 
 551 %type <id>       objc_protolist objc_separator;
 
 552 %type <pl>       objc_args;
 
 556 /* The productions of the grammar with their
 
 557    associated semantic actions. */
 
 562                       for (ii = 0; ii < 256; ii++) {
 
 563                         handler_stack[ii] = 0;
 
 565                       handler_stack[0] = comment_handler;
 
 567                     doc_stack[0] = doctitle;
 
 569                    CommentHandler::cleanup();
 
 571                    doc_entry = doctitle;
 
 576                      fprintf(stderr,"%s : EOF.  Missing #endif detected.\n", input_file);
 
 582 command        : command statement { 
 
 583                      scanner_clear_start();
 
 590 statement      : INCLUDE idstring {
 
 594                     // comment_handler->clear();
 
 599 /* %extern directive */
 
 603                    int oldextern = WrapExtern;
 
 606                    // comment_handler->clear();
 
 608                    if (include_file($2) >= 0) {
 
 609                      add_symbol("SWIGEXTERN",0,0);
 
 611                      WrapExtern = oldextern;
 
 616 /* %import directive.  Like %extern but calls out to a language module */
 
 620                     int oldextern = WrapExtern;
 
 624                     if (include_file($2) >= 0) {
 
 625                       add_symbol("SWIGEXTERN",0,0);
 
 628                       WrapExtern = oldextern;
 
 633 /* %checkout directive.  Like %include, but simply copies the file into the
 
 636                 | CHECKOUT idstring {
 
 638                      if ((checkout_file($2,$2)) == 0) {
 
 639                        fprintf(stderr,"%s checked out from the SWIG library.\n",$2);
 
 644 /* An unknown C preprocessor statement.  Just throw it away */
 
 650                     fprintf(stderr,"%s : Line %d.  CPP %s ignored.\n", input_file, line_number,$1);
 
 655 /* A variable declaration */
 
 657                 | extern type declaration array2 def_args {
 
 660                     if (Active_type) delete Active_type;
 
 661                     Active_type = new DataType($2);
 
 663                     $2->is_pointer += $3.is_pointer;
 
 666                       $2->status = STAT_READONLY;
 
 667                       $2->arraystr = copy_string(ArrayString);
 
 669                     if ($3.is_reference) {
 
 670                       fprintf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
 
 674                         if ((strcmp($2->qualifier,"const") == 0)) {
 
 675                           if ($5.type != T_ERROR)
 
 676                             create_constant($3.id, $2, $5.id);
 
 678                           create_variable($1,$3.id,$2);
 
 680                         create_variable($1,$3.id,$2);
 
 686 /* Global variable that smells like a function pointer */
 
 688                 | extern strict_type LPAREN STAR { 
 
 690                    fprintf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
 
 691                            input_file, line_number);
 
 694 /* A static variable declaration (Ignored) */
 
 696                 | STATIC type declaration array2 def_args {
 
 698                     fprintf(stderr,"static variable %s ignored.\n",$3.id);
 
 706 /* Global variable that smells like a function pointer */
 
 708                 | STATIC strict_type LPAREN STAR { 
 
 710                    fprintf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
 
 711                            input_file, line_number);
 
 715 /* A function declaration */
 
 717                 | extern type declaration LPAREN parms RPAREN cpp_const {
 
 720                     if (Active_type) delete Active_type;
 
 721                     Active_type = new DataType($2);
 
 723                     $2->is_pointer += $3.is_pointer;
 
 724                     $2->is_reference = $3.is_reference;
 
 725                     create_function($1, $3.id, $2, $5);
 
 731 /* A function declaration with code after it */
 
 733                 | extern type declaration LPAREN parms RPAREN func_end {
 
 736                     $2->is_pointer += $3.is_pointer;
 
 737                     $2->is_reference = $3.is_reference;
 
 738                     create_function($1, $3.id, $2, $5);
 
 744 /* A function declared without any return datatype */
 
 746                 | extern declaration LPAREN parms RPAREN cpp_const { 
 
 749                     DataType *t = new DataType(T_INT);
 
 750                     t->is_pointer += $2.is_pointer;
 
 751                     t->is_reference = $2.is_reference;
 
 752                     create_function($1,$2.id,t,$4);
 
 757 /* A static function declaration code after it */
 
 759                 | STATIC type declaration LPAREN parms RPAREN func_end {
 
 760                   if ((allow) && (Inline)) {
 
 761                     if (strlen(CCode.get())) {
 
 763                       $2->is_pointer += $3.is_pointer;
 
 764                       $2->is_reference = $3.is_reference;
 
 765                       create_function(0, $3.id, $2, $5);
 
 772 /* A function with an explicit inline directive. Not safe to use inside a %inline block */
 
 774                 | INLINE type declaration LPAREN parms RPAREN func_end {
 
 777                     $2->is_pointer += $3.is_pointer;
 
 778                     $2->is_reference = $3.is_reference;
 
 780                       fprintf(stderr,"%s : Line %d. Repeated %%inline directive.\n",input_file,line_number);
 
 783                       if (strlen(CCode.get())) {
 
 784                         fprintf(f_header,"static ");
 
 785                         emit_extern_func($3.id,$2,$5,3,f_header);
 
 786                         fprintf(f_header,"%s\n",CCode.get());
 
 788                       create_function(0, $3.id, $2, $5);
 
 795 /* A static function declaration (ignored) */
 
 797                 | STATIC type declaration LPAREN parms RPAREN cpp_const {
 
 800                       fprintf(stderr,"static function %s ignored.\n", $3.id);
 
 810 /* Enable Read-only mode */
 
 814                     Status = Status | STAT_READONLY;
 
 817 /* Enable Read-write mode */
 
 821                    Status = Status & ~STAT_READONLY;
 
 824 /* New %name directive */
 
 825                | NAME LPAREN ID RPAREN {
 
 827                      strcpy(yy_rename,$3);
 
 832 /* %rename directive */
 
 833                | RENAME ID ID SEMI { 
 
 834                  if (name_hash.lookup($2)) {
 
 835                    name_hash.remove($2);
 
 837                  name_hash.add($2,copy_string($3));
 
 848 /* Empty name directive.  No longer allowed  */
 
 850                | NAME LPAREN RPAREN {
 
 852                    fprintf(stderr,"%s : Lind %d. Empty %%name() is no longer supported.\n",
 
 853                            input_file, line_number);
 
 860 /* A native wrapper function */
 
 862                | NATIVE LPAREN ID RPAREN extern ID SEMI {
 
 863                  if (allow && (!WrapExtern)) {
 
 865                    if (add_symbol($3,(DataType *) 0, (char *) 0)) {
 
 866                      fprintf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n",
 
 867                              input_file, line_number, $3);
 
 869                      doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 
 870                      lang->add_native($3,$6);
 
 874                | NATIVE LPAREN ID RPAREN extern type declaration LPAREN parms RPAREN SEMI {
 
 875                  if (allow && (!WrapExtern)) {
 
 877                    $6->is_pointer += $7.is_pointer;
 
 878                    if (add_symbol($3,(DataType *) 0, (char *) 0)) {
 
 879                      fprintf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n",
 
 880                              input_file, line_number, $3);
 
 883                        emit_extern_func($7.id, $6, $9, $5, f_header);
 
 885                      doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 
 886                      lang->add_native($3,$7.id);
 
 893 /* %title directive */
 
 895                | TITLE STRING styletail {
 
 896                  if (allow && (!WrapExtern)) {
 
 900                      if (!comment_handler) {
 
 901                        comment_handler = new CommentHandler();
 
 905                        for (ii = 0; ii < $3.count; ii++) {
 
 906                          comment_handler->style($3.names[ii],$3.values[ii]);
 
 909                      // Create a new title for documentation 
 
 911                        int temp = line_number;
 
 914                          doctitle = new DocTitle($2,0);
 
 916                          doctitle->name = copy_string(title);
 
 917                          doctitle->line_number = $1;
 
 918                          doctitle->end_line = $1;
 
 922                      doctitle->usage = $2;
 
 923                      doc_entry = doctitle;
 
 924                      doc_stack[0] = doc_entry;
 
 926                      handler_stack[0] = comment_handler;
 
 929                        for (ii = 0; ii < $3.count; ii++) {
 
 930                          doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 
 941 /* %section directive */
 
 943                | SECTION STRING styletail {
 
 944                  if (allow && (!WrapExtern) && (!IgnoreDoc)) {
 
 945                    // Copy old comment handler
 
 946                    // if (handler_stack[1]) delete handler_stack[1];
 
 947                    handler_stack[1] = new CommentHandler(handler_stack[0]);  
 
 948                    comment_handler = handler_stack[1];
 
 951                      for (ii = 0; ii < $3.count; ii++) {
 
 952                        comment_handler->style($3.names[ii],$3.values[ii]);
 
 956                      int temp = line_number;
 
 958                      doc_entry = new DocSection($2,doc_stack[0]);
 
 962                    doc_stack[1] = doc_entry;
 
 965                      for (ii = 0; ii < $3.count; ii++) {
 
 966                        doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 
 972 /* %subsection directive */
 
 973                | SUBSECTION STRING styletail {
 
 974                  if (allow && (!WrapExtern) && (!IgnoreDoc)) {
 
 975                    if (doc_stack_top < 1) {
 
 976                      fprintf(stderr,"%s : Line %d. Can't apply %%subsection here.\n", input_file,line_number);
 
 980                      // Copy old comment handler
 
 981                      // if (handler_stack[2]) delete handler_stack[2];
 
 982                      handler_stack[2] = new CommentHandler(handler_stack[1]);
 
 983                      comment_handler = handler_stack[2];
 
 986                        for (ii = 0; ii < $3.count; ii++) {
 
 987                          comment_handler->style($3.names[ii],$3.values[ii]);
 
 991                        int temp = line_number;
 
 993                        doc_entry = new DocSection($2,doc_stack[1]);
 
 997                      doc_stack[2] = doc_entry;
 
1000                        for (ii = 0; ii < $3.count; ii++) {
 
1001                          doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 
1008 /* %subsubsection directive */
 
1009                | SUBSUBSECTION STRING styletail {
 
1010                  if (allow && (!WrapExtern) && (!IgnoreDoc)) {
 
1011                    if (doc_stack_top < 2) {
 
1012                      fprintf(stderr,"%s : Line %d. Can't apply %%subsubsection here.\n", input_file,line_number);
 
1016                      // Copy old comment handler
 
1018                      // if (handler_stack[3]) delete handler_stack[3];
 
1019                      handler_stack[3] = new CommentHandler(handler_stack[2]);
 
1020                      comment_handler = handler_stack[3];
 
1023                        for (ii = 0; ii < $3.count; ii++) {
 
1024                          comment_handler->style($3.names[ii],$3.values[ii]);
 
1028                        int temp = line_number;
 
1030                        doc_entry = new DocSection($2,doc_stack[2]);
 
1034                      doc_stack[3] = doc_entry;
 
1037                        for (ii = 0; ii < $3.count; ii++) {
 
1038                          doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
 
1045 /* %alpha directive (obsolete) */
 
1047                  if (allow && (!WrapExtern)) {
 
1048                    fprintf(stderr,"%%alpha directive is obsolete.  Use '%%style sort' instead.\n");
 
1049                    handler_stack[0]->style("sort",0);
 
1050                    doc_stack[0]->style("sort",0);
 
1053 /* %raw directive (obsolete) */
 
1055                  if (allow && (!WrapExtern)) {
 
1056                    fprintf(stderr,"%%raw directive is obsolete. Use '%%style nosort' instead.\n");
 
1057                    handler_stack[0]->style("nosort",0);
 
1058                    doc_stack[0]->style("nosort",0);
 
1064 /* %text directive */
 
1067                  if (allow && (!WrapExtern)) {
 
1068                    $2[strlen($2) - 1] = 0;
 
1069                    doc_entry = new DocText($2,doc_stack[doc_stack_top]);
 
1077 /* Code insertion block */
 
1080                  if (allow && (!WrapExtern)) {
 
1082                    $1[strlen($1) - 1] = 0;
 
1083 //                 fprintf(f_header,"#line %d \"%s\"\n", start_line, input_file);
 
1084                    fprintf(f_header, "%s\n", $1);
 
1088 /* Super-secret undocumented for people who really know what's going on feature */
 
1091                  if (allow && (!WrapExtern)) {
 
1093                    $2[strlen($2) - 1] = 0;
 
1094                    fprintf(f_wrappers,"%s\n",$2);
 
1098 /* Initialization code */
 
1101                  if (allow && (!WrapExtern)) {
 
1103                    $2[strlen($2) -1] = 0;
 
1104                    fprintf(f_init,"%s\n", $2);
 
1110                  if (allow && (!WrapExtern)) {
 
1112                    $2[strlen($2) - 1] = 0;
 
1113                    fprintf(f_header, "%s\n", $2);
 
1114                    start_inline($2,start_line);
 
1120                  if (allow && (!WrapExtern)) {
 
1121                    fprintf(stderr,"%s\n", $2);
 
1126                  if (allow && (!WrapExtern)) {
 
1127                    fprintf(stderr,"%s\n", $2);
 
1131 /* Disable code generation */
 
1136 /* Init directive--to avoid errors in other modules */
 
1138                | INIT ID initlist {
 
1146                        fprintf(stderr,"%s : Line %d. %%init %s ignored.\n",
 
1147                                input_file, line_number, $2);
 
1150                      fprintf(stderr,"%s : Line %d. Warning. Init list no longer supported.\n",
 
1151                              input_file,line_number);
 
1154                  for (i = 0; i < $3.count; i++)
 
1155                    if ($3.names[i]) delete [] $3.names[i];
 
1158 /* Module directive */
 
1160                | MODULE ID initlist {
 
1163                      lang->set_module($2,$3.names);
 
1165                      lang->set_module($2,0);
 
1169                  for (i = 0; i < $3.count; i++)
 
1170                    if ($3.names[i]) delete [] $3.names[i];
 
1174 /* #define directive */
 
1176                | DEFINE ID definetail {
 
1178                    if (($3.type != T_ERROR) && ($3.type != T_SYMBOL)) {
 
1180                      temp_typeptr = new DataType($3.type);
 
1181                      create_constant($2, temp_typeptr, $3.id);
 
1182                      delete temp_typeptr;
 
1183                    } else if ($3.type == T_SYMBOL) {
 
1184                      // Add a symbol to the SWIG symbol table
 
1185                      if (add_symbol($2,(DataType *) 0, (char *) 0)) {
 
1186                        fprintf(stderr,"%s : Line %d. Warning. Symbol %s already defined.\n", 
 
1187                                input_file,line_number, $2);
 
1193 /* A CPP Macro.   Ignore (hopefully) */
 
1197                    fprintf(stderr,"%s : Line %d.  CPP Macro ignored.\n", input_file, line_number);
 
1201 /* An undef directive */
 
1208                | extern ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE SEMI { 
 
1212                      temp_type.type = T_INT;
 
1213                      temp_type.is_pointer = 0;
 
1214                      temp_type.implicit_ptr = 0;
 
1215                      sprintf(temp_type.name,"int");
 
1216                      temp_type.typedef_add($3,1);
 
1221 /* A typdef'd enum.  Pretty common in C headers */
 
1223                | TYPEDEF ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE ID {
 
1226                    temp_type.type = T_INT;
 
1227                    temp_type.is_pointer = 0;
 
1228                    temp_type.implicit_ptr = 0;
 
1229                    sprintf(temp_type.name,"int");
 
1230                    Active_typedef = new DataType(&temp_type);
 
1231                    temp_type.typedef_add($8,1);
 
1235 /* -----------------------------------------------------------------
 
1238    These constructs are used to support type-maps.
 
1239    ----------------------------------------------------------------- */
 
1241 /* Create a new typemap */
 
1243                | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
 
1248                      typemap_register($5,$3,p->p->t,p->p->name,CCode,p->args);
 
1255 /* Create a new typemap in current language */
 
1256                | TYPEMAP LPAREN tm_method RPAREN tm_list LBRACE {
 
1257                  if (!typemap_lang) {
 
1258                    fprintf(stderr,"SWIG internal error. No typemap_lang specified.\n");
 
1259                    fprintf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
 
1266                      typemap_register($3,typemap_lang,p->p->t,p->p->name,CCode,p->args);
 
1273 /* Clear a typemap */
 
1275                | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list SEMI {
 
1279                    typemap_clear($5,$3,p->p->t,p->p->name);
 
1285 /* Clear a typemap in current language */
 
1287                | TYPEMAP LPAREN tm_method RPAREN tm_list SEMI {
 
1288                  if (!typemap_lang) {
 
1289                    fprintf(stderr,"SWIG internal error. No typemap_lang specified.\n");
 
1290                    fprintf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
 
1296                      typemap_clear($3,typemap_lang,p->p->t,p->p->name);
 
1303 /* Copy a typemap */
 
1305                | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
 
1309                      typemap_copy($5,$3,$9->p->t,$9->p->name,p->p->t,p->p->name);
 
1318 /* Copy typemap in current language */
 
1320                | TYPEMAP LPAREN tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
 
1321                  if (!typemap_lang) {
 
1322                    fprintf(stderr,"SWIG internal error. No typemap_lang specified.\n");
 
1323                    fprintf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
 
1329                      typemap_copy($3,typemap_lang,$7->p->t,$7->p->name,p->p->t,p->p->name);
 
1337 /* -----------------------------------------------------------------
 
1338    apply and clear support (for typemaps)
 
1339    ----------------------------------------------------------------- */
 
1341                | APPLY typemap_parm LBRACE tm_list RBRACE {
 
1345                    typemap_apply($2->p->t,$2->p->name,p->p->t,p->p->name);
 
1352                | CLEAR tm_list SEMI {
 
1356                    typemap_clear_apply(p->p->t, p->p->name);
 
1362 /* -----------------------------------------------------------------
 
1365    These constructs are used to define exceptions
 
1366    ----------------------------------------------------------------- */
 
1368 /* An exception definition */
 
1369                | EXCEPT LPAREN ID RPAREN LBRACE {
 
1371                     fragment_register("except",$3, CCode);
 
1375 /* A Generic Exception (no language specified */
 
1378                     fragment_register("except",typemap_lang, CCode);
 
1381 /* Clear an exception */
 
1383                | EXCEPT LPAREN ID RPAREN SEMI {
 
1384                      fragment_clear("except",$3);
 
1389                      fragment_clear("except",typemap_lang);
 
1392 /* Miscellaenous stuff */
 
1400                      static int last_error_line = -1;
 
1401                      if (last_error_line != line_number) {
 
1402                        fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 
1404                        last_error_line = line_number;
 
1405                        // Try to make some kind of recovery.
 
1413 /* A an extern C type declaration.  Does nothing, but is ignored */
 
1415                | EXTERN STRING LBRACE command RBRACE { }
 
1418 /* Officially, this directive doesn't exist yet */
 
1422 /* %style directive.   This applies to all current styles */
 
1427                    for (ii = 0; ii < $2.count; ii++) {
 
1428                      comment_handler->style($2.names[ii],$2.values[ii]);
 
1429                      for (jj = 0; jj < doc_stack_top; jj++) 
 
1430                        doc_stack[jj]->style($2.names[ii],$2.values[ii]);
 
1432                        doctitle->style($2.names[ii],$2.values[ii]);
 
1433                      doc->style($2.names[ii],$2.values[ii]);
 
1438 /* %localstyle directive.   This applies only to the current style */
 
1440                | LOCALSTYLE stylelist {
 
1443                    for (ii = 0; ii < $2.count; ii++) {
 
1444                      comment_handler = new CommentHandler(comment_handler);
 
1445                      handler_stack[doc_stack_top] = comment_handler;
 
1446                      comment_handler->style($2.names[ii],$2.values[ii]);
 
1447                      doc_stack[doc_stack_top]->style($2.names[ii],$2.values[ii]);
 
1452 /* User defined directive */
 
1457 /* Dcumentation disable/enable */
 
1459 doc_enable     : DOC_DISABLE {
 
1462                      /* Already in a disabled documentation */
 
1466                        fprintf(stderr,"%s : Line %d. Documentation disabled.\n", input_file, line_number);
 
1472 /* %enabledoc directive */
 
1476                      if (doc_scope > 1) {
 
1480                          fprintf(stderr,"%s : Line %d. Documentation enabled.\n", input_file, line_number);
 
1489 /* Note : This really needs to be re-done */
 
1491 /* A typedef with pointers */
 
1492 typedef_decl   : TYPEDEF type declaration {
 
1495                    /* Add a new typedef */
 
1496                    Active_typedef = new DataType($2);
 
1497                    $2->is_pointer += $3.is_pointer;
 
1498                    $2->typedef_add($3.id);
 
1499                    /* If this is %typedef, add it to the header */
 
1501                      fprintf(f_header,"typedef %s %s;\n", $2->print_full(), $3.id);
 
1502                    cplus_register_type($3.id);
 
1506 /* A rudimentary typedef involving function pointers */
 
1508                | TYPEDEF type LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
 
1511                    /* Typedef'd pointer */
 
1513                      sprintf(temp_name,"(*%s)",$5);
 
1514                      fprintf(f_header,"typedef ");
 
1515                      emit_extern_func(temp_name, $2,$8,0,f_header);
 
1517                    strcpy($2->name,"<function ptr>");
 
1520                    $2->typedef_add($5,1);
 
1521                    cplus_register_type($5);
 
1528 /* A typedef involving function pointers again */
 
1530                | TYPEDEF type stars LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
 
1534                      $2->is_pointer += $3;
 
1535                      sprintf(temp_name,"(*%s)",$6);
 
1536                      fprintf(f_header,"typedef ");
 
1537                      emit_extern_func(temp_name, $2,$9,0,f_header);
 
1540                    /* Typedef'd pointer */
 
1541                    strcpy($2->name,"<function ptr>");
 
1544                    $2->typedef_add($6,1);
 
1545                    cplus_register_type($6);
 
1552 /* A typedef involving arrays */
 
1554                | TYPEDEF type declaration array {
 
1557                    Active_typedef = new DataType($2);
 
1558                    // This datatype is going to be readonly
 
1560                    $2->status = STAT_READONLY | STAT_REPLACETYPE;
 
1561                    $2->is_pointer += $3.is_pointer;
 
1562                    // Turn this into a "pointer" corresponding to the array
 
1564                    $2->arraystr = copy_string(ArrayString);
 
1565                    $2->typedef_add($3.id);
 
1566                    fprintf(stderr,"%s : Line %d. Warning. Array type %s will be read-only without a typemap\n",input_file,line_number, $3.id);
 
1567                    cplus_register_type($3.id);
 
1573 /* ------------------------------------------------------------------------
 
1576    The following rules are used to manage typedef lists.  Only a temporary
 
1577    hack until the SWIG 2.0 parser gets online.
 
1579    Active_typedef contains the datatype of the last typedef (if applicable)
 
1580    ------------------------------------------------------------------------ */
 
1583 typedeflist   : COMMA declaration typedeflist {
 
1585                   if (Active_typedef) {
 
1587                     t = new DataType(Active_typedef);
 
1588                     t->is_pointer += $2.is_pointer;
 
1589                     t->typedef_add($2.id);
 
1590                     cplus_register_type($2.id);
 
1595               | COMMA declaration array {
 
1597                     t = new DataType(Active_typedef);
 
1598                     t->status = STAT_READONLY | STAT_REPLACETYPE;
 
1599                     t->is_pointer += $2.is_pointer + 1;
 
1600                     t->arraystr = copy_string(ArrayString);
 
1601                     t->typedef_add($2.id);
 
1602                     cplus_register_type($2.id);
 
1604                     fprintf(stderr,"%s : Line %d. Warning. Array type %s will be read-only without a typemap.\n",input_file,line_number, $2.id);
 
1609 /* ----------------------------------------------------------------------------------
 
1610    Conditional Compilation
 
1612    SWIG supports the following constructs
 
1621    #if, and #elif are a little weak in this implementation
 
1622    ---------------------------------------------------------------------------------- */
 
1625 /* #ifdef directive */
 
1626 cond_compile   : IFDEF ID {
 
1627                  /* Push old if-then-else status */
 
1629                  /* Look a symbol up in the symbol table */
 
1630                  if (lookup_symbol($2)) {
 
1633                    allow = 1 & prev_allow;
 
1635                    /* Condition is false.   Skip over whatever is in this block */
 
1636                    in_else = skip_cond(1);
 
1637                    if (in_else == -1) {
 
1638                      /* Unrecoverable error */
 
1642                      if_pop();        // Pop out. Reached end of block
 
1650 /* #ifndef directive */
 
1654                  if (lookup_symbol($2)) {
 
1655                    /* Condition is false.   Skip over whatever is in this block */
 
1656                    in_else = skip_cond(1);
 
1657                    if (in_else == -1) {
 
1658                      /* Unrecoverable error */
 
1662                      if_pop();        // Pop out. Reached end of block
 
1670                    allow = 1 & prev_allow;
 
1674 /* #else directive */
 
1676                  if ((!in_then) || (in_else)) {
 
1677                    fprintf(stderr,"%s : Line %d. Misplaced else\n", input_file, line_number);
 
1684                      /* Skip over rest of the conditional */
 
1690                    allow = allow & prev_allow;
 
1693 /* #endif directive */
 
1695                  if ((!in_then) && (!in_else)) {
 
1696                    fprintf(stderr,"%s : Line %d. Misplaced endif\n", input_file, line_number);
 
1704                | IF cpp_const_expr {
 
1705                  /* Push old if-then-else status */
 
1710                    allow = 1 & prev_allow;
 
1712                    /* Condition is false.   Skip over whatever is in this block */
 
1713                    in_else = skip_cond(1);
 
1714                    if (in_else == -1) {
 
1715                      /* Unrecoverable error */
 
1719                      if_pop();        // Pop out. Reached end of block
 
1727 /* #elif.  We treat this identical to an #if.  Abit of a hack, but what
 
1730                | ELIF cpp_const_expr {
 
1731                  /* have to pop old if clause off */
 
1734                  /* Push old if-then-else status */
 
1739                    allow = 1 & prev_allow;
 
1741                    /* Condition is false.   Skip over whatever is in this block */
 
1742                    in_else = skip_cond(1);
 
1743                    if (in_else == -1) {
 
1744                      /* Unrecoverable error */
 
1748                      if_pop();        // Pop out. Reached end of block
 
1757 /* C preprocessor expression (only used for conditional compilation */
 
1759 cpp_const_expr : DEFINED LPAREN ID RPAREN {
 
1761                  /* Look ID up in the symbol table */
 
1762                     if (lookup_symbol($3)) {
 
1769                  if (lookup_symbol($2)) {
 
1775                | LNOT cpp_const_expr {
 
1781 pragma         : PRAGMA LPAREN ID COMMA ID stylearg RPAREN {
 
1782                  if (allow && (!WrapExtern))
 
1783                    lang->pragma($3,$5,$6);
 
1784                    fprintf(stderr,"%s : Line %d. Warning. '%%pragma(lang,opt=value)' syntax is obsolete.\n",
 
1785                            input_file,line_number);
 
1786                    fprintf(stderr,"        Use '%%pragma(lang) opt=value' instead.\n");
 
1789                | PRAGMA ID stylearg {
 
1790                  if (allow && (!WrapExtern)) 
 
1793                | PRAGMA LPAREN ID RPAREN ID stylearg {
 
1794                  if (allow && (!WrapExtern))
 
1795                    lang->pragma($3,$5,$6);
 
1799 /* Allow lists of variables and functions to be built up */
 
1802                | COMMA declaration array2 def_args {
 
1805                    temp_typeptr = new DataType(Active_type);
 
1806                    temp_typeptr->is_pointer += $2.is_pointer;
 
1808                      temp_typeptr->is_pointer++;
 
1809                      temp_typeptr->status = STAT_READONLY;
 
1810                      temp_typeptr->arraystr = copy_string(ArrayString);
 
1812                    if ($2.is_reference) {
 
1813                      fprintf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
 
1816                      if (temp_typeptr->qualifier) {
 
1817                        if ((strcmp(temp_typeptr->qualifier,"const") == 0)) {
 
1818                          /* Okay.  This is really some sort of C++ constant here. */
 
1819                          if ($4.type != T_ERROR)
 
1820                            create_constant($2.id, temp_typeptr, $4.id);
 
1822                          create_variable(Active_extern,$2.id, temp_typeptr);
 
1824                        create_variable(Active_extern, $2.id, temp_typeptr);
 
1826                    delete temp_typeptr;
 
1829                | COMMA declaration LPAREN parms RPAREN cpp_const {
 
1832                    temp_typeptr = new DataType(Active_type);
 
1833                    temp_typeptr->is_pointer += $2.is_pointer;
 
1834                    temp_typeptr->is_reference = $2.is_reference;
 
1835                    create_function(Active_extern, $2.id, temp_typeptr, $4);
 
1836                    delete temp_typeptr;
 
1842 definetail     : definetype ENDDEF {
 
1850                    fprintf(stderr,"%s : Line %d.  Warning. Unable to parse #define (ignored)\n", input_file, line_number);
 
1856 extern         : EXTERN { $$ = 1; }
 
1859                  if (strcmp($2,"C") == 0) {
 
1862                    fprintf(stderr,"%s : Line %d.  Unrecognized extern type \"%s\" (ignored).\n", input_file, line_number, $2);
 
1868 /* End of a function declaration.  Allows C++ "const" directive and inline code */
 
1870 func_end       : cpp_const LBRACE { skip_brace(); }
 
1871 /*               | LBRACE { skip_brace(); } */
 
1874 /* ------------------------------------------------------------------------------
 
1875    Function parameter lists
 
1877    ------------------------------------------------------------------------------ */
 
1879 parms          : parm ptail {
 
1880                  if (($1->t->type != T_VOID) || ($1->t->is_pointer))
 
1885                | empty { $$ = new ParmList;}
 
1888 ptail          : COMMA parm ptail {
 
1893                | empty { $$ = new ParmList;}
 
1898                   if (typemap_check("ignore",typemap_lang,$$->t,$$->name))
 
1901                | parm_specifier_list parm_type {
 
1903                   $$->call_type = $$->call_type | $1;
 
1904                   if (InArray && ($$->call_type & CALL_VALUE)) {
 
1905                      fprintf(stderr,"%s : Line %d. Error. Can't use %%val with an array.\n", input_file, line_number);
 
1908                   if (!$$->t->is_pointer) {
 
1909                      fprintf(stderr,"%s : Line %d. Error. Can't use %%val or %%out with a non-pointer argument.\n", input_file, line_number);
 
1912                     $$->t->is_pointer--;
 
1916 parm_type      : type pname {
 
1920                         fprintf(stderr,"%s : Line %d. Warning. Array %s", input_file, line_number, $1->print_type());
 
1922                         fprintf(stderr," has been converted to %s.\n", $1->print_type());
 
1924                       // Add array string to the type
 
1925                       $1->arraystr = copy_string(ArrayString.get());
 
1927                     $$ = new Parm($1,$2);
 
1929                     $$->defvalue = DefArg;
 
1930                     if (($1->type == T_USER) && !($1->is_pointer)) {
 
1932                         fprintf(stderr,"%s : Line %d. Warning : Parameter of type '%s'\nhas been remapped to '%s *' and will be called using *((%s *) ptr).\n",
 
1933                                 input_file, line_number, $1->name, $1->name, $1->name);
 
1935                       $$->call_type = CALL_REFERENCE;
 
1936                       $$->t->is_pointer++;
 
1942                 | type stars pname {
 
1943                    $$ = new Parm($1,$3);
 
1944                    $$->t->is_pointer += $2;
 
1946                    $$->defvalue = DefArg;
 
1948                      $$->t->is_pointer++;
 
1950                        fprintf(stderr,"%s : Line %d. Warning. Array %s", input_file, line_number, $$->t->print_type());
 
1952                        fprintf(stderr," has been converted to %s.\n", $$->t->print_type());
 
1954                      // Add array string to the type
 
1955                      $$->t->arraystr = copy_string(ArrayString.get());
 
1962                   $$ = new Parm($1,$3);
 
1963                   $$->t->is_reference = 1;
 
1965                   $$->t->is_pointer++;
 
1966                   $$->defvalue = DefArg;
 
1968                         fprintf(stderr,"%s : Line %d. Warning.  Use of C++ Reference detected.  Use the -c++ option.\n", input_file, line_number);
 
1973                 | type LPAREN stars pname RPAREN LPAREN parms RPAREN {
 
1974                   fprintf(stderr,"%s : Line %d. Error. Function pointer not allowed (remap with typedef).\n", input_file, line_number);
 
1976                   $$ = new Parm($1,$4);
 
1977                   $$->t->type = T_ERROR;
 
1978                   $$->name = copy_string($4);
 
1979                   strcpy($$->t->name,"<function ptr>");
 
1984                 | PERIOD PERIOD PERIOD {
 
1985                   fprintf(stderr,"%s : Line %d. Variable length arguments not supported (ignored).\n", input_file, line_number);
 
1986                   $$ = new Parm(new DataType(T_INT),"varargs");
 
1987                   $$->t->type = T_ERROR;
 
1988                   $$->name = copy_string("varargs");
 
1989                   strcpy($$->t->name,"<varargs>");
 
1994 pname          : ID def_args {
 
1997                     if ($2.type == T_CHAR)
 
1998                       DefArg = copy_string(ConstChar);
 
2000                       DefArg = copy_string($2.id);
 
2001                     if ($2.id) delete $2.id;
 
2014                | empty { $$ = new char[1];
 
2021 def_args       : EQUAL definetype { $$ = $2; }
 
2023                  $$.id = new char[strlen($3)+2];
 
2025                  strcpy(&$$.id[1], $3);
 
2030                  $$.id = 0; $$.type = T_INT;
 
2034                | empty {$$.id = 0; $$.type = T_INT;}
 
2037 parm_specifier : CVALUE { $$ = CALL_VALUE; }
 
2038                | COUT { $$ = CALL_OUTPUT; }
 
2041 parm_specifier_list : parm_specifier_list parm_specifier {
 
2049 /* Declaration must be an identifier, possibly preceded by a * for pointer types  */
 
2051 declaration    : ID { $$.id = $1;
 
2053                       $$.is_reference = 0;
 
2058                       $$.is_reference = 0;
 
2063                       $$.is_reference = 1;
 
2065                         fprintf(stderr,"%s : Line %d. Warning.  Use of C++ Reference detected.  Use the -c++ option.\n", input_file, line_number);
 
2070 stars :          STAR empty { $$ = 1; }
 
2071                | STAR stars { $$ = $2 + 1;}
 
2075 array :        LBRACKET  RBRACKET array2 {
 
2077                  "[]" >> ArrayString;
 
2079               | LBRACKET expr RBRACKET array2 {
 
2082                  $2.id >> ArrayString;
 
2094 /* Data type must be a built in type or an identifier for user-defined types
 
2095    This type can be preceded by a modifier. */
 
2100                | TYPE_SHORT opt_int {
 
2103                | TYPE_LONG opt_int {
 
2121                | TYPE_SIGNED opt_signed {
 
2125                | TYPE_UNSIGNED opt_unsigned {
 
2129                | TYPE_TYPEDEF objc_protolist {
 
2131                  if (strlen($2) > 0) {
 
2132                     if ((strlen($2) + strlen($$->name)) >= MAX_NAME) {
 
2133                       fprintf(stderr,"%s : Line %d. Fatal error. Type-name is too long!\n", 
 
2134                               input_file, line_number);
 
2136                       strcat($$->name,$2);
 
2140                | ID objc_protolist {
 
2142                   strcpy($$->name,$1);
 
2144                   /* Do a typedef lookup */
 
2145                   $$->typedef_resolve();
 
2146                   if (strlen($2) > 0) {
 
2147                     if ((strlen($2) + strlen($$->name)) >= MAX_NAME) {
 
2148                       fprintf(stderr,"%s : Line %d. Fatal error. Type-name is too long!\n", 
 
2149                               input_file, line_number);
 
2151                       strcat($$->name,$2);
 
2157                   $$->qualifier = new char[6];
 
2158                   strcpy($$->qualifier,"const");
 
2162                   sprintf($$->name,"%s %s",$1, $2);
 
2167                   sprintf($$->name,"%s::%s",$1,$3);
 
2169                   $$->typedef_resolve();
 
2171 /* This declaration causes a shift-reduce conflict.  Unresolved for now */
 
2176                   sprintf($$->name,"%s", $2);
 
2178                   $$->typedef_resolve(1);
 
2182                   sprintf($$->name,"enum %s", $2);
 
2184                   $$->typedef_resolve(1);
 
2188 /* type specification without ID symbol.   Used in some cases to prevent shift-reduce conflicts */
 
2190 strict_type    : TYPE_INT {
 
2193                | TYPE_SHORT opt_int {
 
2196                | TYPE_LONG opt_int {
 
2214                | TYPE_SIGNED opt_signed {
 
2218                | TYPE_UNSIGNED opt_unsigned {
 
2222                | TYPE_TYPEDEF objc_protolist {
 
2224                    strcat($$->name,$2);
 
2228                   $$->qualifier = new char[6];
 
2229                   strcpy($$->qualifier,"const");
 
2233                   sprintf($$->name,"%s %s",$1, $2);
 
2238 /* Optional signed types */
 
2240 opt_signed     : empty {
 
2241                    $$ = (DataType *) 0;
 
2246                    sprintf(temp_name,"signed %s",$1->name);
 
2247                    strcpy($$->name,temp_name);
 
2249                | TYPE_SHORT opt_int {
 
2252                    sprintf(temp_name,"signed %s",$1->name);
 
2253                    strcpy($$->name,temp_name);
 
2255                | TYPE_LONG opt_int {
 
2258                    sprintf(temp_name,"signed %s",$1->name);
 
2259                    strcpy($$->name,temp_name);
 
2264                    sprintf(temp_name,"signed %s",$1->name);
 
2265                    strcpy($$->name,temp_name);
 
2269 /* Optional unsigned types */
 
2271 opt_unsigned   : empty {
 
2272                    $$ = (DataType *) 0;
 
2277                    sprintf(temp_name,"unsigned %s",$1->name);
 
2278                    strcpy($$->name,temp_name);
 
2280                | TYPE_SHORT opt_int {
 
2282                    $$->type = T_USHORT;
 
2283                    sprintf(temp_name,"unsigned %s",$1->name);
 
2284                    strcpy($$->name,temp_name);
 
2286                | TYPE_LONG opt_int {
 
2289                    sprintf(temp_name,"unsigned %s",$1->name);
 
2290                    strcpy($$->name,temp_name);
 
2295                    sprintf(temp_name,"unsigned %s",$1->name);
 
2296                    strcpy($$->name,temp_name);
 
2300 opt_int        : TYPE_INT { }
 
2304 definetype     : { scanner_check_typedef(); } expr {
 
2306                    scanner_ignore_typedef();
 
2307                    if (ConstChar) delete ConstChar;
 
2313                    if (ConstChar) delete ConstChar;
 
2314                    ConstChar = new char[strlen($1)+3];
 
2315                    sprintf(ConstChar,"\"%s\"",$1);
 
2320                    if (ConstChar) delete ConstChar;
 
2321                    ConstChar = new char[strlen($1)+3];
 
2322                    sprintf(ConstChar,"'%s'",$1);
 
2327 /* Initialization function links */
 
2329 initlist       : initlist COMMA ID {
 
2331                  $$.names[$$.count] = copy_string($3);
 
2333                  $$.names[$$.count] = (char *) 0;
 
2336                  $$.names = new char *[NI_NAMES];
 
2338                  for (i = 0; i < NI_NAMES; i++) 
 
2339                    $$.names[i] = (char *) 0;
 
2343 /* Some stuff for handling enums */
 
2345 ename          :  ID { $$ = $1; } 
 
2346                |  empty { $$ = (char *) 0;}
 
2352 enumlist       :  enumlist COMMA edecl {}
 
2358                    temp_typeptr = new DataType(T_INT);
 
2359                    create_constant($1, temp_typeptr, $1);
 
2360                    delete temp_typeptr;
 
2362                  | ID EQUAL { scanner_check_typedef();} etype {
 
2363                    temp_typeptr = new DataType($4.type);
 
2364 // Use enum name instead of value
 
2365 // OLD             create_constant($1, temp_typeptr, $4.id);
 
2366                    create_constant($1, temp_typeptr, $1);
 
2367                    delete temp_typeptr;
 
2369                  | cond_compile edecl { }
 
2375                    if (($$.type != T_INT) && ($$.type != T_UINT) &&
 
2376                        ($$.type != T_LONG) && ($$.type != T_ULONG) &&
 
2377                        ($$.type != T_SHORT) && ($$.type != T_USHORT) && 
 
2378                        ($$.type != T_SCHAR) && ($$.type != T_UCHAR)) {
 
2379                      fprintf(stderr,"%s : Lind %d. Type error. Expecting an int\n",
 
2380                              input_file, line_number);
 
2391 /* Arithmetic expressions.   Used for constants and other cool stuff.
 
2392    Really, we're not doing anything except string concatenation, but
 
2393    this does allow us to parse many constant declarations.
 
2416                |  SIZEOF LPAREN type RPAREN {
 
2417                   $$.id = new char[strlen($3->name)+9];
 
2418                   sprintf($$.id,"sizeof(%s)", $3->name);
 
2421                |  LPAREN strict_type RPAREN expr %prec UMINUS {
 
2422                   $$.id = new char[strlen($4.id)+strlen($2->name)+3];
 
2423                   sprintf($$.id,"(%s)%s",$2->name,$4.id);
 
2427                  $$.id = lookup_symvalue($1);
 
2428                  if ($$.id == (char *) 0)
 
2431                    $$.id = new char[strlen($$.id)+3];
 
2432                    sprintf($$.id,"(%s)",lookup_symvalue($1));
 
2434                  temp_typeptr = lookup_symtype($1);
 
2435                  if (temp_typeptr) $$.type = temp_typeptr->type;
 
2436                  else $$.type = T_INT;
 
2439                   $$.id = new char[strlen($1)+strlen($3)+3];
 
2440                   sprintf($$.id,"%s::%s",$1,$3);
 
2446                  E_BINARY($$.id,$1.id,$3.id,"+");
 
2447                  $$.type = promote($1.type,$3.type);
 
2452                  E_BINARY($$.id,$1.id,$3.id,"-");
 
2453                  $$.type = promote($1.type,$3.type);
 
2458                  E_BINARY($$.id,$1.id,$3.id,"*");
 
2459                  $$.type = promote($1.type,$3.type);
 
2465                  E_BINARY($$.id,$1.id,$3.id,"/");
 
2466                  $$.type = promote($1.type,$3.type);
 
2472                  E_BINARY($$.id,$1.id,$3.id,"&");
 
2473                  $$.type = promote($1.type,$3.type);
 
2474                  if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 
2475                    fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 
2483                  E_BINARY($$.id,$1.id,$3.id,"|");
 
2484                  $$.type = promote($1.type,$3.type);
 
2485                  if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 
2486                    fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 
2495                  E_BINARY($$.id,$1.id,$3.id,"^");
 
2496                  $$.type = promote($1.type,$3.type);
 
2497                  if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 
2498                    fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 
2506                | expr LSHIFT expr {
 
2507                  E_BINARY($$.id,$1.id,$3.id,"<<");
 
2508                  $$.type = promote($1.type,$3.type);
 
2509                  if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 
2510                    fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 
2518                | expr RSHIFT expr {
 
2519                  E_BINARY($$.id,$1.id,$3.id,">>");
 
2520                  $$.type = promote($1.type,$3.type);
 
2521                  if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
 
2522                    fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 
2530                |  MINUS expr %prec UMINUS {
 
2531                   $$.id = new char[strlen($2.id)+2];
 
2532                   sprintf($$.id,"-%s",$2.id);
 
2538                   $$.id = new char[strlen($2.id)+2];
 
2539                   sprintf($$.id,"~%s",$2.id);
 
2540                   if ($2.type == T_DOUBLE) {
 
2541                    fprintf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
 
2547                |  LPAREN expr RPAREN {
 
2548                   $$.id = new char[strlen($2.id)+3];
 
2549                   sprintf($$.id,"(%s)", $2.id);
 
2554 /****************************************************************/
 
2556 /****************************************************************/
 
2564 /* A class/struct/union  definition */
 
2565              extern cpptype ID inherit LBRACE {
 
2569                  DataType::new_scope();
 
2571                  sprintf(temp_name,"CPP_CLASS:%s\n",$3);
 
2572                  if (add_symbol(temp_name, (DataType *) 0, (char *) 0)) {
 
2573                    fprintf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $3);
 
2576                  if ((!CPlusPlus) && (strcmp($2,"class") == 0))
 
2577                    fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 
2579                  iname = make_name($3);
 
2580                  doc_entry = new DocClass(iname, doc_parent());
 
2582                    cplus_open_class($3, 0, $2);
 
2584                    cplus_open_class($3, iname, $2);
 
2585                  if (strcmp($2,"class") == 0)
 
2586                    cplus_mode = CPLUS_PRIVATE;
 
2588                    cplus_mode = CPLUS_PUBLIC;
 
2590                  doc_stack[doc_stack_top] = doc_entry;
 
2591                  scanner_clear_start();
 
2593                  // Merge in scope from base classes
 
2594                  cplus_inherit_scope($4.count,$4.names);
 
2596               } cpp_members RBRACE {
 
2599                     if (strcmp($2,"union") != 0)
 
2600                       cplus_inherit($4.count, $4.names);
 
2602                       fprintf(stderr,"%s : Line %d.  Inheritance not allowed for unions.\n",input_file, line_number);
 
2606                   // Clean up the inheritance list
 
2609                     for (j = 0; j < $4.count; j++) {
 
2610                       if ($4.names[j]) delete [] $4.names[j];
 
2615                   // Dumped nested declarations (if applicable)
 
2618                   // Save and collapse current scope
 
2619                   cplus_register_scope(DataType::collapse_scope($3));
 
2621                   // Restore the original doc entry for this class
 
2622                   doc_entry = doc_stack[doc_stack_top];
 
2623                   cplus_class_close((char *) 0); 
 
2625                   // Bump the documentation stack back down
 
2627                   cplus_mode = CPLUS_PUBLIC;
 
2631 /* Class with a typedef */
 
2633              | TYPEDEF cpptype ID inherit LBRACE {
 
2637                  DataType::new_scope();
 
2639                  sprintf(temp_name,"CPP_CLASS:%s\n",$3);
 
2640                  if (add_symbol(temp_name, (DataType *) 0, (char *) 0)) {
 
2641                    fprintf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $3);
 
2644                  if ((!CPlusPlus) && (strcmp($2,"class") == 0))
 
2645                    fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 
2647                  iname = make_name($3);
 
2648                  doc_entry = new DocClass(iname, doc_parent());
 
2650                    cplus_open_class($3, 0, $2);
 
2652                    cplus_open_class($3, iname, $2);
 
2653                  if (strcmp($2,"class") == 0)
 
2654                    cplus_mode = CPLUS_PRIVATE;
 
2656                    cplus_mode = CPLUS_PUBLIC;
 
2657                  // Create a documentation entry for the class
 
2659                  doc_stack[doc_stack_top] = doc_entry;
 
2660                  scanner_clear_start();
 
2663                  // Merge in scope from base classes
 
2664                  cplus_inherit_scope($4.count,$4.names);
 
2667               } cpp_members RBRACE declaration {
 
2670                     if (strcmp($2,"union") != 0)
 
2671                       cplus_inherit($4.count, $4.names);
 
2673                       fprintf(stderr,"%s : Line %d.  Inheritance not allowed for unions.\n",input_file, line_number);
 
2677                   // Create a datatype for correctly processing the typedef
 
2678                   Active_typedef = new DataType();
 
2679                   Active_typedef->type = T_USER;
 
2680                   sprintf(Active_typedef->name,"%s %s", $2,$3);
 
2681                   Active_typedef->is_pointer = 0;
 
2682                   Active_typedef->implicit_ptr = 0;
 
2684                   // Clean up the inheritance list
 
2687                     for (j = 0; j < $4.count; j++) {
 
2688                       if ($4.names[j]) delete [] $4.names[j];
 
2693                   if ($9.is_pointer > 0) {
 
2694                     fprintf(stderr,"%s : Line %d.  typedef struct { } *id not supported properly. Winging it...\n", input_file, line_number);
 
2697                   // Create dump nested class code
 
2698                   if ($9.is_pointer > 0) {
 
2704                   // Collapse any datatypes created in the the class
 
2706                   cplus_register_scope(DataType::collapse_scope($3));
 
2708                   doc_entry = doc_stack[doc_stack_top];
 
2709                   if ($9.is_pointer > 0) {
 
2710                     cplus_class_close($3);
 
2712                     cplus_class_close($9.id); 
 
2717                   // Create a typedef in global scope
 
2719                   if ($9.is_pointer == 0)
 
2720                     Active_typedef->typedef_add($9.id);
 
2722                     DataType *t = new DataType(Active_typedef);
 
2723                     t->is_pointer += $9.is_pointer;
 
2724                     t->typedef_add($9.id);
 
2725                     cplus_register_type($9.id);
 
2728                   cplus_mode = CPLUS_PUBLIC;
 
2732 /* An unnamed struct with a typedef */
 
2734              | TYPEDEF cpptype LBRACE {
 
2738                  DataType::new_scope();
 
2739                  if ((!CPlusPlus) && (strcmp($2,"class") == 0))
 
2740                    fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 
2742                  iname = make_name("");
 
2743                  doc_entry = new DocClass(iname,doc_parent());
 
2745                    cplus_open_class("", iname, $2);
 
2747                    cplus_open_class("",0,$2);
 
2748                  if (strcmp($2,"class") == 0)
 
2749                    cplus_mode = CPLUS_PRIVATE;
 
2751                    cplus_mode = CPLUS_PUBLIC;
 
2753                  doc_stack[doc_stack_top] = doc_entry;
 
2754                  scanner_clear_start();
 
2757               } cpp_members RBRACE declaration {
 
2759                   if ($7.is_pointer > 0) {
 
2760                     fprintf(stderr,"%s : Line %d. typedef %s {} *%s not supported correctly. Will be ignored.\n", input_file, line_number, $2, $7.id);
 
2763                     sprintf(temp_name,"CPP_CLASS:%s\n",$7.id);
 
2764                     if (add_symbol(temp_name, (DataType *) 0, (char *) 0)) {
 
2765                       fprintf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $7.id);
 
2769                   // Create a datatype for correctly processing the typedef
 
2770                   Active_typedef = new DataType();
 
2771                   Active_typedef->type = T_USER;
 
2772                   sprintf(Active_typedef->name,"%s",$7.id);
 
2773                   Active_typedef->is_pointer = 0;
 
2774                   Active_typedef->implicit_ptr = 0;
 
2776                   // Dump nested classes
 
2777                   if ($7.is_pointer == 0)  
 
2780                   // Go back to previous scope
 
2782                   cplus_register_scope(DataType::collapse_scope((char *) 0));
 
2784                   doc_entry = doc_stack[doc_stack_top];
 
2785                   // Change name of doc_entry
 
2786                   doc_entry->name = copy_string($7.id);
 
2787                   if ($7.is_pointer == 0) 
 
2788                     cplus_class_close($7.id); 
 
2791                   cplus_mode = CPLUS_PUBLIC;
 
2796 cpp_other    :/* A dummy class name */
 
2798              extern cpptype ID SEMI {
 
2802                    iname = make_name($3);
 
2803                    lang->cpp_class_decl($3,iname,$2);
 
2807 /* A static C++ member function (declared out of scope)  */
 
2809               | extern type declaration DCOLON ID LPAREN parms RPAREN SEMI {
 
2813                    fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 
2815                  $2->is_pointer += $3.is_pointer;
 
2816                  $2->is_reference = $3.is_reference;
 
2817                  // Fix up the function name
 
2818                  sprintf(temp_name,"%s::%s",$3.id,$5);
 
2821                    sprintf(yy_rename,"%s_%s",$3.id,$5);
 
2823                  create_function($1, temp_name, $2, $7);
 
2829 /* A static C++ member data */
 
2830              | extern type declaration DCOLON ID SEMI {
 
2834                    fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
 
2836                  $2->is_pointer += $3.is_pointer;
 
2837                  // Fix up the function name
 
2838                  sprintf(temp_name,"%s::%s",$3.id,$5);
 
2841                    sprintf(yy_rename,"%s_%s",$3.id,$5);
 
2843                  create_variable($1,temp_name, $2);
 
2848 /* Operator overloading catch */
 
2850              | extern type declaration DCOLON OPERATOR {
 
2851                fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
 
2857 /* Template catch */
 
2859                fprintf(stderr,"%s : Line %d. Templates not currently supported (ignored).\n",
 
2860                        input_file, line_number);
 
2864 /* %addmethods directive used outside of a class definition */
 
2866              | ADDMETHODS ID LBRACE {
 
2867                cplus_mode = CPLUS_PUBLIC;
 
2868                doc_entry = cplus_set_class($2);
 
2870                  doc_entry = new DocClass($2,doc_parent());
 
2873                doc_stack[doc_stack_top] = doc_entry;
 
2874                scanner_clear_start();
 
2876              } added_members RBRACE {
 
2877                cplus_unset_class();
 
2884 added_members : cpp_member cpp_members { }
 
2885               | objc_method objc_methods { } 
 
2889 cpp_members  : cpp_member cpp_members {}
 
2890              | ADDMETHODS LBRACE {
 
2892              } cpp_members RBRACE {
 
2898                      static int last_error_line = -1;
 
2899                      if (last_error_line != line_number) {
 
2900                        fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 
2902                        last_error_line = line_number;
 
2909 cpp_member   :  type declaration LPAREN parms RPAREN cpp_end {
 
2913                   if (cplus_mode == CPLUS_PUBLIC) {
 
2915                     $1->is_pointer += $2.is_pointer;
 
2916                     $1->is_reference = $2.is_reference;
 
2918                       fprintf(stderr,"Wrapping member function : %s\n",$2.id);
 
2920                     iname = make_name($2.id);
 
2921                     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
2922                     if (iname == $2.id) iname = 0;
 
2923                     cplus_member_func($2.id, iname, $1,$4,0);
 
2925                   scanner_clear_start();
 
2931 /* Virtual member function */
 
2933              |  VIRTUAL type declaration LPAREN parms RPAREN cpp_vend {
 
2937                  if (cplus_mode == CPLUS_PUBLIC) {
 
2939                    $2->is_pointer += $3.is_pointer;
 
2940                    $2->is_reference = $3.is_reference;
 
2942                      fprintf(stderr,"Wrapping virtual member function : %s\n",$3.id);
 
2944                    iname = make_name($3.id);
 
2945                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
2946                    if (iname == $3.id) iname = 0;
 
2947                    cplus_member_func($3.id,iname,$2,$5,1);
 
2949                  scanner_clear_start();
 
2955 /* Possibly a constructor */
 
2956               | ID LPAREN parms RPAREN ctor_end {
 
2960                   if (cplus_mode == CPLUS_PUBLIC) {
 
2963                       fprintf(stderr,"Wrapping C++ constructor %s\n", $1);
 
2965                     iname = make_name($1);
 
2966                     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
2967                     if (iname == $1) iname = 0;
 
2968                     cplus_constructor($1,iname, $3);
 
2970                   scanner_clear_start();
 
2975 /* A destructor (hopefully) */
 
2977               | NOT ID LPAREN parms RPAREN cpp_end {
 
2981                   if (cplus_mode == CPLUS_PUBLIC) {
 
2984                       fprintf(stderr,"Wrapping C++ destructor %s\n", $2);
 
2986                     iname = make_name($2);
 
2987                     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
2988                     if (iname == $2) iname = 0;
 
2989                     cplus_destructor($2,iname);
 
2992                 scanner_clear_start();
 
2995 /* A virtual destructor */
 
2997               | VIRTUAL NOT ID LPAREN RPAREN cpp_end {
 
3001                   if (cplus_mode == CPLUS_PUBLIC) {
 
3004                       fprintf(stderr,"Wrapping C++ destructor %s\n", $3);
 
3006                     iname = make_name($3);
 
3007                     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3008                     if (iname == $3) iname = 0;
 
3009                     cplus_destructor($3,iname);
 
3012                 scanner_clear_start();
 
3017               | type declaration def_args {
 
3021                   if (cplus_mode == CPLUS_PUBLIC) {
 
3022                     if (Active_type) delete Active_type;
 
3023                     Active_type = new DataType($1);
 
3024                     $1->is_pointer += $2.is_pointer;
 
3025                     $1->is_reference = $2.is_reference;
 
3026                     if ($1->qualifier) {
 
3027                       if ((strcmp($1->qualifier,"const") == 0) && ($1->is_pointer == 0)) {
 
3028                         // Okay.  This is really some sort of C++ constant here.
 
3029                           if ($3.type != T_ERROR) {
 
3030                             iname = make_name($2.id);
 
3031                             doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3032                             if (iname == $2.id) iname = 0;
 
3033                             cplus_declare_const($2.id,iname, $1, $3.id);
 
3036                         int oldstatus = Status;
 
3038                         if ($1->status & STAT_READONLY) {
 
3039                           if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 
3040                             Status = Status | STAT_READONLY;
 
3042                         iname = make_name($2.id);
 
3043                         doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3044                         if (iname == $2.id) iname = 0;
 
3045                         cplus_variable($2.id,iname,$1);
 
3050                       int oldstatus = Status;
 
3051                       if ($1->status & STAT_READONLY) {
 
3052                         if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 
3053                           Status = Status | STAT_READONLY;
 
3055                       iname = make_name($2.id);
 
3056                       doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3057                       if (iname == $2.id) iname = 0;
 
3058                       cplus_variable($2.id,iname,$1);
 
3061                         fprintf(stderr,"Wrapping member data %s\n", $2.id);
 
3065                   scanner_clear_start();
 
3070               | type declaration array def_args {
 
3073                   int oldstatus = Status;
 
3076                   if (cplus_mode == CPLUS_PUBLIC) {
 
3077                     if (Active_type) delete Active_type;
 
3078                     Active_type = new DataType($1);
 
3079                     $1->is_pointer += $2.is_pointer + 1;
 
3080                     $1->is_reference = $2.is_reference;
 
3081                     $1->arraystr = copy_string(ArrayString);
 
3082                     if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 
3083                       Status = STAT_READONLY;
 
3085                     iname = make_name($2.id);
 
3086                     doc_entry = new DocDecl(iname, doc_stack[doc_stack_top]);
 
3087                     if (iname == $2.id) iname = 0;
 
3088                     cplus_variable($2.id,iname,$1);
 
3091                       fprintf(stderr,"%s : Line %d. Warning. Array member will be read-only.\n",input_file,line_number);
 
3093                 scanner_clear_start();
 
3099 /* Static Member data */
 
3101               | STATIC type declaration {
 
3105                   if (cplus_mode == CPLUS_PUBLIC) {
 
3106                     $2->is_pointer += $3.is_pointer;
 
3107                     iname = make_name($3.id);
 
3108                     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3109                     if (iname == $3.id) iname = 0;
 
3110                     cplus_static_var($3.id,iname,$2);
 
3111                     if (Active_type) delete Active_type;
 
3112                     Active_type = new DataType($2);
 
3114                       fprintf(stderr,"Wrapping static member data %s\n", $3.id);
 
3117                   scanner_clear_start();
 
3122 /* Static member function */
 
3124               | STATIC type declaration LPAREN parms RPAREN cpp_end {
 
3127                   $2->is_pointer += $3.is_pointer;
 
3128                   $2->is_reference = $3.is_reference;
 
3129                   if (cplus_mode == CPLUS_PUBLIC) {
 
3130                     iname = make_name($3.id);
 
3131                     doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3132                     if (iname == $3.id) iname = 0;
 
3133                     cplus_static_func($3.id, iname, $2, $5);
 
3135                       fprintf(stderr,"Wrapping static member function %s\n",$3.id);
 
3137                   scanner_clear_start();
 
3142 /* Turn on public: mode */
 
3146                   cplus_mode = CPLUS_PUBLIC;
 
3148                     fprintf(stderr,"Public mode\n");
 
3149                   scanner_clear_start();
 
3153 /* Turn on private: mode */
 
3157                   cplus_mode = CPLUS_PRIVATE;
 
3159                     fprintf(stderr,"Private mode\n");
 
3160                   scanner_clear_start();
 
3164 /* Turn on protected mode */
 
3168                   cplus_mode = CPLUS_PROTECTED;
 
3170                     fprintf(stderr,"Protected mode\n");
 
3171                   scanner_clear_start();
 
3175 /* This is the new style rename */
 
3177              | NAME LPAREN ID RPAREN {
 
3179                  strcpy(yy_rename,$3);
 
3192               | ENUM ename LBRACE {scanner_clear_start();} cpp_enumlist RBRACE SEMI {
 
3194                  // if ename was supplied.  Install it as a new integer datatype.
 
3198                   if (cplus_mode == CPLUS_PUBLIC) {
 
3200                      cplus_register_type($2);
 
3201                      temp_type.type = T_INT;
 
3202                      temp_type.is_pointer = 0;
 
3203                      temp_type.implicit_ptr = 0;
 
3204                      sprintf(temp_type.name,"int");
 
3205                      temp_type.typedef_add($2,1); 
 
3212                   Status = Status | STAT_READONLY;
 
3213                 scanner_clear_start();
 
3217                   Status = Status & ~(STAT_READONLY);
 
3218                 scanner_clear_start();
 
3220 /* A friend :   Illegal */
 
3223                   fprintf(stderr,"%s : Line %d. Friends are not allowed--members only! (ignored)\n", input_file, line_number);
 
3225                 scanner_clear_start();
 
3228 /* An operator: Illegal */
 
3229               | type type_extra OPERATOR {
 
3231                   fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
 
3233                 scanner_clear_start();
 
3236                 scanner_clear_start();
 
3239 /* A typedef inside a class */
 
3242 /* Pragma directive */
 
3245                         scanner_clear_start();
 
3249 cpp_pragma    : PRAGMA ID stylearg {
 
3250                  if (allow && (!WrapExtern)) { }
 
3252                | PRAGMA LPAREN ID RPAREN ID stylearg {
 
3253                  if (allow && (!WrapExtern))
 
3254                    cplus_add_pragma($3,$5,$6);
 
3260 /* ----------------------------------------------------------------------
 
3261    Nested structure.    This is a big ugly "hack".   If we encounter
 
3262    a nested structure, we're going to grab the text of its definition and
 
3263    feed it back into the scanner.  In the meantime, we need to grab
 
3264    variable declaration information and generate the associated wrapper
 
3267    This really only works in a limited sense.   Since we use the 
 
3268    code attached to the nested class to generate both C/C++ code,
 
3269    it can't have any SWIG directives in it.  It also needs to be parsable
 
3270    by SWIG or this whole thing is going to puke.
 
3271    ---------------------------------------------------------------------- */
 
3273 /* A struct sname { } id;  declaration */
 
3275               | cpptype ID LBRACE { start_line = line_number; skip_brace(); 
 
3276               } nested_decl SEMI { 
 
3278                 if (cplus_mode == CPLUS_PUBLIC) {
 
3279                   cplus_register_type($2);
 
3281                     if (strcmp($1,"class") == 0) {
 
3282                       fprintf(stderr,"%s : Line %d.  Warning. Nested classes not currently supported (ignored).\n", input_file, line_number);
 
3283                       /* Generate some code for a new class */
 
3285                       Nested *n = new Nested;
 
3286                       n->code << "typedef " << $1 << " " 
 
3287                               << CCode.get() << " $classname_" << $5.id << ";\n";
 
3288                       n->name = copy_string($5.id);
 
3289                       n->line = start_line;
 
3290                       n->type = new DataType;
 
3291                       n->type->type = T_USER;
 
3292                       n->type->is_pointer = $5.is_pointer;
 
3293                       n->type->is_reference = $5.is_reference;
 
3300 /* An unnamed structure definition */
 
3301               | cpptype LBRACE { start_line = line_number; skip_brace();
 
3302               } declaration SEMI { 
 
3303                 if (cplus_mode == CPLUS_PUBLIC) {
 
3304                   if (strcmp($1,"class") == 0) {
 
3305                     fprintf(stderr,"%s : Line %d.  Warning. Nested classes not currently supported (ignored)\n", input_file, line_number);
 
3306                     /* Generate some code for a new class */
 
3308                     /* Generate some code for a new class */
 
3310                     Nested *n = new Nested;
 
3311                     n->code << "typedef " << $1 << " " 
 
3312                             << CCode.get() << " $classname_" << $4.id << ";\n";
 
3313                     n->name = copy_string($4.id);
 
3314                     n->line = start_line;
 
3315                     n->type = new DataType;
 
3316                     n->type->type = T_USER;
 
3317                     n->type->is_pointer = $4.is_pointer;
 
3318                     n->type->is_reference = $4.is_reference;
 
3325 /* An empty class declaration */
 
3327                     if (cplus_mode == CPLUS_PUBLIC) {
 
3328                        cplus_register_type($2);
 
3332 /* Other miscellaneous errors */
 
3333               | type stars LPAREN { 
 
3335                      fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
 
3338               | strict_type LPAREN STAR {
 
3340                      fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
 
3345                      fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
 
3352 nested_decl   : declaration { $$ = $1;}
 
3353               | empty { $$.id = 0; }
 
3356 type_extra    : stars {}
 
3362                | COMMA declaration def_args {
 
3364                    int oldstatus = Status;
 
3368                    if (cplus_mode == CPLUS_PUBLIC) {
 
3369                      temp_typeptr = new DataType(Active_type);
 
3370                      temp_typeptr->is_pointer += $2.is_pointer;
 
3372                        fprintf(stderr,"Wrapping member variable : %s\n",$2.id);
 
3375                      doc_entry = new DocDecl($2.id,doc_stack[doc_stack_top]);
 
3376                      if (temp_typeptr->status & STAT_READONLY) {
 
3377                        if (!(tm = typemap_lookup("memberin",typemap_lang,temp_typeptr,$2.id,"",""))) 
 
3378                          Status = Status | STAT_READONLY;
 
3380                      cplus_variable($2.id,(char *) 0,temp_typeptr);             
 
3382                      delete temp_typeptr;
 
3384                    scanner_clear_start();
 
3387                | COMMA declaration array def_args {
 
3389                    int oldstatus = Status;
 
3393                    if (cplus_mode == CPLUS_PUBLIC) {
 
3394                      temp_typeptr = new DataType(Active_type);
 
3395                      temp_typeptr->is_pointer += $2.is_pointer;
 
3397                        fprintf(stderr,"Wrapping member variable : %s\n",$2.id);
 
3400                      if (!(tm = typemap_lookup("memberin",typemap_lang,temp_typeptr,$2.id,"",""))) 
 
3401                        Status = Status | STAT_READONLY;
 
3402                      doc_entry = new DocDecl($2.id,doc_stack[doc_stack_top]);
 
3403                      if (temp_typeptr->status & STAT_READONLY) Status = Status | STAT_READONLY;
 
3404                      cplus_variable($2.id,(char *) 0,temp_typeptr);             
 
3407                        fprintf(stderr,"%s : Line %d. Warning. Array member will be read-only.\n",input_file,line_number);
 
3408                      delete temp_typeptr;
 
3410                    scanner_clear_start();
 
3415 cpp_end        : cpp_const SEMI { 
 
3418                | cpp_const LBRACE { skip_brace(); }
 
3421 cpp_vend       : cpp_const SEMI { CCode = ""; }
 
3422                | cpp_const EQUAL definetype SEMI { CCode = ""; }
 
3423                | cpp_const LBRACE { skip_brace(); }
 
3426 cpp_enumlist   :  cpp_enumlist COMMA cpp_edecl {}
 
3432                       if (cplus_mode == CPLUS_PUBLIC) {
 
3434                           fprintf(stderr,"Creating enum value %s\n", $1);
 
3437                         temp_typeptr = new DataType(T_INT);
 
3438                         doc_entry = new DocDecl($1,doc_stack[doc_stack_top]);
 
3439                         cplus_declare_const($1, (char *) 0, temp_typeptr, (char *) 0);
 
3440                         delete temp_typeptr;
 
3441                         scanner_clear_start();
 
3447                      if (cplus_mode == CPLUS_PUBLIC) {
 
3449                          fprintf(stderr, "Creating enum value %s = %s\n", $1, $3.id);
 
3452                        temp_typeptr = new DataType(T_INT);
 
3453                        doc_entry = new DocDecl($1,doc_stack[doc_stack_top]);
 
3454                        cplus_declare_const($1,(char *) 0, temp_typeptr,(char *) 0);
 
3455 // OLD : Bug with value     cplus_declare_const($1,(char *) 0, temp_typeptr,$3.id);
 
3456                        delete temp_typeptr;
 
3457                        scanner_clear_start();
 
3461                  | NAME LPAREN ID RPAREN ID {
 
3463                      if (cplus_mode == CPLUS_PUBLIC) {
 
3465                          fprintf(stderr,"Creating enum value %s\n", $5);
 
3468                        temp_typeptr = new DataType(T_INT);
 
3469                        doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 
3470                        cplus_declare_const($5, $3, temp_typeptr, (char *) 0);
 
3471                        delete temp_typeptr;
 
3472                        scanner_clear_start();
 
3476                  | NAME LPAREN ID RPAREN ID EQUAL etype {
 
3478                      if (cplus_mode == CPLUS_PUBLIC) {
 
3480                          fprintf(stderr, "Creating enum value %s = %s\n", $5, $7.id);
 
3483                        temp_typeptr = new DataType(T_INT);
 
3484                        doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 
3485                        cplus_declare_const($5,$3, temp_typeptr, (char *) 0);
 
3486 // Old : bug with value        cplus_declare_const($5,$3, temp_typeptr,$7.id);
 
3487                        delete temp_typeptr;
 
3488                        scanner_clear_start();
 
3492                  | cond_compile cpp_edecl { }
 
3496 inherit        : COLON base_list {
 
3500                    $$.names = (char **) 0;
 
3505 base_list      : base_specifier { 
 
3507                    $$.names = new char *[NI_NAMES];
 
3509                    for (i = 0; i < NI_NAMES; i++){
 
3510                      $$.names[i] = (char *) 0;
 
3513                        $$.names[$$.count] = copy_string($1);
 
3518                | base_list COMMA base_specifier { 
 
3521                      $$.names[$$.count] = copy_string($3);
 
3527 base_specifier : ID {     
 
3528                   fprintf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
 
3529                           input_file,line_number,$1);
 
3533                   fprintf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
 
3534                           input_file,line_number,$2);
 
3537                | VIRTUAL access_specifier ID {
 
3538                  if (strcmp($2,"public") == 0) {
 
3541                    fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
 
3542                            input_file,line_number,$2);
 
3546                | access_specifier ID {
 
3547                  if (strcmp($1,"public") == 0) {
 
3550                    fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
 
3551                            input_file,line_number,$1);
 
3555                | access_specifier VIRTUAL ID {
 
3556                  if (strcmp($1,"public") == 0) {
 
3559                    fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
 
3560                            input_file,line_number,$1);
 
3566 access_specifier :  PUBLIC { $$ = "public"; }
 
3567                | PRIVATE { $$ = "private"; }
 
3568                | PROTECTED { $$ = "protected"; }
 
3572 cpptype        : CLASS { $$ = "class"; }
 
3573                | STRUCT { $$ = "struct"; }
 
3574                | UNION {$$ = "union"; }
 
3577 cpp_const      : CONST {} 
 
3578                | THROW LPAREN parms RPAREN { delete $3;}
 
3582 /* Constructor initializer */
 
3584 ctor_end       : cpp_const ctor_initializer SEMI { 
 
3587                | cpp_const ctor_initializer LBRACE { skip_brace(); }
 
3590 ctor_initializer : COLON mem_initializer_list {}
 
3594 mem_initializer_list : mem_initializer { }
 
3595                | mem_initializer_list COMMA mem_initializer { }
 
3598 mem_initializer : ID LPAREN expr_list RPAREN { }
 
3599                | ID LPAREN RPAREN { }
 
3602 expr_list      : expr { }
 
3603                | expr_list COMMA expr { }
 
3607 /**************************************************************/
 
3608 /* Objective-C parsing                                        */
 
3609 /**************************************************************/
 
3611 objective_c    : OC_INTERFACE ID objc_inherit { 
 
3614                    cplus_mode = CPLUS_PROTECTED;
 
3615                    sprintf(temp_name,"CPP_CLASS:%s\n",$2);
 
3616                    if (add_symbol(temp_name,(DataType *) 0, (char *) 0)) {
 
3617                      fprintf(stderr,"%s : Line %d.  @interface %s is multiple defined.\n",
 
3618                              input_file,line_number,$2);
 
3621                    // Create a new documentation entry
 
3622                    doc_entry = new DocClass($2,doc_parent());
 
3624                    doc_stack[doc_stack_top] = doc_entry;
 
3625                    scanner_clear_start();
 
3626                    cplus_open_class($2, (char *) 0, "");     // Open up a new C++ class
 
3627                 } LBRACE objc_data RBRACE objc_methods OC_END { 
 
3631                       cplus_inherit(1,inames);
 
3633                   // Restore original doc entry for this class
 
3634                   doc_entry = doc_stack[doc_stack_top];
 
3635                   cplus_class_close($2);
 
3638                   cplus_mode = CPLUS_PUBLIC;
 
3643 /* An obj-c category declaration */
 
3644                | OC_INTERFACE ID LPAREN ID RPAREN objc_protolist {
 
3647                  cplus_mode = CPLUS_PROTECTED;
 
3648                  doc_entry = cplus_set_class($2);
 
3650                    doc_entry = new DocClass($2,doc_parent());
 
3653                  doc_stack[doc_stack_top] = doc_entry;
 
3654                  scanner_clear_start();
 
3655                } objc_methods OC_END {
 
3656                  cplus_unset_class();
 
3660                | OC_IMPLEMENT { skip_to_end(); }
 
3661                | OC_PROTOCOL { skip_to_end(); }
 
3662                | OC_CLASS ID initlist SEMI {
 
3663                  char *iname = make_name($2);
 
3665                  lang->cpp_class_decl($2,iname,"");
 
3666                  for (int i = 0; i <$3.count; i++) {
 
3668                      iname = make_name($3.names[i]);
 
3669                      lang->cpp_class_decl($3.names[i],iname,"");
 
3670                      delete [] $3.names[i];
 
3677 objc_inherit   : COLON ID objc_protolist { $$ = $2;}
 
3678                | objc_protolist empty { $$ = 0; }
 
3682 objc_protolist : LESSTHAN { skip_template(); 
 
3683                    CCode.strip();           // Strip whitespace
 
3684                    CCode.replace("<","< ");
 
3685                    CCode.replace(">"," >");
 
3693 objc_data      : objc_vars objc_data { }
 
3695                     cplus_mode = CPLUS_PUBLIC;
 
3698                     cplus_mode = CPLUS_PRIVATE;
 
3701                     cplus_mode = CPLUS_PROTECTED;
 
3707                      static int last_error_line = -1;
 
3708                      if (last_error_line != line_number) {
 
3709                        fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 
3711                        last_error_line = line_number;
 
3720 objc_vars      : objc_var objc_vartail SEMI {
 
3725 /* An objective-C member variable */
 
3727 objc_var       : type declaration { 
 
3728                  if (cplus_mode == CPLUS_PUBLIC) {
 
3729                    int oldstatus = Status;
 
3732                    if (Active_type) delete Active_type;
 
3733                    Active_type = new DataType($1);
 
3734                    $1->is_pointer += $2.is_pointer;
 
3735                    $1->is_reference = $2.is_reference;
 
3736                    if ($1->status & STAT_READONLY) {
 
3737                      if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 
3738                        Status = Status | STAT_READONLY;
 
3740                    iname = make_name($2.id);
 
3741                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3742                    if (iname == $2.id) iname = 0;
 
3743                    cplus_variable($2.id,iname,$1);
 
3746                  scanner_clear_start();
 
3749                | type declaration array { 
 
3750                  if (cplus_mode == CPLUS_PUBLIC) {
 
3751                    int oldstatus = Status;
 
3753                    if (Active_type) delete Active_type;
 
3754                    Active_type = new DataType($1);
 
3755                    $1->is_pointer += $2.is_pointer;
 
3756                    $1->is_reference = $2.is_reference;
 
3757                    $1->arraystr = copy_string(ArrayString);
 
3758                    if ($1->status & STAT_READONLY) {
 
3759                      if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"",""))) 
 
3760                        Status = Status | STAT_READONLY;
 
3762                    iname = make_name($2.id);
 
3763                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3764                    if (iname == $2.id) iname = 0;
 
3765                    cplus_variable($2.id,iname,$1);
 
3768                  scanner_clear_start();
 
3771                | NAME LPAREN ID RPAREN {
 
3772                     strcpy(yy_rename,$3);
 
3776 objc_vartail   : COMMA declaration objc_vartail { 
 
3777                  if (cplus_mode == CPLUS_PUBLIC) {
 
3778                    int oldstatus = Status;
 
3780                    DataType *t = new DataType (Active_type);
 
3781                    t->is_pointer += $2.is_pointer;
 
3782                    t->is_reference = $2.is_reference;
 
3783                    if (t->status & STAT_READONLY) {
 
3784                      if (!(tm = typemap_lookup("memberin",typemap_lang,t,$2.id,"",""))) 
 
3785                        Status = Status | STAT_READONLY;
 
3787                    iname = make_name($2.id);
 
3788                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3789                    if (iname == $2.id) iname = 0;
 
3790                    cplus_variable($2.id,iname,t);
 
3794                  scanner_clear_start();
 
3796                | COMMA declaration array objc_vartail {
 
3798                  if (cplus_mode == CPLUS_PUBLIC) {
 
3799                    int oldstatus = Status;
 
3801                    DataType *t = new DataType (Active_type);
 
3802                    t->is_pointer += $2.is_pointer;
 
3803                    t->is_reference = $2.is_reference;
 
3804                    t->arraystr = copy_string(ArrayString);
 
3805                    if (t->status & STAT_READONLY) {
 
3806                      if (!(tm = typemap_lookup("memberin",typemap_lang,t,$2.id,"",""))) 
 
3807                        Status = Status | STAT_READONLY;
 
3809                    iname = make_name($2.id);
 
3810                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3811                    if (iname == $2.id) iname = 0;
 
3812                    cplus_variable($2.id,iname,t);
 
3816                  scanner_clear_start();
 
3821 objc_methods   : objc_method objc_methods { };
 
3822                | ADDMETHODS LBRACE {
 
3824                } objc_methods RBRACE {
 
3827                | NAME LPAREN ID RPAREN {
 
3828                      strcpy(yy_rename,$3);
 
3835                      static int last_error_line = -1;
 
3836                      if (last_error_line != line_number) {
 
3837                        fprintf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
 
3839                        last_error_line = line_number;
 
3848 objc_method    : MINUS objc_ret_type ID objc_args objc_end {
 
3850                  // An objective-C instance function
 
3851                  // This is like a C++ member function
 
3853                  if (strcmp($3,objc_destruct) == 0) {
 
3854                    // This is an objective C destructor
 
3855                    doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 
3856                    cplus_destructor($3,(char *) 0);
 
3858                    iname = make_name($3);
 
3859                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3860                    if (iname == $3) iname = 0;
 
3861                    cplus_member_func($3,iname,$2,$4,0);
 
3862                    scanner_clear_start();
 
3868                | PLUS objc_ret_type ID objc_args objc_end { 
 
3870                  // An objective-C class function
 
3871                  // This is like a c++ static member function
 
3872                  if (strcmp($3,objc_construct) == 0) {
 
3873                    // This is an objective C constructor
 
3874                    doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
 
3875                    cplus_constructor($3,0,$4);
 
3877                    iname = make_name($3);
 
3878                    doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
 
3879                    if (iname == $3) iname = 0;
 
3880                    cplus_static_func($3,iname,$2,$4);
 
3882                  scanner_clear_start();
 
3889 objc_end       : SEMI { CCode = ""; }
 
3890                | LBRACE { skip_brace(); }
 
3893 objc_ret_type  : LPAREN type RPAREN { 
 
3896                | LPAREN type stars RPAREN { 
 
3898                   $$->is_pointer += $3;
 
3900                | empty {       /* Empty type means "id" type */
 
3901                   $$ = new DataType(T_VOID);
 
3902                   sprintf($$->name,"id");
 
3904                   $$->implicit_ptr = 1;
 
3908 objc_arg_type  : LPAREN parm RPAREN { 
 
3909                   $$ = new DataType($2->t);
 
3913                   $$ = new DataType(T_VOID);
 
3914                   sprintf($$->name,"id");
 
3916                   $$->implicit_ptr = 1;
 
3920 objc_args      : objc_args objc_separator objc_arg_type ID { 
 
3921                    Parm *p= new Parm($3,$4);
 
3922                    p->objc_separator = $2;
 
3931 objc_separator : COLON { $$ = copy_string(":"); }
 
3932                | ID COLON { $$ = new char[strlen($1)+2]; 
 
3939 /* Miscellaneous stuff */
 
3941 /* Documentation style list */
 
3943 stylelist      : ID stylearg styletail {
 
3945                     $$.names[$$.count] = copy_string($1);
 
3946                     $$.values[$$.count] = copy_string($2);
 
3947                     format_string($$.values[$$.count]);
 
3953 styletail      : styletail COMMA ID stylearg {
 
3955                     $$.names[$$.count] = copy_string($3);
 
3956                     $$.values[$$.count] = copy_string($4);
 
3957                     format_string($$.values[$$.count]);
 
3961                     $$.names = new char *[NI_NAMES];
 
3962                     $$.values = new char *[NI_NAMES];
 
3967 stylearg       : EQUAL NUM_INT {
 
3979 /* --------------------------------------------------------------
 
3980  * Type-map parameters 
 
3981  * -------------------------------------------------------------- */
 
3987                  $$ = copy_string("const");
 
3991 tm_list        : typemap_parm tm_tail {
 
3997 tm_tail        : COMMA typemap_parm tm_tail {
 
4004 typemap_parm   : type typemap_name {
 
4007                       $1->arraystr = copy_string(ArrayString);
 
4010                     $$->p = new Parm($1,$2);
 
4011                     $$->p->call_type = 0;
 
4017                 | type stars typemap_name {
 
4019                    $$->p = new Parm($1,$3);
 
4020                    $$->p->t->is_pointer += $2;
 
4021                    $$->p->call_type = 0;
 
4023                      $$->p->t->is_pointer++;
 
4024                      $$->p->t->arraystr = copy_string(ArrayString);
 
4031                 | type AND typemap_name {
 
4033                   $$->p = new Parm($1,$3);
 
4034                   $$->p->t->is_reference = 1;
 
4035                   $$->p->call_type = 0;
 
4036                   $$->p->t->is_pointer++;
 
4038                         fprintf(stderr,"%s : Line %d. Warning.  Use of C++ Reference detected.  Use the -c++ option.\n", input_file, line_number);
 
4044                 | type LPAREN stars typemap_name RPAREN LPAREN parms RPAREN {
 
4045                   fprintf(stderr,"%s : Line %d. Error. Function pointer not allowed (remap with typedef).\n", input_file, line_number);
 
4048                   $$->p = new Parm($1,$4);
 
4049                   $$->p->t->type = T_ERROR;
 
4050                   $$->p->name = copy_string($4);
 
4051                   strcpy($$->p->t->name,"<function ptr>");
 
4059 typemap_name    : ID typemap_args {
 
4065                     ArrayBackup << ArrayString;
 
4070                     ArrayString << ArrayBackup;
 
4074                     ArrayBackup << ArrayString;
 
4080                     ArrayString << ArrayBackup;
 
4082                 | typemap_args { $$ = new char[1];
 
4088 typemap_args    : LPAREN parms RPAREN {
 
4096 idstring       : ID {$$ = $1;}
 
4097                | STRING { $$ = $1;}
 
4101 /* User defined directive */
 
4103 user_directive : USERDIRECTIVE LPAREN parms RPAREN uservalue { }
 
4104                | USERDIRECTIVE uservalue { }
 
4107 uservalue      : ID SEMI { }
 
4114 /* Parsing of expressions, but only for throw away code */
 
4116 /* Might need someday 
 
4117 dummyexpr      :  NUM_INT { }
 
4122                |  SIZEOF LPAREN type RPAREN { }
 
4124                |  dummyexpr PLUS dummyexpr {           }
 
4125                |  dummyexpr MINUS dummyexpr {          }
 
4126                |  dummyexpr STAR dummyexpr {           }
 
4127                |  dummyexpr SLASH dummyexpr {          }
 
4128                |  dummyexpr AND dummyexpr {            }
 
4129                |  dummyexpr OR dummyexpr {             }
 
4130                |  dummyexpr XOR dummyexpr {            }
 
4131                |  dummyexpr LSHIFT dummyexpr {         }
 
4132                |  dummyexpr RSHIFT dummyexpr {         }
 
4133                |  MINUS dummyexpr %prec UMINUS {               }
 
4135                |  LPAREN dummyexpr RPAREN {            }
 
4145 void error_recover() {
 
4148   while ((c > 0) && (c != SEMI)) 
 
4152 /* Called by the parser (yyparse) when an error is found.*/
 
4153 void yyerror (char *) {
 
4154   //  Fprintf(stderr,"%s : Line %d. Syntax error.\n", input_file, line_number);