]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/SWIG/parser.y
Since I have made several changes to SWIG over the years to accomodate
[wxWidgets.git] / wxPython / wxSWIG / SWIG / parser.y
1 %{
2 /*******************************************************************************
3 * Simplified Wrapper and Interface Generator (SWIG)
4 *
5 * Author : David Beazley
6 *
7 * Department of Computer Science
8 * University of Chicago
9 * 1100 E 58th Street
10 * Chicago, IL 60637
11 * beazley@cs.uchicago.edu
12 *
13 * Please read the file LICENSE for the copyright and terms by which SWIG
14 * can be used and distributed.
15 *******************************************************************************/
16 /***********************************************************************
17 * $Header$
18 *
19 * parser.y
20 *
21 * YACC parser for parsing function declarations.
22 *
23 * *** DISCLAIMER ***
24 *
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 ***********************************************************************/
32
33 #define yylex yylex
34
35 extern "C" int yylex();
36 void yyerror (char *s);
37
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 *);
52
53 #include "internal.h"
54
55 #ifdef NEED_ALLOC
56 void *alloca(unsigned n) {
57 return((void *) malloc(n));
58 }
59 #else
60 // This redefinition is apparently needed on a number of machines,
61 // particularly HPUX
62 #undef alloca
63 #define alloca malloc
64 #endif
65
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
69 // versions).
70
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;
74
75 static int lang_init = 0; /* Indicates if the language has been initialized */
76
77 static int i;
78 int Error = 0;
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
100
101 /* Some macros for building constants */
102
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);
106
107 /* C++ modes */
108
109 #define CPLUS_PUBLIC 1
110 #define CPLUS_PRIVATE 2
111 #define CPLUS_PROTECTED 3
112
113 int cplus_mode;
114
115 // Declarations of some functions for handling C++
116
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();
135
136 // ----------------------------------------------------------------------
137 // static init_language()
138 //
139 // Initialize the target language.
140 // Does nothing if this function has already been called.
141 // ----------------------------------------------------------------------
142
143 static void init_language() {
144 if (!lang_init) {
145 lang->initialize();
146
147 // Initialize the documentation system
148
149 if (!doctitle) {
150 doctitle = new DocTitle(title,0);
151 }
152 if (!doc_init)
153 doctitle->usage = title;
154
155 doc_stack[0] = doctitle;
156 doc_stack_top = 0;
157
158 int oldignore = IgnoreDoc;
159 IgnoreDoc = 1;
160 if (ConfigFile) {
161 include_file(ConfigFile);
162 }
163 IgnoreDoc = oldignore;
164 }
165 lang_init = 1;
166 title_init = 1;
167 }
168
169 // ----------------------------------------------------------------------
170 // int promote(int t1, int t2)
171 //
172 // Promote types (for constant expressions)
173 // ----------------------------------------------------------------------
174
175 int promote(int t1, int t2) {
176
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;
187 if (t1 != t2) {
188 fprintf(stderr,"%s : Line %d. Type mismatch in constant expression\n",
189 input_file, line_number);
190 FatalError();
191 }
192 return t1;
193 }
194
195 /* Generate the scripting name of an object. Takes %name directive into
196 account among other things */
197
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.
202
203 if (Rename_true) {
204 Rename_true = 0;
205 return yy_rename;
206 } else {
207 // Now check to see if the name contains a $
208 if (strchr(name,'$')) {
209 static String temp;
210 temp = "";
211 temp << name;
212 temp.replace("$","_S_");
213 return temp;
214 } else {
215 return name;
216 }
217 }
218 }
219
220 /* Return the parent of a documentation entry. If wrapping externally, this is 0 */
221
222 static DocEntry *doc_parent() {
223 if (!WrapExtern)
224 return doc_stack[doc_stack_top];
225 else
226 return 0;
227 }
228
229 // ----------------------------------------------------------------------
230 // create_function(int ext, char *name, DataType *t, ParmList *l)
231 //
232 // Creates a function and manages documentation creation. Really
233 // only used internally to the parser.
234 // ----------------------------------------------------------------------
235
236 void create_function(int ext, char *name, DataType *t, ParmList *l) {
237 if (Active_static) return; // Static declaration. Ignore
238
239 init_language();
240 if (WrapExtern) return; // External wrapper file. Ignore
241
242 char *iname = make_name(name);
243
244 // Check if symbol already exists
245
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);
249 } else {
250 Stat_func++;
251 if (Verbose) {
252 fprintf(stderr,"Wrapping function : ");
253 emit_extern_func(name, t, l, 0, stderr);
254 }
255
256 // If extern, make an extern declaration in the SWIG wrapper file
257
258 if (ext)
259 emit_extern_func(name, t, l, ext, f_header);
260 else if (ForceExtern) {
261 emit_extern_func(name, t, l, 1, f_header);
262 }
263
264 // If this function has been declared inline, produce a function
265
266 doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
267 lang->create_function(name, iname, t, l);
268 l->check_defined();
269 t->check_defined();
270 }
271 scanner_clear_start();
272 }
273
274 // -------------------------------------------------------------------
275 // create_variable(int ext, char *name, DataType *t)
276 //
277 // Create a link to a global variable.
278 // -------------------------------------------------------------------
279
280 void create_variable(int ext, char *name, DataType *t) {
281
282 if (WrapExtern) return; // External wrapper file. Ignore
283 int oldstatus = Status;
284
285 if (Active_static) return; // If static ignore
286
287 init_language();
288
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);
293 } else {
294 Stat_var++;
295 if (Verbose) {
296 fprintf(stderr,"Wrapping variable : ");
297 emit_extern_var(name, t, 0, stderr);
298 }
299
300 // If externed, output an external declaration
301
302 if (ext)
303 emit_extern_var(name, t, ext, f_header);
304 else if (ForceExtern) {
305 emit_extern_var(name, t, 1, f_header);
306 }
307
308 // If variable datatype is read-only, we'll force it to be readonly
309 if (t->status & STAT_READONLY) Status = Status | STAT_READONLY;
310
311 // Now dump it out
312 doc_entry = new DocDecl(iname,doc_stack[doc_stack_top]);
313 lang->link_variable(name, iname, t);
314 t->check_defined();
315 Status = oldstatus;
316 }
317 scanner_clear_start();
318 }
319
320 // ------------------------------------------------------------------
321 // create_constant(char *name, DataType *type, char *value)
322 //
323 // Creates a new constant.
324 // -------------------------------------------------------------------
325
326 void create_constant(char *name, DataType *type, char *value) {
327
328 if (Active_static) return;
329 if (WrapExtern) return; // External wrapper file. Ignore
330 init_language();
331
332 if (Rename_true) {
333 fprintf(stderr,"%s : Line %d. %%name directive ignored with #define\n",
334 input_file, line_number);
335 Rename_true = 0;
336 }
337
338 if ((type->type == T_CHAR) && (!type->is_pointer))
339 type->is_pointer++;
340
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);
346 } else {
347 // Update symbols value if already defined.
348 update_symbol(name, type, value);
349
350 if (!WrapExtern) { // Only wrap the constant if not in %extern mode
351 Stat_const++;
352 if (Verbose)
353 fprintf(stderr,"Creating constant %s = %s\n", name, value);
354
355 doc_entry = new DocDecl(name,doc_stack[doc_stack_top]);
356 lang->declare_const(name, name, type, value);
357 type->check_defined();
358 }
359 }
360 scanner_clear_start();
361 }
362
363
364 /* Print out array brackets */
365 void print_array() {
366 int i;
367 for (i = 0; i < InArray; i++)
368 fprintf(stderr,"[]");
369 }
370
371 /* manipulate small stack for managing if-then-else */
372
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;
378
379 void if_push() {
380 then_data[te_index] = in_then;
381 else_data[te_index] = in_else;
382 allow_data[te_index] = allow;
383 prev_allow = allow;
384 te_index++;
385 if (te_index >= 100) {
386 fprintf(stderr,"SWIG. Internal parser error. if-then-else stack overflow.\n");
387 SWIG_exit(1);
388 }
389 }
390
391 void if_pop() {
392 if (te_index > 0) {
393 te_index--;
394 in_then = then_data[te_index];
395 in_else = else_data[te_index];
396 allow = allow_data[te_index];
397 if (te_index > 0) {
398 prev_allow = allow_data[te_index-1];
399 } else {
400 prev_allow = 1;
401 }
402 }
403 }
404
405 // Structures for handling code fragments built for nested classes
406
407 struct Nested {
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
413 };
414
415 // Some internal variables for saving nested class information
416
417 static Nested *nested_list = 0;
418
419 // Add a function to the nested list
420
421 static void add_nested(Nested *n) {
422 Nested *n1;
423 if (!nested_list) nested_list = n;
424 else {
425 n1 = nested_list;
426 while (n1->next) n1 = n1->next;
427 n1->next = n;
428 }
429 }
430
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!
434
435 static void dump_nested(char *parent) {
436 Nested *n,*n1;
437 n = nested_list;
438 int oldstatus = Status;
439
440 Status = STAT_READONLY;
441 while (n) {
442 // Token replace the name of the parent class
443 n->code.replace("$classname",parent);
444
445 // Fix up the name of the datatype (for building typedefs and other stuff)
446 sprintf(n->type->name,"%s_%s",parent,n->name);
447
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);
451
452 // Dump the code to the scanner
453 if (Verbose)
454 fprintf(stderr,"Splitting from %s : (line %d) \n%s\n", parent,n->line, n->code.get());
455
456 fprintf(f_header,"\n%s\n", n->code.get());
457 start_inline(n->code.get(),n->line);
458
459 n1 = n->next;
460 delete n;
461 n = n1;
462 }
463 nested_list = 0;
464 Status = oldstatus;
465 }
466
467 %}
468
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
473 in parser.tab.h. */
474
475 %union {
476 char *id;
477 struct Declaration {
478 char *id;
479 int is_pointer;
480 int is_reference;
481 } decl;
482 struct InitList {
483 char **names;
484 int count;
485 } ilist;
486 struct DocList {
487 char **names;
488 char **values;
489 int count;
490 } dlist;
491 struct Define {
492 char *id;
493 int type;
494 } dtype;
495 DataType *type;
496 Parm *p;
497 TMParm *tmparm;
498 ParmList *pl;
499 int ivalue;
500 };
501
502 %token <id> ID
503 %token <id> HBLOCK WRAPPER POUND
504 %token <id> STRING
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
512 %token CVALUE COUT
513 %token ENUM ENDDEF MACRO
514 %token CLASS PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND OPERATOR THROW TEMPLATE
515 %token NATIVE INLINE
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
522
523 /* Objective C tokens */
524
525 %token OC_INTERFACE OC_END OC_PUBLIC OC_PRIVATE OC_PROTECTED OC_CLASS OC_IMPLEMENT OC_PROTOCOL
526
527 %left OR
528 %left XOR
529 %left AND
530 %left LSHIFT RSHIFT
531 %left PLUS MINUS
532 %left STAR SLASH
533 %left UMINUS NOT LNOT
534 %left DCOLON
535
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;
546 %type <dtype> etype;
547 %type <dtype> expr;
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;
553
554 %%
555
556 /* The productions of the grammar with their
557 associated semantic actions. */
558
559 program : {
560 {
561 int ii;
562 for (ii = 0; ii < 256; ii++) {
563 handler_stack[ii] = 0;
564 }
565 handler_stack[0] = comment_handler;
566 }
567 doc_stack[0] = doctitle;
568 } command {
569 CommentHandler::cleanup();
570 cplus_cleanup();
571 doc_entry = doctitle;
572 if (lang_init) {
573 lang->close();
574 }
575 if (te_index) {
576 fprintf(stderr,"%s : EOF. Missing #endif detected.\n", input_file);
577 FatalError();
578 }
579 }
580 ;
581
582 command : command statement {
583 scanner_clear_start();
584 Error = 0;
585 }
586 | empty {
587 }
588 ;
589
590 statement : INCLUDE idstring {
591 if (allow) {
592 // init_language();
593 doc_entry = 0;
594 // comment_handler->clear();
595 include_file($2);
596 }
597 }
598
599 /* %extern directive */
600
601 | WEXTERN idstring {
602 if (allow) {
603 int oldextern = WrapExtern;
604 // init_language();
605 doc_entry = 0;
606 // comment_handler->clear();
607 WrapExtern = 1;
608 if (include_file($2) >= 0) {
609 add_symbol("SWIGEXTERN",0,0);
610 } else {
611 WrapExtern = oldextern;
612 }
613 }
614 }
615
616 /* %import directive. Like %extern but calls out to a language module */
617
618 | IMPORT idstring {
619 if (allow) {
620 int oldextern = WrapExtern;
621 init_language();
622 doc_entry = 0;
623 WrapExtern = 1;
624 if (include_file($2) >= 0) {
625 add_symbol("SWIGEXTERN",0,0);
626 lang->import($2);
627 } else {
628 WrapExtern = oldextern;
629 }
630 }
631 }
632
633 /* %checkout directive. Like %include, but simply copies the file into the
634 current directory */
635
636 | CHECKOUT idstring {
637 if (allow) {
638 if ((checkout_file($2,$2)) == 0) {
639 fprintf(stderr,"%s checked out from the SWIG library.\n",$2);
640 }
641 }
642 }
643
644 /* An unknown C preprocessor statement. Just throw it away */
645
646 | POUND {
647 if (allow) {
648 doc_entry = 0;
649 if (Verbose) {
650 fprintf(stderr,"%s : Line %d. CPP %s ignored.\n", input_file, line_number,$1);
651 }
652 }
653 }
654
655 /* A variable declaration */
656
657 | extern type declaration array2 def_args {
658 if (allow) {
659 init_language();
660 if (Active_type) delete Active_type;
661 Active_type = new DataType($2);
662 Active_extern = $1;
663 $2->is_pointer += $3.is_pointer;
664 if ($4 > 0) {
665 $2->is_pointer++;
666 $2->status = STAT_READONLY;
667 $2->arraystr = copy_string(ArrayString);
668 }
669 if ($3.is_reference) {
670 fprintf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
671 FatalError();
672 } else {
673 if ($2->qualifier) {
674 if ((strcmp($2->qualifier,"const") == 0)) {
675 if ($5.type != T_ERROR)
676 create_constant($3.id, $2, $5.id);
677 } else
678 create_variable($1,$3.id,$2);
679 } else
680 create_variable($1,$3.id,$2);
681 }
682 }
683 delete $2;
684 } stail { }
685
686 /* Global variable that smells like a function pointer */
687
688 | extern strict_type LPAREN STAR {
689 skip_decl();
690 fprintf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
691 input_file, line_number);
692 }
693
694 /* A static variable declaration (Ignored) */
695
696 | STATIC type declaration array2 def_args {
697 if (Verbose) {
698 fprintf(stderr,"static variable %s ignored.\n",$3.id);
699 }
700 Active_static = 1;
701 delete $2;
702 } stail {
703 Active_static = 0;
704 }
705
706 /* Global variable that smells like a function pointer */
707
708 | STATIC strict_type LPAREN STAR {
709 skip_decl();
710 fprintf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
711 input_file, line_number);
712 }
713
714
715 /* A function declaration */
716
717 | extern type declaration LPAREN parms RPAREN cpp_const {
718 if (allow) {
719 init_language();
720 if (Active_type) delete Active_type;
721 Active_type = new DataType($2);
722 Active_extern = $1;
723 $2->is_pointer += $3.is_pointer;
724 $2->is_reference = $3.is_reference;
725 create_function($1, $3.id, $2, $5);
726 }
727 delete $2;
728 delete $5;
729 } stail { }
730
731 /* A function declaration with code after it */
732
733 | extern type declaration LPAREN parms RPAREN func_end {
734 if (allow) {
735 init_language();
736 $2->is_pointer += $3.is_pointer;
737 $2->is_reference = $3.is_reference;
738 create_function($1, $3.id, $2, $5);
739 }
740 delete $2;
741 delete $5;
742 };
743
744 /* A function declared without any return datatype */
745
746 | extern declaration LPAREN parms RPAREN cpp_const {
747 if (allow) {
748 init_language();
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);
753 delete t;
754 }
755 } stail { };
756
757 /* A static function declaration code after it */
758
759 | STATIC type declaration LPAREN parms RPAREN func_end {
760 if ((allow) && (Inline)) {
761 if (strlen(CCode.get())) {
762 init_language();
763 $2->is_pointer += $3.is_pointer;
764 $2->is_reference = $3.is_reference;
765 create_function(0, $3.id, $2, $5);
766 }
767 }
768 delete $2;
769 delete $5;
770 };
771
772 /* A function with an explicit inline directive. Not safe to use inside a %inline block */
773
774 | INLINE type declaration LPAREN parms RPAREN func_end {
775 if (allow) {
776 init_language();
777 $2->is_pointer += $3.is_pointer;
778 $2->is_reference = $3.is_reference;
779 if (Inline) {
780 fprintf(stderr,"%s : Line %d. Repeated %%inline directive.\n",input_file,line_number);
781 FatalError();
782 } else {
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());
787 }
788 create_function(0, $3.id, $2, $5);
789 }
790 }
791 delete $2;
792 delete $5;
793 };
794
795 /* A static function declaration (ignored) */
796
797 | STATIC type declaration LPAREN parms RPAREN cpp_const {
798 if (allow) {
799 if (Verbose) {
800 fprintf(stderr,"static function %s ignored.\n", $3.id);
801 }
802 }
803 Active_static = 1;
804 delete $2;
805 delete $5;
806 } stail {
807 Active_static = 0;
808 }
809
810 /* Enable Read-only mode */
811
812 | READONLY {
813 if (allow)
814 Status = Status | STAT_READONLY;
815 }
816
817 /* Enable Read-write mode */
818
819 | READWRITE {
820 if (allow)
821 Status = Status & ~STAT_READONLY;
822 }
823
824 /* New %name directive */
825 | NAME LPAREN ID RPAREN {
826 if (allow) {
827 strcpy(yy_rename,$3);
828 Rename_true = 1;
829 }
830 }
831
832 /* %rename directive */
833 | RENAME ID ID SEMI {
834 if (name_hash.lookup($2)) {
835 name_hash.remove($2);
836 }
837 name_hash.add($2,copy_string($3));
838 }
839
840 /* %new directive */
841
842 | NEW {
843 NewObject = 1;
844 } statement {
845 NewObject = 0;
846 }
847
848 /* Empty name directive. No longer allowed */
849
850 | NAME LPAREN RPAREN {
851 if (allow) {
852 fprintf(stderr,"%s : Lind %d. Empty %%name() is no longer supported.\n",
853 input_file, line_number);
854 FatalError();
855 }
856 } cpp {
857 Rename_true = 0;
858 }
859
860 /* A native wrapper function */
861
862 | NATIVE LPAREN ID RPAREN extern ID SEMI {
863 if (allow && (!WrapExtern)) {
864 init_language();
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);
868 } else {
869 doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
870 lang->add_native($3,$6);
871 }
872 }
873 }
874 | NATIVE LPAREN ID RPAREN extern type declaration LPAREN parms RPAREN SEMI {
875 if (allow && (!WrapExtern)) {
876 init_language();
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);
881 } else {
882 if ($5) {
883 emit_extern_func($7.id, $6, $9, $5, f_header);
884 }
885 doc_entry = new DocDecl($3,doc_stack[doc_stack_top]);
886 lang->add_native($3,$7.id);
887 }
888 }
889 delete $6;
890 delete $9;
891 }
892
893 /* %title directive */
894
895 | TITLE STRING styletail {
896 if (allow && (!WrapExtern)) {
897 if (!title_init) {
898 title_init = 1;
899 doc_init = 1;
900 if (!comment_handler) {
901 comment_handler = new CommentHandler();
902 }
903 {
904 int ii;
905 for (ii = 0; ii < $3.count; ii++) {
906 comment_handler->style($3.names[ii],$3.values[ii]);
907 }
908 }
909 // Create a new title for documentation
910 {
911 int temp = line_number;
912 line_number = $1;
913 if (!doctitle)
914 doctitle = new DocTitle($2,0);
915 else {
916 doctitle->name = copy_string(title);
917 doctitle->line_number = $1;
918 doctitle->end_line = $1;
919 }
920 line_number = temp;
921 }
922 doctitle->usage = $2;
923 doc_entry = doctitle;
924 doc_stack[0] = doc_entry;
925 doc_stack_top = 0;
926 handler_stack[0] = comment_handler;
927 {
928 int ii;
929 for (ii = 0; ii < $3.count; ii++) {
930 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
931 }
932 }
933
934 } else {
935 // Ignore it
936 }
937 }
938 }
939
940
941 /* %section directive */
942
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];
949 {
950 int ii;
951 for (ii = 0; ii < $3.count; ii++) {
952 comment_handler->style($3.names[ii],$3.values[ii]);
953 }
954 }
955 {
956 int temp = line_number;
957 line_number = $1;
958 doc_entry = new DocSection($2,doc_stack[0]);
959 line_number = temp;
960 }
961 doc_stack_top = 1;
962 doc_stack[1] = doc_entry;
963 {
964 int ii;
965 for (ii = 0; ii < $3.count; ii++) {
966 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
967 }
968 }
969 }
970 }
971
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);
977 FatalError();
978 } else {
979
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];
984 {
985 int ii;
986 for (ii = 0; ii < $3.count; ii++) {
987 comment_handler->style($3.names[ii],$3.values[ii]);
988 }
989 }
990 {
991 int temp = line_number;
992 line_number = $1;
993 doc_entry = new DocSection($2,doc_stack[1]);
994 line_number = temp;
995 }
996 doc_stack_top = 2;
997 doc_stack[2] = doc_entry;
998 {
999 int ii;
1000 for (ii = 0; ii < $3.count; ii++) {
1001 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
1002 }
1003 }
1004 }
1005 }
1006 }
1007
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);
1013 FatalError();
1014 } else {
1015
1016 // Copy old comment handler
1017
1018 // if (handler_stack[3]) delete handler_stack[3];
1019 handler_stack[3] = new CommentHandler(handler_stack[2]);
1020 comment_handler = handler_stack[3];
1021 {
1022 int ii;
1023 for (ii = 0; ii < $3.count; ii++) {
1024 comment_handler->style($3.names[ii],$3.values[ii]);
1025 }
1026 }
1027 {
1028 int temp = line_number;
1029 line_number = $1;
1030 doc_entry = new DocSection($2,doc_stack[2]);
1031 line_number = temp;
1032 }
1033 doc_stack_top = 3;
1034 doc_stack[3] = doc_entry;
1035 {
1036 int ii;
1037 for (ii = 0; ii < $3.count; ii++) {
1038 doc_stack[doc_stack_top]->style($3.names[ii],$3.values[ii]);
1039 }
1040 }
1041 }
1042 }
1043 }
1044
1045 /* %alpha directive (obsolete) */
1046 | ALPHA_MODE {
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);
1051 }
1052 }
1053 /* %raw directive (obsolete) */
1054 | RAW_MODE {
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);
1059 }
1060 }
1061
1062 | doc_enable { }
1063
1064 /* %text directive */
1065
1066 | TEXT HBLOCK {
1067 if (allow && (!WrapExtern)) {
1068 $2[strlen($2) - 1] = 0;
1069 doc_entry = new DocText($2,doc_stack[doc_stack_top]);
1070 doc_entry = 0;
1071 }
1072 }
1073
1074
1075 | typedef_decl { }
1076
1077 /* Code insertion block */
1078
1079 | HBLOCK {
1080 if (allow && (!WrapExtern)) {
1081 init_language();
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);
1085 }
1086 }
1087
1088 /* Super-secret undocumented for people who really know what's going on feature */
1089
1090 | WRAPPER HBLOCK {
1091 if (allow && (!WrapExtern)) {
1092 init_language();
1093 $2[strlen($2) - 1] = 0;
1094 fprintf(f_wrappers,"%s\n",$2);
1095 }
1096 }
1097
1098 /* Initialization code */
1099
1100 | INIT HBLOCK {
1101 if (allow && (!WrapExtern)) {
1102 init_language();
1103 $2[strlen($2) -1] = 0;
1104 fprintf(f_init,"%s\n", $2);
1105 }
1106 }
1107
1108 /* Inline block */
1109 | INLINE HBLOCK {
1110 if (allow && (!WrapExtern)) {
1111 init_language();
1112 $2[strlen($2) - 1] = 0;
1113 fprintf(f_header, "%s\n", $2);
1114 start_inline($2,start_line);
1115 }
1116 }
1117
1118 /* Echo mode */
1119 | ECHO HBLOCK {
1120 if (allow && (!WrapExtern)) {
1121 fprintf(stderr,"%s\n", $2);
1122 }
1123 }
1124
1125 | ECHO STRING {
1126 if (allow && (!WrapExtern)) {
1127 fprintf(stderr,"%s\n", $2);
1128 }
1129 }
1130
1131 /* Disable code generation */
1132 | DOCONLY {
1133 DocOnly = 1;
1134 }
1135
1136 /* Init directive--to avoid errors in other modules */
1137
1138 | INIT ID initlist {
1139 if (allow) {
1140 if (!module_init) {
1141 lang->set_init($2);
1142 module_init = 1;
1143 init_language();
1144 } else {
1145 if (Verbose)
1146 fprintf(stderr,"%s : Line %d. %%init %s ignored.\n",
1147 input_file, line_number, $2);
1148 }
1149 if ($3.count > 0) {
1150 fprintf(stderr,"%s : Line %d. Warning. Init list no longer supported.\n",
1151 input_file,line_number);
1152 }
1153 }
1154 for (i = 0; i < $3.count; i++)
1155 if ($3.names[i]) delete [] $3.names[i];
1156 delete [] $3.names;
1157 }
1158 /* Module directive */
1159
1160 | MODULE ID initlist {
1161 if (allow) {
1162 if ($3.count)
1163 lang->set_module($2,$3.names);
1164 else
1165 lang->set_module($2,0);
1166 module_init = 1;
1167 init_language();
1168 }
1169 for (i = 0; i < $3.count; i++)
1170 if ($3.names[i]) delete [] $3.names[i];
1171 delete [] $3.names;
1172 }
1173
1174 /* #define directive */
1175
1176 | DEFINE ID definetail {
1177 if (allow) {
1178 if (($3.type != T_ERROR) && ($3.type != T_SYMBOL)) {
1179 init_language();
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);
1188 }
1189 }
1190 }
1191 }
1192
1193 /* A CPP Macro. Ignore (hopefully) */
1194
1195 | DEFINE MACRO {
1196 if (Verbose) {
1197 fprintf(stderr,"%s : Line %d. CPP Macro ignored.\n", input_file, line_number);
1198 }
1199 }
1200
1201 /* An undef directive */
1202 | UNDEF ID {
1203 remove_symbol($2);
1204 }
1205
1206 /* Enumerations */
1207
1208 | extern ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE SEMI {
1209 if (allow) {
1210 init_language();
1211 if ($3) {
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);
1217 }
1218 }
1219 }
1220
1221 /* A typdef'd enum. Pretty common in C headers */
1222
1223 | TYPEDEF ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE ID {
1224 if (allow) {
1225 init_language();
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);
1232 }
1233 } typedeflist { }
1234
1235 /* -----------------------------------------------------------------
1236 typemap support.
1237
1238 These constructs are used to support type-maps.
1239 ----------------------------------------------------------------- */
1240
1241 /* Create a new typemap */
1242
1243 | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
1244 TMParm *p;
1245 skip_brace();
1246 p = $7;
1247 while (p) {
1248 typemap_register($5,$3,p->p->t,p->p->name,CCode,p->args);
1249 p = p->next;
1250 }
1251 delete $3;
1252 delete $5;
1253 }
1254
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);
1260 FatalError();
1261 } else {
1262 TMParm *p;
1263 skip_brace();
1264 p = $5;
1265 while (p) {
1266 typemap_register($3,typemap_lang,p->p->t,p->p->name,CCode,p->args);
1267 p = p->next;
1268 }
1269 }
1270 delete $3;
1271 }
1272
1273 /* Clear a typemap */
1274
1275 | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list SEMI {
1276 TMParm *p;
1277 p = $7;
1278 while (p) {
1279 typemap_clear($5,$3,p->p->t,p->p->name);
1280 p = p->next;
1281 }
1282 delete $3;
1283 delete $5;
1284 }
1285 /* Clear a typemap in current language */
1286
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);
1291 FatalError();
1292 } else {
1293 TMParm *p;
1294 p = $5;
1295 while (p) {
1296 typemap_clear($3,typemap_lang,p->p->t,p->p->name);
1297 p = p->next;
1298 }
1299 }
1300 delete $3;
1301 }
1302
1303 /* Copy a typemap */
1304
1305 | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
1306 TMParm *p;
1307 p = $7;
1308 while (p) {
1309 typemap_copy($5,$3,$9->p->t,$9->p->name,p->p->t,p->p->name);
1310 p = p->next;
1311 }
1312 delete $3;
1313 delete $5;
1314 delete $9->p;
1315 delete $9;
1316 }
1317
1318 /* Copy typemap in current language */
1319
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);
1324 FatalError();
1325 } else {
1326 TMParm *p;
1327 p = $5;
1328 while (p) {
1329 typemap_copy($3,typemap_lang,$7->p->t,$7->p->name,p->p->t,p->p->name);
1330 p = p->next;
1331 }
1332 }
1333 delete $3;
1334 delete $7->p;
1335 delete $7;
1336 }
1337 /* -----------------------------------------------------------------
1338 apply and clear support (for typemaps)
1339 ----------------------------------------------------------------- */
1340
1341 | APPLY typemap_parm LBRACE tm_list RBRACE {
1342 TMParm *p;
1343 p = $4;
1344 while(p) {
1345 typemap_apply($2->p->t,$2->p->name,p->p->t,p->p->name);
1346 p = p->next;
1347 }
1348 delete $4;
1349 delete $2->args;
1350 delete $2;
1351 }
1352 | CLEAR tm_list SEMI {
1353 TMParm *p;
1354 p = $2;
1355 while (p) {
1356 typemap_clear_apply(p->p->t, p->p->name);
1357 p = p->next;
1358 }
1359 }
1360
1361
1362 /* -----------------------------------------------------------------
1363 exception support
1364
1365 These constructs are used to define exceptions
1366 ----------------------------------------------------------------- */
1367
1368 /* An exception definition */
1369 | EXCEPT LPAREN ID RPAREN LBRACE {
1370 skip_brace();
1371 fragment_register("except",$3, CCode);
1372 delete $3;
1373 }
1374
1375 /* A Generic Exception (no language specified */
1376 | EXCEPT LBRACE {
1377 skip_brace();
1378 fragment_register("except",typemap_lang, CCode);
1379 }
1380
1381 /* Clear an exception */
1382
1383 | EXCEPT LPAREN ID RPAREN SEMI {
1384 fragment_clear("except",$3);
1385 }
1386
1387 /* Generic clear */
1388 | EXCEPT SEMI {
1389 fragment_clear("except",typemap_lang);
1390 }
1391
1392 /* Miscellaenous stuff */
1393
1394 | SEMI { }
1395 | cpp { }
1396 | objective_c { }
1397 | error {
1398 if (!Error) {
1399 {
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);
1403 FatalError();
1404 last_error_line = line_number;
1405 // Try to make some kind of recovery.
1406 skip_decl();
1407 }
1408 Error = 1;
1409 }
1410 }
1411 }
1412
1413 /* A an extern C type declaration. Does nothing, but is ignored */
1414
1415 | EXTERN STRING LBRACE command RBRACE { }
1416 | cond_compile { }
1417
1418 /* Officially, this directive doesn't exist yet */
1419
1420 | pragma { }
1421
1422 /* %style directive. This applies to all current styles */
1423
1424 | STYLE stylelist {
1425 {
1426 int ii,jj;
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]);
1431 if (doctitle)
1432 doctitle->style($2.names[ii],$2.values[ii]);
1433 doc->style($2.names[ii],$2.values[ii]);
1434 }
1435 }
1436 }
1437
1438 /* %localstyle directive. This applies only to the current style */
1439
1440 | LOCALSTYLE stylelist {
1441 {
1442 int ii;
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]);
1448 }
1449 }
1450 }
1451
1452 /* User defined directive */
1453 | user_directive{ }
1454 ;
1455
1456
1457 /* Dcumentation disable/enable */
1458
1459 doc_enable : DOC_DISABLE {
1460 if (allow) {
1461 if (IgnoreDoc) {
1462 /* Already in a disabled documentation */
1463 doc_scope++;
1464 } else {
1465 if (Verbose)
1466 fprintf(stderr,"%s : Line %d. Documentation disabled.\n", input_file, line_number);
1467 IgnoreDoc = 1;
1468 doc_scope = 1;
1469 }
1470 }
1471 }
1472 /* %enabledoc directive */
1473 | DOC_ENABLE {
1474 if (allow) {
1475 if (IgnoreDoc) {
1476 if (doc_scope > 1) {
1477 doc_scope--;
1478 } else {
1479 if (Verbose)
1480 fprintf(stderr,"%s : Line %d. Documentation enabled.\n", input_file, line_number);
1481 IgnoreDoc = 0;
1482 doc_scope = 0;
1483 }
1484 }
1485 }
1486 }
1487 ;
1488
1489 /* Note : This really needs to be re-done */
1490
1491 /* A typedef with pointers */
1492 typedef_decl : TYPEDEF type declaration {
1493 if (allow) {
1494 init_language();
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 */
1500 if ($1)
1501 fprintf(f_header,"typedef %s %s;\n", $2->print_full(), $3.id);
1502 cplus_register_type($3.id);
1503 }
1504 } typedeflist { };
1505
1506 /* A rudimentary typedef involving function pointers */
1507
1508 | TYPEDEF type LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
1509 if (allow) {
1510 init_language();
1511 /* Typedef'd pointer */
1512 if ($1) {
1513 sprintf(temp_name,"(*%s)",$5);
1514 fprintf(f_header,"typedef ");
1515 emit_extern_func(temp_name, $2,$8,0,f_header);
1516 }
1517 strcpy($2->name,"<function ptr>");
1518 $2->type = T_USER;
1519 $2->is_pointer = 1;
1520 $2->typedef_add($5,1);
1521 cplus_register_type($5);
1522 }
1523 delete $2;
1524 delete $5;
1525 delete $8;
1526 }
1527
1528 /* A typedef involving function pointers again */
1529
1530 | TYPEDEF type stars LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
1531 if (allow) {
1532 init_language();
1533 if ($1) {
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);
1538 }
1539
1540 /* Typedef'd pointer */
1541 strcpy($2->name,"<function ptr>");
1542 $2->type = T_USER;
1543 $2->is_pointer = 1;
1544 $2->typedef_add($6,1);
1545 cplus_register_type($6);
1546 }
1547 delete $2;
1548 delete $6;
1549 delete $9;
1550 }
1551
1552 /* A typedef involving arrays */
1553
1554 | TYPEDEF type declaration array {
1555 if (allow) {
1556 init_language();
1557 Active_typedef = new DataType($2);
1558 // This datatype is going to be readonly
1559
1560 $2->status = STAT_READONLY | STAT_REPLACETYPE;
1561 $2->is_pointer += $3.is_pointer;
1562 // Turn this into a "pointer" corresponding to the array
1563 $2->is_pointer++;
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);
1568
1569 }
1570 } typedeflist { }
1571 ;
1572
1573 /* ------------------------------------------------------------------------
1574 Typedef list
1575
1576 The following rules are used to manage typedef lists. Only a temporary
1577 hack until the SWIG 2.0 parser gets online.
1578
1579 Active_typedef contains the datatype of the last typedef (if applicable)
1580 ------------------------------------------------------------------------ */
1581
1582
1583 typedeflist : COMMA declaration typedeflist {
1584 if (allow) {
1585 if (Active_typedef) {
1586 DataType *t;
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);
1591 delete t;
1592 }
1593 }
1594 }
1595 | COMMA declaration array {
1596 DataType *t;
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);
1603 delete t;
1604 fprintf(stderr,"%s : Line %d. Warning. Array type %s will be read-only without a typemap.\n",input_file,line_number, $2.id);
1605 }
1606 | empty { }
1607 ;
1608
1609 /* ----------------------------------------------------------------------------------
1610 Conditional Compilation
1611
1612 SWIG supports the following constructs
1613 #ifdef
1614 #ifndef
1615 #else
1616 #endif
1617 #if defined(ID)
1618 #if ! defined(ID)
1619 #elif
1620
1621 #if, and #elif are a little weak in this implementation
1622 ---------------------------------------------------------------------------------- */
1623
1624
1625 /* #ifdef directive */
1626 cond_compile : IFDEF ID {
1627 /* Push old if-then-else status */
1628 if_push();
1629 /* Look a symbol up in the symbol table */
1630 if (lookup_symbol($2)) {
1631 in_then = 1;
1632 in_else = 0;
1633 allow = 1 & prev_allow;
1634 } else {
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 */
1639 SWIG_exit(1);
1640 }
1641 if (!in_else) {
1642 if_pop(); // Pop out. Reached end of block
1643 } else {
1644 allow = prev_allow;
1645 in_then = 0;
1646 }
1647 }
1648 }
1649
1650 /* #ifndef directive */
1651
1652 | IFNDEF ID {
1653 if_push();
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 */
1659 SWIG_exit(1);
1660 }
1661 if (!in_else) {
1662 if_pop(); // Pop out. Reached end of block
1663 } else {
1664 allow = prev_allow;
1665 in_then = 0;
1666 }
1667 } else {
1668 in_then = 1;
1669 in_else = 0;
1670 allow = 1 & prev_allow;
1671 }
1672 }
1673
1674 /* #else directive */
1675 | ELSE {
1676 if ((!in_then) || (in_else)) {
1677 fprintf(stderr,"%s : Line %d. Misplaced else\n", input_file, line_number);
1678 FatalError();
1679 } else {
1680 in_then = 0;
1681 in_else = 1;
1682 if (allow) {
1683 allow = 0;
1684 /* Skip over rest of the conditional */
1685 skip_cond(0);
1686 if_pop();
1687 } else {
1688 allow = 1;
1689 }
1690 allow = allow & prev_allow;
1691 }
1692 }
1693 /* #endif directive */
1694 | ENDIF {
1695 if ((!in_then) && (!in_else)) {
1696 fprintf(stderr,"%s : Line %d. Misplaced endif\n", input_file, line_number);
1697 FatalError();
1698 } else {
1699 if_pop();
1700 }
1701 }
1702
1703 /* #if */
1704 | IF cpp_const_expr {
1705 /* Push old if-then-else status */
1706 if_push();
1707 if ($2) {
1708 in_then = 1;
1709 in_else = 0;
1710 allow = 1 & prev_allow;
1711 } else {
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 */
1716 SWIG_exit(1);
1717 }
1718 if (!in_else) {
1719 if_pop(); // Pop out. Reached end of block
1720 } else {
1721 allow = prev_allow;
1722 in_then = 0;
1723 }
1724 }
1725 }
1726
1727 /* #elif. We treat this identical to an #if. Abit of a hack, but what
1728 the hell. */
1729
1730 | ELIF cpp_const_expr {
1731 /* have to pop old if clause off */
1732 if_pop();
1733
1734 /* Push old if-then-else status */
1735 if_push();
1736 if ($2) {
1737 in_then = 1;
1738 in_else = 0;
1739 allow = 1 & prev_allow;
1740 } else {
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 */
1745 SWIG_exit(1);
1746 }
1747 if (!in_else) {
1748 if_pop(); // Pop out. Reached end of block
1749 } else {
1750 allow = prev_allow;
1751 in_then = 0;
1752 }
1753 }
1754 }
1755 ;
1756
1757 /* C preprocessor expression (only used for conditional compilation */
1758
1759 cpp_const_expr : DEFINED LPAREN ID RPAREN {
1760
1761 /* Look ID up in the symbol table */
1762 if (lookup_symbol($3)) {
1763 $$ = 1;
1764 } else {
1765 $$ = 0;
1766 }
1767 }
1768 | DEFINED ID {
1769 if (lookup_symbol($2)) {
1770 $$ = 1;
1771 } else {
1772 $$ = 0;
1773 }
1774 }
1775 | LNOT cpp_const_expr {
1776 if ($2) $$ = 0;
1777 else $$ = 1;
1778 }
1779 ;
1780
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");
1787 }
1788
1789 | PRAGMA ID stylearg {
1790 if (allow && (!WrapExtern))
1791 swig_pragma($2,$3);
1792 }
1793 | PRAGMA LPAREN ID RPAREN ID stylearg {
1794 if (allow && (!WrapExtern))
1795 lang->pragma($3,$5,$6);
1796 }
1797 ;
1798
1799 /* Allow lists of variables and functions to be built up */
1800
1801 stail : SEMI { }
1802 | COMMA declaration array2 def_args {
1803 if (allow) {
1804 init_language();
1805 temp_typeptr = new DataType(Active_type);
1806 temp_typeptr->is_pointer += $2.is_pointer;
1807 if ($3 > 0) {
1808 temp_typeptr->is_pointer++;
1809 temp_typeptr->status = STAT_READONLY;
1810 temp_typeptr->arraystr = copy_string(ArrayString);
1811 }
1812 if ($2.is_reference) {
1813 fprintf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
1814 FatalError();
1815 } else {
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);
1821 } else
1822 create_variable(Active_extern,$2.id, temp_typeptr);
1823 } else
1824 create_variable(Active_extern, $2.id, temp_typeptr);
1825 }
1826 delete temp_typeptr;
1827 }
1828 } stail { }
1829 | COMMA declaration LPAREN parms RPAREN cpp_const {
1830 if (allow) {
1831 init_language();
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;
1837 }
1838 delete $4;
1839 } stail { }
1840 ;
1841
1842 definetail : definetype ENDDEF {
1843 $$ = $1;
1844 }
1845 | ENDDEF {
1846 $$.type = T_SYMBOL;
1847 }
1848 | error ENDDEF {
1849 if (Verbose)
1850 fprintf(stderr,"%s : Line %d. Warning. Unable to parse #define (ignored)\n", input_file, line_number);
1851 $$.type = T_ERROR;
1852 }
1853
1854 ;
1855
1856 extern : EXTERN { $$ = 1; }
1857 | empty {$$ = 0; }
1858 | EXTERN STRING {
1859 if (strcmp($2,"C") == 0) {
1860 $$ = 2;
1861 } else {
1862 fprintf(stderr,"%s : Line %d. Unrecognized extern type \"%s\" (ignored).\n", input_file, line_number, $2);
1863 FatalError();
1864 }
1865 }
1866 ;
1867
1868 /* End of a function declaration. Allows C++ "const" directive and inline code */
1869
1870 func_end : cpp_const LBRACE { skip_brace(); }
1871 /* | LBRACE { skip_brace(); } */
1872 ;
1873
1874 /* ------------------------------------------------------------------------------
1875 Function parameter lists
1876
1877 ------------------------------------------------------------------------------ */
1878
1879 parms : parm ptail {
1880 if (($1->t->type != T_VOID) || ($1->t->is_pointer))
1881 $2->insert($1,0);
1882 $$ = $2;
1883 delete $1;
1884 }
1885 | empty { $$ = new ParmList;}
1886 ;
1887
1888 ptail : COMMA parm ptail {
1889 $3->insert($2,0);
1890 $$ = $3;
1891 delete $2;
1892 }
1893 | empty { $$ = new ParmList;}
1894 ;
1895
1896 parm : parm_type {
1897 $$ = $1;
1898 if (typemap_check("ignore",typemap_lang,$$->t,$$->name))
1899 $$->ignore = 1;
1900 }
1901 | parm_specifier_list parm_type {
1902 $$ = $2;
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);
1906 FatalError();
1907 }
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);
1910 FatalError();
1911 } else {
1912 $$->t->is_pointer--;
1913 }
1914 }
1915
1916 parm_type : type pname {
1917 if (InArray) {
1918 $1->is_pointer++;
1919 if (Verbose) {
1920 fprintf(stderr,"%s : Line %d. Warning. Array %s", input_file, line_number, $1->print_type());
1921 print_array();
1922 fprintf(stderr," has been converted to %s.\n", $1->print_type());
1923 }
1924 // Add array string to the type
1925 $1->arraystr = copy_string(ArrayString.get());
1926 }
1927 $$ = new Parm($1,$2);
1928 $$->call_type = 0;
1929 $$->defvalue = DefArg;
1930 if (($1->type == T_USER) && !($1->is_pointer)) {
1931 if (Verbose)
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);
1934
1935 $$->call_type = CALL_REFERENCE;
1936 $$->t->is_pointer++;
1937 }
1938 delete $1;
1939 delete $2;
1940 }
1941
1942 | type stars pname {
1943 $$ = new Parm($1,$3);
1944 $$->t->is_pointer += $2;
1945 $$->call_type = 0;
1946 $$->defvalue = DefArg;
1947 if (InArray) {
1948 $$->t->is_pointer++;
1949 if (Verbose) {
1950 fprintf(stderr,"%s : Line %d. Warning. Array %s", input_file, line_number, $$->t->print_type());
1951 print_array();
1952 fprintf(stderr," has been converted to %s.\n", $$->t->print_type());
1953 }
1954 // Add array string to the type
1955 $$->t->arraystr = copy_string(ArrayString.get());
1956 }
1957 delete $1;
1958 delete $3;
1959 }
1960
1961 | type AND pname {
1962 $$ = new Parm($1,$3);
1963 $$->t->is_reference = 1;
1964 $$->call_type = 0;
1965 $$->t->is_pointer++;
1966 $$->defvalue = DefArg;
1967 if (!CPlusPlus) {
1968 fprintf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number);
1969 }
1970 delete $1;
1971 delete $3;
1972 }
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);
1975 FatalError();
1976 $$ = new Parm($1,$4);
1977 $$->t->type = T_ERROR;
1978 $$->name = copy_string($4);
1979 strcpy($$->t->name,"<function ptr>");
1980 delete $1;
1981 delete $4;
1982 delete $7;
1983 }
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>");
1990 FatalError();
1991 }
1992 ;
1993
1994 pname : ID def_args {
1995 $$ = $1;
1996 InArray = 0;
1997 if ($2.type == T_CHAR)
1998 DefArg = copy_string(ConstChar);
1999 else
2000 DefArg = copy_string($2.id);
2001 if ($2.id) delete $2.id;
2002 }
2003 | ID array {
2004 $$ = $1;
2005 InArray = $2;
2006 DefArg = 0;
2007 }
2008 | array {
2009 $$ = new char[1];
2010 $$[0] = 0;
2011 InArray = $1;
2012 DefArg = 0;
2013 }
2014 | empty { $$ = new char[1];
2015 $$[0] = 0;
2016 InArray = 0;
2017 DefArg = 0;
2018 }
2019 ;
2020
2021 def_args : EQUAL definetype { $$ = $2; }
2022 | EQUAL AND ID {
2023 $$.id = new char[strlen($3)+2];
2024 $$.id[0] = '&';
2025 strcpy(&$$.id[1], $3);
2026 $$.type = T_USER;
2027 }
2028 | EQUAL LBRACE {
2029 skip_brace();
2030 $$.id = 0; $$.type = T_INT;
2031 }
2032 | COLON NUM_INT {
2033 }
2034 | empty {$$.id = 0; $$.type = T_INT;}
2035 ;
2036
2037 parm_specifier : CVALUE { $$ = CALL_VALUE; }
2038 | COUT { $$ = CALL_OUTPUT; }
2039 ;
2040
2041 parm_specifier_list : parm_specifier_list parm_specifier {
2042 $$ = $1 | $2;
2043 }
2044 | parm_specifier {
2045 $$ = $1;
2046 }
2047 ;
2048
2049 /* Declaration must be an identifier, possibly preceded by a * for pointer types */
2050
2051 declaration : ID { $$.id = $1;
2052 $$.is_pointer = 0;
2053 $$.is_reference = 0;
2054 }
2055 | stars ID {
2056 $$.id = $2;
2057 $$.is_pointer = $1;
2058 $$.is_reference = 0;
2059 }
2060 | AND ID {
2061 $$.id = $2;
2062 $$.is_pointer = 1;
2063 $$.is_reference = 1;
2064 if (!CPlusPlus) {
2065 fprintf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number);
2066 }
2067 }
2068 ;
2069
2070 stars : STAR empty { $$ = 1; }
2071 | STAR stars { $$ = $2 + 1;}
2072 ;
2073
2074
2075 array : LBRACKET RBRACKET array2 {
2076 $$ = $3 + 1;
2077 "[]" >> ArrayString;
2078 }
2079 | LBRACKET expr RBRACKET array2 {
2080 $$ = $4 + 1;
2081 "]" >> ArrayString;
2082 $2.id >> ArrayString;
2083 "[" >> ArrayString;
2084 }
2085 ;
2086 array2 : array {
2087 $$ = $1;
2088 }
2089 | empty { $$ = 0;
2090 ArrayString = "";
2091 }
2092 ;
2093
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. */
2096
2097 type : TYPE_INT {
2098 $$ = $1;
2099 }
2100 | TYPE_SHORT opt_int {
2101 $$ = $1;
2102 }
2103 | TYPE_LONG opt_int {
2104 $$ = $1;
2105 }
2106 | TYPE_CHAR {
2107 $$ = $1;
2108 }
2109 | TYPE_BOOL {
2110 $$ = $1;
2111 }
2112 | TYPE_FLOAT {
2113 $$ = $1;
2114 }
2115 | TYPE_DOUBLE {
2116 $$ = $1;
2117 }
2118 | TYPE_VOID {
2119 $$ = $1;
2120 }
2121 | TYPE_SIGNED opt_signed {
2122 if ($2) $$ = $2;
2123 else $$ = $1;
2124 }
2125 | TYPE_UNSIGNED opt_unsigned {
2126 if ($2) $$ = $2;
2127 else $$ = $1;
2128 }
2129 | TYPE_TYPEDEF objc_protolist {
2130 $$ = $1;
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);
2135 } else {
2136 strcat($$->name,$2);
2137 }
2138 }
2139 }
2140 | ID objc_protolist {
2141 $$ = new DataType;
2142 strcpy($$->name,$1);
2143 $$->type = T_USER;
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);
2150 } else {
2151 strcat($$->name,$2);
2152 }
2153 }
2154 }
2155 | CONST type {
2156 $$ = $2;
2157 $$->qualifier = new char[6];
2158 strcpy($$->qualifier,"const");
2159 }
2160 | cpptype ID {
2161 $$ = new DataType;
2162 sprintf($$->name,"%s %s",$1, $2);
2163 $$->type = T_USER;
2164 }
2165 | ID DCOLON ID {
2166 $$ = new DataType;
2167 sprintf($$->name,"%s::%s",$1,$3);
2168 $$->type = T_USER;
2169 $$->typedef_resolve();
2170 }
2171 /* This declaration causes a shift-reduce conflict. Unresolved for now */
2172
2173
2174 | DCOLON ID {
2175 $$ = new DataType;
2176 sprintf($$->name,"%s", $2);
2177 $$->type = T_USER;
2178 $$->typedef_resolve(1);
2179 }
2180 | ENUM ID {
2181 $$ = new DataType;
2182 sprintf($$->name,"enum %s", $2);
2183 $$->type = T_INT;
2184 $$->typedef_resolve(1);
2185 }
2186 ;
2187
2188 /* type specification without ID symbol. Used in some cases to prevent shift-reduce conflicts */
2189
2190 strict_type : TYPE_INT {
2191 $$ = $1;
2192 }
2193 | TYPE_SHORT opt_int {
2194 $$ = $1;
2195 }
2196 | TYPE_LONG opt_int {
2197 $$ = $1;
2198 }
2199 | TYPE_CHAR {
2200 $$ = $1;
2201 }
2202 | TYPE_BOOL {
2203 $$ = $1;
2204 }
2205 | TYPE_FLOAT {
2206 $$ = $1;
2207 }
2208 | TYPE_DOUBLE {
2209 $$ = $1;
2210 }
2211 | TYPE_VOID {
2212 $$ = $1;
2213 }
2214 | TYPE_SIGNED opt_signed {
2215 if ($2) $$ = $2;
2216 else $$ = $1;
2217 }
2218 | TYPE_UNSIGNED opt_unsigned {
2219 if ($2) $$ = $2;
2220 else $$ = $1;
2221 }
2222 | TYPE_TYPEDEF objc_protolist {
2223 $$ = $1;
2224 strcat($$->name,$2);
2225 }
2226 | CONST type {
2227 $$ = $2;
2228 $$->qualifier = new char[6];
2229 strcpy($$->qualifier,"const");
2230 }
2231 | cpptype ID {
2232 $$ = new DataType;
2233 sprintf($$->name,"%s %s",$1, $2);
2234 $$->type = T_USER;
2235 }
2236 ;
2237
2238 /* Optional signed types */
2239
2240 opt_signed : empty {
2241 $$ = (DataType *) 0;
2242 }
2243 | TYPE_INT {
2244 $$ = $1;
2245 $$->type = T_INT;
2246 sprintf(temp_name,"signed %s",$1->name);
2247 strcpy($$->name,temp_name);
2248 }
2249 | TYPE_SHORT opt_int {
2250 $$ = $1;
2251 $$->type = T_SHORT;
2252 sprintf(temp_name,"signed %s",$1->name);
2253 strcpy($$->name,temp_name);
2254 }
2255 | TYPE_LONG opt_int {
2256 $$ = $1;
2257 $$->type = T_LONG;
2258 sprintf(temp_name,"signed %s",$1->name);
2259 strcpy($$->name,temp_name);
2260 }
2261 | TYPE_CHAR {
2262 $$ = $1;
2263 $$->type = T_SCHAR;
2264 sprintf(temp_name,"signed %s",$1->name);
2265 strcpy($$->name,temp_name);
2266 }
2267 ;
2268
2269 /* Optional unsigned types */
2270
2271 opt_unsigned : empty {
2272 $$ = (DataType *) 0;
2273 }
2274 | TYPE_INT {
2275 $$ = $1;
2276 $$->type = T_UINT;
2277 sprintf(temp_name,"unsigned %s",$1->name);
2278 strcpy($$->name,temp_name);
2279 }
2280 | TYPE_SHORT opt_int {
2281 $$ = $1;
2282 $$->type = T_USHORT;
2283 sprintf(temp_name,"unsigned %s",$1->name);
2284 strcpy($$->name,temp_name);
2285 }
2286 | TYPE_LONG opt_int {
2287 $$ = $1;
2288 $$->type = T_ULONG;
2289 sprintf(temp_name,"unsigned %s",$1->name);
2290 strcpy($$->name,temp_name);
2291 }
2292 | TYPE_CHAR {
2293 $$ = $1;
2294 $$->type = T_UCHAR;
2295 sprintf(temp_name,"unsigned %s",$1->name);
2296 strcpy($$->name,temp_name);
2297 }
2298 ;
2299
2300 opt_int : TYPE_INT { }
2301 | empty { }
2302 ;
2303
2304 definetype : { scanner_check_typedef(); } expr {
2305 $$ = $2;
2306 scanner_ignore_typedef();
2307 if (ConstChar) delete ConstChar;
2308 ConstChar = 0;
2309 }
2310 | STRING {
2311 $$.id = $1;
2312 $$.type = T_CHAR;
2313 if (ConstChar) delete ConstChar;
2314 ConstChar = new char[strlen($1)+3];
2315 sprintf(ConstChar,"\"%s\"",$1);
2316 }
2317 | CHARCONST {
2318 $$.id = $1;
2319 $$.type = T_CHAR;
2320 if (ConstChar) delete ConstChar;
2321 ConstChar = new char[strlen($1)+3];
2322 sprintf(ConstChar,"'%s'",$1);
2323 }
2324 ;
2325
2326
2327 /* Initialization function links */
2328
2329 initlist : initlist COMMA ID {
2330 $$ = $1;
2331 $$.names[$$.count] = copy_string($3);
2332 $$.count++;
2333 $$.names[$$.count] = (char *) 0;
2334 }
2335 | empty {
2336 $$.names = new char *[NI_NAMES];
2337 $$.count = 0;
2338 for (i = 0; i < NI_NAMES; i++)
2339 $$.names[i] = (char *) 0;
2340 }
2341 ;
2342
2343 /* Some stuff for handling enums */
2344
2345 ename : ID { $$ = $1; }
2346 | empty { $$ = (char *) 0;}
2347 ;
2348
2349 /* SWIG enum list.
2350 */
2351
2352 enumlist : enumlist COMMA edecl {}
2353 | edecl {}
2354 ;
2355
2356
2357 edecl : ID {
2358 temp_typeptr = new DataType(T_INT);
2359 create_constant($1, temp_typeptr, $1);
2360 delete temp_typeptr;
2361 }
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;
2368 }
2369 | cond_compile edecl { }
2370 | empty { }
2371 ;
2372
2373 etype : expr {
2374 $$ = $1;
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);
2381 FatalError();
2382 }
2383
2384 }
2385 | CHARCONST {
2386 $$.id = $1;
2387 $$.type = T_CHAR;
2388 }
2389 ;
2390
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.
2394 */
2395
2396 expr : NUM_INT {
2397 $$.id = $1;
2398 $$.type = T_INT;
2399 }
2400 | NUM_FLOAT {
2401 $$.id = $1;
2402 $$.type = T_DOUBLE;
2403 }
2404 | NUM_UNSIGNED {
2405 $$.id = $1;
2406 $$.type = T_UINT;
2407 }
2408 | NUM_LONG {
2409 $$.id = $1;
2410 $$.type = T_LONG;
2411 }
2412 | NUM_ULONG {
2413 $$.id = $1;
2414 $$.type = T_ULONG;
2415 }
2416 | SIZEOF LPAREN type RPAREN {
2417 $$.id = new char[strlen($3->name)+9];
2418 sprintf($$.id,"sizeof(%s)", $3->name);
2419 $$.type = T_INT;
2420 }
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);
2424 $$.type = $2->type;
2425 }
2426 | ID {
2427 $$.id = lookup_symvalue($1);
2428 if ($$.id == (char *) 0)
2429 $$.id = $1;
2430 else {
2431 $$.id = new char[strlen($$.id)+3];
2432 sprintf($$.id,"(%s)",lookup_symvalue($1));
2433 }
2434 temp_typeptr = lookup_symtype($1);
2435 if (temp_typeptr) $$.type = temp_typeptr->type;
2436 else $$.type = T_INT;
2437 }
2438 | ID DCOLON ID {
2439 $$.id = new char[strlen($1)+strlen($3)+3];
2440 sprintf($$.id,"%s::%s",$1,$3);
2441 $$.type = T_INT;
2442 delete $1;
2443 delete $3;
2444 }
2445 | expr PLUS expr {
2446 E_BINARY($$.id,$1.id,$3.id,"+");
2447 $$.type = promote($1.type,$3.type);
2448 delete $1.id;
2449 delete $3.id;
2450 }
2451 | expr MINUS expr {
2452 E_BINARY($$.id,$1.id,$3.id,"-");
2453 $$.type = promote($1.type,$3.type);
2454 delete $1.id;
2455 delete $3.id;
2456 }
2457 | expr STAR expr {
2458 E_BINARY($$.id,$1.id,$3.id,"*");
2459 $$.type = promote($1.type,$3.type);
2460 delete $1.id;
2461 delete $3.id;
2462
2463 }
2464 | expr SLASH expr {
2465 E_BINARY($$.id,$1.id,$3.id,"/");
2466 $$.type = promote($1.type,$3.type);
2467 delete $1.id;
2468 delete $3.id;
2469
2470 }
2471 | expr AND expr {
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);
2476 FatalError();
2477 }
2478 delete $1.id;
2479 delete $3.id;
2480
2481 }
2482 | expr OR expr {
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);
2487 FatalError();
2488 }
2489 $$.type = T_INT;
2490 delete $1.id;
2491 delete $3.id;
2492
2493 }
2494 | expr XOR expr {
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);
2499 FatalError();
2500 }
2501 $$.type = T_INT;
2502 delete $1.id;
2503 delete $3.id;
2504
2505 }
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);
2511 FatalError();
2512 }
2513 $$.type = T_INT;
2514 delete $1.id;
2515 delete $3.id;
2516
2517 }
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);
2523 FatalError();
2524 }
2525 $$.type = T_INT;
2526 delete $1.id;
2527 delete $3.id;
2528
2529 }
2530 | MINUS expr %prec UMINUS {
2531 $$.id = new char[strlen($2.id)+2];
2532 sprintf($$.id,"-%s",$2.id);
2533 $$.type = $2.type;
2534 delete $2.id;
2535
2536 }
2537 | NOT expr {
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);
2542 FatalError();
2543 }
2544 $$.type = $2.type;
2545 delete $2.id;
2546 }
2547 | LPAREN expr RPAREN {
2548 $$.id = new char[strlen($2.id)+3];
2549 sprintf($$.id,"(%s)", $2.id);
2550 $$.type = $2.type;
2551 delete $2.id;
2552 }
2553 ;
2554 /****************************************************************/
2555 /* C++ Support */
2556 /****************************************************************/
2557
2558 cpp : cpp_class { }
2559 | cpp_other {}
2560 ;
2561
2562 cpp_class :
2563
2564 /* A class/struct/union definition */
2565 extern cpptype ID inherit LBRACE {
2566 char *iname;
2567 if (allow) {
2568 init_language();
2569 DataType::new_scope();
2570
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);
2574 FatalError();
2575 }
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);
2578
2579 iname = make_name($3);
2580 doc_entry = new DocClass(iname, doc_parent());
2581 if (iname == $3)
2582 cplus_open_class($3, 0, $2);
2583 else
2584 cplus_open_class($3, iname, $2);
2585 if (strcmp($2,"class") == 0)
2586 cplus_mode = CPLUS_PRIVATE;
2587 else
2588 cplus_mode = CPLUS_PUBLIC;
2589 doc_stack_top++;
2590 doc_stack[doc_stack_top] = doc_entry;
2591 scanner_clear_start();
2592 nested_list = 0;
2593 // Merge in scope from base classes
2594 cplus_inherit_scope($4.count,$4.names);
2595 }
2596 } cpp_members RBRACE {
2597 if (allow) {
2598 if ($4.names) {
2599 if (strcmp($2,"union") != 0)
2600 cplus_inherit($4.count, $4.names);
2601 else {
2602 fprintf(stderr,"%s : Line %d. Inheritance not allowed for unions.\n",input_file, line_number);
2603 FatalError();
2604 }
2605 }
2606 // Clean up the inheritance list
2607 if ($4.names) {
2608 int j;
2609 for (j = 0; j < $4.count; j++) {
2610 if ($4.names[j]) delete [] $4.names[j];
2611 }
2612 delete [] $4.names;
2613 }
2614
2615 // Dumped nested declarations (if applicable)
2616 dump_nested($3);
2617
2618 // Save and collapse current scope
2619 cplus_register_scope(DataType::collapse_scope($3));
2620
2621 // Restore the original doc entry for this class
2622 doc_entry = doc_stack[doc_stack_top];
2623 cplus_class_close((char *) 0);
2624 doc_entry = 0;
2625 // Bump the documentation stack back down
2626 doc_stack_top--;
2627 cplus_mode = CPLUS_PUBLIC;
2628 }
2629 }
2630
2631 /* Class with a typedef */
2632
2633 | TYPEDEF cpptype ID inherit LBRACE {
2634 if (allow) {
2635 char *iname;
2636 init_language();
2637 DataType::new_scope();
2638
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);
2642 FatalError();
2643 }
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);
2646
2647 iname = make_name($3);
2648 doc_entry = new DocClass(iname, doc_parent());
2649 if ($3 == iname)
2650 cplus_open_class($3, 0, $2);
2651 else
2652 cplus_open_class($3, iname, $2);
2653 if (strcmp($2,"class") == 0)
2654 cplus_mode = CPLUS_PRIVATE;
2655 else
2656 cplus_mode = CPLUS_PUBLIC;
2657 // Create a documentation entry for the class
2658 doc_stack_top++;
2659 doc_stack[doc_stack_top] = doc_entry;
2660 scanner_clear_start();
2661 nested_list = 0;
2662
2663 // Merge in scope from base classes
2664 cplus_inherit_scope($4.count,$4.names);
2665
2666 }
2667 } cpp_members RBRACE declaration {
2668 if (allow) {
2669 if ($4.names) {
2670 if (strcmp($2,"union") != 0)
2671 cplus_inherit($4.count, $4.names);
2672 else {
2673 fprintf(stderr,"%s : Line %d. Inheritance not allowed for unions.\n",input_file, line_number);
2674 FatalError();
2675 }
2676 }
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;
2683
2684 // Clean up the inheritance list
2685 if ($4.names) {
2686 int j;
2687 for (j = 0; j < $4.count; j++) {
2688 if ($4.names[j]) delete [] $4.names[j];
2689 }
2690 delete [] $4.names;
2691 }
2692
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);
2695
2696 }
2697 // Create dump nested class code
2698 if ($9.is_pointer > 0) {
2699 dump_nested($3);
2700 } else {
2701 dump_nested($9.id);
2702 }
2703
2704 // Collapse any datatypes created in the the class
2705
2706 cplus_register_scope(DataType::collapse_scope($3));
2707
2708 doc_entry = doc_stack[doc_stack_top];
2709 if ($9.is_pointer > 0) {
2710 cplus_class_close($3);
2711 } else {
2712 cplus_class_close($9.id);
2713 }
2714 doc_stack_top--;
2715 doc_entry = 0;
2716
2717 // Create a typedef in global scope
2718
2719 if ($9.is_pointer == 0)
2720 Active_typedef->typedef_add($9.id);
2721 else {
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);
2726 delete t;
2727 }
2728 cplus_mode = CPLUS_PUBLIC;
2729 }
2730 } typedeflist { };
2731
2732 /* An unnamed struct with a typedef */
2733
2734 | TYPEDEF cpptype LBRACE {
2735 char *iname;
2736 if (allow) {
2737 init_language();
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);
2741
2742 iname = make_name("");
2743 doc_entry = new DocClass(iname,doc_parent());
2744 if (strlen(iname))
2745 cplus_open_class("", iname, $2);
2746 else
2747 cplus_open_class("",0,$2);
2748 if (strcmp($2,"class") == 0)
2749 cplus_mode = CPLUS_PRIVATE;
2750 else
2751 cplus_mode = CPLUS_PUBLIC;
2752 doc_stack_top++;
2753 doc_stack[doc_stack_top] = doc_entry;
2754 scanner_clear_start();
2755 nested_list = 0;
2756 }
2757 } cpp_members RBRACE declaration {
2758 if (allow) {
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);
2761 cplus_abort();
2762 } else {
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);
2766 FatalError();
2767 }
2768 }
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;
2775
2776 // Dump nested classes
2777 if ($7.is_pointer == 0)
2778 dump_nested($7.id);
2779
2780 // Go back to previous scope
2781
2782 cplus_register_scope(DataType::collapse_scope((char *) 0));
2783
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);
2789 doc_entry = 0;
2790 doc_stack_top--;
2791 cplus_mode = CPLUS_PUBLIC;
2792 }
2793 } typedeflist { }
2794 ;
2795
2796 cpp_other :/* A dummy class name */
2797
2798 extern cpptype ID SEMI {
2799 char *iname;
2800 if (allow) {
2801 init_language();
2802 iname = make_name($3);
2803 lang->cpp_class_decl($3,iname,$2);
2804 }
2805 }
2806
2807 /* A static C++ member function (declared out of scope) */
2808
2809 | extern type declaration DCOLON ID LPAREN parms RPAREN SEMI {
2810 if (allow) {
2811 init_language();
2812 if (!CPlusPlus)
2813 fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
2814
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);
2819 if (!Rename_true) {
2820 Rename_true = 1;
2821 sprintf(yy_rename,"%s_%s",$3.id,$5);
2822 }
2823 create_function($1, temp_name, $2, $7);
2824 }
2825 delete $2;
2826 delete $7;
2827 }
2828
2829 /* A static C++ member data */
2830 | extern type declaration DCOLON ID SEMI {
2831 if (allow) {
2832 init_language();
2833 if (!CPlusPlus)
2834 fprintf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
2835
2836 $2->is_pointer += $3.is_pointer;
2837 // Fix up the function name
2838 sprintf(temp_name,"%s::%s",$3.id,$5);
2839 if (!Rename_true) {
2840 Rename_true = 1;
2841 sprintf(yy_rename,"%s_%s",$3.id,$5);
2842 }
2843 create_variable($1,temp_name, $2);
2844 }
2845 delete $2;
2846 }
2847
2848 /* Operator overloading catch */
2849
2850 | extern type declaration DCOLON OPERATOR {
2851 fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
2852 skip_decl();
2853 delete $2;
2854 }
2855
2856
2857 /* Template catch */
2858 | TEMPLATE {
2859 fprintf(stderr,"%s : Line %d. Templates not currently supported (ignored).\n",
2860 input_file, line_number);
2861 skip_decl();
2862 }
2863
2864 /* %addmethods directive used outside of a class definition */
2865
2866 | ADDMETHODS ID LBRACE {
2867 cplus_mode = CPLUS_PUBLIC;
2868 doc_entry = cplus_set_class($2);
2869 if (!doc_entry) {
2870 doc_entry = new DocClass($2,doc_parent());
2871 };
2872 doc_stack_top++;
2873 doc_stack[doc_stack_top] = doc_entry;
2874 scanner_clear_start();
2875 AddMethods = 1;
2876 } added_members RBRACE {
2877 cplus_unset_class();
2878 doc_entry = 0;
2879 doc_stack_top--;
2880 AddMethods = 0;
2881 }
2882 ;
2883
2884 added_members : cpp_member cpp_members { }
2885 | objc_method objc_methods { }
2886 | empty { }
2887 ;
2888
2889 cpp_members : cpp_member cpp_members {}
2890 | ADDMETHODS LBRACE {
2891 AddMethods = 1;
2892 } cpp_members RBRACE {
2893 AddMethods = 0;
2894 } cpp_members { }
2895 | error {
2896 skip_decl();
2897 {
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);
2901 FatalError();
2902 last_error_line = line_number;
2903 }
2904 }
2905 } cpp_members { }
2906 | empty { }
2907 ;
2908
2909 cpp_member : type declaration LPAREN parms RPAREN cpp_end {
2910 char *iname;
2911 if (allow) {
2912 init_language();
2913 if (cplus_mode == CPLUS_PUBLIC) {
2914 Stat_func++;
2915 $1->is_pointer += $2.is_pointer;
2916 $1->is_reference = $2.is_reference;
2917 if (Verbose) {
2918 fprintf(stderr,"Wrapping member function : %s\n",$2.id);
2919 }
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);
2924 }
2925 scanner_clear_start();
2926 }
2927 delete $1;
2928 delete $4;
2929 }
2930
2931 /* Virtual member function */
2932
2933 | VIRTUAL type declaration LPAREN parms RPAREN cpp_vend {
2934 char *iname;
2935 if (allow) {
2936 init_language();
2937 if (cplus_mode == CPLUS_PUBLIC) {
2938 Stat_func++;
2939 $2->is_pointer += $3.is_pointer;
2940 $2->is_reference = $3.is_reference;
2941 if (Verbose) {
2942 fprintf(stderr,"Wrapping virtual member function : %s\n",$3.id);
2943 }
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);
2948 }
2949 scanner_clear_start();
2950 }
2951 delete $2;
2952 delete $5;
2953 }
2954
2955 /* Possibly a constructor */
2956 | ID LPAREN parms RPAREN ctor_end {
2957 char *iname;
2958 if (allow) {
2959 init_language();
2960 if (cplus_mode == CPLUS_PUBLIC) {
2961 Stat_func++;
2962 if (Verbose) {
2963 fprintf(stderr,"Wrapping C++ constructor %s\n", $1);
2964 }
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);
2969 }
2970 scanner_clear_start();
2971 }
2972 delete $3;
2973 }
2974
2975 /* A destructor (hopefully) */
2976
2977 | NOT ID LPAREN parms RPAREN cpp_end {
2978 char *iname;
2979 if (allow) {
2980 init_language();
2981 if (cplus_mode == CPLUS_PUBLIC) {
2982 Stat_func++;
2983 if (Verbose) {
2984 fprintf(stderr,"Wrapping C++ destructor %s\n", $2);
2985 }
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);
2990 }
2991 }
2992 scanner_clear_start();
2993 }
2994
2995 /* A virtual destructor */
2996
2997 | VIRTUAL NOT ID LPAREN RPAREN cpp_end {
2998 char *iname;
2999 if (allow) {
3000 init_language();
3001 if (cplus_mode == CPLUS_PUBLIC) {
3002 Stat_func++;
3003 if (Verbose) {
3004 fprintf(stderr,"Wrapping C++ destructor %s\n", $3);
3005 }
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);
3010 }
3011 }
3012 scanner_clear_start();
3013 }
3014
3015 /* Member data */
3016
3017 | type declaration def_args {
3018 if (allow) {
3019 char *iname;
3020 init_language();
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);
3034 }
3035 } else {
3036 int oldstatus = Status;
3037 char *tm;
3038 if ($1->status & STAT_READONLY) {
3039 if (!(tm = typemap_lookup("memberin",typemap_lang,$1,$2.id,"","")))
3040 Status = Status | STAT_READONLY;
3041 }
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);
3046 Status = oldstatus;
3047 }
3048 } else {
3049 char *tm = 0;
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;
3054 }
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);
3059 Status = oldstatus;
3060 if (Verbose) {
3061 fprintf(stderr,"Wrapping member data %s\n", $2.id);
3062 }
3063 }
3064 }
3065 scanner_clear_start();
3066 }
3067 delete $1;
3068 } cpp_tail { }
3069
3070 | type declaration array def_args {
3071 char *iname;
3072 if (allow) {
3073 int oldstatus = Status;
3074 char *tm = 0;
3075 init_language();
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;
3084
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);
3089 Status = oldstatus;
3090 if (!tm)
3091 fprintf(stderr,"%s : Line %d. Warning. Array member will be read-only.\n",input_file,line_number);
3092 }
3093 scanner_clear_start();
3094 }
3095 delete $1;
3096 }
3097
3098
3099 /* Static Member data */
3100
3101 | STATIC type declaration {
3102 char *iname;
3103 if (allow) {
3104 init_language();
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);
3113 if (Verbose) {
3114 fprintf(stderr,"Wrapping static member data %s\n", $3.id);
3115 }
3116 }
3117 scanner_clear_start();
3118 }
3119 delete $2;
3120 } cpp_tail { }
3121
3122 /* Static member function */
3123
3124 | STATIC type declaration LPAREN parms RPAREN cpp_end {
3125 char *iname;
3126 if (allow) {
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);
3134 if (Verbose)
3135 fprintf(stderr,"Wrapping static member function %s\n",$3.id);
3136 }
3137 scanner_clear_start();
3138 }
3139 delete $2;
3140 delete $5;
3141 }
3142 /* Turn on public: mode */
3143
3144 | PUBLIC COLON {
3145 if (allow) {
3146 cplus_mode = CPLUS_PUBLIC;
3147 if (Verbose)
3148 fprintf(stderr,"Public mode\n");
3149 scanner_clear_start();
3150 }
3151 }
3152
3153 /* Turn on private: mode */
3154
3155 | PRIVATE COLON {
3156 if (allow) {
3157 cplus_mode = CPLUS_PRIVATE;
3158 if (Verbose)
3159 fprintf(stderr,"Private mode\n");
3160 scanner_clear_start();
3161 }
3162 }
3163
3164 /* Turn on protected mode */
3165
3166 | PROTECTED COLON {
3167 if (allow) {
3168 cplus_mode = CPLUS_PROTECTED;
3169 if (Verbose)
3170 fprintf(stderr,"Protected mode\n");
3171 scanner_clear_start();
3172 }
3173 }
3174
3175 /* This is the new style rename */
3176
3177 | NAME LPAREN ID RPAREN {
3178 if (allow) {
3179 strcpy(yy_rename,$3);
3180 Rename_true = 1;
3181 }
3182 }
3183
3184 /* New mode */
3185 | NEW {
3186 NewObject = 1;
3187 } cpp_member {
3188 NewObject = 0;
3189 }
3190
3191 /* C++ Enum */
3192 | ENUM ename LBRACE {scanner_clear_start();} cpp_enumlist RBRACE SEMI {
3193
3194 // if ename was supplied. Install it as a new integer datatype.
3195
3196 if (allow) {
3197 init_language();
3198 if (cplus_mode == CPLUS_PUBLIC) {
3199 if ($2) {
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);
3206 }
3207 }
3208 }
3209 }
3210 | READONLY {
3211 if (allow)
3212 Status = Status | STAT_READONLY;
3213 scanner_clear_start();
3214 }
3215 | READWRITE {
3216 if (allow)
3217 Status = Status & ~(STAT_READONLY);
3218 scanner_clear_start();
3219 }
3220 /* A friend : Illegal */
3221 | FRIEND {
3222 if (allow)
3223 fprintf(stderr,"%s : Line %d. Friends are not allowed--members only! (ignored)\n", input_file, line_number);
3224 skip_decl();
3225 scanner_clear_start();
3226 }
3227
3228 /* An operator: Illegal */
3229 | type type_extra OPERATOR {
3230 if (allow)
3231 fprintf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
3232 skip_decl();
3233 scanner_clear_start();
3234 }
3235 | cond_compile {
3236 scanner_clear_start();
3237 }
3238
3239 /* A typedef inside a class */
3240 | typedef_decl { }
3241
3242 /* Pragma directive */
3243
3244 | cpp_pragma {
3245 scanner_clear_start();
3246 }
3247
3248
3249 cpp_pragma : PRAGMA ID stylearg {
3250 if (allow && (!WrapExtern)) { }
3251 }
3252 | PRAGMA LPAREN ID RPAREN ID stylearg {
3253 if (allow && (!WrapExtern))
3254 cplus_add_pragma($3,$5,$6);
3255 }
3256 ;
3257
3258
3259
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
3265 code later. Yikes!
3266
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 ---------------------------------------------------------------------- */
3272
3273 /* A struct sname { } id; declaration */
3274
3275 | cpptype ID LBRACE { start_line = line_number; skip_brace();
3276 } nested_decl SEMI {
3277
3278 if (cplus_mode == CPLUS_PUBLIC) {
3279 cplus_register_type($2);
3280 if ($5.id) {
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 */
3284 } else {
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;
3294 n->next = 0;
3295 add_nested(n);
3296 }
3297 }
3298 }
3299 }
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 */
3307 } else {
3308 /* Generate some code for a new class */
3309
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;
3319 n->next = 0;
3320 add_nested(n);
3321
3322 }
3323 }
3324 }
3325 /* An empty class declaration */
3326 | cpptype ID SEMI {
3327 if (cplus_mode == CPLUS_PUBLIC) {
3328 cplus_register_type($2);
3329 }
3330 }
3331
3332 /* Other miscellaneous errors */
3333 | type stars LPAREN {
3334 skip_decl();
3335 fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
3336
3337 }
3338 | strict_type LPAREN STAR {
3339 skip_decl();
3340 fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
3341
3342 }
3343 | ID LPAREN STAR {
3344 skip_decl();
3345 fprintf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
3346
3347 }
3348 | doc_enable { }
3349 | SEMI { }
3350 ;
3351
3352 nested_decl : declaration { $$ = $1;}
3353 | empty { $$.id = 0; }
3354 ;
3355
3356 type_extra : stars {}
3357 | AND {}
3358 | empty {}
3359 ;
3360
3361 cpp_tail : SEMI { }
3362 | COMMA declaration def_args {
3363 if (allow) {
3364 int oldstatus = Status;
3365 char *tm;
3366
3367 init_language();
3368 if (cplus_mode == CPLUS_PUBLIC) {
3369 temp_typeptr = new DataType(Active_type);
3370 temp_typeptr->is_pointer += $2.is_pointer;
3371 if (Verbose) {
3372 fprintf(stderr,"Wrapping member variable : %s\n",$2.id);
3373 }
3374 Stat_var++;
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;
3379 }
3380 cplus_variable($2.id,(char *) 0,temp_typeptr);
3381 Status = oldstatus;
3382 delete temp_typeptr;
3383 }
3384 scanner_clear_start();
3385 }
3386 } cpp_tail { }
3387 | COMMA declaration array def_args {
3388 if (allow) {
3389 int oldstatus = Status;
3390 char *tm;
3391
3392 init_language();
3393 if (cplus_mode == CPLUS_PUBLIC) {
3394 temp_typeptr = new DataType(Active_type);
3395 temp_typeptr->is_pointer += $2.is_pointer;
3396 if (Verbose) {
3397 fprintf(stderr,"Wrapping member variable : %s\n",$2.id);
3398 }
3399 Stat_var++;
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);
3405 Status = oldstatus;
3406 if (!tm)
3407 fprintf(stderr,"%s : Line %d. Warning. Array member will be read-only.\n",input_file,line_number);
3408 delete temp_typeptr;
3409 }
3410 scanner_clear_start();
3411 }
3412 } cpp_tail { }
3413 ;
3414
3415 cpp_end : cpp_const SEMI {
3416 CCode = "";
3417 }
3418 | cpp_const LBRACE { skip_brace(); }
3419 ;
3420
3421 cpp_vend : cpp_const SEMI { CCode = ""; }
3422 | cpp_const EQUAL definetype SEMI { CCode = ""; }
3423 | cpp_const LBRACE { skip_brace(); }
3424 ;
3425
3426 cpp_enumlist : cpp_enumlist COMMA cpp_edecl {}
3427 | cpp_edecl {}
3428 ;
3429
3430 cpp_edecl : ID {
3431 if (allow) {
3432 if (cplus_mode == CPLUS_PUBLIC) {
3433 if (Verbose) {
3434 fprintf(stderr,"Creating enum value %s\n", $1);
3435 }
3436 Stat_const++;
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();
3442 }
3443 }
3444 }
3445 | ID EQUAL etype {
3446 if (allow) {
3447 if (cplus_mode == CPLUS_PUBLIC) {
3448 if (Verbose) {
3449 fprintf(stderr, "Creating enum value %s = %s\n", $1, $3.id);
3450 }
3451 Stat_const++;
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();
3458 }
3459 }
3460 }
3461 | NAME LPAREN ID RPAREN ID {
3462 if (allow) {
3463 if (cplus_mode == CPLUS_PUBLIC) {
3464 if (Verbose) {
3465 fprintf(stderr,"Creating enum value %s\n", $5);
3466 }
3467 Stat_const++;
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();
3473 }
3474 }
3475 }
3476 | NAME LPAREN ID RPAREN ID EQUAL etype {
3477 if (allow) {
3478 if (cplus_mode == CPLUS_PUBLIC) {
3479 if (Verbose) {
3480 fprintf(stderr, "Creating enum value %s = %s\n", $5, $7.id);
3481 }
3482 Stat_const++;
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();
3489 }
3490 }
3491 }
3492 | cond_compile cpp_edecl { }
3493 | empty { }
3494 ;
3495
3496 inherit : COLON base_list {
3497 $$ = $2;
3498 }
3499 | empty {
3500 $$.names = (char **) 0;
3501 $$.count = 0;
3502 }
3503 ;
3504
3505 base_list : base_specifier {
3506 int i;
3507 $$.names = new char *[NI_NAMES];
3508 $$.count = 0;
3509 for (i = 0; i < NI_NAMES; i++){
3510 $$.names[i] = (char *) 0;
3511 }
3512 if ($1) {
3513 $$.names[$$.count] = copy_string($1);
3514 $$.count++;
3515 }
3516 }
3517
3518 | base_list COMMA base_specifier {
3519 $$ = $1;
3520 if ($3) {
3521 $$.names[$$.count] = copy_string($3);
3522 $$.count++;
3523 }
3524 }
3525 ;
3526
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);
3530 $$ = (char *) 0;
3531 }
3532 | VIRTUAL ID {
3533 fprintf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
3534 input_file,line_number,$2);
3535 $$ = (char *) 0;
3536 }
3537 | VIRTUAL access_specifier ID {
3538 if (strcmp($2,"public") == 0) {
3539 $$ = $3;
3540 } else {
3541 fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
3542 input_file,line_number,$2);
3543 $$ = (char *) 0;
3544 }
3545 }
3546 | access_specifier ID {
3547 if (strcmp($1,"public") == 0) {
3548 $$ = $2;
3549 } else {
3550 fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
3551 input_file,line_number,$1);
3552 $$ = (char *) 0;
3553 }
3554 }
3555 | access_specifier VIRTUAL ID {
3556 if (strcmp($1,"public") == 0) {
3557 $$ = $3;
3558 } else {
3559 fprintf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
3560 input_file,line_number,$1);
3561 $$ = (char *) 0;
3562 }
3563 }
3564 ;
3565
3566 access_specifier : PUBLIC { $$ = "public"; }
3567 | PRIVATE { $$ = "private"; }
3568 | PROTECTED { $$ = "protected"; }
3569 ;
3570
3571
3572 cpptype : CLASS { $$ = "class"; }
3573 | STRUCT { $$ = "struct"; }
3574 | UNION {$$ = "union"; }
3575 ;
3576
3577 cpp_const : CONST {}
3578 | THROW LPAREN parms RPAREN { delete $3;}
3579 | empty {}
3580 ;
3581
3582 /* Constructor initializer */
3583
3584 ctor_end : cpp_const ctor_initializer SEMI {
3585 CCode = "";
3586 }
3587 | cpp_const ctor_initializer LBRACE { skip_brace(); }
3588 ;
3589
3590 ctor_initializer : COLON mem_initializer_list {}
3591 | empty {}
3592 ;
3593
3594 mem_initializer_list : mem_initializer { }
3595 | mem_initializer_list COMMA mem_initializer { }
3596 ;
3597
3598 mem_initializer : ID LPAREN expr_list RPAREN { }
3599 | ID LPAREN RPAREN { }
3600 ;
3601
3602 expr_list : expr { }
3603 | expr_list COMMA expr { }
3604 ;
3605
3606
3607 /**************************************************************/
3608 /* Objective-C parsing */
3609 /**************************************************************/
3610
3611 objective_c : OC_INTERFACE ID objc_inherit {
3612 ObjCClass = 1;
3613 init_language();
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);
3619 FatalError();
3620 }
3621 // Create a new documentation entry
3622 doc_entry = new DocClass($2,doc_parent());
3623 doc_stack_top++;
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 {
3628 if ($3) {
3629 char *inames[1];
3630 inames[0] = $3;
3631 cplus_inherit(1,inames);
3632 }
3633 // Restore original doc entry for this class
3634 doc_entry = doc_stack[doc_stack_top];
3635 cplus_class_close($2);
3636 doc_entry = 0;
3637 doc_stack_top--;
3638 cplus_mode = CPLUS_PUBLIC;
3639 ObjCClass = 0;
3640 delete $2;
3641 delete $3;
3642 }
3643 /* An obj-c category declaration */
3644 | OC_INTERFACE ID LPAREN ID RPAREN objc_protolist {
3645 ObjCClass = 1;
3646 init_language();
3647 cplus_mode = CPLUS_PROTECTED;
3648 doc_entry = cplus_set_class($2);
3649 if (!doc_entry) {
3650 doc_entry = new DocClass($2,doc_parent());
3651 }
3652 doc_stack_top++;
3653 doc_stack[doc_stack_top] = doc_entry;
3654 scanner_clear_start();
3655 } objc_methods OC_END {
3656 cplus_unset_class();
3657 doc_entry = 0;
3658 doc_stack_top--;
3659 }
3660 | OC_IMPLEMENT { skip_to_end(); }
3661 | OC_PROTOCOL { skip_to_end(); }
3662 | OC_CLASS ID initlist SEMI {
3663 char *iname = make_name($2);
3664 init_language();
3665 lang->cpp_class_decl($2,iname,"");
3666 for (int i = 0; i <$3.count; i++) {
3667 if ($3.names[i]) {
3668 iname = make_name($3.names[i]);
3669 lang->cpp_class_decl($3.names[i],iname,"");
3670 delete [] $3.names[i];
3671 }
3672 }
3673 delete [] $3.names;
3674 }
3675 ;
3676
3677 objc_inherit : COLON ID objc_protolist { $$ = $2;}
3678 | objc_protolist empty { $$ = 0; }
3679 ;
3680
3681
3682 objc_protolist : LESSTHAN { skip_template();
3683 CCode.strip(); // Strip whitespace
3684 CCode.replace("<","< ");
3685 CCode.replace(">"," >");
3686 $$ = CCode.get();
3687 }
3688 | empty {
3689 $$ = "";
3690 }
3691 ;
3692
3693 objc_data : objc_vars objc_data { }
3694 | OC_PUBLIC {
3695 cplus_mode = CPLUS_PUBLIC;
3696 } objc_data { }
3697 | OC_PRIVATE {
3698 cplus_mode = CPLUS_PRIVATE;
3699 } objc_data { }
3700 | OC_PROTECTED {
3701 cplus_mode = CPLUS_PROTECTED;
3702 } objc_data { }
3703 | error {
3704 if (!Error) {
3705 skip_decl();
3706 {
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);
3710 FatalError();
3711 last_error_line = line_number;
3712 }
3713 Error = 1;
3714 }
3715 }
3716 } objc_data { }
3717 | empty { }
3718 ;
3719
3720 objc_vars : objc_var objc_vartail SEMI {
3721
3722 }
3723 ;
3724
3725 /* An objective-C member variable */
3726
3727 objc_var : type declaration {
3728 if (cplus_mode == CPLUS_PUBLIC) {
3729 int oldstatus = Status;
3730 char *tm;
3731 char *iname;
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;
3739 }
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);
3744 Status = oldstatus;
3745 }
3746 scanner_clear_start();
3747 delete $1;
3748 }
3749 | type declaration array {
3750 if (cplus_mode == CPLUS_PUBLIC) {
3751 int oldstatus = Status;
3752 char *tm, *iname;
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;
3761 }
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);
3766 Status = oldstatus;
3767 }
3768 scanner_clear_start();
3769 delete $1;
3770 }
3771 | NAME LPAREN ID RPAREN {
3772 strcpy(yy_rename,$3);
3773 Rename_true = 1;
3774 } objc_var { };
3775
3776 objc_vartail : COMMA declaration objc_vartail {
3777 if (cplus_mode == CPLUS_PUBLIC) {
3778 int oldstatus = Status;
3779 char *tm, *iname;
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;
3786 }
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);
3791 Status = oldstatus;
3792 delete t;
3793 }
3794 scanner_clear_start();
3795 }
3796 | COMMA declaration array objc_vartail {
3797 char *iname;
3798 if (cplus_mode == CPLUS_PUBLIC) {
3799 int oldstatus = Status;
3800 char *tm;
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;
3808 }
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);
3813 Status = oldstatus;
3814 delete t;
3815 }
3816 scanner_clear_start();
3817 }
3818 | empty { }
3819 ;
3820
3821 objc_methods : objc_method objc_methods { };
3822 | ADDMETHODS LBRACE {
3823 AddMethods = 1;
3824 } objc_methods RBRACE {
3825 AddMethods = 0;
3826 }
3827 | NAME LPAREN ID RPAREN {
3828 strcpy(yy_rename,$3);
3829 Rename_true = 1;
3830 } objc_methods { }
3831 | error {
3832 skip_decl();
3833 if (!Error) {
3834 {
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);
3838 FatalError();
3839 last_error_line = line_number;
3840 }
3841 Error = 1;
3842 }
3843 }
3844 } objc_methods { }
3845 | empty { }
3846 ;
3847
3848 objc_method : MINUS objc_ret_type ID objc_args objc_end {
3849 char *iname;
3850 // An objective-C instance function
3851 // This is like a C++ member function
3852
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);
3857 } else {
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();
3863 delete $2;
3864 delete $3;
3865 delete $4;
3866 }
3867 }
3868 | PLUS objc_ret_type ID objc_args objc_end {
3869 char *iname;
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);
3876 } else {
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);
3881 }
3882 scanner_clear_start();
3883 delete $2;
3884 delete $3;
3885 delete $4;
3886 }
3887 ;
3888
3889 objc_end : SEMI { CCode = ""; }
3890 | LBRACE { skip_brace(); }
3891 ;
3892
3893 objc_ret_type : LPAREN type RPAREN {
3894 $$ = $2;
3895 }
3896 | LPAREN type stars RPAREN {
3897 $$ = $2;
3898 $$->is_pointer += $3;
3899 }
3900 | empty { /* Empty type means "id" type */
3901 $$ = new DataType(T_VOID);
3902 sprintf($$->name,"id");
3903 $$->is_pointer = 1;
3904 $$->implicit_ptr = 1;
3905 }
3906 ;
3907
3908 objc_arg_type : LPAREN parm RPAREN {
3909 $$ = new DataType($2->t);
3910 delete $2;
3911 }
3912 | empty {
3913 $$ = new DataType(T_VOID);
3914 sprintf($$->name,"id");
3915 $$->is_pointer = 1;
3916 $$->implicit_ptr = 1;
3917 }
3918 ;
3919
3920 objc_args : objc_args objc_separator objc_arg_type ID {
3921 Parm *p= new Parm($3,$4);
3922 p->objc_separator = $2;
3923 $$ = $1;
3924 $$->append(p);
3925 }
3926 | empty {
3927 $$ = new ParmList;
3928 }
3929 ;
3930
3931 objc_separator : COLON { $$ = copy_string(":"); }
3932 | ID COLON { $$ = new char[strlen($1)+2];
3933 strcpy($$,$1);
3934 strcat($$,":");
3935 delete $1;
3936 }
3937 ;
3938
3939 /* Miscellaneous stuff */
3940
3941 /* Documentation style list */
3942
3943 stylelist : ID stylearg styletail {
3944 $$ = $3;
3945 $$.names[$$.count] = copy_string($1);
3946 $$.values[$$.count] = copy_string($2);
3947 format_string($$.values[$$.count]);
3948 $$.count++;
3949 }
3950 ;
3951
3952
3953 styletail : styletail COMMA ID stylearg {
3954 $$ = $1;
3955 $$.names[$$.count] = copy_string($3);
3956 $$.values[$$.count] = copy_string($4);
3957 format_string($$.values[$$.count]);
3958 $$.count++;
3959 }
3960 | empty {
3961 $$.names = new char *[NI_NAMES];
3962 $$.values = new char *[NI_NAMES];
3963 $$.count = 0;
3964 }
3965 ;
3966
3967 stylearg : EQUAL NUM_INT {
3968 $$ = $2;
3969 }
3970 | EQUAL STRING {
3971 $$ = $2;
3972 }
3973 | empty {
3974 $$ = 0;
3975 }
3976 ;
3977
3978
3979 /* --------------------------------------------------------------
3980 * Type-map parameters
3981 * -------------------------------------------------------------- */
3982
3983 tm_method : ID {
3984 $$ = $1;
3985 }
3986 | CONST {
3987 $$ = copy_string("const");
3988 }
3989 ;
3990
3991 tm_list : typemap_parm tm_tail {
3992 $$ = $1;
3993 $$->next = $2;
3994 }
3995 ;
3996
3997 tm_tail : COMMA typemap_parm tm_tail {
3998 $$ = $2;
3999 $$->next = $3;
4000 }
4001 | empty { $$ = 0;}
4002 ;
4003
4004 typemap_parm : type typemap_name {
4005 if (InArray) {
4006 $1->is_pointer++;
4007 $1->arraystr = copy_string(ArrayString);
4008 }
4009 $$ = new TMParm;
4010 $$->p = new Parm($1,$2);
4011 $$->p->call_type = 0;
4012 $$->args = tm_parm;
4013 delete $1;
4014 delete $2;
4015 }
4016
4017 | type stars typemap_name {
4018 $$ = new TMParm;
4019 $$->p = new Parm($1,$3);
4020 $$->p->t->is_pointer += $2;
4021 $$->p->call_type = 0;
4022 if (InArray) {
4023 $$->p->t->is_pointer++;
4024 $$->p->t->arraystr = copy_string(ArrayString);
4025 }
4026 $$->args = tm_parm;
4027 delete $1;
4028 delete $3;
4029 }
4030
4031 | type AND typemap_name {
4032 $$ = new TMParm;
4033 $$->p = new Parm($1,$3);
4034 $$->p->t->is_reference = 1;
4035 $$->p->call_type = 0;
4036 $$->p->t->is_pointer++;
4037 if (!CPlusPlus) {
4038 fprintf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number);
4039 }
4040 $$->args = tm_parm;
4041 delete $1;
4042 delete $3;
4043 }
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);
4046 FatalError();
4047 $$ = new TMParm;
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>");
4052 $$->args = tm_parm;
4053 delete $1;
4054 delete $4;
4055 delete $7;
4056 }
4057 ;
4058
4059 typemap_name : ID typemap_args {
4060 $$ = $1;
4061 InArray = 0;
4062 }
4063 | ID array {
4064 ArrayBackup = "";
4065 ArrayBackup << ArrayString;
4066 } typemap_args {
4067 $$ = $1;
4068 InArray = $2;
4069 ArrayString = "";
4070 ArrayString << ArrayBackup;
4071 }
4072 | array {
4073 ArrayBackup = "";
4074 ArrayBackup << ArrayString;
4075 } typemap_args {
4076 $$ = new char[1];
4077 $$[0] = 0;
4078 InArray = $1;
4079 ArrayString = "";
4080 ArrayString << ArrayBackup;
4081 }
4082 | typemap_args { $$ = new char[1];
4083 $$[0] = 0;
4084 InArray = 0;
4085 }
4086 ;
4087
4088 typemap_args : LPAREN parms RPAREN {
4089 tm_parm = $2;
4090 }
4091 | empty {
4092 tm_parm = 0;
4093 }
4094 ;
4095
4096 idstring : ID {$$ = $1;}
4097 | STRING { $$ = $1;}
4098 ;
4099
4100
4101 /* User defined directive */
4102
4103 user_directive : USERDIRECTIVE LPAREN parms RPAREN uservalue { }
4104 | USERDIRECTIVE uservalue { }
4105 ;
4106
4107 uservalue : ID SEMI { }
4108 | STRING SEMI { }
4109 | LBRACE RBRACE { }
4110 ;
4111
4112
4113
4114 /* Parsing of expressions, but only for throw away code */
4115
4116 /* Might need someday
4117 dummyexpr : NUM_INT { }
4118 | NUM_FLOAT { }
4119 | NUM_UNSIGNED { }
4120 | NUM_LONG { }
4121 | NUM_ULONG { }
4122 | SIZEOF LPAREN type RPAREN { }
4123 | ID { }
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 { }
4134 | NOT dummyexpr { }
4135 | LPAREN dummyexpr RPAREN { }
4136 ;
4137
4138 */
4139
4140
4141 empty : ;
4142
4143 %%
4144
4145 void error_recover() {
4146 int c;
4147 c = yylex();
4148 while ((c > 0) && (c != SEMI))
4149 c = yylex();
4150 }
4151
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);
4155 // error_recover();
4156 }
4157