Mercurial > repos > ktnyt > gembassy
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; - } -}