0
|
1 /*
|
|
2 soapcpp2_yacc.y
|
|
3
|
|
4 Yacc/Bison grammar.
|
|
5
|
|
6 Build notes:
|
|
7
|
|
8 1. Bison 1.6 is known to crash on Win32 systems if YYINITDEPTH is too
|
|
9 small Compile with -DYYINITDEPTH=5000
|
|
10
|
|
11 2. This grammar has one shift/reduce conflict related to the use of a
|
|
12 class declaration with a base class (e.g. class Y : public X) and the
|
|
13 use of a maxOccurs (class Y :10). Internally the conflict is resolved
|
|
14 in favor of a shift by Bison/Yacc, which leads to the correct parsing
|
|
15 behavior. Therefore, the warning can be ignored. If this leads to an
|
|
16 error, then please enable the following directive (around line 121):
|
|
17
|
|
18 %expect 1 // Bison: ignore one shift/reduce conflict
|
|
19
|
|
20 --------------------------------------------------------------------------------
|
|
21 gSOAP XML Web services tools
|
|
22 Copyright (C) 2000-2011, Robert van Engelen, Genivia Inc. All Rights Reserved.
|
|
23 This part of the software is released under ONE of the following licenses:
|
|
24 GPL or Genivia's license for commercial use.
|
|
25 --------------------------------------------------------------------------------
|
|
26 GPL license.
|
|
27
|
|
28 This program is free software; you can redistribute it and/or modify it under
|
|
29 the terms of the GNU General Public License as published by the Free Software
|
|
30 Foundation; either version 2 of the License, or (at your option) any later
|
|
31 version.
|
|
32
|
|
33 This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
34 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
35 PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
36
|
|
37 You should have received a copy of the GNU General Public License along with
|
|
38 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
39 Place, Suite 330, Boston, MA 02111-1307 USA
|
|
40
|
|
41 Author contact information:
|
|
42 engelen@genivia.com / engelen@acm.org
|
|
43
|
|
44 This program is released under the GPL with the additional exemption that
|
|
45 compiling, linking, and/or using OpenSSL is allowed.
|
|
46 --------------------------------------------------------------------------------
|
|
47 A commercial use license is available from Genivia, Inc., contact@genivia.com
|
|
48 --------------------------------------------------------------------------------
|
|
49 */
|
|
50
|
|
51 %{
|
|
52
|
|
53 #include "soapcpp2.h"
|
|
54
|
|
55 #ifdef WIN32
|
|
56 #ifndef __STDC__
|
|
57 #define __STDC__
|
|
58 #endif
|
|
59 #define YYINCLUDED_STDLIB_H
|
|
60 #ifdef WIN32_WITHOUT_SOLARIS_FLEX
|
|
61 extern int soapcpp2lex(void);
|
|
62 #else
|
|
63 extern int yylex(void);
|
|
64 #endif
|
|
65 #else
|
|
66 extern int yylex(void);
|
|
67 #endif
|
|
68
|
|
69 extern int is_XML(Tnode*);
|
|
70
|
|
71 #define MAXNEST 16 /* max. nesting depth of scopes */
|
|
72
|
|
73 struct Scope
|
|
74 { Table *table;
|
|
75 Entry *entry;
|
|
76 Node node;
|
|
77 LONG64 val;
|
|
78 int offset;
|
|
79 Bool grow; /* true if offset grows with declarations */
|
|
80 Bool mask; /* true if enum is mask */
|
|
81 } stack[MAXNEST], /* stack of tables and offsets */
|
|
82 *sp; /* current scope stack pointer */
|
|
83
|
|
84 Table *classtable = (Table*)0,
|
|
85 *enumtable = (Table*)0,
|
|
86 *typetable = (Table*)0,
|
|
87 *booltable = (Table*)0,
|
|
88 *templatetable = (Table*)0;
|
|
89
|
|
90 char *namespaceid = NULL;
|
|
91 int transient = 0;
|
|
92 int permission = 0;
|
|
93 int custom_header = 1;
|
|
94 int custom_fault = 1;
|
|
95 Pragma *pragmas = NULL;
|
|
96 Tnode *qname = NULL;
|
|
97 Tnode *xml = NULL;
|
|
98
|
|
99 /* function prototypes for support routine section */
|
|
100 static Entry *undefined(Symbol*);
|
|
101 static Tnode *mgtype(Tnode*, Tnode*);
|
|
102 static Node op(const char*, Node, Node), iop(const char*, Node, Node), relop(const char*, Node, Node);
|
|
103 static void mkscope(Table*, int), enterscope(Table*, int), exitscope(void);
|
|
104 static int integer(Tnode*), real(Tnode*), numeric(Tnode*);
|
|
105 static void add_soap(void), add_XML(void), add_qname(void), add_header(Table*), add_fault(Table*), add_response(Entry*, Entry*), add_result(Tnode*);
|
|
106 extern char *c_storage(Storage), *c_type(Tnode*), *c_ident(Tnode*);
|
|
107 extern int is_primitive_or_string(Tnode*), is_stdstr(Tnode*), is_binary(Tnode*), is_external(Tnode*), is_mutable(Tnode*), has_attachment(Tnode*);
|
|
108
|
|
109 /* Temporaries used in semantic rules */
|
|
110 int i;
|
|
111 char *s, *s1, *s2;
|
|
112 Symbol *sym;
|
|
113 Entry *p, *q;
|
|
114 Tnode *t;
|
|
115 Node tmp, c;
|
|
116 Pragma **pp;
|
|
117
|
|
118 %}
|
|
119
|
|
120 /* We expect one shift-reduce conflict, see build notes in the header above */
|
|
121 /* %expect 1 */ /* directive is not compatible with Yacc */
|
|
122 /* If Yacc complains then remove the line above to allow Yacc to proceed */
|
|
123
|
|
124 %union
|
|
125 { Symbol *sym;
|
|
126 LONG64 i;
|
|
127 double r;
|
|
128 char c;
|
|
129 char *s;
|
|
130 Tnode *typ;
|
|
131 Storage sto;
|
|
132 Node rec;
|
|
133 Entry *e;
|
|
134 }
|
|
135
|
|
136 /* pragmas */
|
|
137 %token <s> PRAGMA
|
|
138 /* keywords */
|
|
139 %token <sym> AUTO DOUBLE INT STRUCT
|
|
140 %token <sym> BREAK ELSE LONG SWITCH
|
|
141 %token <sym> CASE ENUM REGISTER TYPEDEF
|
|
142 %token <sym> CHAR EXTERN RETURN UNION
|
|
143 %token <sym> CONST FLOAT SHORT UNSIGNED
|
|
144 %token <sym> CONTINUE FOR SIGNED VOID
|
|
145 %token <sym> DEFAULT GOTO SIZEOF VOLATILE
|
|
146 %token <sym> DO IF STATIC WHILE
|
|
147 %token <sym> CLASS PRIVATE PROTECTED PUBLIC
|
|
148 %token <sym> VIRTUAL INLINE OPERATOR LLONG
|
|
149 %token <sym> BOOL CFALSE CTRUE WCHAR
|
|
150 %token <sym> TIME USING NAMESPACE ULLONG
|
|
151 %token <sym> MUSTUNDERSTAND SIZE FRIEND
|
|
152 %token <sym> TEMPLATE EXPLICIT TYPENAME
|
|
153 %token <sym> RESTRICT null
|
|
154 %token <sym> UCHAR USHORT UINT ULONG
|
|
155 /* */
|
|
156 %token NONE
|
|
157 /* identifiers (TYPE = typedef identifier) */
|
|
158 %token <sym> ID LAB TYPE
|
|
159 /* constants */
|
|
160 %token <i> LNG
|
|
161 %token <r> DBL
|
|
162 %token <c> CHR
|
|
163 %token <s> TAG STR
|
|
164 /* types and related */
|
|
165 %type <typ> type
|
|
166 %type <sto> store virtual constobj abstract
|
|
167 %type <e> fname struct class base enum
|
|
168 %type <sym> id arg name
|
|
169 %type <s> tag patt
|
|
170 %type <i> cint
|
|
171 /* expressions and statements */
|
|
172 %type <rec> expr cexp oexp obex aexp abex rexp lexp pexp init spec tspec ptrs array arrayck texp qexp occurs
|
|
173 /* terminals */
|
|
174 %left ','
|
|
175 %right '=' PA NA TA DA MA AA XA OA LA RA /* += -= *= /= %= &= ^= |= <<= >>= */
|
|
176 %right '?'
|
|
177 %right ':'
|
|
178 %left OR /* || */
|
|
179 %left AN /* && */
|
|
180 %left '|'
|
|
181 %left '^'
|
|
182 %left '&'
|
|
183 %left EQ NE /* == != */
|
|
184 %left '<' LE '>' GE /* <= >= */
|
|
185 %left LS RS /* << >> */
|
|
186 %left '+' '-'
|
|
187 %left '*' '/' '%'
|
|
188 %left AR /* -> */
|
|
189 %token PP NN /* ++ -- */
|
|
190
|
|
191 %%
|
|
192
|
|
193 /******************************************************************************\
|
|
194
|
|
195 Program syntax
|
|
196
|
|
197 \******************************************************************************/
|
|
198
|
|
199 prog : s1 exts { if (lflag)
|
|
200 { custom_header = 0;
|
|
201 custom_fault = 0;
|
|
202 }
|
|
203 else
|
|
204 { add_header(sp->table);
|
|
205 add_fault(sp->table);
|
|
206 }
|
|
207 compile(sp->table);
|
|
208 freetable(classtable);
|
|
209 freetable(enumtable);
|
|
210 freetable(typetable);
|
|
211 freetable(booltable);
|
|
212 freetable(templatetable);
|
|
213 }
|
|
214 ;
|
|
215 s1 : /* empty */ { classtable = mktable((Table*)0);
|
|
216 enumtable = mktable((Table*)0);
|
|
217 typetable = mktable((Table*)0);
|
|
218 booltable = mktable((Table*)0);
|
|
219 templatetable = mktable((Table*)0);
|
|
220 p = enter(booltable, lookup("false"));
|
|
221 p->info.typ = mkint();
|
|
222 p->info.val.i = 0;
|
|
223 p = enter(booltable, lookup("true"));
|
|
224 p->info.typ = mkint();
|
|
225 p->info.val.i = 1;
|
|
226 mkscope(mktable(mktable((Table*)0)), 0);
|
|
227 }
|
|
228 ;
|
|
229 exts : NAMESPACE ID '{' exts1 '}'
|
|
230 { namespaceid = $2->name; }
|
|
231 | exts1 { }
|
|
232 ;
|
|
233 exts1 : /* empty */ { add_soap();
|
|
234 add_qname();
|
|
235 add_XML();
|
|
236 }
|
|
237 | exts1 ext { }
|
|
238 ;
|
|
239 ext : dclrs ';' { }
|
|
240 | pragma { }
|
|
241 | error ';' { synerror("input before ; skipped");
|
|
242 while (sp > stack)
|
|
243 { freetable(sp->table);
|
|
244 exitscope();
|
|
245 }
|
|
246 yyerrok;
|
|
247 }
|
|
248 | t1 { }
|
|
249 | t2 { }
|
|
250 ;
|
|
251 pragma : PRAGMA { if ($1[1] >= 'a' && $1[1] <= 'z')
|
|
252 { for (pp = &pragmas; *pp; pp = &(*pp)->next)
|
|
253 ;
|
|
254 *pp = (Pragma*)emalloc(sizeof(Pragma));
|
|
255 (*pp)->pragma = (char*)emalloc(strlen($1)+1);
|
|
256 strcpy((*pp)->pragma, $1);
|
|
257 (*pp)->next = NULL;
|
|
258 }
|
|
259 else if ((i = atoi($1+2)) > 0)
|
|
260 yylineno = i;
|
|
261 else
|
|
262 { sprintf(errbuf, "directive '%s' ignored (use #import to import files)", $1);
|
|
263 semwarn(errbuf);
|
|
264 }
|
|
265 }
|
|
266 ;
|
|
267
|
|
268 /******************************************************************************\
|
|
269
|
|
270 Declarations
|
|
271
|
|
272 \******************************************************************************/
|
|
273
|
|
274 decls : /* empty */ { transient &= ~6;
|
|
275 permission = 0;
|
|
276 }
|
|
277 | dclrs ';' decls
|
|
278 { }
|
|
279 | PRIVATE ':' t3 decls
|
|
280 { }
|
|
281 | PROTECTED ':' t4 decls
|
|
282 { }
|
|
283 | PUBLIC ':' t5 decls
|
|
284 { }
|
|
285 | t1 decls t2 decls
|
|
286 { }
|
|
287 | error ';' { synerror("declaration expected"); yyerrok; }
|
|
288 ;
|
|
289 t1 : '[' { transient |= 1;
|
|
290 }
|
|
291 ;
|
|
292 t2 : ']' { transient &= ~1;
|
|
293 }
|
|
294 ;
|
|
295 t3 : { permission = Sprivate;
|
|
296 }
|
|
297 ;
|
|
298 t4 : { permission = Sprotected;
|
|
299 }
|
|
300 ;
|
|
301 t5 : { permission = 0;
|
|
302 }
|
|
303 ;
|
|
304 dclrs : spec { }
|
|
305 | spec dclr { }
|
|
306 | spec fdclr func
|
|
307 { }
|
|
308 | constr func { }
|
|
309 | destr func { }
|
|
310 | dclrs ',' dclr{ }
|
|
311 | dclrs ',' fdclr func
|
|
312 { }
|
|
313 ;
|
|
314 dclr : ptrs ID arrayck tag occurs init
|
|
315 { if (($3.sto & Stypedef) && sp->table->level == GLOBAL)
|
|
316 { if (($3.typ->type != Tstruct && $3.typ->type != Tunion && $3.typ->type != Tenum) || strcmp($2->name, $3.typ->id->name))
|
|
317 { p = enter(typetable, $2);
|
|
318 p->info.typ = mksymtype($3.typ, $2);
|
|
319 if ($3.sto & Sextern)
|
|
320 p->info.typ->transient = -1;
|
|
321 else
|
|
322 p->info.typ->transient = $3.typ->transient;
|
|
323 p->info.sto = $3.sto;
|
|
324 p->info.typ->pattern = $5.pattern;
|
|
325 p->info.typ->minLength = $5.minLength;
|
|
326 p->info.typ->maxLength = $5.maxLength;
|
|
327 }
|
|
328 $2->token = TYPE;
|
|
329 }
|
|
330 else
|
|
331 { p = enter(sp->table, $2);
|
|
332 p->tag = $4;
|
|
333 p->info.typ = $3.typ;
|
|
334 p->info.sto = (Storage)((int)$3.sto | permission);
|
|
335 if ($6.hasval)
|
|
336 { p->info.hasval = True;
|
|
337 switch ($3.typ->type)
|
|
338 { case Tchar:
|
|
339 case Tuchar:
|
|
340 case Tshort:
|
|
341 case Tushort:
|
|
342 case Tint:
|
|
343 case Tuint:
|
|
344 case Tlong:
|
|
345 case Tulong:
|
|
346 case Tllong:
|
|
347 case Tullong:
|
|
348 case Tenum:
|
|
349 case Ttime:
|
|
350 if ($6.typ->type == Tint || $6.typ->type == Tchar || $6.typ->type == Tenum)
|
|
351 sp->val = p->info.val.i = $6.val.i;
|
|
352 else
|
|
353 { semerror("type error in initialization constant");
|
|
354 p->info.hasval = False;
|
|
355 }
|
|
356 break;
|
|
357 case Tfloat:
|
|
358 case Tdouble:
|
|
359 case Tldouble:
|
|
360 if ($6.typ->type == Tfloat || $6.typ->type == Tdouble || $6.typ->type == Tldouble)
|
|
361 p->info.val.r = $6.val.r;
|
|
362 else if ($6.typ->type == Tint)
|
|
363 p->info.val.r = (double)$6.val.i;
|
|
364 else
|
|
365 { semerror("type error in initialization constant");
|
|
366 p->info.hasval = False;
|
|
367 }
|
|
368 break;
|
|
369 default:
|
|
370 if ($3.typ->type == Tpointer
|
|
371 && (((Tnode*)$3.typ->ref)->type == Tchar || ((Tnode*)$3.typ->ref)->type == Twchar)
|
|
372 && $6.typ->type == Tpointer
|
|
373 && ((Tnode*)$6.typ->ref)->type == Tchar)
|
|
374 p->info.val.s = $6.val.s;
|
|
375 else if (bflag
|
|
376 && $3.typ->type == Tarray
|
|
377 && ((Tnode*)$3.typ->ref)->type == Tchar
|
|
378 && $6.typ->type == Tpointer
|
|
379 && ((Tnode*)$6.typ->ref)->type == Tchar)
|
|
380 { if ($3.typ->width / ((Tnode*)$3.typ->ref)->width - 1 < strlen($6.val.s))
|
|
381 { semerror("char[] initialization constant too long");
|
|
382 p->info.val.s = "";
|
|
383 }
|
|
384
|
|
385 else
|
|
386 p->info.val.s = $6.val.s;
|
|
387 }
|
|
388 else if ($3.typ->type == Tpointer
|
|
389 && (((Tnode*)$3.typ->ref)->id == lookup("std::string") || ((Tnode*)$3.typ->ref)->id == lookup("std::wstring")))
|
|
390 p->info.val.s = $6.val.s;
|
|
391 else if ($3.typ->id == lookup("std::string") || $3.typ->id == lookup("std::wstring"))
|
|
392 p->info.val.s = $6.val.s;
|
|
393 else if ($3.typ->type == Tpointer
|
|
394 && $6.typ->type == Tint
|
|
395 && $6.val.i == 0)
|
|
396 p->info.val.i = 0;
|
|
397 else
|
|
398 { semerror("type error in initialization constant");
|
|
399 p->info.hasval = False;
|
|
400 }
|
|
401 break;
|
|
402 }
|
|
403 }
|
|
404 else
|
|
405 p->info.val.i = sp->val;
|
|
406 if ($5.minOccurs < 0)
|
|
407 { if ($6.hasval || ($3.sto & Sattribute) || $3.typ->type == Tpointer || $3.typ->type == Ttemplate || !strncmp($2->name, "__size", 6))
|
|
408 p->info.minOccurs = 0;
|
|
409 else
|
|
410 p->info.minOccurs = 1;
|
|
411 }
|
|
412 else
|
|
413 p->info.minOccurs = $5.minOccurs;
|
|
414 p->info.maxOccurs = $5.maxOccurs;
|
|
415 if (sp->mask)
|
|
416 sp->val <<= 1;
|
|
417 else
|
|
418 sp->val++;
|
|
419 p->info.offset = sp->offset;
|
|
420 if ($3.sto & Sextern)
|
|
421 p->level = GLOBAL;
|
|
422 else if ($3.sto & Stypedef)
|
|
423 ;
|
|
424 else if (sp->grow)
|
|
425 sp->offset += p->info.typ->width;
|
|
426 else if (p->info.typ->width > sp->offset)
|
|
427 sp->offset = p->info.typ->width;
|
|
428 }
|
|
429 sp->entry = p;
|
|
430 }
|
|
431 ;
|
|
432 fdclr : ptrs name { if ($1.sto & Stypedef)
|
|
433 { sprintf(errbuf, "invalid typedef qualifier for '%s'", $2->name);
|
|
434 semwarn(errbuf);
|
|
435 }
|
|
436 p = enter(sp->table, $2);
|
|
437 p->info.typ = $1.typ;
|
|
438 p->info.sto = $1.sto;
|
|
439 p->info.hasval = False;
|
|
440 p->info.offset = sp->offset;
|
|
441 if (sp->grow)
|
|
442 sp->offset += p->info.typ->width;
|
|
443 else if (p->info.typ->width > sp->offset)
|
|
444 sp->offset = p->info.typ->width;
|
|
445 sp->entry = p;
|
|
446 }
|
|
447 ;
|
|
448 id : ID { $$ = $1; }
|
|
449 | TYPE { $$ = $1; }
|
|
450 ;
|
|
451 name : ID { $$ = $1; }
|
|
452 | OPERATOR '!' { $$ = lookup("operator!"); }
|
|
453 | OPERATOR '~' { $$ = lookup("operator~"); }
|
|
454 | OPERATOR '=' { $$ = lookup("operator="); }
|
|
455 | OPERATOR PA { $$ = lookup("operator+="); }
|
|
456 | OPERATOR NA { $$ = lookup("operator-="); }
|
|
457 | OPERATOR TA { $$ = lookup("operator*="); }
|
|
458 | OPERATOR DA { $$ = lookup("operator/="); }
|
|
459 | OPERATOR MA { $$ = lookup("operator%="); }
|
|
460 | OPERATOR AA { $$ = lookup("operator&="); }
|
|
461 | OPERATOR XA { $$ = lookup("operator^="); }
|
|
462 | OPERATOR OA { $$ = lookup("operator|="); }
|
|
463 | OPERATOR LA { $$ = lookup("operator<<="); }
|
|
464 | OPERATOR RA { $$ = lookup("operator>>="); }
|
|
465 | OPERATOR OR { $$ = lookup("operator||"); }
|
|
466 | OPERATOR AN { $$ = lookup("operator&&"); }
|
|
467 | OPERATOR '|' { $$ = lookup("operator|"); }
|
|
468 | OPERATOR '^' { $$ = lookup("operator^"); }
|
|
469 | OPERATOR '&' { $$ = lookup("operator&"); }
|
|
470 | OPERATOR EQ { $$ = lookup("operator=="); }
|
|
471 | OPERATOR NE { $$ = lookup("operator!="); }
|
|
472 | OPERATOR '<' { $$ = lookup("operator<"); }
|
|
473 | OPERATOR LE { $$ = lookup("operator<="); }
|
|
474 | OPERATOR '>' { $$ = lookup("operator>"); }
|
|
475 | OPERATOR GE { $$ = lookup("operator>="); }
|
|
476 | OPERATOR LS { $$ = lookup("operator<<"); }
|
|
477 | OPERATOR RS { $$ = lookup("operator>>"); }
|
|
478 | OPERATOR '+' { $$ = lookup("operator+"); }
|
|
479 | OPERATOR '-' { $$ = lookup("operator-"); }
|
|
480 | OPERATOR '*' { $$ = lookup("operator*"); }
|
|
481 | OPERATOR '/' { $$ = lookup("operator/"); }
|
|
482 | OPERATOR '%' { $$ = lookup("operator%"); }
|
|
483 | OPERATOR PP { $$ = lookup("operator++"); }
|
|
484 | OPERATOR NN { $$ = lookup("operator--"); }
|
|
485 | OPERATOR AR { $$ = lookup("operator->"); }
|
|
486 | OPERATOR'['']'{ $$ = lookup("operator[]"); }
|
|
487 | OPERATOR'('')'{ $$ = lookup("operator()"); }
|
|
488 | OPERATOR texp { s1 = c_storage($2.sto);
|
|
489 s2 = c_type($2.typ);
|
|
490 s = (char*)emalloc(strlen(s1) + strlen(s2) + 10);
|
|
491 strcpy(s, "operator ");
|
|
492 strcat(s, s1);
|
|
493 strcat(s, s2);
|
|
494 $$ = lookup(s);
|
|
495 if (!$$)
|
|
496 $$ = install(s, ID);
|
|
497 }
|
|
498 ;
|
|
499 constr : TYPE { if (!(p = entry(classtable, $1)))
|
|
500 semerror("invalid constructor");
|
|
501 sp->entry = enter(sp->table, $1);
|
|
502 sp->entry->info.typ = mknone();
|
|
503 sp->entry->info.sto = Snone;
|
|
504 sp->entry->info.offset = sp->offset;
|
|
505 sp->node.typ = mkvoid();
|
|
506 sp->node.sto = Snone;
|
|
507 }
|
|
508 ;
|
|
509 destr : virtual '~' TYPE
|
|
510 { if (!(p = entry(classtable, $3)))
|
|
511 semerror("invalid destructor");
|
|
512 s = (char*)emalloc(strlen($3->name) + 2);
|
|
513 strcpy(s, "~");
|
|
514 strcat(s, $3->name);
|
|
515 sym = lookup(s);
|
|
516 if (!sym)
|
|
517 sym = install(s, ID);
|
|
518 sp->entry = enter(sp->table, sym);
|
|
519 sp->entry->info.typ = mknone();
|
|
520 sp->entry->info.sto = $1;
|
|
521 sp->entry->info.offset = sp->offset;
|
|
522 sp->node.typ = mkvoid();
|
|
523 sp->node.sto = Snone;
|
|
524 }
|
|
525 ;
|
|
526 func : fname '(' s6 fargso ')' constobj abstract
|
|
527 { if ($1->level == GLOBAL)
|
|
528 { if (!($1->info.sto & Sextern) && sp->entry && sp->entry->info.typ->type == Tpointer && ((Tnode*)sp->entry->info.typ->ref)->type == Tchar)
|
|
529 { 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);
|
|
530 semwarn(errbuf);
|
|
531 }
|
|
532 if ($1->info.sto & Sextern)
|
|
533 $1->info.typ = mkmethod($1->info.typ, sp->table);
|
|
534 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)))
|
|
535 { if ($1->info.typ->type == Tint)
|
|
536 { sp->entry->info.sto = (Storage)((int)sp->entry->info.sto | (int)Sreturn);
|
|
537 $1->info.typ = mkfun(sp->entry);
|
|
538 $1->info.typ->id = $1->sym;
|
|
539 if (!is_transient(sp->entry->info.typ))
|
|
540 { if (!is_response(sp->entry->info.typ))
|
|
541 { if (!is_XML(sp->entry->info.typ))
|
|
542 add_response($1, sp->entry);
|
|
543 }
|
|
544 else
|
|
545 add_result(sp->entry->info.typ);
|
|
546 }
|
|
547 }
|
|
548 else
|
|
549 { sprintf(errbuf, "return type of remote method function prototype '%s' must be integer", $1->sym->name);
|
|
550 semerror(errbuf);
|
|
551 }
|
|
552 }
|
|
553 else
|
|
554 { 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);
|
|
555 semerror(errbuf);
|
|
556 }
|
|
557 if (!($1->info.sto & Sextern))
|
|
558 { unlinklast(sp->table);
|
|
559 if ((p = entry(classtable, $1->sym)))
|
|
560 { if (p->info.typ->ref)
|
|
561 { sprintf(errbuf, "remote method name clash: struct/class '%s' already declared at line %d", $1->sym->name, p->lineno);
|
|
562 semerror(errbuf);
|
|
563 }
|
|
564 else
|
|
565 { p->info.typ->ref = sp->table;
|
|
566 p->info.typ->width = sp->offset;
|
|
567 }
|
|
568 }
|
|
569 else
|
|
570 { p = enter(classtable, $1->sym);
|
|
571 p->info.typ = mkstruct(sp->table, sp->offset);
|
|
572 p->info.typ->id = $1->sym;
|
|
573 }
|
|
574 }
|
|
575 }
|
|
576 else if ($1->level == INTERNAL)
|
|
577 { $1->info.typ = mkmethod($1->info.typ, sp->table);
|
|
578 $1->info.sto = (Storage)((int)$1->info.sto | (int)$6 | (int)$7);
|
|
579 transient &= ~1;
|
|
580 }
|
|
581 exitscope();
|
|
582 }
|
|
583 ;
|
|
584 fname : { $$ = sp->entry; }
|
|
585 ;
|
|
586 fargso : /* empty */ { }
|
|
587 | fargs { }
|
|
588 ;
|
|
589 fargs : farg { }
|
|
590 | farg ',' fargs{ }
|
|
591 ;
|
|
592 farg : tspec ptrs arg arrayck occurs init
|
|
593 { if ($4.sto & Stypedef)
|
|
594 semwarn("typedef in function argument");
|
|
595 p = enter(sp->table, $3);
|
|
596 p->info.typ = $4.typ;
|
|
597 p->info.sto = $4.sto;
|
|
598 if ($5.minOccurs < 0)
|
|
599 { if ($6.hasval || ($4.sto & Sattribute) || $4.typ->type == Tpointer)
|
|
600 p->info.minOccurs = 0;
|
|
601 else
|
|
602 p->info.minOccurs = 1;
|
|
603 }
|
|
604 else
|
|
605 p->info.minOccurs = $5.minOccurs;
|
|
606 p->info.maxOccurs = $5.maxOccurs;
|
|
607 if ($6.hasval)
|
|
608 { p->info.hasval = True;
|
|
609 switch ($4.typ->type)
|
|
610 { case Tchar:
|
|
611 case Tuchar:
|
|
612 case Tshort:
|
|
613 case Tushort:
|
|
614 case Tint:
|
|
615 case Tuint:
|
|
616 case Tlong:
|
|
617 case Tulong:
|
|
618 case Tenum:
|
|
619 case Ttime:
|
|
620 if ($6.typ->type == Tint || $6.typ->type == Tchar || $6.typ->type == Tenum)
|
|
621 sp->val = p->info.val.i = $6.val.i;
|
|
622 else
|
|
623 { semerror("type error in initialization constant");
|
|
624 p->info.hasval = False;
|
|
625 }
|
|
626 break;
|
|
627 case Tfloat:
|
|
628 case Tdouble:
|
|
629 case Tldouble:
|
|
630 if ($6.typ->type == Tfloat || $6.typ->type == Tdouble || $6.typ->type == Tldouble)
|
|
631 p->info.val.r = $6.val.r;
|
|
632 else if ($6.typ->type == Tint)
|
|
633 p->info.val.r = (double)$6.val.i;
|
|
634 else
|
|
635 { semerror("type error in initialization constant");
|
|
636 p->info.hasval = False;
|
|
637 }
|
|
638 break;
|
|
639 default:
|
|
640 if ($4.typ->type == Tpointer
|
|
641 && (((Tnode*)$4.typ->ref)->type == Tchar || ((Tnode*)$4.typ->ref)->type == Twchar)
|
|
642 && $6.typ->type == Tpointer
|
|
643 && ((Tnode*)$6.typ->ref)->type == Tchar)
|
|
644 p->info.val.s = $6.val.s;
|
|
645 else if ($4.typ->type == Tpointer
|
|
646 && (((Tnode*)$4.typ->ref)->id == lookup("std::string") || ((Tnode*)$4.typ->ref)->id == lookup("std::wstring")))
|
|
647 p->info.val.s = $6.val.s;
|
|
648 else if ($4.typ->id == lookup("std::string") || $4.typ->id == lookup("std::wstring"))
|
|
649 p->info.val.s = $6.val.s;
|
|
650 else if ($4.typ->type == Tpointer
|
|
651 && $6.typ->type == Tint
|
|
652 && $6.val.i == 0)
|
|
653 p->info.val.i = 0;
|
|
654 else
|
|
655 { semerror("type error in initialization constant");
|
|
656 p->info.hasval = False;
|
|
657 }
|
|
658 break;
|
|
659 }
|
|
660 }
|
|
661 p->info.offset = sp->offset;
|
|
662 if ($4.sto & Sextern)
|
|
663 p->level = GLOBAL;
|
|
664 else if (sp->grow)
|
|
665 sp->offset += p->info.typ->width;
|
|
666 else if (p->info.typ->width > sp->offset)
|
|
667 sp->offset = p->info.typ->width;
|
|
668 sp->entry = p;
|
|
669 }
|
|
670 ;
|
|
671 arg : /* empty */ { if (sp->table->level != PARAM)
|
|
672 $$ = gensymidx("param", (int)++sp->val);
|
|
673 else if (eflag)
|
|
674 $$ = gensymidx("_param", (int)++sp->val);
|
|
675 else
|
|
676 $$ = gensym("_param");
|
|
677 }
|
|
678 | ID { if (vflag == 2 && *$1->name == '_' && sp->table->level == GLOBAL)
|
|
679 { sprintf(errbuf, "SOAP 1.2 does not support anonymous parameters '%s'", $1->name);
|
|
680 semwarn(errbuf);
|
|
681 }
|
|
682 $$ = $1;
|
|
683 }
|
|
684 ;
|
|
685
|
|
686 /******************************************************************************\
|
|
687
|
|
688 Type specification
|
|
689
|
|
690 \******************************************************************************/
|
|
691
|
|
692 /* texp : type expression (subset of C) */
|
|
693 texp : tspec ptrs array
|
|
694 { $$ = $3; }
|
|
695 | tspec ptrs ID array
|
|
696 { $$ = $4; }
|
|
697 ;
|
|
698 spec : /*empty */ { $$.typ = mkint();
|
|
699 $$.sto = Snone;
|
|
700 sp->node = $$;
|
|
701 }
|
|
702 | store spec { if (($1 & Stypedef) && is_external($2.typ) && $2.typ->type != Tstruct && $2.typ->type != Tclass)
|
|
703 $$.typ = mktype($2.typ->type, $2.typ->ref, $2.typ->width);
|
|
704 else
|
|
705 $$.typ = $2.typ;
|
|
706 $$.sto = (Storage)((int)$1 | ((int)($2.sto)));
|
|
707 if (($$.sto & Sattribute) && !is_primitive_or_string($2.typ) && !is_stdstr($2.typ) && !is_binary($2.typ) && !is_external($2.typ))
|
|
708 { semwarn("invalid attribute type");
|
|
709 $$.sto = (Storage)((int)$$.sto & ~Sattribute);
|
|
710 }
|
|
711 sp->node = $$;
|
|
712 if ($1 & Sextern)
|
|
713 transient = 0;
|
|
714 }
|
|
715 | type spec { if ($1->type == Tint)
|
|
716 switch ($2.typ->type)
|
|
717 { case Tchar: $$.typ = $2.typ; break;
|
|
718 case Tshort: $$.typ = $2.typ; break;
|
|
719 case Tint: $$.typ = $1; break;
|
|
720 case Tlong: $$.typ = $2.typ; break;
|
|
721 case Tllong: $$.typ = $2.typ; break;
|
|
722 default: semwarn("illegal use of 'signed'");
|
|
723 $$.typ = $2.typ;
|
|
724 }
|
|
725 else if ($1->type == Tuint)
|
|
726 switch ($2.typ->type)
|
|
727 { case Tchar: $$.typ = mkuchar(); break;
|
|
728 case Tshort: $$.typ = mkushort(); break;
|
|
729 case Tint: $$.typ = $1; break;
|
|
730 case Tlong: $$.typ = mkulong(); break;
|
|
731 case Tllong: $$.typ = mkullong(); break;
|
|
732 default: semwarn("illegal use of 'unsigned'");
|
|
733 $$.typ = $2.typ;
|
|
734 }
|
|
735 else if ($1->type == Tlong)
|
|
736 switch ($2.typ->type)
|
|
737 { case Tint: $$.typ = $1; break;
|
|
738 case Tlong: $$.typ = mkllong(); break;
|
|
739 case Tuint: $$.typ = mkulong(); break;
|
|
740 case Tulong: $$.typ = mkullong(); break;
|
|
741 case Tdouble: $$.typ = mkldouble(); break;
|
|
742 default: semwarn("illegal use of 'long'");
|
|
743 $$.typ = $2.typ;
|
|
744 }
|
|
745 else if ($1->type == Tulong)
|
|
746 switch ($2.typ->type)
|
|
747 { case Tint: $$.typ = $1; break;
|
|
748 case Tlong: $$.typ = mkullong(); break;
|
|
749 case Tuint: $$.typ = $1; break;
|
|
750 case Tulong: $$.typ = mkullong(); break;
|
|
751 default: semwarn("illegal use of 'long'");
|
|
752 $$.typ = $2.typ;
|
|
753 }
|
|
754 else if ($2.typ->type == Tint)
|
|
755 $$.typ = $1;
|
|
756 else
|
|
757 semwarn("invalid type (missing ';' or type name used as non-type identifier?)");
|
|
758 $$.sto = $2.sto;
|
|
759 sp->node = $$;
|
|
760 }
|
|
761 ;
|
|
762 tspec : store { $$.typ = mkint();
|
|
763 $$.sto = $1;
|
|
764 sp->node = $$;
|
|
765 if ($1 & Sextern)
|
|
766 transient = 0;
|
|
767 }
|
|
768 | type { $$.typ = $1;
|
|
769 $$.sto = Snone;
|
|
770 sp->node = $$;
|
|
771 }
|
|
772 | store tspec { $$.typ = $2.typ;
|
|
773 $$.sto = (Storage)((int)$1 | (int)$2.sto);
|
|
774 if (($$.sto & Sattribute) && !is_primitive_or_string($2.typ) && !is_stdstr($2.typ) && !is_binary($2.typ) && !is_external($2.typ))
|
|
775 { semwarn("invalid attribute type");
|
|
776 $$.sto = (Storage)((int)$$.sto & ~Sattribute);
|
|
777 }
|
|
778 sp->node = $$;
|
|
779 if ($1 & Sextern)
|
|
780 transient = 0;
|
|
781 }
|
|
782 | type tspec { if ($1->type == Tint)
|
|
783 switch ($2.typ->type)
|
|
784 { case Tchar: $$.typ = $2.typ; break;
|
|
785 case Tshort: $$.typ = $2.typ; break;
|
|
786 case Tint: $$.typ = $1; break;
|
|
787 case Tlong: $$.typ = $2.typ; break;
|
|
788 case Tllong: $$.typ = $2.typ; break;
|
|
789 default: semwarn("illegal use of 'signed'");
|
|
790 $$.typ = $2.typ;
|
|
791 }
|
|
792 else if ($1->type == Tuint)
|
|
793 switch ($2.typ->type)
|
|
794 { case Tchar: $$.typ = mkuchar(); break;
|
|
795 case Tshort: $$.typ = mkushort(); break;
|
|
796 case Tint: $$.typ = $1; break;
|
|
797 case Tlong: $$.typ = mkulong(); break;
|
|
798 case Tllong: $$.typ = mkullong(); break;
|
|
799 default: semwarn("illegal use of 'unsigned'");
|
|
800 $$.typ = $2.typ;
|
|
801 }
|
|
802 else if ($1->type == Tlong)
|
|
803 switch ($2.typ->type)
|
|
804 { case Tint: $$.typ = $1; break;
|
|
805 case Tlong: $$.typ = mkllong(); break;
|
|
806 case Tuint: $$.typ = mkulong(); break;
|
|
807 case Tulong: $$.typ = mkullong(); break;
|
|
808 case Tdouble: $$.typ = mkldouble(); break;
|
|
809 default: semwarn("illegal use of 'long'");
|
|
810 $$.typ = $2.typ;
|
|
811 }
|
|
812 else if ($1->type == Tulong)
|
|
813 switch ($2.typ->type)
|
|
814 { case Tint: $$.typ = $1; break;
|
|
815 case Tlong: $$.typ = mkullong(); break;
|
|
816 case Tuint: $$.typ = $1; break;
|
|
817 case Tulong: $$.typ = mkullong(); break;
|
|
818 default: semwarn("illegal use of 'long'");
|
|
819 $$.typ = $2.typ;
|
|
820 }
|
|
821 else if ($2.typ->type == Tint)
|
|
822 $$.typ = $1;
|
|
823 else
|
|
824 semwarn("invalid type");
|
|
825 $$.sto = $2.sto;
|
|
826 sp->node = $$;
|
|
827 }
|
|
828 ;
|
|
829 type : VOID { $$ = mkvoid(); }
|
|
830 | BOOL { $$ = mkbool(); }
|
|
831 | CHAR { $$ = mkchar(); }
|
|
832 | WCHAR { $$ = mkwchart(); }
|
|
833 | SHORT { $$ = mkshort(); }
|
|
834 | INT { $$ = mkint(); }
|
|
835 | LONG { $$ = mklong(); }
|
|
836 | LLONG { $$ = mkllong(); }
|
|
837 | ULLONG { $$ = mkullong(); }
|
|
838 | SIZE { $$ = mkulong(); }
|
|
839 | FLOAT { $$ = mkfloat(); }
|
|
840 | DOUBLE { $$ = mkdouble(); }
|
|
841 | SIGNED { $$ = mkint(); }
|
|
842 | UNSIGNED { $$ = mkuint(); }
|
|
843 | UCHAR { $$ = mkuchar(); }
|
|
844 | USHORT { $$ = mkushort(); }
|
|
845 | UINT { $$ = mkuint(); }
|
|
846 | ULONG { $$ = mkulong(); }
|
|
847 | TIME { $$ = mktimet(); }
|
|
848 | TEMPLATE '<' tname id '>' CLASS id
|
|
849 { if (!(p = entry(templatetable, $7)))
|
|
850 { p = enter(templatetable, $7);
|
|
851 p->info.typ = mktemplate(NULL, $7);
|
|
852 $7->token = TYPE;
|
|
853 }
|
|
854 $$ = p->info.typ;
|
|
855 }
|
|
856 | CLASS '{' s2 decls '}'
|
|
857 { sym = gensym("_Struct");
|
|
858 sprintf(errbuf, "anonymous class will be named '%s'", sym->name);
|
|
859 semwarn(errbuf);
|
|
860 if ((p = entry(classtable, sym)))
|
|
861 { if (p->info.typ->ref || p->info.typ->type != Tclass)
|
|
862 { sprintf(errbuf, "class '%s' already declared at line %d", sym->name, p->lineno);
|
|
863 semerror(errbuf);
|
|
864 }
|
|
865 }
|
|
866 else
|
|
867 { p = enter(classtable, sym);
|
|
868 p->info.typ = mkclass((Table*)0, 0);
|
|
869 }
|
|
870 sym->token = TYPE;
|
|
871 sp->table->sym = sym;
|
|
872 p->info.typ->ref = sp->table;
|
|
873 p->info.typ->width = sp->offset;
|
|
874 p->info.typ->id = sym;
|
|
875 $$ = p->info.typ;
|
|
876 exitscope();
|
|
877 }
|
|
878 | class '{' s2 decls '}'
|
|
879 { p = reenter(classtable, $1->sym);
|
|
880 sp->table->sym = p->sym;
|
|
881 p->info.typ->ref = sp->table;
|
|
882 p->info.typ->width = sp->offset;
|
|
883 p->info.typ->id = p->sym;
|
|
884 if (p->info.typ->base)
|
|
885 sp->table->prev = (Table*)entry(classtable, p->info.typ->base)->info.typ->ref;
|
|
886 $$ = p->info.typ;
|
|
887 exitscope();
|
|
888 }
|
|
889 | class ':' base '{' s2 decls '}'
|
|
890 { p = reenter(classtable, $1->sym);
|
|
891 sp->table->sym = p->sym;
|
|
892 if (!$3)
|
|
893 semerror("invalid base class");
|
|
894 else
|
|
895 { sp->table->prev = (Table*)$3->info.typ->ref;
|
|
896 if (!sp->table->prev && !$3->info.typ->transient)
|
|
897 { sprintf(errbuf, "class '%s' has incomplete type", $3->sym->name);
|
|
898 semerror(errbuf);
|
|
899 }
|
|
900 p->info.typ->base = $3->info.typ->id;
|
|
901 }
|
|
902 p->info.typ->ref = sp->table;
|
|
903 p->info.typ->width = sp->offset;
|
|
904 p->info.typ->id = p->sym;
|
|
905 $$ = p->info.typ;
|
|
906 exitscope();
|
|
907 }
|
|
908 | class { $1->info.typ->id = $1->sym;
|
|
909 $$ = $1->info.typ;
|
|
910 }
|
|
911 | class ':' base
|
|
912 { if (!$3)
|
|
913 semerror("invalid base class");
|
|
914 else
|
|
915 { if (!$3->info.typ->ref && !$3->info.typ->transient)
|
|
916 { sprintf(errbuf, "class '%s' has incomplete type", $3->sym->name);
|
|
917 semerror(errbuf);
|
|
918 }
|
|
919 $1->info.typ->base = $3->info.typ->id;
|
|
920 }
|
|
921 $1->info.typ->id = $1->sym;
|
|
922 $$ = $1->info.typ;
|
|
923 }
|
|
924 | STRUCT '{' s2 decls '}'
|
|
925 { sym = gensym("_Struct");
|
|
926 sprintf(errbuf, "anonymous struct will be named '%s'", sym->name);
|
|
927 semwarn(errbuf);
|
|
928 if ((p = entry(classtable, sym)))
|
|
929 { if (p->info.typ->ref || p->info.typ->type != Tstruct)
|
|
930 { sprintf(errbuf, "struct '%s' already declared at line %d", sym->name, p->lineno);
|
|
931 semerror(errbuf);
|
|
932 }
|
|
933 else
|
|
934 { p->info.typ->ref = sp->table;
|
|
935 p->info.typ->width = sp->offset;
|
|
936 }
|
|
937 }
|
|
938 else
|
|
939 { p = enter(classtable, sym);
|
|
940 p->info.typ = mkstruct(sp->table, sp->offset);
|
|
941 }
|
|
942 p->info.typ->id = sym;
|
|
943 $$ = p->info.typ;
|
|
944 exitscope();
|
|
945 }
|
|
946 | struct '{' s2 decls '}'
|
|
947 { if ((p = entry(classtable, $1->sym)) && p->info.typ->ref)
|
|
948 { if (is_mutable(p->info.typ))
|
|
949 { if (merge((Table*)p->info.typ->ref, sp->table))
|
|
950 { sprintf(errbuf, "member name clash in struct '%s' declared at line %d", $1->sym->name, p->lineno);
|
|
951 semerror(errbuf);
|
|
952 }
|
|
953 p->info.typ->width += sp->offset;
|
|
954 }
|
|
955 }
|
|
956 else
|
|
957 { p = reenter(classtable, $1->sym);
|
|
958 p->info.typ->ref = sp->table;
|
|
959 p->info.typ->width = sp->offset;
|
|
960 p->info.typ->id = p->sym;
|
|
961 }
|
|
962 $$ = p->info.typ;
|
|
963 exitscope();
|
|
964 }
|
|
965 | STRUCT ID { if ((p = entry(classtable, $2)))
|
|
966 { if (p->info.typ->type == Tstruct)
|
|
967 $$ = p->info.typ;
|
|
968 else
|
|
969 { sprintf(errbuf, "'struct %s' redeclaration (line %d)", $2->name, p->lineno);
|
|
970 semerror(errbuf);
|
|
971 $$ = mkint();
|
|
972 }
|
|
973 }
|
|
974 else
|
|
975 { p = enter(classtable, $2);
|
|
976 $$ = p->info.typ = mkstruct((Table*)0, 0);
|
|
977 p->info.typ->id = $2;
|
|
978 }
|
|
979 }
|
|
980 | STRUCT TYPE { if ((p = entry(classtable, $2)))
|
|
981 { if (p->info.typ->type == Tstruct)
|
|
982 $$ = p->info.typ;
|
|
983 else
|
|
984 { sprintf(errbuf, "'struct %s' redeclaration (line %d)", $2->name, p->lineno);
|
|
985 semerror(errbuf);
|
|
986 $$ = mkint();
|
|
987 }
|
|
988 }
|
|
989 else
|
|
990 { p = enter(classtable, $2);
|
|
991 $$ = p->info.typ = mkstruct((Table*)0, 0);
|
|
992 p->info.typ->id = $2;
|
|
993 }
|
|
994 }
|
|
995 | UNION '{' s3 decls '}'
|
|
996 { sym = gensym("_Union");
|
|
997 sprintf(errbuf, "anonymous union will be named '%s'", sym->name);
|
|
998 semwarn(errbuf);
|
|
999 $$ = mkunion(sp->table, sp->offset);
|
|
1000 if ((p = entry(classtable, sym)))
|
|
1001 { if (p->info.typ->ref)
|
|
1002 { sprintf(errbuf, "union or struct '%s' already declared at line %d", sym->name, p->lineno);
|
|
1003 semerror(errbuf);
|
|
1004 }
|
|
1005 else
|
|
1006 { p->info.typ->ref = sp->table;
|
|
1007 p->info.typ->width = sp->offset;
|
|
1008 }
|
|
1009 }
|
|
1010 else
|
|
1011 { p = enter(classtable, sym);
|
|
1012 p->info.typ = mkunion(sp->table, sp->offset);
|
|
1013 }
|
|
1014 p->info.typ->id = sym;
|
|
1015 $$ = p->info.typ;
|
|
1016 exitscope();
|
|
1017 }
|
|
1018 | UNION id '{' s3 decls '}'
|
|
1019 { if ((p = entry(classtable, $2)))
|
|
1020 { if (p->info.typ->ref || p->info.typ->type != Tunion)
|
|
1021 { sprintf(errbuf, "union '%s' already declared at line %d", $2->name, p->lineno);
|
|
1022 semerror(errbuf);
|
|
1023 }
|
|
1024 else
|
|
1025 { p = reenter(classtable, $2);
|
|
1026 p->info.typ->ref = sp->table;
|
|
1027 p->info.typ->width = sp->offset;
|
|
1028 }
|
|
1029 }
|
|
1030 else
|
|
1031 { p = enter(classtable, $2);
|
|
1032 p->info.typ = mkunion(sp->table, sp->offset);
|
|
1033 }
|
|
1034 p->info.typ->id = $2;
|
|
1035 $$ = p->info.typ;
|
|
1036 exitscope();
|
|
1037 }
|
|
1038 | UNION ID { if ((p = entry(classtable, $2)))
|
|
1039 { if (p->info.typ->type == Tunion)
|
|
1040 $$ = p->info.typ;
|
|
1041 else
|
|
1042 { sprintf(errbuf, "'union %s' redeclaration (line %d)", $2->name, p->lineno);
|
|
1043 semerror(errbuf);
|
|
1044 $$ = mkint();
|
|
1045 }
|
|
1046 }
|
|
1047 else
|
|
1048 { p = enter(classtable, $2);
|
|
1049 $$ = p->info.typ = mkunion((Table*) 0, 0);
|
|
1050 p->info.typ->id = $2;
|
|
1051 }
|
|
1052 }
|
|
1053 | UNION TYPE { if ((p = entry(classtable, $2)))
|
|
1054 { if (p->info.typ->type == Tunion)
|
|
1055 $$ = p->info.typ;
|
|
1056 else
|
|
1057 { sprintf(errbuf, "'union %s' redeclaration (line %d)", $2->name, p->lineno);
|
|
1058 semerror(errbuf);
|
|
1059 $$ = mkint();
|
|
1060 }
|
|
1061 }
|
|
1062 else
|
|
1063 { p = enter(classtable, $2);
|
|
1064 $$ = p->info.typ = mkunion((Table*) 0, 0);
|
|
1065 p->info.typ->id = $2;
|
|
1066 }
|
|
1067 }
|
|
1068 | ENUM '{' s2 dclrs s5 '}'
|
|
1069 { sym = gensym("_Enum");
|
|
1070 sprintf(errbuf, "anonymous enum will be named '%s'", sym->name);
|
|
1071 semwarn(errbuf);
|
|
1072 if ((p = entry(enumtable, sym)))
|
|
1073 { if (p->info.typ->ref)
|
|
1074 { sprintf(errbuf, "enum '%s' already declared at line %d", sym->name, p->lineno);
|
|
1075 semerror(errbuf);
|
|
1076 }
|
|
1077 else
|
|
1078 { p->info.typ->ref = sp->table;
|
|
1079 p->info.typ->width = 4; /* 4 = enum */
|
|
1080 }
|
|
1081 }
|
|
1082 else
|
|
1083 { p = enter(enumtable, sym);
|
|
1084 p->info.typ = mkenum(sp->table);
|
|
1085 }
|
|
1086 p->info.typ->id = sym;
|
|
1087 $$ = p->info.typ;
|
|
1088 exitscope();
|
|
1089 }
|
|
1090 | enum '{' s2 dclrs s5 '}'
|
|
1091 { if ((p = entry(enumtable, $1->sym)))
|
|
1092 { if (p->info.typ->ref)
|
|
1093 { sprintf(errbuf, "enum '%s' already declared at line %d", $1->sym->name, p->lineno);
|
|
1094 semerror(errbuf);
|
|
1095 }
|
|
1096 else
|
|
1097 { p->info.typ->ref = sp->table;
|
|
1098 p->info.typ->width = 4; /* 4 = enum */
|
|
1099 }
|
|
1100 }
|
|
1101 else
|
|
1102 { p = enter(enumtable, $1->sym);
|
|
1103 p->info.typ = mkenum(sp->table);
|
|
1104 }
|
|
1105 p->info.typ->id = $1->sym;
|
|
1106 $$ = p->info.typ;
|
|
1107 exitscope();
|
|
1108 }
|
|
1109 | ENUM '*' id '{' s4 dclrs s5 '}'
|
|
1110 { if ((p = entry(enumtable, $3)))
|
|
1111 { if (p->info.typ->ref)
|
|
1112 { sprintf(errbuf, "enum '%s' already declared at line %d", $3->name, p->lineno);
|
|
1113 semerror(errbuf);
|
|
1114 }
|
|
1115 else
|
|
1116 { p->info.typ->ref = sp->table;
|
|
1117 p->info.typ->width = 8; /* 8 = mask */
|
|
1118 }
|
|
1119 }
|
|
1120 else
|
|
1121 { p = enter(enumtable, $3);
|
|
1122 p->info.typ = mkmask(sp->table);
|
|
1123 }
|
|
1124 p->info.typ->id = $3;
|
|
1125 $$ = p->info.typ;
|
|
1126 exitscope();
|
|
1127 }
|
|
1128 | ENUM ID { if ((p = entry(enumtable, $2)))
|
|
1129 $$ = p->info.typ;
|
|
1130 else
|
|
1131 { p = enter(enumtable, $2);
|
|
1132 $$ = p->info.typ = mkenum((Table*)0);
|
|
1133 p->info.typ->id = $2;
|
|
1134 }
|
|
1135 }
|
|
1136 | ENUM TYPE { if ((p = entry(enumtable, $2)))
|
|
1137 $$ = p->info.typ;
|
|
1138 else
|
|
1139 { p = enter(enumtable, $2);
|
|
1140 $$ = p->info.typ = mkenum((Table*)0);
|
|
1141 p->info.typ->id = $2;
|
|
1142 }
|
|
1143 }
|
|
1144 | TYPE { if ((p = entry(typetable, $1)))
|
|
1145 $$ = p->info.typ;
|
|
1146 else if ((p = entry(classtable, $1)))
|
|
1147 $$ = p->info.typ;
|
|
1148 else if ((p = entry(enumtable, $1)))
|
|
1149 $$ = p->info.typ;
|
|
1150 else if ($1 == lookup("std::string") || $1 == lookup("std::wstring"))
|
|
1151 { p = enter(classtable, $1);
|
|
1152 $$ = p->info.typ = mkclass((Table*)0, 0);
|
|
1153 p->info.typ->id = $1;
|
|
1154 if (cflag)
|
|
1155 p->info.typ->transient = 1; /* make std::string transient in C */
|
|
1156 else
|
|
1157 p->info.typ->transient = -2;
|
|
1158 }
|
|
1159 else
|
|
1160 { sprintf(errbuf, "unknown type '%s'", $1->name);
|
|
1161 semerror(errbuf);
|
|
1162 $$ = mkint();
|
|
1163 }
|
|
1164 }
|
|
1165 | TYPE '<' texp '>'
|
|
1166 { if ((p = entry(templatetable, $1)))
|
|
1167 { $$ = mktemplate($3.typ, $1);
|
|
1168 if (has_attachment($3.typ))
|
|
1169 { 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 : "");
|
|
1170 semwarn(errbuf);
|
|
1171 }
|
|
1172 }
|
|
1173 else
|
|
1174 { sprintf(errbuf, "invalid template '%s'", $1->name);
|
|
1175 semerror(errbuf);
|
|
1176 $$ = mkint();
|
|
1177 }
|
|
1178 }
|
|
1179 | CLASS error '}'
|
|
1180 { synerror("malformed class definition (use spacing around ':' to separate derived : base)");
|
|
1181 yyerrok;
|
|
1182 $$ = mkint();
|
|
1183 }
|
|
1184 | STRUCT error '}'
|
|
1185 { synerror("malformed struct definition");
|
|
1186 yyerrok;
|
|
1187 $$ = mkint();
|
|
1188 }
|
|
1189 | UNION error '}'
|
|
1190 { synerror("malformed union definition");
|
|
1191 yyerrok;
|
|
1192 $$ = mkint();
|
|
1193 }
|
|
1194 | ENUM error '}'
|
|
1195 { synerror("malformed enum definition");
|
|
1196 yyerrok;
|
|
1197 $$ = mkint();
|
|
1198 }
|
|
1199 ;
|
|
1200 struct : STRUCT id { if ((p = entry(classtable, $2)))
|
|
1201 { if (p->info.typ->ref)
|
|
1202 { if (!is_mutable(p->info.typ))
|
|
1203 { sprintf(errbuf, "struct '%s' already declared at line %d", $2->name, p->lineno);
|
|
1204 semerror(errbuf);
|
|
1205 }
|
|
1206 }
|
|
1207 else
|
|
1208 p = reenter(classtable, $2);
|
|
1209 }
|
|
1210 else
|
|
1211 { p = enter(classtable, $2);
|
|
1212 p->info.typ = mkstruct((Table*)0, 0);
|
|
1213 }
|
|
1214 $$ = p;
|
|
1215 }
|
|
1216 ;
|
|
1217 class : CLASS id { if ((p = entry(classtable, $2)))
|
|
1218 { if (p->info.typ->ref)
|
|
1219 { if (!is_mutable(p->info.typ))
|
|
1220 { sprintf(errbuf, "class '%s' already declared at line %d (redundant 'class' specifier here?)", $2->name, p->lineno);
|
|
1221 semerror(errbuf);
|
|
1222 }
|
|
1223 }
|
|
1224 else
|
|
1225 p = reenter(classtable, $2);
|
|
1226 }
|
|
1227 else
|
|
1228 { p = enter(classtable, $2);
|
|
1229 p->info.typ = mkclass((Table*)0, 0);
|
|
1230 p->info.typ->id = p->sym;
|
|
1231 }
|
|
1232 $2->token = TYPE;
|
|
1233 $$ = p;
|
|
1234 }
|
|
1235 ;
|
|
1236 enum : ENUM id { if ((p = entry(enumtable, $2)))
|
|
1237 { if (p->info.typ->ref)
|
|
1238 { sprintf(errbuf, "enum '%s' already declared at line %d", $2->name, p->lineno);
|
|
1239 semerror(errbuf);
|
|
1240 }
|
|
1241 /*
|
|
1242 else
|
|
1243 p = reenter(classtable, $2);
|
|
1244 */
|
|
1245 }
|
|
1246 else
|
|
1247 { p = enter(enumtable, $2);
|
|
1248 p->info.typ = mkenum(0);
|
|
1249 }
|
|
1250 $$ = p;
|
|
1251 }
|
|
1252 ;
|
|
1253 tname : CLASS { }
|
|
1254 | TYPENAME { }
|
|
1255 ;
|
|
1256 base : PROTECTED base{ $$ = $2; }
|
|
1257 | PRIVATE base { $$ = $2; }
|
|
1258 | PUBLIC base { $$ = $2; }
|
|
1259 | TYPE { $$ = entry(classtable, $1);
|
|
1260 if (!$$)
|
|
1261 { p = entry(typetable, $1);
|
|
1262 if (p && (p->info.typ->type == Tclass || p->info.typ->type == Tstruct))
|
|
1263 $$ = p;
|
|
1264 }
|
|
1265 }
|
|
1266 | STRUCT ID { $$ = entry(classtable, $2); }
|
|
1267 ;
|
|
1268 s2 : /* empty */ { if (transient == -2)
|
|
1269 transient = 0;
|
|
1270 permission = 0;
|
|
1271 enterscope(mktable(NULL), 0);
|
|
1272 sp->entry = NULL;
|
|
1273 }
|
|
1274 ;
|
|
1275 s3 : /* empty */ { if (transient == -2)
|
|
1276 transient = 0;
|
|
1277 permission = 0;
|
|
1278 enterscope(mktable(NULL), 0);
|
|
1279 sp->entry = NULL;
|
|
1280 sp->grow = False;
|
|
1281 }
|
|
1282 ;
|
|
1283 s4 : /* empty */ { enterscope(mktable(NULL), 0);
|
|
1284 sp->entry = NULL;
|
|
1285 sp->mask = True;
|
|
1286 sp->val = 1;
|
|
1287 }
|
|
1288 ;
|
|
1289 s5 : /* empty */ { }
|
|
1290 | ',' { }
|
|
1291 ;
|
|
1292 s6 : /* empty */ { if (sp->table->level == INTERNAL)
|
|
1293 transient |= 1;
|
|
1294 permission = 0;
|
|
1295 enterscope(mktable(NULL), 0);
|
|
1296 sp->entry = NULL;
|
|
1297 sp->table->level = PARAM;
|
|
1298 }
|
|
1299 ;
|
|
1300 store : AUTO { $$ = Sauto; }
|
|
1301 | REGISTER { $$ = Sregister; }
|
|
1302 | STATIC { $$ = Sstatic; }
|
|
1303 | EXPLICIT { $$ = Sexplicit; }
|
|
1304 | EXTERN { $$ = Sextern; transient = 1; }
|
|
1305 | TYPEDEF { $$ = Stypedef; }
|
|
1306 | VIRTUAL { $$ = Svirtual; }
|
|
1307 | CONST { $$ = Sconst; }
|
|
1308 | FRIEND { $$ = Sfriend; }
|
|
1309 | INLINE { $$ = Sinline; }
|
|
1310 | MUSTUNDERSTAND{ $$ = SmustUnderstand; }
|
|
1311 | RETURN { $$ = Sreturn; }
|
|
1312 | '@' { $$ = Sattribute;
|
|
1313 if (eflag)
|
|
1314 semwarn("SOAP RPC encoding does not support XML attributes");
|
|
1315 }
|
|
1316 | '$' { $$ = Sspecial; }
|
|
1317 | VOLATILE { $$ = Sextern; transient = -2; }
|
|
1318 ;
|
|
1319 constobj: /* empty */ { $$ = Snone; }
|
|
1320 | CONST { $$ = Sconstobj; }
|
|
1321 ;
|
|
1322 abstract: /* empty */ { $$ = Snone; }
|
|
1323 | '=' LNG { $$ = Sabstract; }
|
|
1324 ;
|
|
1325 virtual : /* empty */ { $$ = Snone; }
|
|
1326 | VIRTUAL { $$ = Svirtual; }
|
|
1327 ;
|
|
1328 ptrs : /* empty */ { $$ = tmp = sp->node; }
|
|
1329 | ptrs '*' { /* handle const pointers, such as const char* */
|
|
1330 if ((tmp.sto & Sconst))
|
|
1331 tmp.sto = (Storage)(((int)tmp.sto & ~Sconst) | Sconstptr);
|
|
1332 tmp.typ = mkpointer(tmp.typ);
|
|
1333 tmp.typ->transient = transient;
|
|
1334 $$ = tmp;
|
|
1335 }
|
|
1336 | ptrs '&' { tmp.typ = mkreference(tmp.typ);
|
|
1337 tmp.typ->transient = transient;
|
|
1338 $$ = tmp;
|
|
1339 }
|
|
1340 ;
|
|
1341 array : /* empty */ { $$ = tmp; /* tmp is inherited */
|
|
1342 }
|
|
1343 | '[' cexp ']' array
|
|
1344 { if (!bflag && $4.typ->type == Tchar)
|
|
1345 { 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);
|
|
1346 semwarn(errbuf);
|
|
1347 }
|
|
1348 if ($2.hasval && $2.typ->type == Tint && $2.val.i > 0 && $4.typ->width > 0)
|
|
1349 $$.typ = mkarray($4.typ, (int) $2.val.i * $4.typ->width);
|
|
1350 else
|
|
1351 { $$.typ = mkarray($4.typ, 0);
|
|
1352 semerror("undetermined array size");
|
|
1353 }
|
|
1354 $$.sto = $4.sto;
|
|
1355 }
|
|
1356 | '[' ']' array { $$.typ = mkpointer($3.typ); /* zero size array = pointer */
|
|
1357 $$.sto = $3.sto;
|
|
1358 }
|
|
1359 ;
|
|
1360 arrayck : array { if ($1.typ->type == Tstruct || $1.typ->type == Tclass)
|
|
1361 if (!$1.typ->ref && !$1.typ->transient && !($1.sto & Stypedef))
|
|
1362 { sprintf(errbuf, "struct/class '%s' has incomplete type", $1.typ->id->name);
|
|
1363 semerror(errbuf);
|
|
1364 }
|
|
1365 $$ = $1;
|
|
1366 }
|
|
1367 ;
|
|
1368 init : /* empty */ { $$.hasval = False; }
|
|
1369 | '=' cexp { if ($2.hasval)
|
|
1370 { $$.typ = $2.typ;
|
|
1371 $$.hasval = True;
|
|
1372 $$.val = $2.val;
|
|
1373 }
|
|
1374 else
|
|
1375 { $$.hasval = False;
|
|
1376 semerror("initialization expression not constant");
|
|
1377 }
|
|
1378 }
|
|
1379 ;
|
|
1380 tag : /* empty */ { $$ = NULL; }
|
|
1381 | TAG { $$ = $1; }
|
|
1382 ;
|
|
1383 occurs : patt
|
|
1384 { $$.minOccurs = -1;
|
|
1385 $$.maxOccurs = 1;
|
|
1386 $$.minLength = MINLONG64;
|
|
1387 $$.maxLength = MAXLONG64;
|
|
1388 $$.pattern = $1;
|
|
1389 }
|
|
1390 | patt cint
|
|
1391 { $$.minOccurs = (LONG64)$2;
|
|
1392 $$.maxOccurs = 1;
|
|
1393 $$.minLength = (LONG64)$2;
|
|
1394 $$.maxLength = MAXLONG64;
|
|
1395 $$.pattern = $1;
|
|
1396 }
|
|
1397 | patt cint ':'
|
|
1398 { $$.minOccurs = (LONG64)$2;
|
|
1399 $$.maxOccurs = 1;
|
|
1400 $$.minLength = (LONG64)$2;
|
|
1401 $$.maxLength = MAXLONG64;
|
|
1402 $$.pattern = $1;
|
|
1403 }
|
|
1404 | patt cint ':' cint
|
|
1405 { $$.minOccurs = (LONG64)$2;
|
|
1406 $$.maxOccurs = (LONG64)$4;
|
|
1407 $$.minLength = (LONG64)$2;
|
|
1408 $$.maxLength = (LONG64)$4;
|
|
1409 $$.pattern = $1;
|
|
1410 }
|
|
1411 | patt ':' cint
|
|
1412 { $$.minOccurs = -1;
|
|
1413 $$.maxOccurs = (LONG64)$3;
|
|
1414 $$.minLength = MINLONG64;
|
|
1415 $$.maxLength = (LONG64)$3;
|
|
1416 $$.pattern = $1;
|
|
1417 }
|
|
1418 ;
|
|
1419 patt : /* empty */ { $$ = NULL; }
|
|
1420 | STR { $$ = $1; }
|
|
1421 ;
|
|
1422 cint : LNG { $$ = $1; }
|
|
1423 | '+' LNG { $$ = $2; }
|
|
1424 | '-' LNG { $$ = -$2; }
|
|
1425 ;
|
|
1426
|
|
1427 /******************************************************************************\
|
|
1428
|
|
1429 Expressions
|
|
1430
|
|
1431 \******************************************************************************/
|
|
1432
|
|
1433 expr : expr ',' expr { $$ = $3; }
|
|
1434 | cexp { $$ = $1; }
|
|
1435 ;
|
|
1436 /* cexp : conditional expression */
|
|
1437 cexp : obex '?' qexp ':' cexp
|
|
1438 { $$.typ = $3.typ;
|
|
1439 $$.sto = Snone;
|
|
1440 $$.hasval = False;
|
|
1441 }
|
|
1442 | oexp
|
|
1443 ;
|
|
1444 /* qexp : true-branch of ? : conditional expression */
|
|
1445 qexp : expr { $$ = $1; }
|
|
1446 ;
|
|
1447 /* oexp : or-expression */
|
|
1448 oexp : obex OR aexp { $$.hasval = False;
|
|
1449 $$.typ = mkint();
|
|
1450 }
|
|
1451 | aexp { $$ = $1; }
|
|
1452 ;
|
|
1453 obex : oexp { $$ = $1; }
|
|
1454 ;
|
|
1455 /* aexp : and-expression */
|
|
1456 aexp : abex AN rexp { $$.hasval = False;
|
|
1457 $$.typ = mkint();
|
|
1458 }
|
|
1459 | rexp { $$ = $1; }
|
|
1460 ;
|
|
1461 abex : aexp { $$ = $1; }
|
|
1462 ;
|
|
1463 /* rexp : relational expression */
|
|
1464 rexp : rexp '|' rexp { $$ = iop("|", $1, $3); }
|
|
1465 | rexp '^' rexp { $$ = iop("^", $1, $3); }
|
|
1466 | rexp '&' rexp { $$ = iop("&", $1, $3); }
|
|
1467 | rexp EQ rexp { $$ = relop("==", $1, $3); }
|
|
1468 | rexp NE rexp { $$ = relop("!=", $1, $3); }
|
|
1469 | rexp '<' rexp { $$ = relop("<", $1, $3); }
|
|
1470 | rexp LE rexp { $$ = relop("<=", $1, $3); }
|
|
1471 | rexp '>' rexp { $$ = relop(">", $1, $3); }
|
|
1472 | rexp GE rexp { $$ = relop(">=", $1, $3); }
|
|
1473 | rexp LS rexp { $$ = iop("<<", $1, $3); }
|
|
1474 | rexp RS rexp { $$ = iop(">>", $1, $3); }
|
|
1475 | rexp '+' rexp { $$ = op("+", $1, $3); }
|
|
1476 | rexp '-' rexp { $$ = op("-", $1, $3); }
|
|
1477 | rexp '*' rexp { $$ = op("*", $1, $3); }
|
|
1478 | rexp '/' rexp { $$ = op("/", $1, $3); }
|
|
1479 | rexp '%' rexp { $$ = iop("%", $1, $3); }
|
|
1480 | lexp { $$ = $1; }
|
|
1481 ;
|
|
1482 /* lexp : lvalue kind of expression with optional prefix contructs */
|
|
1483 lexp : '!' lexp { if ($2.hasval)
|
|
1484 $$.val.i = !$2.val.i;
|
|
1485 $$.typ = $2.typ;
|
|
1486 $$.hasval = $2.hasval;
|
|
1487 }
|
|
1488 | '~' lexp { if ($2.hasval)
|
|
1489 $$.val.i = ~$2.val.i;
|
|
1490 $$.typ = $2.typ;
|
|
1491 $$.hasval = $2.hasval;
|
|
1492 }
|
|
1493 | '-' lexp { if ($2.hasval) {
|
|
1494 if (integer($2.typ))
|
|
1495 $$.val.i = -$2.val.i;
|
|
1496 else if (real($2.typ))
|
|
1497 $$.val.r = -$2.val.r;
|
|
1498 else typerror("string?");
|
|
1499 }
|
|
1500 $$.typ = $2.typ;
|
|
1501 $$.hasval = $2.hasval;
|
|
1502 }
|
|
1503 | '+' lexp { $$ = $2; }
|
|
1504 | '*' lexp { if ($2.typ->type == Tpointer) {
|
|
1505 $$.typ = (Tnode*)$2.typ->ref;
|
|
1506 } else
|
|
1507 typerror("dereference of non-pointer type");
|
|
1508 $$.sto = Snone;
|
|
1509 $$.hasval = False;
|
|
1510 }
|
|
1511 | '&' lexp { $$.typ = mkpointer($2.typ);
|
|
1512 $$.sto = Snone;
|
|
1513 $$.hasval = False;
|
|
1514 }
|
|
1515 | SIZEOF '(' texp ')'
|
|
1516 { $$.hasval = True;
|
|
1517 $$.typ = mkint();
|
|
1518 $$.val.i = $3.typ->width;
|
|
1519 }
|
|
1520 | pexp { $$ = $1; }
|
|
1521 ;
|
|
1522 /* pexp : primitive expression with optional postfix constructs */
|
|
1523 pexp : '(' expr ')' { $$ = $2; }
|
|
1524 | ID { if ((p = enumentry($1)) == (Entry*) 0)
|
|
1525 p = undefined($1);
|
|
1526 else
|
|
1527 $$.hasval = True;
|
|
1528 $$.typ = p->info.typ;
|
|
1529 $$.val = p->info.val;
|
|
1530 }
|
|
1531 | LNG { $$.typ = mkint();
|
|
1532 $$.hasval = True;
|
|
1533 $$.val.i = $1;
|
|
1534 }
|
|
1535 | null { $$.typ = mkint();
|
|
1536 $$.hasval = True;
|
|
1537 $$.val.i = 0;
|
|
1538 }
|
|
1539 | DBL { $$.typ = mkfloat();
|
|
1540 $$.hasval = True;
|
|
1541 $$.val.r = $1;
|
|
1542 }
|
|
1543 | CHR { $$.typ = mkchar();
|
|
1544 $$.hasval = True;
|
|
1545 $$.val.i = $1;
|
|
1546 }
|
|
1547 | STR { $$.typ = mkstring();
|
|
1548 $$.hasval = True;
|
|
1549 $$.val.s = $1;
|
|
1550 }
|
|
1551 | CFALSE { $$.typ = mkbool();
|
|
1552 $$.hasval = True;
|
|
1553 $$.val.i = 0;
|
|
1554 }
|
|
1555 | CTRUE { $$.typ = mkbool();
|
|
1556 $$.hasval = True;
|
|
1557 $$.val.i = 1;
|
|
1558 }
|
|
1559 ;
|
|
1560
|
|
1561 %%
|
|
1562
|
|
1563 /*
|
|
1564 * ???
|
|
1565 */
|
|
1566 int
|
|
1567 yywrap(void)
|
|
1568 { return 1;
|
|
1569 }
|
|
1570
|
|
1571 /******************************************************************************\
|
|
1572
|
|
1573 Support routines
|
|
1574
|
|
1575 \******************************************************************************/
|
|
1576
|
|
1577 static Node
|
|
1578 op(const char *op, Node p, Node q)
|
|
1579 { Node r;
|
|
1580 Tnode *typ;
|
|
1581 r.typ = p.typ;
|
|
1582 r.sto = Snone;
|
|
1583 if (p.hasval && q.hasval) {
|
|
1584 if (integer(p.typ) && integer(q.typ))
|
|
1585 switch (op[0]) {
|
|
1586 case '|': r.val.i = p.val.i | q.val.i; break;
|
|
1587 case '^': r.val.i = p.val.i ^ q.val.i; break;
|
|
1588 case '&': r.val.i = p.val.i & q.val.i; break;
|
|
1589 case '<': r.val.i = p.val.i << q.val.i; break;
|
|
1590 case '>': r.val.i = p.val.i >> q.val.i; break;
|
|
1591 case '+': r.val.i = p.val.i + q.val.i; break;
|
|
1592 case '-': r.val.i = p.val.i - q.val.i; break;
|
|
1593 case '*': r.val.i = p.val.i * q.val.i; break;
|
|
1594 case '/': r.val.i = p.val.i / q.val.i; break;
|
|
1595 case '%': r.val.i = p.val.i % q.val.i; break;
|
|
1596 default: typerror(op);
|
|
1597 }
|
|
1598 else if (real(p.typ) && real(q.typ))
|
|
1599 switch (op[0]) {
|
|
1600 case '+': r.val.r = p.val.r + q.val.r; break;
|
|
1601 case '-': r.val.r = p.val.r - q.val.r; break;
|
|
1602 case '*': r.val.r = p.val.r * q.val.r; break;
|
|
1603 case '/': r.val.r = p.val.r / q.val.r; break;
|
|
1604 default: typerror(op);
|
|
1605 }
|
|
1606 else semerror("illegal constant operation");
|
|
1607 r.hasval = True;
|
|
1608 } else {
|
|
1609 typ = mgtype(p.typ, q.typ);
|
|
1610 r.hasval = False;
|
|
1611 }
|
|
1612 return r;
|
|
1613 }
|
|
1614
|
|
1615 static Node
|
|
1616 iop(const char *iop, Node p, Node q)
|
|
1617 { if (integer(p.typ) && integer(q.typ))
|
|
1618 return op(iop, p, q);
|
|
1619 typerror("integer operands only");
|
|
1620 return p;
|
|
1621 }
|
|
1622
|
|
1623 static Node
|
|
1624 relop(const char *op, Node p, Node q)
|
|
1625 { Node r;
|
|
1626 Tnode *typ;
|
|
1627 r.typ = mkint();
|
|
1628 r.sto = Snone;
|
|
1629 r.hasval = False;
|
|
1630 if (p.typ->type != Tpointer || p.typ != q.typ)
|
|
1631 typ = mgtype(p.typ, q.typ);
|
|
1632 return r;
|
|
1633 }
|
|
1634
|
|
1635 /******************************************************************************\
|
|
1636
|
|
1637 Scope management
|
|
1638
|
|
1639 \******************************************************************************/
|
|
1640
|
|
1641 /*
|
|
1642 mkscope - initialize scope stack with a new table and offset
|
|
1643 */
|
|
1644 static void
|
|
1645 mkscope(Table *table, int offset)
|
|
1646 { sp = stack-1;
|
|
1647 enterscope(table, offset);
|
|
1648 }
|
|
1649
|
|
1650 /*
|
|
1651 enterscope - enter a new scope by pushing a new table and offset on the stack
|
|
1652 */
|
|
1653 static void
|
|
1654 enterscope(Table *table, int offset)
|
|
1655 { if (++sp == stack+MAXNEST)
|
|
1656 execerror("maximum scope depth exceeded");
|
|
1657 sp->table = table;
|
|
1658 sp->val = 0;
|
|
1659 sp->offset = offset;
|
|
1660 sp->grow = True; /* by default, offset grows */
|
|
1661 sp->mask = False;
|
|
1662 }
|
|
1663
|
|
1664 /*
|
|
1665 exitscope - exit a scope by popping the table and offset from the stack
|
|
1666 */
|
|
1667 static void
|
|
1668 exitscope(void)
|
|
1669 { check(sp-- != stack, "exitscope() has no matching enterscope()");
|
|
1670 }
|
|
1671
|
|
1672 /******************************************************************************\
|
|
1673
|
|
1674 Undefined symbol
|
|
1675
|
|
1676 \******************************************************************************/
|
|
1677
|
|
1678 static Entry*
|
|
1679 undefined(Symbol *sym)
|
|
1680 { Entry *p;
|
|
1681 sprintf(errbuf, "undefined identifier '%s'", sym->name);
|
|
1682 semwarn(errbuf);
|
|
1683 p = enter(sp->table, sym);
|
|
1684 p->level = GLOBAL;
|
|
1685 p->info.typ = mkint();
|
|
1686 p->info.sto = Sextern;
|
|
1687 p->info.hasval = False;
|
|
1688 return p;
|
|
1689 }
|
|
1690
|
|
1691 /*
|
|
1692 mgtype - return most general type among two numerical types
|
|
1693 */
|
|
1694 Tnode*
|
|
1695 mgtype(Tnode *typ1, Tnode *typ2)
|
|
1696 { if (numeric(typ1) && numeric(typ2)) {
|
|
1697 if (typ1->type < typ2->type)
|
|
1698 return typ2;
|
|
1699 } else typerror("non-numeric type");
|
|
1700 return typ1;
|
|
1701 }
|
|
1702
|
|
1703 /******************************************************************************\
|
|
1704
|
|
1705 Type checks
|
|
1706
|
|
1707 \******************************************************************************/
|
|
1708
|
|
1709 static int
|
|
1710 integer(Tnode *typ)
|
|
1711 { switch (typ->type) {
|
|
1712 case Tchar:
|
|
1713 case Tshort:
|
|
1714 case Tint:
|
|
1715 case Tlong: return True;
|
|
1716 default: break;
|
|
1717 }
|
|
1718 return False;
|
|
1719 }
|
|
1720
|
|
1721 static int
|
|
1722 real(Tnode *typ)
|
|
1723 { switch (typ->type) {
|
|
1724 case Tfloat:
|
|
1725 case Tdouble:
|
|
1726 case Tldouble: return True;
|
|
1727 default: break;
|
|
1728 }
|
|
1729 return False;
|
|
1730 }
|
|
1731
|
|
1732 static int
|
|
1733 numeric(Tnode *typ)
|
|
1734 { return integer(typ) || real(typ);
|
|
1735 }
|
|
1736
|
|
1737 static void
|
|
1738 add_fault(Table *gt)
|
|
1739 { Table *t;
|
|
1740 Entry *p1, *p2, *p3, *p4;
|
|
1741 Symbol *s1, *s2, *s3, *s4;
|
|
1742 imported = NULL;
|
|
1743 s1 = lookup("SOAP_ENV__Code");
|
|
1744 p1 = entry(classtable, s1);
|
|
1745 if (!p1 || !p1->info.typ->ref)
|
|
1746 { t = mktable((Table*)0);
|
|
1747 if (!p1)
|
|
1748 { p1 = enter(classtable, s1);
|
|
1749 p1->info.typ = mkstruct(t, 3*4);
|
|
1750 p1->info.typ->id = s1;
|
|
1751 }
|
|
1752 else
|
|
1753 p1->info.typ->ref = t;
|
|
1754 p2 = enter(t, lookup("SOAP_ENV__Value"));
|
|
1755 p2->info.typ = qname;
|
|
1756 p2->info.minOccurs = 0;
|
|
1757 p2 = enter(t, lookup("SOAP_ENV__Subcode"));
|
|
1758 p2->info.typ = mkpointer(p1->info.typ);
|
|
1759 p2->info.minOccurs = 0;
|
|
1760 }
|
|
1761 s2 = lookup("SOAP_ENV__Detail");
|
|
1762 p2 = entry(classtable, s2);
|
|
1763 if (!p2 || !p2->info.typ->ref)
|
|
1764 { t = mktable((Table*)0);
|
|
1765 if (!p2)
|
|
1766 { p2 = enter(classtable, s2);
|
|
1767 p2->info.typ = mkstruct(t, 3*4);
|
|
1768 p2->info.typ->id = s2;
|
|
1769 }
|
|
1770 else
|
|
1771 p2->info.typ->ref = t;
|
|
1772 p3 = enter(t, lookup("__any"));
|
|
1773 p3->info.typ = xml;
|
|
1774 p3->info.minOccurs = 0;
|
|
1775 p3 = enter(t, lookup("__type"));
|
|
1776 p3->info.typ = mkint();
|
|
1777 p3->info.minOccurs = 0;
|
|
1778 p3 = enter(t, lookup("fault"));
|
|
1779 p3->info.typ = mkpointer(mkvoid());
|
|
1780 p3->info.minOccurs = 0;
|
|
1781 custom_fault = 0;
|
|
1782 }
|
|
1783 s4 = lookup("SOAP_ENV__Reason");
|
|
1784 p4 = entry(classtable, s4);
|
|
1785 if (!p4 || !p4->info.typ->ref)
|
|
1786 { t = mktable((Table*)0);
|
|
1787 if (!p4)
|
|
1788 { p4 = enter(classtable, s4);
|
|
1789 p4->info.typ = mkstruct(t, 4);
|
|
1790 p4->info.typ->id = s4;
|
|
1791 }
|
|
1792 else
|
|
1793 p4->info.typ->ref = t;
|
|
1794 p3 = enter(t, lookup("SOAP_ENV__Text"));
|
|
1795 p3->info.typ = mkstring();
|
|
1796 p3->info.minOccurs = 0;
|
|
1797 }
|
|
1798 s3 = lookup("SOAP_ENV__Fault");
|
|
1799 p3 = entry(classtable, s3);
|
|
1800 if (!p3 || !p3->info.typ->ref)
|
|
1801 { t = mktable(NULL);
|
|
1802 if (!p3)
|
|
1803 { p3 = enter(classtable, s3);
|
|
1804 p3->info.typ = mkstruct(t, 9*4);
|
|
1805 p3->info.typ->id = s3;
|
|
1806 }
|
|
1807 else
|
|
1808 p3->info.typ->ref = t;
|
|
1809 p3 = enter(t, lookup("faultcode"));
|
|
1810 p3->info.typ = qname;
|
|
1811 p3->info.minOccurs = 0;
|
|
1812 p3 = enter(t, lookup("faultstring"));
|
|
1813 p3->info.typ = mkstring();
|
|
1814 p3->info.minOccurs = 0;
|
|
1815 p3 = enter(t, lookup("faultactor"));
|
|
1816 p3->info.typ = mkstring();
|
|
1817 p3->info.minOccurs = 0;
|
|
1818 p3 = enter(t, lookup("detail"));
|
|
1819 p3->info.typ = mkpointer(p2->info.typ);
|
|
1820 p3->info.minOccurs = 0;
|
|
1821 p3 = enter(t, s1);
|
|
1822 p3->info.typ = mkpointer(p1->info.typ);
|
|
1823 p3->info.minOccurs = 0;
|
|
1824 p3 = enter(t, s4);
|
|
1825 p3->info.typ = mkpointer(p4->info.typ);
|
|
1826 p3->info.minOccurs = 0;
|
|
1827 p3 = enter(t, lookup("SOAP_ENV__Node"));
|
|
1828 p3->info.typ = mkstring();
|
|
1829 p3->info.minOccurs = 0;
|
|
1830 p3 = enter(t, lookup("SOAP_ENV__Role"));
|
|
1831 p3->info.typ = mkstring();
|
|
1832 p3->info.minOccurs = 0;
|
|
1833 p3 = enter(t, lookup("SOAP_ENV__Detail"));
|
|
1834 p3->info.typ = mkpointer(p2->info.typ);
|
|
1835 p3->info.minOccurs = 0;
|
|
1836 }
|
|
1837 }
|
|
1838
|
|
1839 static void
|
|
1840 add_soap(void)
|
|
1841 { Symbol *s = lookup("soap");
|
|
1842 p = enter(classtable, s);
|
|
1843 p->info.typ = mkstruct(NULL, 0);
|
|
1844 p->info.typ->transient = -2;
|
|
1845 p->info.typ->id = s;
|
|
1846 }
|
|
1847
|
|
1848 static void
|
|
1849 add_XML(void)
|
|
1850 { Symbol *s = lookup("_XML");
|
|
1851 s->token = TYPE;
|
|
1852 p = enter(typetable, s);
|
|
1853 xml = p->info.typ = mksymtype(mkstring(), s);
|
|
1854 p->info.sto = Stypedef;
|
|
1855 }
|
|
1856
|
|
1857 static void
|
|
1858 add_qname(void)
|
|
1859 { Symbol *s = lookup("_QName");
|
|
1860 s->token = TYPE;
|
|
1861 p = enter(typetable, s);
|
|
1862 qname = p->info.typ = mksymtype(mkstring(), s);
|
|
1863 p->info.sto = Stypedef;
|
|
1864 }
|
|
1865
|
|
1866 static void
|
|
1867 add_header(Table *gt)
|
|
1868 { Table *t;
|
|
1869 Entry *p;
|
|
1870 Symbol *s = lookup("SOAP_ENV__Header");
|
|
1871 imported = NULL;
|
|
1872 p = entry(classtable, s);
|
|
1873 if (!p || !p->info.typ->ref)
|
|
1874 { t = mktable((Table*)0);
|
|
1875 if (!p)
|
|
1876 p = enter(classtable, s);
|
|
1877 p->info.typ = mkstruct(t, 0);
|
|
1878 p->info.typ->id = s;
|
|
1879 custom_header = 0;
|
|
1880 }
|
|
1881 }
|
|
1882
|
|
1883 static void
|
|
1884 add_response(Entry *fun, Entry *ret)
|
|
1885 { Table *t;
|
|
1886 Entry *p, *q;
|
|
1887 Symbol *s;
|
|
1888 size_t i = 0, j, n = strlen(fun->sym->name);
|
|
1889 char *r = (char*)emalloc(n+100);
|
|
1890 strcpy(r, fun->sym->name);
|
|
1891 strcat(r, "Response");
|
|
1892 do
|
|
1893 { for (j = 0; j < i; j++)
|
|
1894 r[n+j+8] = '_';
|
|
1895 r[n+i+8] = '\0';
|
|
1896 if (!(s = lookup(r)))
|
|
1897 s = install(r, ID);
|
|
1898 i++;
|
|
1899 } while (entry(classtable, s));
|
|
1900 free(r);
|
|
1901 t = mktable((Table*)0);
|
|
1902 q = enter(t, ret->sym);
|
|
1903 q->info = ret->info;
|
|
1904 if (q->info.typ->type == Treference)
|
|
1905 q->info.typ = (Tnode*)q->info.typ->ref;
|
|
1906 p = enter(classtable, s);
|
|
1907 p->info.typ = mkstruct(t, 4);
|
|
1908 p->info.typ->id = s;
|
|
1909 fun->info.typ->response = p;
|
|
1910 }
|
|
1911
|
|
1912 static void
|
|
1913 add_result(Tnode *typ)
|
|
1914 { Entry *p;
|
|
1915 if (!typ->ref || !((Tnode*)typ->ref)->ref)
|
|
1916 { semwarn("response struct/class must be declared before used in function prototype");
|
|
1917 return;
|
|
1918 }
|
|
1919 for (p = ((Table*)((Tnode*)typ->ref)->ref)->list; p; p = p->next)
|
|
1920 if (p->info.sto & Sreturn)
|
|
1921 return;
|
|
1922 for (p = ((Table*)((Tnode*)typ->ref)->ref)->list; p; p = p->next)
|
|
1923 { if (p->info.typ->type != Tfun && !(p->info.sto & Sattribute) && !is_transient(p->info.typ) && !(p->info.sto & (Sprivate|Sprotected)))
|
|
1924 p->info.sto = (Storage)((int)p->info.sto | (int)Sreturn);
|
|
1925 return;
|
|
1926 }
|
|
1927 }
|