diff GEMBASSY-1.0.3/gsoap/src/soapcpp2_yacc.y @ 2:8947fca5f715 draft default tip

Uploaded
author ktnyt
date Fri, 26 Jun 2015 05:21:44 -0400
parents 84a17b3fad1f
children
line wrap: on
line diff
--- a/GEMBASSY-1.0.3/gsoap/src/soapcpp2_yacc.y	Fri Jun 26 05:20:29 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1927 +0,0 @@
-/*
-	soapcpp2_yacc.y
-
-	Yacc/Bison grammar.
-
-	Build notes:
-
-	1. Bison 1.6 is known to crash on Win32 systems if YYINITDEPTH is too
-	small Compile with -DYYINITDEPTH=5000
-
-	2. This grammar has one shift/reduce conflict related to the use of a
-	class declaration with a base class (e.g. class Y : public X) and the
-	use of a maxOccurs (class Y :10). Internally the conflict is resolved
-	in favor of a shift by Bison/Yacc, which leads to the correct parsing
-	behavior. Therefore, the warning can be ignored. If this leads to an
-	error, then please enable the following directive (around line 121):
-
-%expect 1 // Bison: ignore one shift/reduce conflict
-
---------------------------------------------------------------------------------
-gSOAP XML Web services tools
-Copyright (C) 2000-2011, Robert van Engelen, Genivia Inc. All Rights Reserved.
-This part of the software is released under ONE of the following licenses:
-GPL or Genivia's license for commercial use.
---------------------------------------------------------------------------------
-GPL license.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; either version 2 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-Author contact information:
-engelen@genivia.com / engelen@acm.org
-
-This program is released under the GPL with the additional exemption that
-compiling, linking, and/or using OpenSSL is allowed.
---------------------------------------------------------------------------------
-A commercial use license is available from Genivia, Inc., contact@genivia.com
---------------------------------------------------------------------------------
-*/
-
-%{
-
-#include "soapcpp2.h"
-
-#ifdef WIN32
-#ifndef __STDC__
-#define __STDC__
-#endif
-#define YYINCLUDED_STDLIB_H
-#ifdef WIN32_WITHOUT_SOLARIS_FLEX
-extern int soapcpp2lex(void);
-#else
-extern int yylex(void);
-#endif
-#else
-extern int yylex(void);
-#endif
-
-extern int is_XML(Tnode*);
-
-#define MAXNEST 16	/* max. nesting depth of scopes */
-
-struct Scope
-{	Table	*table;
-	Entry	*entry;
-	Node	node;
-	LONG64	val;
-	int	offset;
-	Bool	grow;	/* true if offset grows with declarations */
-	Bool	mask;	/* true if enum is mask */
-}	stack[MAXNEST],	/* stack of tables and offsets */
-	*sp;		/* current scope stack pointer */
-
-Table	*classtable = (Table*)0,
-	*enumtable = (Table*)0,
-	*typetable = (Table*)0,
-	*booltable = (Table*)0,
-	*templatetable = (Table*)0;
-
-char	*namespaceid = NULL;
-int	transient = 0;
-int	permission = 0;
-int	custom_header = 1;
-int	custom_fault = 1;
-Pragma	*pragmas = NULL;
-Tnode	*qname = NULL;
-Tnode	*xml = NULL;
-
-/* function prototypes for support routine section */
-static Entry	*undefined(Symbol*);
-static Tnode	*mgtype(Tnode*, Tnode*);
-static Node	op(const char*, Node, Node), iop(const char*, Node, Node), relop(const char*, Node, Node);
-static void	mkscope(Table*, int), enterscope(Table*, int), exitscope(void);
-static int	integer(Tnode*), real(Tnode*), numeric(Tnode*);
-static void	add_soap(void), add_XML(void), add_qname(void), add_header(Table*), add_fault(Table*), add_response(Entry*, Entry*), add_result(Tnode*);
-extern char	*c_storage(Storage), *c_type(Tnode*), *c_ident(Tnode*);
-extern int	is_primitive_or_string(Tnode*), is_stdstr(Tnode*), is_binary(Tnode*), is_external(Tnode*), is_mutable(Tnode*), has_attachment(Tnode*);
-
-/* Temporaries used in semantic rules */
-int	i;
-char	*s, *s1, *s2;
-Symbol	*sym;
-Entry	*p, *q;
-Tnode	*t;
-Node	tmp, c;
-Pragma	**pp;
-
-%}
-
-/* We expect one shift-reduce conflict, see build notes in the header above */
-/* %expect 1 */ /* directive is not compatible with Yacc */
-/* If Yacc complains then remove the line above to allow Yacc to proceed */
-
-%union
-{	Symbol	*sym;
-	LONG64	i;
-	double	r;
-	char	c;
-	char	*s;
-	Tnode	*typ;
-	Storage	sto;
-	Node	rec;
-	Entry	*e;
-}
-
-/* pragmas */
-%token	<s> PRAGMA
-/* keywords */
-%token	<sym> AUTO     DOUBLE  INT       STRUCT
-%token	<sym> BREAK    ELSE    LONG      SWITCH
-%token	<sym> CASE     ENUM    REGISTER  TYPEDEF
-%token	<sym> CHAR     EXTERN  RETURN    UNION
-%token	<sym> CONST    FLOAT   SHORT     UNSIGNED
-%token	<sym> CONTINUE FOR     SIGNED    VOID
-%token	<sym> DEFAULT  GOTO    SIZEOF    VOLATILE
-%token	<sym> DO       IF      STATIC    WHILE
-%token	<sym> CLASS    PRIVATE PROTECTED PUBLIC
-%token	<sym> VIRTUAL  INLINE  OPERATOR  LLONG
-%token	<sym> BOOL     CFALSE  CTRUE	 WCHAR
-%token	<sym> TIME     USING   NAMESPACE ULLONG
-%token	<sym> MUSTUNDERSTAND   SIZE      FRIEND
-%token	<sym> TEMPLATE EXPLICIT		 TYPENAME
-%token	<sym> RESTRICT null
-%token	<sym> UCHAR    USHORT  UINT      ULONG
-/* */
-%token	NONE
-/* identifiers (TYPE = typedef identifier) */
-%token	<sym> ID LAB TYPE
-/* constants */
-%token	<i> LNG
-%token	<r> DBL
-%token	<c> CHR
-%token	<s> TAG STR
-/* types and related */
-%type	<typ> type
-%type	<sto> store virtual constobj abstract
-%type	<e> fname struct class base enum
-%type	<sym> id arg name
-%type	<s> tag patt
-%type	<i> cint
-/* expressions and statements */
-%type	<rec> expr cexp oexp obex aexp abex rexp lexp pexp init spec tspec ptrs array arrayck texp qexp occurs
-/* terminals */
-%left	','
-%right	'=' PA NA TA DA MA AA XA OA LA RA  /* += -= *= /= %= &= ^= |= <<= >>= */
-%right	'?'
-%right	':'
-%left	OR		/* || */
-%left	AN		/* && */
-%left	'|'
-%left	'^'
-%left	'&'
-%left	EQ NE		/* == != */
-%left	'<' LE '>' GE	/* <= >= */
-%left	LS RS		/* << >> */
-%left	'+' '-'
-%left	'*' '/' '%'
-%left	AR		/* -> */
-%token	PP NN		/* ++ -- */
-
-%%
-
-/******************************************************************************\
-
-	Program syntax
-
-\******************************************************************************/
-
-prog	: s1 exts	{ if (lflag)
-    			  {	custom_header = 0;
-    			  	custom_fault = 0;
-			  }
-			  else
-			  {	add_header(sp->table);
-			  	add_fault(sp->table);
-			  }
-			  compile(sp->table);
-			  freetable(classtable);
-			  freetable(enumtable);
-			  freetable(typetable);
-			  freetable(booltable);
-			  freetable(templatetable);
-			}
-	;
-s1	: /* empty */	{ classtable = mktable((Table*)0);
-			  enumtable = mktable((Table*)0);
-			  typetable = mktable((Table*)0);
-			  booltable = mktable((Table*)0);
-			  templatetable = mktable((Table*)0);
-			  p = enter(booltable, lookup("false"));
-			  p->info.typ = mkint();
-			  p->info.val.i = 0;
-			  p = enter(booltable, lookup("true"));
-			  p->info.typ = mkint();
-			  p->info.val.i = 1;
-			  mkscope(mktable(mktable((Table*)0)), 0);
-			}
-	;
-exts	: NAMESPACE ID '{' exts1 '}'
-			{ namespaceid = $2->name; }
-	| exts1		{ }
-	;
-exts1	: /* empty */	{ add_soap();
-			  add_qname();
-			  add_XML();
-			}
-	| exts1 ext	{ }
-	;
-ext	: dclrs ';'	{ }
-	| pragma	{ }
-	| error ';'	{ synerror("input before ; skipped");
-			  while (sp > stack)
-			  {	freetable(sp->table);
-			  	exitscope();
-			  }
-			  yyerrok;
-			}
-	| t1		{ }
-	| t2		{ }
-	;
-pragma	: PRAGMA	{ if ($1[1] >= 'a' && $1[1] <= 'z')
-			  {	for (pp = &pragmas; *pp; pp = &(*pp)->next)
-			          ;
-				*pp = (Pragma*)emalloc(sizeof(Pragma));
-				(*pp)->pragma = (char*)emalloc(strlen($1)+1);
-				strcpy((*pp)->pragma, $1);
-				(*pp)->next = NULL;
-			  }
-			  else if ((i = atoi($1+2)) > 0)
-				yylineno = i;
-			  else
-			  {	sprintf(errbuf, "directive '%s' ignored (use #import to import files)", $1);
-			  	semwarn(errbuf);
-			  }
-			}
-	;
-
-/******************************************************************************\
-
-	Declarations
-
-\******************************************************************************/
-
-decls	: /* empty */	{ transient &= ~6;
-			  permission = 0;
-			}
-	| dclrs ';' decls
-			{ }
-	| PRIVATE ':' t3 decls
-			{ }
-	| PROTECTED ':' t4 decls
-			{ }
-	| PUBLIC ':' t5 decls
-			{ }
-	| t1 decls t2 decls
-			{ }
-	| error ';' 	{ synerror("declaration expected"); yyerrok; }
-	;
-t1	: '['		{ transient |= 1;
-			}
-	;
-t2	: ']'		{ transient &= ~1;
-			}
-	;
-t3	:		{ permission = Sprivate;
-			}
-	;
-t4	:		{ permission = Sprotected;
-			}
-	;
-t5	:		{ permission = 0;
-			}
-	;
-dclrs	: spec		{ }
-	| spec dclr	{ }
-	| spec fdclr func
-			{ }
-	| constr func	{ }
-	| destr func	{ }
-	| dclrs ',' dclr{ }
-	| dclrs ',' fdclr func
-			{ }
-	;
-dclr	: ptrs ID arrayck tag occurs init
-			{ if (($3.sto & Stypedef) && sp->table->level == GLOBAL)
-			  {	if (($3.typ->type != Tstruct && $3.typ->type != Tunion && $3.typ->type != Tenum) || strcmp($2->name, $3.typ->id->name))
-				{	p = enter(typetable, $2);
-					p->info.typ = mksymtype($3.typ, $2);
-			  		if ($3.sto & Sextern)
-						p->info.typ->transient = -1;
-					else
-						p->info.typ->transient = $3.typ->transient;
-			  		p->info.sto = $3.sto;
-					p->info.typ->pattern = $5.pattern;
-					p->info.typ->minLength = $5.minLength;
-					p->info.typ->maxLength = $5.maxLength;
-				}
-				$2->token = TYPE;
-			  }
-			  else
-			  {	p = enter(sp->table, $2);
-			  	p->tag = $4;
-			  	p->info.typ = $3.typ;
-			  	p->info.sto = (Storage)((int)$3.sto | permission);
-				if ($6.hasval)
-				{	p->info.hasval = True;
-					switch ($3.typ->type)
-					{	case Tchar:
-						case Tuchar:
-						case Tshort:
-						case Tushort:
-						case Tint:
-						case Tuint:
-						case Tlong:
-						case Tulong:
-						case Tllong:
-						case Tullong:
-						case Tenum:
-						case Ttime:
-							if ($6.typ->type == Tint || $6.typ->type == Tchar || $6.typ->type == Tenum)
-								sp->val = p->info.val.i = $6.val.i;
-							else
-							{	semerror("type error in initialization constant");
-								p->info.hasval = False;
-							}
-							break;
-						case Tfloat:
-						case Tdouble:
-						case Tldouble:
-							if ($6.typ->type == Tfloat || $6.typ->type == Tdouble || $6.typ->type == Tldouble)
-								p->info.val.r = $6.val.r;
-							else if ($6.typ->type == Tint)
-								p->info.val.r = (double)$6.val.i;
-							else
-							{	semerror("type error in initialization constant");
-								p->info.hasval = False;
-							}
-							break;
-						default:
-							if ($3.typ->type == Tpointer
-							 && (((Tnode*)$3.typ->ref)->type == Tchar || ((Tnode*)$3.typ->ref)->type == Twchar)
-							 && $6.typ->type == Tpointer
-							 && ((Tnode*)$6.typ->ref)->type == Tchar)
-								p->info.val.s = $6.val.s;
-							else if (bflag
-							 && $3.typ->type == Tarray
-							 && ((Tnode*)$3.typ->ref)->type == Tchar
-							 && $6.typ->type == Tpointer
-							 && ((Tnode*)$6.typ->ref)->type == Tchar)
-							{	if ($3.typ->width / ((Tnode*)$3.typ->ref)->width - 1 < strlen($6.val.s))
-								{	semerror("char[] initialization constant too long");
-									p->info.val.s = "";
-								}
-
-								else
-									p->info.val.s = $6.val.s;
-							}
-							else if ($3.typ->type == Tpointer
-							      && (((Tnode*)$3.typ->ref)->id == lookup("std::string") || ((Tnode*)$3.typ->ref)->id == lookup("std::wstring")))
-							      	p->info.val.s = $6.val.s;
-							else if ($3.typ->id == lookup("std::string") || $3.typ->id == lookup("std::wstring"))
-							      	p->info.val.s = $6.val.s;
-							else if ($3.typ->type == Tpointer
-							      && $6.typ->type == Tint
-							      && $6.val.i == 0)
-								p->info.val.i = 0;
-							else
-							{	semerror("type error in initialization constant");
-								p->info.hasval = False;
-							}
-							break;
-					}
-				}
-				else
-					p->info.val.i = sp->val;
-			        if ($5.minOccurs < 0)
-			        {	if ($6.hasval || ($3.sto & Sattribute) || $3.typ->type == Tpointer || $3.typ->type == Ttemplate || !strncmp($2->name, "__size", 6))
-			        		p->info.minOccurs = 0;
-			        	else
-			        		p->info.minOccurs = 1;
-				}
-				else
-					p->info.minOccurs = $5.minOccurs;
-				p->info.maxOccurs = $5.maxOccurs;
-				if (sp->mask)
-					sp->val <<= 1;
-				else
-					sp->val++;
-			  	p->info.offset = sp->offset;
-				if ($3.sto & Sextern)
-					p->level = GLOBAL;
-				else if ($3.sto & Stypedef)
-					;
-			  	else if (sp->grow)
-					sp->offset += p->info.typ->width;
-				else if (p->info.typ->width > sp->offset)
-					sp->offset = p->info.typ->width;
-			  }
-			  sp->entry = p;
-			}
-	;
-fdclr	: ptrs name	{ if ($1.sto & Stypedef)
-			  {	sprintf(errbuf, "invalid typedef qualifier for '%s'", $2->name);
-				semwarn(errbuf);
-			  }
-			  p = enter(sp->table, $2);
-			  p->info.typ = $1.typ;
-			  p->info.sto = $1.sto;
-			  p->info.hasval = False;
-			  p->info.offset = sp->offset;
-			  if (sp->grow)
-				sp->offset += p->info.typ->width;
-			  else if (p->info.typ->width > sp->offset)
-				sp->offset = p->info.typ->width;
-			  sp->entry = p;
-			}
-	;
-id	: ID		{ $$ = $1; }
-	| TYPE		{ $$ = $1; }
-	;
-name	: ID		{ $$ = $1; }
-	| OPERATOR '!'	{ $$ = lookup("operator!"); }
-	| OPERATOR '~'	{ $$ = lookup("operator~"); }
-	| OPERATOR '='	{ $$ = lookup("operator="); }
-	| OPERATOR PA	{ $$ = lookup("operator+="); }
-	| OPERATOR NA	{ $$ = lookup("operator-="); }
-	| OPERATOR TA	{ $$ = lookup("operator*="); }
-	| OPERATOR DA	{ $$ = lookup("operator/="); }
-	| OPERATOR MA	{ $$ = lookup("operator%="); }
-	| OPERATOR AA	{ $$ = lookup("operator&="); }
-	| OPERATOR XA	{ $$ = lookup("operator^="); }
-	| OPERATOR OA	{ $$ = lookup("operator|="); }
-	| OPERATOR LA	{ $$ = lookup("operator<<="); }
-	| OPERATOR RA	{ $$ = lookup("operator>>="); }
-	| OPERATOR OR	{ $$ = lookup("operator||"); }
-	| OPERATOR AN	{ $$ = lookup("operator&&"); }
-	| OPERATOR '|'	{ $$ = lookup("operator|"); }
-	| OPERATOR '^'	{ $$ = lookup("operator^"); }
-	| OPERATOR '&'	{ $$ = lookup("operator&"); }
-	| OPERATOR EQ	{ $$ = lookup("operator=="); }
-	| OPERATOR NE	{ $$ = lookup("operator!="); }
-	| OPERATOR '<'	{ $$ = lookup("operator<"); }
-	| OPERATOR LE	{ $$ = lookup("operator<="); }
-	| OPERATOR '>'	{ $$ = lookup("operator>"); }
-	| OPERATOR GE	{ $$ = lookup("operator>="); }
-	| OPERATOR LS	{ $$ = lookup("operator<<"); }
-	| OPERATOR RS	{ $$ = lookup("operator>>"); }
-	| OPERATOR '+'	{ $$ = lookup("operator+"); }
-	| OPERATOR '-'	{ $$ = lookup("operator-"); }
-	| OPERATOR '*'	{ $$ = lookup("operator*"); }
-	| OPERATOR '/'	{ $$ = lookup("operator/"); }
-	| OPERATOR '%'	{ $$ = lookup("operator%"); }
-	| OPERATOR PP	{ $$ = lookup("operator++"); }
-	| OPERATOR NN	{ $$ = lookup("operator--"); }
-	| OPERATOR AR   { $$ = lookup("operator->"); }
-	| OPERATOR'['']'{ $$ = lookup("operator[]"); }
-	| OPERATOR'('')'{ $$ = lookup("operator()"); }
-	| OPERATOR texp { s1 = c_storage($2.sto);
-			  s2 = c_type($2.typ);
-			  s = (char*)emalloc(strlen(s1) + strlen(s2) + 10);
-			  strcpy(s, "operator ");
-			  strcat(s, s1);
-			  strcat(s, s2);
-			  $$ = lookup(s);
-			  if (!$$)
-				$$ = install(s, ID);
-			}
-	;
-constr	: TYPE		{ if (!(p = entry(classtable, $1)))
-			  	semerror("invalid constructor");
-			  sp->entry = enter(sp->table, $1);
-			  sp->entry->info.typ = mknone();
-			  sp->entry->info.sto = Snone;
-			  sp->entry->info.offset = sp->offset;
-			  sp->node.typ = mkvoid();
-			  sp->node.sto = Snone;
-			}
-	;
-destr	: virtual '~' TYPE
-			{ if (!(p = entry(classtable, $3)))
-			  	semerror("invalid destructor");
-			  s = (char*)emalloc(strlen($3->name) + 2);
-			  strcpy(s, "~");
-			  strcat(s, $3->name);
-			  sym = lookup(s);
-			  if (!sym)
-				sym = install(s, ID);
-			  sp->entry = enter(sp->table, sym);
-			  sp->entry->info.typ = mknone();
-			  sp->entry->info.sto = $1;
-			  sp->entry->info.offset = sp->offset;
-			  sp->node.typ = mkvoid();
-			  sp->node.sto = Snone;
-			}
-	;
-func	: fname '(' s6 fargso ')' constobj abstract
-			{ if ($1->level == GLOBAL)
-			  {	if (!($1->info.sto & Sextern) && sp->entry && sp->entry->info.typ->type == Tpointer && ((Tnode*)sp->entry->info.typ->ref)->type == Tchar)
-			  	{	sprintf(errbuf, "last output parameter of remote method function prototype '%s' is a pointer to a char which will only return one byte: use char** instead to return a string", $1->sym->name);
-					semwarn(errbuf);
-				}
-				if ($1->info.sto & Sextern)
-				 	$1->info.typ = mkmethod($1->info.typ, sp->table);
-			  	else if (sp->entry && (sp->entry->info.typ->type == Tpointer || sp->entry->info.typ->type == Treference || sp->entry->info.typ->type == Tarray || is_transient(sp->entry->info.typ)))
-				{	if ($1->info.typ->type == Tint)
-					{	sp->entry->info.sto = (Storage)((int)sp->entry->info.sto | (int)Sreturn);
-						$1->info.typ = mkfun(sp->entry);
-						$1->info.typ->id = $1->sym;
-						if (!is_transient(sp->entry->info.typ))
-						{	if (!is_response(sp->entry->info.typ))
-							{	if (!is_XML(sp->entry->info.typ))
-									add_response($1, sp->entry);
-							}
-							else
-								add_result(sp->entry->info.typ);
-						}
-					}
-					else
-					{	sprintf(errbuf, "return type of remote method function prototype '%s' must be integer", $1->sym->name);
-						semerror(errbuf);
-					}
-				}
-			  	else
-			  	{	sprintf(errbuf, "last output parameter of remote method function prototype '%s' is a return parameter and must be a pointer or reference, or use %s(..., void) for one-way sends", $1->sym->name, $1->sym->name);
-					semerror(errbuf);
-			  	}
-				if (!($1->info.sto & Sextern))
-			  	{	unlinklast(sp->table);
-			  		if ((p = entry(classtable, $1->sym)))
-					{	if (p->info.typ->ref)
-						{	sprintf(errbuf, "remote method name clash: struct/class '%s' already declared at line %d", $1->sym->name, p->lineno);
-							semerror(errbuf);
-						}
-						else
-						{	p->info.typ->ref = sp->table;
-							p->info.typ->width = sp->offset;
-						}
-					}
-			  		else
-			  		{	p = enter(classtable, $1->sym);
-						p->info.typ = mkstruct(sp->table, sp->offset);
-						p->info.typ->id = $1->sym;
-			  		}
-			  	}
-			  }
-			  else if ($1->level == INTERNAL)
-			  {	$1->info.typ = mkmethod($1->info.typ, sp->table);
-				$1->info.sto = (Storage)((int)$1->info.sto | (int)$6 | (int)$7);
-			  	transient &= ~1;
-			  }
-			  exitscope();
-			}
-	;
-fname	:		{ $$ = sp->entry; }
-	;
-fargso	: /* empty */	{ }
-	| fargs		{ }
-	;
-fargs	: farg		{ }
-	| farg ',' fargs{ }
-	;
-farg	: tspec ptrs arg arrayck occurs init
-			{ if ($4.sto & Stypedef)
-			  	semwarn("typedef in function argument");
-			  p = enter(sp->table, $3);
-			  p->info.typ = $4.typ;
-			  p->info.sto = $4.sto;
-			  if ($5.minOccurs < 0)
-			  {	if ($6.hasval || ($4.sto & Sattribute) || $4.typ->type == Tpointer)
-			        	p->info.minOccurs = 0;
-			       	else
-			        	p->info.minOccurs = 1;
-			  }
-			  else
-				p->info.minOccurs = $5.minOccurs;
-			  p->info.maxOccurs = $5.maxOccurs;
-			  if ($6.hasval)
-			  {	p->info.hasval = True;
-				switch ($4.typ->type)
-				{	case Tchar:
-					case Tuchar:
-					case Tshort:
-					case Tushort:
-					case Tint:
-					case Tuint:
-					case Tlong:
-					case Tulong:
-					case Tenum:
-					case Ttime:
-						if ($6.typ->type == Tint || $6.typ->type == Tchar || $6.typ->type == Tenum)
-							sp->val = p->info.val.i = $6.val.i;
-						else
-						{	semerror("type error in initialization constant");
-							p->info.hasval = False;
-						}
-						break;
-					case Tfloat:
-					case Tdouble:
-					case Tldouble:
-						if ($6.typ->type == Tfloat || $6.typ->type == Tdouble || $6.typ->type == Tldouble)
-							p->info.val.r = $6.val.r;
-						else if ($6.typ->type == Tint)
-							p->info.val.r = (double)$6.val.i;
-						else
-						{	semerror("type error in initialization constant");
-							p->info.hasval = False;
-						}
-						break;
-					default:
-						if ($4.typ->type == Tpointer
-						 && (((Tnode*)$4.typ->ref)->type == Tchar || ((Tnode*)$4.typ->ref)->type == Twchar)
-						 && $6.typ->type == Tpointer
-						 && ((Tnode*)$6.typ->ref)->type == Tchar)
-							p->info.val.s = $6.val.s;
-						else if ($4.typ->type == Tpointer
-						      && (((Tnode*)$4.typ->ref)->id == lookup("std::string") || ((Tnode*)$4.typ->ref)->id == lookup("std::wstring")))
-						      	p->info.val.s = $6.val.s;
-						else if ($4.typ->id == lookup("std::string") || $4.typ->id == lookup("std::wstring"))
-						      	p->info.val.s = $6.val.s;
-						else if ($4.typ->type == Tpointer
-						      && $6.typ->type == Tint
-						      && $6.val.i == 0)
-							p->info.val.i = 0;
-						else
-						{	semerror("type error in initialization constant");
-							p->info.hasval = False;
-						}
-						break;
-				}
-			  }
-			  p->info.offset = sp->offset;
-			  if ($4.sto & Sextern)
-				p->level = GLOBAL;
-			  else if (sp->grow)
-				sp->offset += p->info.typ->width;
-			  else if (p->info.typ->width > sp->offset)
-				sp->offset = p->info.typ->width;
-			  sp->entry = p;
-			}
-	;
-arg	: /* empty */	{ if (sp->table->level != PARAM)
-			    $$ = gensymidx("param", (int)++sp->val);
-			  else if (eflag)
-				$$ = gensymidx("_param", (int)++sp->val);
-			  else
-				$$ = gensym("_param");
-			}
-	| ID		{ if (vflag == 2 && *$1->name == '_' && sp->table->level == GLOBAL)
-			  { sprintf(errbuf, "SOAP 1.2 does not support anonymous parameters '%s'", $1->name);
-			    semwarn(errbuf);
-			  }
-			  $$ = $1;
-			}
-	;
-
-/******************************************************************************\
-
-	Type specification
-
-\******************************************************************************/
-
-/* texp : type expression (subset of C) */
-texp	: tspec ptrs array
-			{ $$ = $3; }
-	| tspec ptrs ID array
-			{ $$ = $4; }
-	;
-spec	: /*empty */	{ $$.typ = mkint();
-			  $$.sto = Snone;
-			  sp->node = $$;
-			}
-	| store spec	{ if (($1 & Stypedef) && is_external($2.typ) && $2.typ->type != Tstruct && $2.typ->type != Tclass)
-			  	$$.typ = mktype($2.typ->type, $2.typ->ref, $2.typ->width);
-			  else
-			  	$$.typ = $2.typ;
-			  $$.sto = (Storage)((int)$1 | ((int)($2.sto)));
-			  if (($$.sto & Sattribute) && !is_primitive_or_string($2.typ) && !is_stdstr($2.typ) && !is_binary($2.typ) && !is_external($2.typ))
-			  {	semwarn("invalid attribute type");
-			  	$$.sto = (Storage)((int)$$.sto & ~Sattribute);
-			  }
-			  sp->node = $$;
-			  if ($1 & Sextern)
-				transient = 0;
-			}
-	| type spec	{ if ($1->type == Tint)
-				switch ($2.typ->type)
-				{ case Tchar:	$$.typ = $2.typ; break;
-				  case Tshort:	$$.typ = $2.typ; break;
-				  case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = $2.typ; break;
-				  case Tllong:	$$.typ = $2.typ; break;
-				  default:	semwarn("illegal use of 'signed'");
-						$$.typ = $2.typ;
-				}
-			  else if ($1->type == Tuint)
-				switch ($2.typ->type)
-				{ case Tchar:	$$.typ = mkuchar(); break;
-				  case Tshort:	$$.typ = mkushort(); break;
-				  case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = mkulong(); break;
-				  case Tllong:	$$.typ = mkullong(); break;
-				  default:	semwarn("illegal use of 'unsigned'");
-						$$.typ = $2.typ;
-				}
-			  else if ($1->type == Tlong)
-				switch ($2.typ->type)
-				{ case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = mkllong(); break;
-				  case Tuint:	$$.typ = mkulong(); break;
-				  case Tulong:	$$.typ = mkullong(); break;
-				  case Tdouble:	$$.typ = mkldouble(); break;
-				  default:	semwarn("illegal use of 'long'");
-						$$.typ = $2.typ;
-				}
-			  else if ($1->type == Tulong)
-				switch ($2.typ->type)
-				{ case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = mkullong(); break;
-				  case Tuint:	$$.typ = $1; break;
-				  case Tulong:	$$.typ = mkullong(); break;
-				  default:	semwarn("illegal use of 'long'");
-						$$.typ = $2.typ;
-				}
-			  else if ($2.typ->type == Tint)
-				$$.typ = $1;
-			  else
-			  	semwarn("invalid type (missing ';' or type name used as non-type identifier?)");
-			  $$.sto = $2.sto;
-			  sp->node = $$;
-			}
-	;
-tspec	: store		{ $$.typ = mkint();
-			  $$.sto = $1;
-			  sp->node = $$;
-			  if ($1 & Sextern)
-				transient = 0;
-			}
-	| type		{ $$.typ = $1;
-			  $$.sto = Snone;
-			  sp->node = $$;
-			}
-	| store tspec	{ $$.typ = $2.typ;
-			  $$.sto = (Storage)((int)$1 | (int)$2.sto);
-			  if (($$.sto & Sattribute) && !is_primitive_or_string($2.typ) && !is_stdstr($2.typ) && !is_binary($2.typ) && !is_external($2.typ))
-			  {	semwarn("invalid attribute type");
-			  	$$.sto = (Storage)((int)$$.sto & ~Sattribute);
-			  }
-			  sp->node = $$;
-			  if ($1 & Sextern)
-				transient = 0;
-			}
-	| type tspec	{ if ($1->type == Tint)
-				switch ($2.typ->type)
-				{ case Tchar:	$$.typ = $2.typ; break;
-				  case Tshort:	$$.typ = $2.typ; break;
-				  case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = $2.typ; break;
-				  case Tllong:	$$.typ = $2.typ; break;
-				  default:	semwarn("illegal use of 'signed'");
-						$$.typ = $2.typ;
-				}
-			  else if ($1->type == Tuint)
-				switch ($2.typ->type)
-				{ case Tchar:	$$.typ = mkuchar(); break;
-				  case Tshort:	$$.typ = mkushort(); break;
-				  case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = mkulong(); break;
-				  case Tllong:	$$.typ = mkullong(); break;
-				  default:	semwarn("illegal use of 'unsigned'");
-						$$.typ = $2.typ;
-				}
-			  else if ($1->type == Tlong)
-				switch ($2.typ->type)
-				{ case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = mkllong(); break;
-				  case Tuint:	$$.typ = mkulong(); break;
-				  case Tulong:	$$.typ = mkullong(); break;
-				  case Tdouble:	$$.typ = mkldouble(); break;
-				  default:	semwarn("illegal use of 'long'");
-						$$.typ = $2.typ;
-				}
-			  else if ($1->type == Tulong)
-				switch ($2.typ->type)
-				{ case Tint:	$$.typ = $1; break;
-				  case Tlong:	$$.typ = mkullong(); break;
-				  case Tuint:	$$.typ = $1; break;
-				  case Tulong:	$$.typ = mkullong(); break;
-				  default:	semwarn("illegal use of 'long'");
-						$$.typ = $2.typ;
-				}
-			  else if ($2.typ->type == Tint)
-				$$.typ = $1;
-			  else
-			  	semwarn("invalid type");
-			  $$.sto = $2.sto;
-			  sp->node = $$;
-			}
-	;
-type	: VOID		{ $$ = mkvoid(); }
-	| BOOL		{ $$ = mkbool(); }
-	| CHAR		{ $$ = mkchar(); }
-	| WCHAR		{ $$ = mkwchart(); }
-	| SHORT		{ $$ = mkshort(); }
-	| INT		{ $$ = mkint(); }
-	| LONG		{ $$ = mklong(); }
-	| LLONG		{ $$ = mkllong(); }
-	| ULLONG	{ $$ = mkullong(); }
-	| SIZE		{ $$ = mkulong(); }
-	| FLOAT		{ $$ = mkfloat(); }
-	| DOUBLE	{ $$ = mkdouble(); }
-	| SIGNED	{ $$ = mkint(); }
-	| UNSIGNED	{ $$ = mkuint(); }
-	| UCHAR		{ $$ = mkuchar(); }
-	| USHORT	{ $$ = mkushort(); }
-	| UINT		{ $$ = mkuint(); }
-	| ULONG		{ $$ = mkulong(); }
-	| TIME		{ $$ = mktimet(); }
-	| TEMPLATE '<' tname id '>' CLASS id
-			{ if (!(p = entry(templatetable, $7)))
-			  {	p = enter(templatetable, $7);
-			  	p->info.typ = mktemplate(NULL, $7);
-			  	$7->token = TYPE;
-			  }
-			  $$ = p->info.typ;
-			}
-	| CLASS '{' s2 decls '}'
-			{ sym = gensym("_Struct");
-			  sprintf(errbuf, "anonymous class will be named '%s'", sym->name);
-			  semwarn(errbuf);
-			  if ((p = entry(classtable, sym)))
-			  {	if (p->info.typ->ref || p->info.typ->type != Tclass)
-				{	sprintf(errbuf, "class '%s' already declared at line %d", sym->name, p->lineno);
-					semerror(errbuf);
-				}
-			  }
-			  else
-			  {	p = enter(classtable, sym);
-				p->info.typ = mkclass((Table*)0, 0);
-			  }
-			  sym->token = TYPE;
-			  sp->table->sym = sym;
-			  p->info.typ->ref = sp->table;
-			  p->info.typ->width = sp->offset;
-			  p->info.typ->id = sym;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| class '{' s2 decls '}'
-			{ p = reenter(classtable, $1->sym);
-			  sp->table->sym = p->sym;
-			  p->info.typ->ref = sp->table;
-			  p->info.typ->width = sp->offset;
-			  p->info.typ->id = p->sym;
-			  if (p->info.typ->base)
-			  	sp->table->prev = (Table*)entry(classtable, p->info.typ->base)->info.typ->ref;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| class ':' base '{' s2 decls '}'
-			{ p = reenter(classtable, $1->sym);
-			  sp->table->sym = p->sym;
-			  if (!$3)
-				semerror("invalid base class");
-			  else
-			  {	sp->table->prev = (Table*)$3->info.typ->ref;
-				if (!sp->table->prev && !$3->info.typ->transient)
-				{	sprintf(errbuf, "class '%s' has incomplete type", $3->sym->name);
-					semerror(errbuf);
-				}
-			  	p->info.typ->base = $3->info.typ->id;
-			  }
-			  p->info.typ->ref = sp->table;
-			  p->info.typ->width = sp->offset;
-			  p->info.typ->id = p->sym;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| class		{ $1->info.typ->id = $1->sym;
-			  $$ = $1->info.typ;
-			}
-	| class ':' base
-			{ if (!$3)
-				semerror("invalid base class");
-			  else
-			  {	if (!$3->info.typ->ref && !$3->info.typ->transient)
-				{	sprintf(errbuf, "class '%s' has incomplete type", $3->sym->name);
-					semerror(errbuf);
-				}
-			  	$1->info.typ->base = $3->info.typ->id;
-			  }
-			  $1->info.typ->id = $1->sym;
-			  $$ = $1->info.typ;
-			}
-	| STRUCT '{' s2 decls '}'
-			{ sym = gensym("_Struct");
-			  sprintf(errbuf, "anonymous struct will be named '%s'", sym->name);
-			  semwarn(errbuf);
-			  if ((p = entry(classtable, sym)))
-			  {	if (p->info.typ->ref || p->info.typ->type != Tstruct)
-				{	sprintf(errbuf, "struct '%s' already declared at line %d", sym->name, p->lineno);
-					semerror(errbuf);
-				}
-				else
-				{	p->info.typ->ref = sp->table;
-					p->info.typ->width = sp->offset;
-				}
-			  }
-			  else
-			  {	p = enter(classtable, sym);
-				p->info.typ = mkstruct(sp->table, sp->offset);
-			  }
-			  p->info.typ->id = sym;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| struct '{' s2 decls '}'
-			{ if ((p = entry(classtable, $1->sym)) && p->info.typ->ref)
-			  {	if (is_mutable(p->info.typ))
-			  	{	if (merge((Table*)p->info.typ->ref, sp->table))
-					{	sprintf(errbuf, "member name clash in struct '%s' declared at line %d", $1->sym->name, p->lineno);
-						semerror(errbuf);
-					}
-			  		p->info.typ->width += sp->offset;
-				}
-			  }
-			  else
-			  {	p = reenter(classtable, $1->sym);
-			  	p->info.typ->ref = sp->table;
-			  	p->info.typ->width = sp->offset;
-			  	p->info.typ->id = p->sym;
-			  }
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| STRUCT ID	{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->type == Tstruct)
-			  		$$ = p->info.typ;
-			  	else
-				{	sprintf(errbuf, "'struct %s' redeclaration (line %d)", $2->name, p->lineno);
-			  		semerror(errbuf);
-			  		$$ = mkint();
-				}
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-			  	$$ = p->info.typ = mkstruct((Table*)0, 0);
-				p->info.typ->id = $2;
-			  }
-			}
-	| STRUCT TYPE	{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->type == Tstruct)
-					$$ = p->info.typ;
-			  	else
-				{	sprintf(errbuf, "'struct %s' redeclaration (line %d)", $2->name, p->lineno);
-			  		semerror(errbuf);
-			  		$$ = mkint();
-				}
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-			  	$$ = p->info.typ = mkstruct((Table*)0, 0);
-				p->info.typ->id = $2;
-			  }
-			}
-	| UNION '{' s3 decls '}'
-			{ sym = gensym("_Union");
-			  sprintf(errbuf, "anonymous union will be named '%s'", sym->name);
-			  semwarn(errbuf);
-			  $$ = mkunion(sp->table, sp->offset);
-			  if ((p = entry(classtable, sym)))
-			  {	if (p->info.typ->ref)
-				{	sprintf(errbuf, "union or struct '%s' already declared at line %d", sym->name, p->lineno);
-					semerror(errbuf);
-				}
-				else
-				{	p->info.typ->ref = sp->table;
-					p->info.typ->width = sp->offset;
-				}
-			  }
-			  else
-			  {	p = enter(classtable, sym);
-				p->info.typ = mkunion(sp->table, sp->offset);
-			  }
-			  p->info.typ->id = sym;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| UNION id '{' s3 decls '}'
-			{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->ref || p->info.typ->type != Tunion)
-			  	{	sprintf(errbuf, "union '%s' already declared at line %d", $2->name, p->lineno);
-					semerror(errbuf);
-				}
-				else
-				{	p = reenter(classtable, $2);
-					p->info.typ->ref = sp->table;
-					p->info.typ->width = sp->offset;
-				}
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-				p->info.typ = mkunion(sp->table, sp->offset);
-			  }
-			  p->info.typ->id = $2;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| UNION ID	{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->type == Tunion)
-					$$ = p->info.typ;
-			  	else
-				{	sprintf(errbuf, "'union %s' redeclaration (line %d)", $2->name, p->lineno);
-			  		semerror(errbuf);
-			  		$$ = mkint();
-				}
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-			  	$$ = p->info.typ = mkunion((Table*) 0, 0);
-				p->info.typ->id = $2;
-			  }
-			}
-	| UNION TYPE	{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->type == Tunion)
-					$$ = p->info.typ;
-			  	else
-				{	sprintf(errbuf, "'union %s' redeclaration (line %d)", $2->name, p->lineno);
-			  		semerror(errbuf);
-			  		$$ = mkint();
-				}
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-			  	$$ = p->info.typ = mkunion((Table*) 0, 0);
-				p->info.typ->id = $2;
-			  }
-			}
-	| ENUM '{' s2 dclrs s5 '}'
-			{ sym = gensym("_Enum");
-			  sprintf(errbuf, "anonymous enum will be named '%s'", sym->name);
-			  semwarn(errbuf);
-			  if ((p = entry(enumtable, sym)))
-			  {	if (p->info.typ->ref)
-				{	sprintf(errbuf, "enum '%s' already declared at line %d", sym->name, p->lineno);
-					semerror(errbuf);
-				}
-				else
-				{	p->info.typ->ref = sp->table;
-					p->info.typ->width = 4; /* 4 = enum */
-				}
-			  }
-			  else
-			  {	p = enter(enumtable, sym);
-				p->info.typ = mkenum(sp->table);
-			  }
-			  p->info.typ->id = sym;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| enum '{' s2 dclrs s5 '}'
-			{ if ((p = entry(enumtable, $1->sym)))
-			  {	if (p->info.typ->ref)
-				{	sprintf(errbuf, "enum '%s' already declared at line %d", $1->sym->name, p->lineno);
-					semerror(errbuf);
-				}
-				else
-				{	p->info.typ->ref = sp->table;
-					p->info.typ->width = 4; /* 4 = enum */
-				}
-			  }
-			  else
-			  {	p = enter(enumtable, $1->sym);
-				p->info.typ = mkenum(sp->table);
-			  }
-			  p->info.typ->id = $1->sym;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| ENUM '*' id '{' s4 dclrs s5 '}'
-			{ if ((p = entry(enumtable, $3)))
-			  {	if (p->info.typ->ref)
-				{	sprintf(errbuf, "enum '%s' already declared at line %d", $3->name, p->lineno);
-					semerror(errbuf);
-				}
-				else
-				{	p->info.typ->ref = sp->table;
-					p->info.typ->width = 8; /* 8 = mask */
-				}
-			  }
-			  else
-			  {	p = enter(enumtable, $3);
-				p->info.typ = mkmask(sp->table);
-			  }
-			  p->info.typ->id = $3;
-			  $$ = p->info.typ;
-			  exitscope();
-			}
-	| ENUM ID	{ if ((p = entry(enumtable, $2)))
-			  	$$ = p->info.typ;
-			  else
-			  {	p = enter(enumtable, $2);
-			  	$$ = p->info.typ = mkenum((Table*)0);
-				p->info.typ->id = $2;
-			  }
-			}
-	| ENUM TYPE	{ if ((p = entry(enumtable, $2)))
-				$$ = p->info.typ;
-			  else
-			  {	p = enter(enumtable, $2);
-			  	$$ = p->info.typ = mkenum((Table*)0);
-				p->info.typ->id = $2;
-			  }
-			}
-	| TYPE		{ if ((p = entry(typetable, $1)))
-			  	$$ = p->info.typ;
-			  else if ((p = entry(classtable, $1)))
-			  	$$ = p->info.typ;
-			  else if ((p = entry(enumtable, $1)))
-			  	$$ = p->info.typ;
-			  else if ($1 == lookup("std::string") || $1 == lookup("std::wstring"))
-			  {	p = enter(classtable, $1);
-				$$ = p->info.typ = mkclass((Table*)0, 0);
-			  	p->info.typ->id = $1;
-				if (cflag)
-			  		p->info.typ->transient = 1;	/* make std::string transient in C */
-				else
-			  		p->info.typ->transient = -2;
-			  }
-			  else
-			  {	sprintf(errbuf, "unknown type '%s'", $1->name);
-				semerror(errbuf);
-				$$ = mkint();
-			  }
-			}
-	| TYPE '<' texp '>'
-			{ if ((p = entry(templatetable, $1)))
-			  {	$$ = mktemplate($3.typ, $1);
-			  	if (has_attachment($3.typ))
-				{	sprintf(errbuf, "template type '%s<%s>' of attachment objects may lead to deserialization failures, use '%s<*%s>' instead", $1->name, $3.typ->id ? $3.typ->id->name : "", $1->name, $3.typ->id ? $3.typ->id->name : "");
-					semwarn(errbuf);
-				}
-			  }
-			  else
-			  {	sprintf(errbuf, "invalid template '%s'", $1->name);
-				semerror(errbuf);
-				$$ = mkint();
-			  }
-			}
-	| CLASS error '}'
-			{ synerror("malformed class definition (use spacing around ':' to separate derived : base)");
-			  yyerrok;
-			  $$ = mkint();
-			}
-	| STRUCT error '}'
-			{ synerror("malformed struct definition");
-			  yyerrok;
-			  $$ = mkint();
-			}
-	| UNION error '}'
-			{ synerror("malformed union definition");
-			  yyerrok;
-			  $$ = mkint();
-			}
-	| ENUM error '}'
-			{ synerror("malformed enum definition");
-			  yyerrok;
-			  $$ = mkint();
-			}
-	;
-struct	: STRUCT id	{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->ref)
-			   	{	if (!is_mutable(p->info.typ))
-					{	sprintf(errbuf, "struct '%s' already declared at line %d", $2->name, p->lineno);
-						semerror(errbuf);
-					}
-				}
-				else
-					p = reenter(classtable, $2);
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-				p->info.typ = mkstruct((Table*)0, 0);
-			  }
-			  $$ = p;
-			}
-	;
-class	: CLASS id	{ if ((p = entry(classtable, $2)))
-			  {	if (p->info.typ->ref)
-			   	{	if (!is_mutable(p->info.typ))
-					{	sprintf(errbuf, "class '%s' already declared at line %d (redundant 'class' specifier here?)", $2->name, p->lineno);
-						semerror(errbuf);
-					}
-				}
-				else
-					p = reenter(classtable, $2);
-			  }
-			  else
-			  {	p = enter(classtable, $2);
-				p->info.typ = mkclass((Table*)0, 0);
-				p->info.typ->id = p->sym;
-			  }
-			  $2->token = TYPE;
-			  $$ = p;
-			}
-	;
-enum	: ENUM id	{ if ((p = entry(enumtable, $2)))
-			  {	if (p->info.typ->ref)
-				{	sprintf(errbuf, "enum '%s' already declared at line %d", $2->name, p->lineno);
-					semerror(errbuf);
-				}
-				/*
-				else
-					p = reenter(classtable, $2);
-			  	*/
-			  }
-			  else
-			  {	p = enter(enumtable, $2);
-				p->info.typ = mkenum(0);
-			  }
-			  $$ = p;
-			}
-	;
-tname	: CLASS		{ }
-	| TYPENAME	{ }
-	;
-base	: PROTECTED base{ $$ = $2; }
-	| PRIVATE base	{ $$ = $2; }
-	| PUBLIC base	{ $$ = $2; }
-	| TYPE		{ $$ = entry(classtable, $1);
-			  if (!$$)
-			  {	p = entry(typetable, $1);
-			  	if (p && (p->info.typ->type == Tclass || p->info.typ->type == Tstruct))
-					$$ = p;
-			  }
-			}
-	| STRUCT ID	{ $$ = entry(classtable, $2); }
-	;
-s2	: /* empty */	{ if (transient == -2)
-			  	transient = 0;
-			  permission = 0;
-			  enterscope(mktable(NULL), 0);
-			  sp->entry = NULL;
-			}
-	;
-s3	: /* empty */	{ if (transient == -2)
-			  	transient = 0;
-			  permission = 0;
-			  enterscope(mktable(NULL), 0);
-			  sp->entry = NULL;
-			  sp->grow = False;
-			}
-	;
-s4	: /* empty */	{ enterscope(mktable(NULL), 0);
-			  sp->entry = NULL;
-			  sp->mask = True;
-			  sp->val = 1;
-			}
-	;
-s5	: /* empty */	{ }
-	| ','		{ }
-	;
-s6	: /* empty */	{ if (sp->table->level == INTERNAL)
-			  	transient |= 1;
-			  permission = 0;
-			  enterscope(mktable(NULL), 0);
-			  sp->entry = NULL;
-			  sp->table->level = PARAM;
-			}
-	;
-store	: AUTO		{ $$ = Sauto; }
-	| REGISTER	{ $$ = Sregister; }
-	| STATIC	{ $$ = Sstatic; }
-	| EXPLICIT	{ $$ = Sexplicit; }
-	| EXTERN	{ $$ = Sextern; transient = 1; }
-	| TYPEDEF	{ $$ = Stypedef; }
-	| VIRTUAL	{ $$ = Svirtual; }
-	| CONST		{ $$ = Sconst; }
-	| FRIEND	{ $$ = Sfriend; }
-	| INLINE	{ $$ = Sinline; }
-	| MUSTUNDERSTAND{ $$ = SmustUnderstand; }
-	| RETURN	{ $$ = Sreturn; }
-	| '@'		{ $$ = Sattribute;
-			  if (eflag)
-			   	semwarn("SOAP RPC encoding does not support XML attributes");
-			}
-	| '$'		{ $$ = Sspecial; }
-	| VOLATILE	{ $$ = Sextern; transient = -2; }
-	;
-constobj: /* empty */	{ $$ = Snone; }
-	| CONST		{ $$ = Sconstobj; }
-	;
-abstract: /* empty */	{ $$ = Snone; }
-	| '=' LNG	{ $$ = Sabstract; }
-	;
-virtual : /* empty */	{ $$ = Snone; }
-	| VIRTUAL	{ $$ = Svirtual; }
-	;
-ptrs	: /* empty */	{ $$ = tmp = sp->node; }
-	| ptrs '*'	{ /* handle const pointers, such as const char* */
-			  if ((tmp.sto & Sconst))
-			  	tmp.sto = (Storage)(((int)tmp.sto & ~Sconst) | Sconstptr);
-			  tmp.typ = mkpointer(tmp.typ);
-			  tmp.typ->transient = transient;
-			  $$ = tmp;
-			}
-	| ptrs '&'	{ tmp.typ = mkreference(tmp.typ);
-			  tmp.typ->transient = transient;
-			  $$ = tmp;
-			}
-	;
-array	: /* empty */ 	{ $$ = tmp;	/* tmp is inherited */
-			}
-	| '[' cexp ']' array
-			{ if (!bflag && $4.typ->type == Tchar)
-			  {	sprintf(errbuf, "char[" SOAP_LONG_FORMAT "] will be serialized as an array of " SOAP_LONG_FORMAT " bytes: use soapcpp2 option -b to enable char[] string serialization or use char* for strings", $2.val.i, $2.val.i);
-			  	semwarn(errbuf);
-			  }
-			  if ($2.hasval && $2.typ->type == Tint && $2.val.i > 0 && $4.typ->width > 0)
-				$$.typ = mkarray($4.typ, (int) $2.val.i * $4.typ->width);
-			  else
-			  {	$$.typ = mkarray($4.typ, 0);
-			  	semerror("undetermined array size");
-			  }
-			  $$.sto = $4.sto;
-			}
-	| '[' ']' array	{ $$.typ = mkpointer($3.typ); /* zero size array = pointer */
-			  $$.sto = $3.sto;
-			}
-	;
-arrayck	: array		{ if ($1.typ->type == Tstruct || $1.typ->type == Tclass)
-				if (!$1.typ->ref && !$1.typ->transient && !($1.sto & Stypedef))
-			   	{	sprintf(errbuf, "struct/class '%s' has incomplete type", $1.typ->id->name);
-					semerror(errbuf);
-				}
-			  $$ = $1;
-			}
-	;
-init	: /* empty */   { $$.hasval = False; }
-	| '=' cexp      { if ($2.hasval)
-			  {	$$.typ = $2.typ;
-				$$.hasval = True;
-				$$.val = $2.val;
-			  }
-			  else
-			  {	$$.hasval = False;
-				semerror("initialization expression not constant");
-			  }
-			}
-	;
-tag	: /* empty */	{ $$ = NULL; }
-	| TAG		{ $$ = $1; }
-	;
-occurs	: patt
-			{ $$.minOccurs = -1;
-			  $$.maxOccurs = 1;
-			  $$.minLength = MINLONG64;
-			  $$.maxLength = MAXLONG64;
-			  $$.pattern = $1;
-			}
-	| patt cint
-			{ $$.minOccurs = (LONG64)$2;
-			  $$.maxOccurs = 1;
-			  $$.minLength = (LONG64)$2;
-			  $$.maxLength = MAXLONG64;
-			  $$.pattern = $1;
-			}
-	| patt cint ':'
-			{ $$.minOccurs = (LONG64)$2;
-			  $$.maxOccurs = 1;
-			  $$.minLength = (LONG64)$2;
-			  $$.maxLength = MAXLONG64;
-			  $$.pattern = $1;
-			}
-	| patt cint ':' cint
-			{ $$.minOccurs = (LONG64)$2;
-			  $$.maxOccurs = (LONG64)$4;
-			  $$.minLength = (LONG64)$2;
-			  $$.maxLength = (LONG64)$4;
-			  $$.pattern = $1;
-			}
-	| patt ':' cint
-			{ $$.minOccurs = -1;
-			  $$.maxOccurs = (LONG64)$3;
-			  $$.minLength = MINLONG64;
-			  $$.maxLength = (LONG64)$3;
-			  $$.pattern = $1;
-			}
-	;
-patt	: /* empty */	{ $$ = NULL; }
-	| STR		{ $$ = $1; }
-	;
-cint	: LNG		{ $$ = $1; }
-	| '+' LNG	{ $$ = $2; }
-	| '-' LNG	{ $$ = -$2; }
-	;
-
-/******************************************************************************\
-
-	Expressions
-
-\******************************************************************************/
-
-expr	: expr ',' expr	{ $$ = $3; }
-	| cexp		{ $$ = $1; }
-	;
-/* cexp : conditional expression */
-cexp	: obex '?' qexp ':' cexp
-			{ $$.typ = $3.typ;
-			  $$.sto = Snone;
-			  $$.hasval = False;
-			}
-	| oexp
-	;
-/* qexp : true-branch of ? : conditional expression */
-qexp	: expr		{ $$ = $1; }
-	;
-/* oexp : or-expression */
-oexp	: obex OR aexp	{ $$.hasval = False;
-			  $$.typ = mkint();
-			}
-	| aexp		{ $$ = $1; }
-	;
-obex	: oexp		{ $$ = $1; }
-	;
-/* aexp : and-expression */
-aexp	: abex AN rexp	{ $$.hasval = False;
-			  $$.typ = mkint();
-			}
-	| rexp		{ $$ = $1; }
-	;
-abex	: aexp		{ $$ = $1; }
-	;
-/* rexp : relational expression */
-rexp	: rexp '|' rexp	{ $$ = iop("|", $1, $3); }
-	| rexp '^' rexp	{ $$ = iop("^", $1, $3); }
-	| rexp '&' rexp	{ $$ = iop("&", $1, $3); }
-	| rexp EQ  rexp	{ $$ = relop("==", $1, $3); }
-	| rexp NE  rexp	{ $$ = relop("!=", $1, $3); }
-	| rexp '<' rexp	{ $$ = relop("<", $1, $3); }
-	| rexp LE  rexp	{ $$ = relop("<=", $1, $3); }
-	| rexp '>' rexp	{ $$ = relop(">", $1, $3); }
-	| rexp GE  rexp	{ $$ = relop(">=", $1, $3); }
-	| rexp LS  rexp	{ $$ = iop("<<", $1, $3); }
-	| rexp RS  rexp	{ $$ = iop(">>", $1, $3); }
-	| rexp '+' rexp	{ $$ = op("+", $1, $3); }
-	| rexp '-' rexp	{ $$ = op("-", $1, $3); }
-	| rexp '*' rexp	{ $$ = op("*", $1, $3); }
-	| rexp '/' rexp	{ $$ = op("/", $1, $3); }
-	| rexp '%' rexp	{ $$ = iop("%", $1, $3); }
-	| lexp		{ $$ = $1; }
-	;
-/* lexp : lvalue kind of expression with optional prefix contructs */
-lexp	: '!' lexp	{ if ($2.hasval)
-				$$.val.i = !$2.val.i;
-			  $$.typ = $2.typ;
-			  $$.hasval = $2.hasval;
-			}
-	| '~' lexp	{ if ($2.hasval)
-				$$.val.i = ~$2.val.i;
-			  $$.typ = $2.typ;
-			  $$.hasval = $2.hasval;
-			}
-	| '-' lexp	{ if ($2.hasval) {
-				if (integer($2.typ))
-					$$.val.i = -$2.val.i;
-				else if (real($2.typ))
-					$$.val.r = -$2.val.r;
-				else	typerror("string?");
-			  }
-			  $$.typ = $2.typ;
-			  $$.hasval = $2.hasval;
-			}
-	| '+' lexp	{ $$ = $2; }
-	| '*' lexp	{ if ($2.typ->type == Tpointer) {
-			  	$$.typ = (Tnode*)$2.typ->ref;
-			  } else
-			  	typerror("dereference of non-pointer type");
-			  $$.sto = Snone;
-			  $$.hasval = False;
-			}
-	| '&' lexp	{ $$.typ = mkpointer($2.typ);
-			  $$.sto = Snone;
-			  $$.hasval = False;
-			}
-	| SIZEOF '(' texp ')'
-			{ $$.hasval = True;
-			  $$.typ = mkint();
-			  $$.val.i = $3.typ->width;
-			}
-	| pexp		{ $$ = $1; }
-	;
-/* pexp : primitive expression with optional postfix constructs */
-pexp	: '(' expr ')'	{ $$ = $2; }
-	| ID		{ if ((p = enumentry($1)) == (Entry*) 0)
-				p = undefined($1);
-			  else
-			  	$$.hasval = True;
-			  $$.typ = p->info.typ;
-			  $$.val = p->info.val;
-			}
-	| LNG		{ $$.typ = mkint();
-			  $$.hasval = True;
-			  $$.val.i = $1;
-			}
-	| null		{ $$.typ = mkint();
-			  $$.hasval = True;
-			  $$.val.i = 0;
-			}
-	| DBL		{ $$.typ = mkfloat();
-			  $$.hasval = True;
-			  $$.val.r = $1;
-			}
-	| CHR		{ $$.typ = mkchar();
-			  $$.hasval = True;
-			  $$.val.i = $1;
-			}
-	| STR		{ $$.typ = mkstring();
-			  $$.hasval = True;
-			  $$.val.s = $1;
-			}
-	| CFALSE	{ $$.typ = mkbool();
-			  $$.hasval = True;
-			  $$.val.i = 0;
-			}
-	| CTRUE		{ $$.typ = mkbool();
-			  $$.hasval = True;
-			  $$.val.i = 1;
-			}
-	;
-
-%%
-
-/*
- * ???
- */
-int
-yywrap(void)
-{	return 1;
-}
-
-/******************************************************************************\
-
-	Support routines
-
-\******************************************************************************/
-
-static Node
-op(const char *op, Node p, Node q)
-{	Node	r;
-	Tnode	*typ;
-	r.typ = p.typ;
-	r.sto = Snone;
-	if (p.hasval && q.hasval) {
-		if (integer(p.typ) && integer(q.typ))
-			switch (op[0]) {
-			case '|':	r.val.i = p.val.i |  q.val.i; break;
-			case '^':	r.val.i = p.val.i ^  q.val.i; break;
-			case '&':	r.val.i = p.val.i &  q.val.i; break;
-			case '<':	r.val.i = p.val.i << q.val.i; break;
-			case '>':	r.val.i = p.val.i >> q.val.i; break;
-			case '+':	r.val.i = p.val.i +  q.val.i; break;
-			case '-':	r.val.i = p.val.i -  q.val.i; break;
-			case '*':	r.val.i = p.val.i *  q.val.i; break;
-			case '/':	r.val.i = p.val.i /  q.val.i; break;
-			case '%':	r.val.i = p.val.i %  q.val.i; break;
-			default:	typerror(op);
-			}
-		else if (real(p.typ) && real(q.typ))
-			switch (op[0]) {
-			case '+':	r.val.r = p.val.r + q.val.r; break;
-			case '-':	r.val.r = p.val.r - q.val.r; break;
-			case '*':	r.val.r = p.val.r * q.val.r; break;
-			case '/':	r.val.r = p.val.r / q.val.r; break;
-			default:	typerror(op);
-			}
-		else	semerror("illegal constant operation");
-		r.hasval = True;
-	} else {
-		typ = mgtype(p.typ, q.typ);
-		r.hasval = False;
-	}
-	return r;
-}
-
-static Node
-iop(const char *iop, Node p, Node q)
-{	if (integer(p.typ) && integer(q.typ))
-		return op(iop, p, q);
-	typerror("integer operands only");
-	return p;
-}
-
-static Node
-relop(const char *op, Node p, Node q)
-{	Node	r;
-	Tnode	*typ;
-	r.typ = mkint();
-	r.sto = Snone;
-	r.hasval = False;
-	if (p.typ->type != Tpointer || p.typ != q.typ)
-		typ = mgtype(p.typ, q.typ);
-	return r;
-}
-
-/******************************************************************************\
-
-	Scope management
-
-\******************************************************************************/
-
-/*
-mkscope - initialize scope stack with a new table and offset
-*/
-static void
-mkscope(Table *table, int offset)
-{	sp = stack-1;
-	enterscope(table, offset);
-}
-
-/*
-enterscope - enter a new scope by pushing a new table and offset on the stack
-*/
-static void
-enterscope(Table *table, int offset)
-{	if (++sp == stack+MAXNEST)
-		execerror("maximum scope depth exceeded");
-	sp->table = table;
-	sp->val = 0;
-	sp->offset = offset;
-	sp->grow = True;	/* by default, offset grows */
-	sp->mask = False;
-}
-
-/*
-exitscope - exit a scope by popping the table and offset from the stack
-*/
-static void
-exitscope(void)
-{	check(sp-- != stack, "exitscope() has no matching enterscope()");
-}
-
-/******************************************************************************\
-
-	Undefined symbol
-
-\******************************************************************************/
-
-static Entry*
-undefined(Symbol *sym)
-{	Entry	*p;
-	sprintf(errbuf, "undefined identifier '%s'", sym->name);
-	semwarn(errbuf);
-	p = enter(sp->table, sym);
-	p->level = GLOBAL;
-	p->info.typ = mkint();
-	p->info.sto = Sextern;
-	p->info.hasval = False;
-	return p;
-}
-
-/*
-mgtype - return most general type among two numerical types
-*/
-Tnode*
-mgtype(Tnode *typ1, Tnode *typ2)
-{	if (numeric(typ1) && numeric(typ2)) {
-		if (typ1->type < typ2->type)
-			return typ2;
-	} else	typerror("non-numeric type");
-	return typ1;
-}
-
-/******************************************************************************\
-
-	Type checks
-
-\******************************************************************************/
-
-static int
-integer(Tnode *typ)
-{	switch (typ->type) {
-	case Tchar:
-	case Tshort:
-	case Tint:
-	case Tlong:	return True;
-	default:	break;
-	}
-	return False;
-}
-
-static int
-real(Tnode *typ)
-{	switch (typ->type) {
-	case Tfloat:
-	case Tdouble:
-	case Tldouble:	return True;
-	default:	break;
-	}
-	return False;
-}
-
-static int
-numeric(Tnode *typ)
-{	return integer(typ) || real(typ);
-}
-
-static void
-add_fault(Table *gt)
-{ Table *t;
-  Entry *p1, *p2, *p3, *p4;
-  Symbol *s1, *s2, *s3, *s4;
-  imported = NULL;
-  s1 = lookup("SOAP_ENV__Code");
-  p1 = entry(classtable, s1);
-  if (!p1 || !p1->info.typ->ref)
-  { t = mktable((Table*)0);
-    if (!p1)
-    { p1 = enter(classtable, s1);
-      p1->info.typ = mkstruct(t, 3*4);
-      p1->info.typ->id = s1;
-    }
-    else
-      p1->info.typ->ref = t;
-    p2 = enter(t, lookup("SOAP_ENV__Value"));
-    p2->info.typ = qname;
-    p2->info.minOccurs = 0;
-    p2 = enter(t, lookup("SOAP_ENV__Subcode"));
-    p2->info.typ = mkpointer(p1->info.typ);
-    p2->info.minOccurs = 0;
-  }
-  s2 = lookup("SOAP_ENV__Detail");
-  p2 = entry(classtable, s2);
-  if (!p2 || !p2->info.typ->ref)
-  { t = mktable((Table*)0);
-    if (!p2)
-    { p2 = enter(classtable, s2);
-      p2->info.typ = mkstruct(t, 3*4);
-      p2->info.typ->id = s2;
-    }
-    else
-      p2->info.typ->ref = t;
-    p3 = enter(t, lookup("__any"));
-    p3->info.typ = xml;
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("__type"));
-    p3->info.typ = mkint();
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("fault"));
-    p3->info.typ = mkpointer(mkvoid());
-    p3->info.minOccurs = 0;
-    custom_fault = 0;
-  }
-  s4 = lookup("SOAP_ENV__Reason");
-  p4 = entry(classtable, s4);
-  if (!p4 || !p4->info.typ->ref)
-  { t = mktable((Table*)0);
-    if (!p4)
-    { p4 = enter(classtable, s4);
-      p4->info.typ = mkstruct(t, 4);
-      p4->info.typ->id = s4;
-    }
-    else
-      p4->info.typ->ref = t;
-    p3 = enter(t, lookup("SOAP_ENV__Text"));
-    p3->info.typ = mkstring();
-    p3->info.minOccurs = 0;
-  }
-  s3 = lookup("SOAP_ENV__Fault");
-  p3 = entry(classtable, s3);
-  if (!p3 || !p3->info.typ->ref)
-  { t = mktable(NULL);
-    if (!p3)
-    { p3 = enter(classtable, s3);
-      p3->info.typ = mkstruct(t, 9*4);
-      p3->info.typ->id = s3;
-    }
-    else
-      p3->info.typ->ref = t;
-    p3 = enter(t, lookup("faultcode"));
-    p3->info.typ = qname;
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("faultstring"));
-    p3->info.typ = mkstring();
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("faultactor"));
-    p3->info.typ = mkstring();
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("detail"));
-    p3->info.typ = mkpointer(p2->info.typ);
-    p3->info.minOccurs = 0;
-    p3 = enter(t, s1);
-    p3->info.typ = mkpointer(p1->info.typ);
-    p3->info.minOccurs = 0;
-    p3 = enter(t, s4);
-    p3->info.typ = mkpointer(p4->info.typ);
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("SOAP_ENV__Node"));
-    p3->info.typ = mkstring();
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("SOAP_ENV__Role"));
-    p3->info.typ = mkstring();
-    p3->info.minOccurs = 0;
-    p3 = enter(t, lookup("SOAP_ENV__Detail"));
-    p3->info.typ = mkpointer(p2->info.typ);
-    p3->info.minOccurs = 0;
-  }
-}
-
-static void
-add_soap(void)
-{ Symbol *s = lookup("soap");
-  p = enter(classtable, s);
-  p->info.typ = mkstruct(NULL, 0);
-  p->info.typ->transient = -2;
-  p->info.typ->id = s;
-}
-
-static void
-add_XML(void)
-{ Symbol *s = lookup("_XML");
-  s->token = TYPE;
-  p = enter(typetable, s);
-  xml = p->info.typ = mksymtype(mkstring(), s);
-  p->info.sto = Stypedef;
-}
-
-static void
-add_qname(void)
-{ Symbol *s = lookup("_QName");
-  s->token = TYPE;
-  p = enter(typetable, s);
-  qname = p->info.typ = mksymtype(mkstring(), s);
-  p->info.sto = Stypedef;
-}
-
-static void
-add_header(Table *gt)
-{ Table *t;
-  Entry *p;
-  Symbol *s = lookup("SOAP_ENV__Header");
-  imported = NULL;
-  p = entry(classtable, s);
-  if (!p || !p->info.typ->ref)
-  { t = mktable((Table*)0);
-    if (!p)
-      p = enter(classtable, s);
-    p->info.typ = mkstruct(t, 0);
-    p->info.typ->id = s;
-    custom_header = 0;
-  }
-}
-
-static void
-add_response(Entry *fun, Entry *ret)
-{ Table *t;
-  Entry *p, *q;
-  Symbol *s;
-  size_t i = 0, j, n = strlen(fun->sym->name);
-  char *r = (char*)emalloc(n+100);
-  strcpy(r, fun->sym->name);
-  strcat(r, "Response");
-  do
-  { for (j = 0; j < i; j++)
-      r[n+j+8] = '_';
-    r[n+i+8] = '\0';
-    if (!(s = lookup(r)))
-      s = install(r, ID);
-    i++;
-  } while (entry(classtable, s));
-  free(r);
-  t = mktable((Table*)0);
-  q = enter(t, ret->sym);
-  q->info = ret->info;
-  if (q->info.typ->type == Treference)
-    q->info.typ = (Tnode*)q->info.typ->ref;
-  p = enter(classtable, s);
-  p->info.typ = mkstruct(t, 4);
-  p->info.typ->id = s;
-  fun->info.typ->response = p;
-}
-
-static void
-add_result(Tnode *typ)
-{ Entry *p;
-  if (!typ->ref || !((Tnode*)typ->ref)->ref)
-  { semwarn("response struct/class must be declared before used in function prototype");
-    return;
-  }
-  for (p = ((Table*)((Tnode*)typ->ref)->ref)->list; p; p = p->next)
-    if (p->info.sto & Sreturn)
-      return;
-  for (p = ((Table*)((Tnode*)typ->ref)->ref)->list; p; p = p->next)
-  { if (p->info.typ->type != Tfun && !(p->info.sto & Sattribute) && !is_transient(p->info.typ) && !(p->info.sto & (Sprivate|Sprotected)))
-      p->info.sto = (Storage)((int)p->info.sto | (int)Sreturn);
-      return;
-  }
-}