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);