Mercurial > repos > ktnyt > gembassy
comparison 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 |
comparison
equal
deleted
inserted
replaced
1:84a17b3fad1f | 2:8947fca5f715 |
---|---|
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 } |