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