1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include "ASTBuilder.hpp"
28
29 #include <klib/symbol.h>
30
31 #include <kfs/directory.h>
32 #include <kfs/mmap.h>
33
34 #include "../vdb/schema-parse.h"
35 #include "../vdb/dbmgr-priv.h"
36 #include "../vdb/schema-expr.h"
37
38 #include "SchemaParser.hpp"
39
40 using namespace ncbi::SchemaParser;
41 #define YYDEBUG 1
42 #include "schema-ast-tokens.h"
43
44 using namespace std;
45
46 // data types, constants, etc.
47
48 void
DeclareType(const AST_FQN & p_fqn,const KSymbol & p_super,const AST_Expr * p_dimension)49 ASTBuilder :: DeclareType ( const AST_FQN& p_fqn, const KSymbol& p_super, const AST_Expr* p_dimension )
50 {
51 /* capture supertype */
52 assert ( p_super . type == eDatatype );
53 const SDatatype * super = static_cast < const SDatatype * > ( p_super . u . obj );
54
55 /* allocate a datatype */
56 SDatatype * dt = Alloc < SDatatype > ();
57 if ( dt != 0 )
58 {
59 /* insert into type vector */
60 if ( VectorAppend ( m_schema -> dt, & dt -> id, dt ) )
61 {
62 // create a symtab entry
63 const KSymbol* symbol = CreateFqnSymbol ( p_fqn, eDatatype, dt ); // will add missing namespaces to symtab
64 if ( symbol != 0 )
65 {
66 /* fill it out from super-type */
67 dt -> super = super;
68 dt -> byte_swap = super -> byte_swap;
69 dt -> name = symbol;
70 uint32_t dimension = p_dimension == 0 ? 1 : ( uint32_t ) EvalConstExpr ( * p_dimension );
71 dt -> size = super -> size * dimension;
72 dt -> dim = dimension;
73 dt -> domain = super -> domain;
74 }
75 }
76 else
77 {
78 SDatatypeWhack ( dt, 0 );
79 }
80 }
81 }
82
83 static
84 void
TypeExprInit(STypeExpr & p_expr)85 TypeExprInit ( STypeExpr & p_expr )
86 {
87 p_expr . dad . var = eTypeExpr;
88 atomic32_set ( & p_expr . dad . refcount, 1 );
89 p_expr . fmt = 0;
90 p_expr . dt = 0;
91 p_expr . ts = 0;
92 p_expr . id = 0;
93 p_expr . dim = 0;
94 p_expr . fd . fmt = 0;
95 p_expr . resolved = true;
96 }
97
98 static
99 void
TypeExprFillTypeId(ASTBuilder & p_builder,const AST & p_node,STypeExpr & p_expr,const KSymbol & p_sym)100 TypeExprFillTypeId ( ASTBuilder & p_builder, const AST & p_node, STypeExpr & p_expr, const KSymbol & p_sym )
101 {
102 switch ( p_sym . type )
103 {
104 case eDatatype:
105 p_expr . dt = static_cast < const SDatatype * > ( p_sym . u . obj );
106 p_expr . fd . td . type_id = p_expr . dt -> id;
107 break;
108 case eTypeset:
109 p_expr . ts = static_cast < const STypeset * > ( p_sym . u . obj );
110 p_expr . fd . td . type_id = p_expr . ts -> id;
111 break;
112 case eFormat:
113 p_expr . fmt = static_cast < const SFormat * > ( p_sym . u . obj );
114 p_expr . fd . fmt = p_expr . fmt -> id;
115 break;
116 case eSchemaType:
117 p_expr . id = static_cast < const SIndirectType * > ( p_sym . u . obj );
118 p_expr . fd . td . type_id = p_expr . id -> id;
119 p_expr . resolved = false;
120 break;
121 default:
122 p_builder . ReportError ( p_node . GetLocation (), "Not a datatype", p_sym . name );
123 break;
124 }
125 }
126
127 STypeExpr *
MakeTypeExpr(const AST & p_type)128 ASTBuilder :: MakeTypeExpr ( const AST & p_type )
129 {
130 STypeExpr * ret = Alloc < STypeExpr > ();
131 if ( ret == 0 )
132 {
133 return 0;
134 }
135 TypeExprInit ( * ret );
136
137 const AST_FQN * fqn = 0;
138 switch ( p_type . GetTokenType () )
139 {
140 case PT_IDENT : // scalar
141 {
142 fqn = ToFQN ( & p_type );
143 ret -> fd . td . dim = 1;
144 }
145 break;
146 case PT_ARRAY : // fqn [ const-expr | * ]
147 {
148 const AST & arrayType = p_type;
149 assert ( arrayType . ChildrenCount () == 2 );
150 fqn = ToFQN ( arrayType . GetChild ( 0 ) );
151 const AST & dimension = * arrayType . GetChild ( 1 );
152 if ( dimension . GetTokenType() == PT_EMPTY )
153 {
154 ret -> fd . td . dim = 0;
155 }
156 else
157 {
158 SExpression * expr = ToExpr ( & dimension ) -> MakeExpression ( * this ); // will report problems
159 if ( expr != 0 )
160 {
161 switch ( expr -> var )
162 {
163 case eConstExpr :
164 {
165 SConstExpr* cexpr = reinterpret_cast < SConstExpr* > ( expr );
166 // this may change as more kinds of const expressions are supported
167 assert ( cexpr -> td . type_id == IntrinsicTypeId ( "U64" ) );
168 ret -> fd . td . dim = ( uint32_t ) cexpr -> u . u64 [ 0 ];
169 ret -> dim = expr;
170 }
171 break;
172 case eIndirectExpr:
173 {
174 ret -> fd . td . dim = 0;
175 ret -> dim = expr;
176 ret -> resolved = false;
177 break;
178 }
179 default:
180 ReportError ( dimension . GetLocation (), "Not allowed in array subscripts", expr -> var );
181 SExpressionWhack ( expr );
182 break;
183 }
184 }
185 }
186 }
187 break;
188 case PT_TYPEEXPR : // fqn (format) / fqn (type)
189 {
190 fqn = ToFQN ( p_type . GetChild ( 0 ) );
191 const KSymbol * fmt = Resolve ( * fqn ); // will report unknown name
192 if ( fmt -> type != eFormat )
193 {
194 ReportError ( "Not a format", *fqn );
195 fqn = 0;
196 }
197 else
198 {
199 ret -> fmt = static_cast < const SFormat * > ( fmt -> u . obj );
200 ret -> fd . fmt = ret -> fmt -> id;
201 ret -> fd . td . dim = 1;
202
203 fqn = ToFQN ( p_type . GetChild ( 1 ) ); // has to be a type!
204 }
205 }
206 break;
207 default:
208 assert ( false ); // should not happen
209 break;
210 }
211
212 if ( fqn != 0 )
213 {
214 const KSymbol * type = Resolve ( * fqn ); // will report unknown name
215 if ( type != 0 )
216 {
217 TypeExprFillTypeId ( * this, * fqn, * ret, * type );
218 }
219 }
220
221 return ret;
222 }
223
224 bool
FillSchemaParms(const AST & p_parms,Vector & p_v)225 ASTBuilder :: FillSchemaParms ( const AST & p_parms, Vector & p_v )
226 {
227 uint32_t count = p_parms . ChildrenCount ();
228 for ( uint32_t i = 0; i < count; ++ i )
229 {
230 const AST & parm = * p_parms . GetChild ( i );
231 switch ( parm . GetTokenType () )
232 {
233 case PT_IDENT :
234 {
235 const KSymbol * sym = Resolve ( * ToFQN ( & parm ) ); // will report unknown name
236 if ( sym == 0 )
237 {
238 return false;
239 }
240
241 switch ( sym -> type )
242 {
243 /* type parameter */
244 case eFormat:
245 case eDatatype:
246 case eTypeset:
247 case eSchemaType:
248 {
249 STypeExpr * ret = Alloc < STypeExpr > ();
250 if ( ret == 0 )
251 {
252 return false;
253 }
254 TypeExprInit ( * ret );
255 ret -> fd . td . dim = 1;
256 TypeExprFillTypeId ( * this, parm, * ret, * sym );
257 if ( ! VectorAppend ( p_v, 0, ret ) )
258 {
259 SExpressionWhack ( & ret -> dad );
260 return false;
261 }
262 }
263 break;
264
265 case eConstant:
266 {
267 const SConstant * cnst = static_cast < const SConstant * > ( sym -> u . obj );
268 assert ( cnst -> expr != NULL );
269 const SDatatype *dt = VSchemaFindTypeid ( m_schema, cnst -> td . type_id );
270 assert ( dt != 0 );
271 if ( dt -> domain == ddUint && dt -> dim == 1 )
272 {
273 atomic32_inc ( & ( ( SExpression* ) cnst -> expr ) -> refcount );
274 if ( ! VectorAppend ( p_v, 0, cnst -> expr ) )
275 {
276 atomic32_dec ( & ( ( SExpression* ) cnst -> expr ) -> refcount );
277 return false;
278 }
279 }
280 else
281 {
282 ReportError ( parm . GetLocation (),
283 "Schema argument constant has to be an unsigned integer scalar",
284 sym -> name );
285 return false;
286 }
287 }
288 break;
289
290 /* schema or factory constant must be uint
291 but may not yet be completely resolved */
292 case eSchemaParam:
293 case eFactParam:
294 //TODO: return indirect_const_expr ( tbl, src, t, env, self, v );
295 assert ( false );
296 break;
297
298 default:
299 ReportError ( parm. GetChild ( 0 ) -> GetLocation (), "Cannot be used as a schema parameter", sym -> name );
300 return false;
301 }
302 }
303 break;
304
305 case PT_UINT :
306 VectorAppend ( p_v, 0, ToExpr ( & parm ) -> MakeUnsigned ( * this ) );
307 break;
308
309 case PT_ARRAY:
310 VectorAppend ( p_v, 0, MakeTypeExpr ( parm ) );
311 break;
312
313 default:
314 assert ( false );
315 }
316 }
317 return true;
318 }
319
320 bool
FillFactoryParms(const AST & p_parms,Vector & p_v)321 ASTBuilder :: FillFactoryParms ( const AST & p_parms, Vector & p_v )
322 {
323 uint32_t count = p_parms . ChildrenCount ();
324 for ( uint32_t i = 0; i < count; ++ i )
325 {
326 SExpression * expr = ToExpr ( p_parms . GetChild ( i ) ) -> MakeExpression ( * this );
327 if ( expr != 0 )
328 {
329 // allowed:
330 // eConstExpr, eIndirectExpr, eVectorExpr, eCastExpr, eFuncParamExpr, eNegateExpr
331 switch ( expr -> var )
332 {
333 case eConstExpr:
334 case eIndirectExpr:
335 case eVectorExpr:
336 case eCastExpr:
337 case eFuncParamExpr:
338 case eNegateExpr:
339 if ( ! VectorAppend ( p_v, 0, expr ) )
340 {
341 SExpressionWhack ( expr );
342 return false;
343 }
344 break;
345 default:
346 ReportError ( p_parms . GetChild ( i ) -> GetLocation (), "Cannot be used as a factory parameter" );
347 break;
348 }
349 }
350 else
351 {
352 return false;
353 }
354 }
355 return true;
356 }
357
358 bool
FillArguments(const AST & p_parms,Vector & p_v)359 ASTBuilder :: FillArguments ( const AST & p_parms, Vector & p_v )
360 {
361 uint32_t count = p_parms . ChildrenCount ();
362 for ( uint32_t i = 0; i < count; ++ i )
363 {
364 const AST_Expr * parm = ToExpr ( p_parms . GetChild ( i ) );
365 // allowed tags: PT_AT, PHYSICAL_IDENTIFIER_1_0, PT_CAST, PT_IDENT, PT_MEMBEREXPR
366 // for PT_IDENT, allowed object types: eFuncParam, eProduction, eIdent, eForward, eVirtual, eColumn, ePhysMember
367 SExpression * expr = 0;
368 switch ( parm -> GetTokenType () )
369 {
370 case '@':
371 case PT_IDENT:
372 case PHYSICAL_IDENTIFIER_1_0:
373 case PT_MEMBEREXPR:
374 expr = parm -> MakeExpression ( * this );
375 break;
376 default:
377 ReportError ( p_parms . GetChild ( i ) -> GetLocation (), "Cannot be used as a function call parameter" );
378 break;
379 }
380 if ( expr == 0 )
381 {
382 return false;
383 }
384 if ( ! VectorAppend ( p_v, 0, expr ) )
385 {
386 SExpressionWhack ( expr );
387 return false;
388 }
389 }
390 return true;
391 }
392
393 /*--------------------------------------------------------------------------
394 * STypesetMbr
395 * a typedecl that can be tested for uniqueness
396 */
397 typedef struct STypesetMbr STypesetMbr;
398 struct STypesetMbr
399 {
400 BSTNode n;
401 VTypedecl td;
402 };
403
404 static
STypesetPopulate(BSTNode * n,void * data)405 void CC STypesetPopulate ( BSTNode *n, void *data )
406 {
407 const STypesetMbr *mbr = ( const STypesetMbr* ) n;
408 STypeset *ts = static_cast < STypeset * > ( data );
409 ts -> td [ ts -> count ++ ] = mbr -> td;
410 }
411
412 /* Cmp
413 * Sort
414 */
415 static
VTypedeclCmp(const VTypedecl * a,const VTypedecl * b)416 int64_t VTypedeclCmp ( const VTypedecl *a, const VTypedecl *b )
417 {
418 if ( a -> type_id != b -> type_id )
419 return ( int64_t ) a -> type_id - ( int64_t ) b -> type_id;
420 return ( int64_t ) a -> dim - ( int64_t ) b -> dim;
421 }
422
423 static
STypesetMbrSort(const BSTNode * item,const BSTNode * n)424 int64_t CC STypesetMbrSort ( const BSTNode *item, const BSTNode *n )
425 {
426 const STypesetMbr *a = ( const STypesetMbr* ) item;
427 const STypesetMbr *b = ( const STypesetMbr* ) n;
428 return VTypedeclCmp ( & a -> td, & b -> td );
429 }
430
431 void
DeclareTypeSet(const AST_FQN & p_fqn,const BSTree & p_types,uint32_t p_typeCount)432 ASTBuilder :: DeclareTypeSet ( const AST_FQN & p_fqn, const BSTree & p_types, uint32_t p_typeCount )
433 {
434 STypeset *ts = Alloc < STypeset > ( sizeof * ts - sizeof ts -> td + p_typeCount * sizeof ts -> td [ 0 ] );
435 if ( ts != 0 )
436 {
437 ts -> count = 0;
438 BSTreeForEach ( & p_types, false, STypesetPopulate, ts );
439
440 if ( VectorAppend ( m_schema -> ts, & ts -> id, ts ) )
441 {
442 const KSymbol* symbol = CreateFqnSymbol ( p_fqn, eTypeset, ts ); // will add missing namespaces to symtab
443 ts -> name = symbol;
444 ts -> count = p_typeCount;
445 }
446 else
447 {
448 STypesetWhack ( ts, 0 );
449 }
450 }
451 }
452
453 AST *
TypeDef(const Token * p_token,AST_FQN * p_baseType,AST * p_newTypes)454 ASTBuilder :: TypeDef ( const Token * p_token, AST_FQN* p_baseType, AST* p_newTypes )
455 { //TODO: do we need to keep all these subtrees beyond the population of symtab?
456 AST * ret = new AST ( p_token, p_baseType, p_newTypes );
457
458 const KSymbol * baseType = Resolve ( * p_baseType ); // will report unknown name
459 if ( baseType != 0 )
460 {
461 if ( baseType -> type != eDatatype )
462 {
463 ReportError ( "Not a datatype", * p_baseType );
464 }
465 else
466 {
467 uint32_t count = p_newTypes -> ChildrenCount ();
468 for ( uint32_t i = 0; i < count; ++i )
469 {
470 const AST * newType = p_newTypes -> GetChild ( i );
471 if ( newType -> GetTokenType () == PT_IDENT )
472 {
473 DeclareType ( * ToFQN ( newType ), * baseType, 0 ); // will report duplicate definition
474 }
475 else // fqn [ const-expr ]
476 {
477 assert ( newType -> ChildrenCount () == 2 );
478 DeclareType ( * ToFQN ( newType -> GetChild ( 0 ) ),
479 * baseType,
480 ToExpr ( newType -> GetChild ( 1 ) ) ); // will report duplicate definition
481 }
482 }
483 }
484 }
485 return ret;
486 }
487
488 static
489 bool
TypeSetAddType(ASTBuilder & p_builder,BSTree & p_tree,const VTypedecl & p_type,uint32_t & p_typeCount)490 TypeSetAddType ( ASTBuilder & p_builder, BSTree & p_tree, const VTypedecl & p_type, uint32_t & p_typeCount )
491 {
492 STypesetMbr * mbr = p_builder . Alloc < STypesetMbr > ();
493 if ( mbr == 0 )
494 {
495 return false;
496 }
497
498 mbr -> td = p_type;
499
500 /* ignore/allow duplicates */
501 BSTNode * exist;
502 if ( BSTreeInsertUnique ( & p_tree, & mbr -> n, & exist, STypesetMbrSort ) != 0 )
503 {
504 free ( mbr );
505 }
506 else
507 {
508 ++ p_typeCount;
509 }
510 return true;
511 }
512
513 const KSymbol *
TypeSpec(const AST & p_spec,VTypedecl & p_td)514 ASTBuilder :: TypeSpec ( const AST & p_spec, VTypedecl & p_td )
515 {
516 const KSymbol * ret = 0;
517 if ( p_spec . GetTokenType () == PT_IDENT )
518 { // scalar
519 const AST_FQN & fqn = * ToFQN ( & p_spec );
520 ret = Resolve ( fqn ); // will report unknown name
521 if ( ret != 0 )
522 {
523 switch ( ret -> type )
524 {
525 case eDatatype:
526 {
527 const SDatatype * typeDef = static_cast < const SDatatype * > ( ret -> u . obj );
528 p_td . type_id = typeDef -> id;
529 p_td . dim = 1;
530 }
531 break;
532 case eTypeset:
533 {
534 const STypeset * typeset = static_cast < const STypeset * > ( ret -> u . obj );
535 p_td . type_id = typeset -> id;
536 p_td . dim = 1;
537 }
538 break;
539 default:
540 {
541 ReportError ( "Not a datatype", fqn );
542 }
543 return 0;
544 }
545 }
546 }
547 else // fqn [ const-expr ]
548 {
549 assert ( p_spec . GetTokenType () == PT_ARRAY );
550 assert ( p_spec . ChildrenCount () == 2 ); // fqn expr
551 const AST_FQN & fqn = * ToFQN ( p_spec . GetChild ( 0 ) );
552 ret = Resolve ( fqn ); // will report unknown name
553 if ( ret != 0 )
554 {
555 if ( ret -> type != eDatatype )
556 {
557 ReportError ( "Not a datatype", fqn );
558 return 0;
559 }
560 const SDatatype * typeDef = static_cast < const SDatatype * > ( ret -> u . obj );
561 p_td . type_id = typeDef -> id;
562 p_td.dim = (uint32_t) EvalConstExpr(*ToExpr(p_spec.GetChild(1)));
563 }
564 }
565 return ret;
566 }
567
568 AST *
TypeSet(const Token * p_token,AST_FQN * p_name,AST * p_typeSpecs)569 ASTBuilder :: TypeSet ( const Token* p_token, AST_FQN * p_name, AST * p_typeSpecs )
570 {
571 AST * ret = new AST ( p_token, p_name, p_typeSpecs );
572
573 const KSymbol * existing = Resolve ( * p_name, false );
574
575 // traverse p_typeSpecs, add to tree
576 BSTree tree;
577 BSTreeInit ( & tree );
578
579 uint32_t typeCount = 0;
580 uint32_t count = p_typeSpecs -> ChildrenCount ();
581 bool error = false;
582 for ( uint32_t i = 0; i < count; ++i )
583 {
584 const AST * spec = p_typeSpecs -> GetChild ( i );
585 VTypedecl td;
586 const KSymbol * type = TypeSpec ( * spec, td );
587 if ( type != 0 )
588 {
589 if ( type -> type == eDatatype )
590 {
591 if ( ! TypeSetAddType ( * this, tree, td, typeCount ) )
592 {
593 error = true;
594 }
595 }
596 else
597 {
598 assert ( type -> type == eTypeset );
599 const STypeset * typeset = static_cast < const STypeset * > ( type -> u . obj );
600 for ( uint16_t j = 0; j < typeset -> count; ++j )
601 {
602 if ( ! TypeSetAddType ( *this, tree, typeset -> td [ j ], typeCount ) )
603 {
604 error = true;
605 }
606 }
607 }
608 }
609 else
610 {
611 error = true;
612 }
613 }
614
615 if ( ! error && existing != 0 )
616 {
617 if ( existing -> type != eTypeset )
618 {
619 ReportError ( "Already declared and is not a typeset", * p_name );
620 }
621 else
622 { // allow benign redefine
623 const STypeset * orig = static_cast < const STypeset * > ( existing -> u . obj );
624 if ( orig -> count != typeCount )
625 {
626 ReportError ( "Typeset already declared differently", * p_name );
627 }
628 else
629 {
630 BSTNode* node = BSTreeFirst ( &tree );
631 for ( uint32_t i = 0; i < typeCount; ++ i )
632 {
633 assert ( node != 0 );
634 STypesetMbr * mbr = reinterpret_cast < STypesetMbr * > ( node );
635 if ( VTypedeclCmp ( & orig -> td [ i ], & mbr -> td ) != 0 )
636 {
637 ReportError ( "Typeset already declared differently", * p_name );
638 break;
639 }
640 node = BSTNodeNext ( node );
641 }
642 }
643 }
644 }
645 else
646 {
647 DeclareTypeSet ( * p_name, tree, typeCount );
648 }
649
650 BSTreeWhack ( & tree, BSTreeMbrWhack, 0 );
651
652 return ret;
653 }
654
655 AST *
FmtDef(const Token * p_token,AST_FQN * p_fqn,AST_FQN * p_super_opt)656 ASTBuilder :: FmtDef ( const Token* p_token, AST_FQN* p_fqn, AST_FQN* p_super_opt )
657 {
658 AST * ret = new AST ( p_token, p_fqn );
659 if ( p_super_opt != 0 )
660 {
661 ret -> AddNode ( p_super_opt );
662 }
663
664 SFormat * fmt = Alloc < SFormat > ();
665 if ( fmt != 0 )
666 {
667 // superfmt
668 fmt -> super = 0;
669 if ( p_super_opt != 0 )
670 {
671 const KSymbol* super = Resolve ( * p_super_opt ); // will report undefined
672 if ( super != 0 )
673 {
674 if ( super -> type != eFormat )
675 {
676 ReportError ( "Not a format", * p_super_opt );
677 SFormatWhack ( fmt, 0 );
678 return ret;
679 }
680 fmt -> super = static_cast < const SFormat * > ( super -> u . obj );
681 }
682 }
683
684 /* insert into vector */
685 if ( VectorAppend ( m_schema -> fmt, & fmt -> id, fmt ) )
686 { // create a symtab entry, link fmt to it
687 fmt -> name = CreateFqnSymbol ( * p_fqn, eFormat, fmt ); // will add missing namespaces to symtab
688 }
689 else
690 {
691 SFormatWhack ( fmt, 0 );
692 }
693 }
694
695 return ret;
696 }
697
698 AST *
ConstDef(const Token * p_token,AST * p_type,AST_FQN * p_fqn,AST_Expr * p_expr)699 ASTBuilder :: ConstDef ( const Token* p_token, AST* p_type, AST_FQN* p_fqn, AST_Expr* p_expr )
700 {
701 AST * ret = new AST ( p_token, p_type, p_fqn, p_expr );
702
703 SConstant *cnst = Alloc < SConstant > ();
704 if ( cnst != 0 )
705 {
706 if ( p_type -> GetTokenType () == PT_IDENT )
707 { // scalar
708 const KSymbol * type = Resolve ( * ToFQN ( p_type ) ); // will report unknown name
709 if ( type != 0 )
710 {
711 if ( VectorAppend ( m_schema -> cnst, & cnst -> id, cnst ) )
712 {
713 cnst -> name = CreateFqnSymbol ( * p_fqn, eConstant, cnst );
714 cnst -> expr = p_expr -> EvaluateConst ( *this ); // will report problems
715 const SDatatype * typeDef = static_cast < const SDatatype * > ( type -> u . obj );
716 cnst -> td . type_id = typeDef -> id;
717 cnst -> td . dim = 1;
718 }
719 else
720 {
721 SConstantWhack ( cnst, 0 );
722 }
723 }
724 }
725 else // fqn [ const-expr ]
726 {
727 assert ( p_type -> GetTokenType () == PT_ARRAY );
728 assert ( p_type -> ChildrenCount () == 2 ); // fqn expr
729 const AST_FQN & fqn = * ToFQN ( p_type -> GetChild ( 0 ) );
730 const KSymbol * sym = Resolve ( fqn ); // will report unknown name
731 if ( sym != 0 )
732 {
733 if ( sym -> type != eDatatype )
734 {
735 ReportError ( "Not a datatype", fqn );
736 return 0;
737 }
738 if ( VectorAppend ( m_schema -> cnst, & cnst -> id, cnst ) )
739 {
740 cnst -> name = CreateFqnSymbol ( * p_fqn, eConstant, cnst );
741 cnst -> expr = p_expr -> EvaluateConst ( *this ); // will report problems
742 const SDatatype * typeDef = static_cast < const SDatatype * > ( sym -> u . obj );
743 cnst -> td . type_id = typeDef -> id;
744 cnst->td.dim = (uint32_t) EvalConstExpr(*ToExpr(p_type->GetChild(1)));
745 }
746 }
747 }
748 }
749
750 return ret;
751 }
752
753 AST *
AliasDef(const Token * p_token,AST_FQN * p_name,AST_FQN * p_newName)754 ASTBuilder :: AliasDef ( const Token* p_token, AST_FQN* p_name, AST_FQN* p_newName )
755 {
756 AST * ret = new AST ( p_token, p_name, p_newName );
757
758 const KSymbol * sym = Resolve ( * p_name ); // will report unknown name
759 if ( sym != 0 )
760 {
761 VectorAppend ( m_schema -> alias, 0, CreateFqnSymbol ( * p_newName, sym -> type, sym -> u . obj ) );
762 }
763
764 return ret;
765 }
766
767 void
AddIncludePath(const char * path)768 ASTBuilder :: AddIncludePath ( const char * path )
769 {
770 rc_t rc = VSchemaAddIncludePath ( m_schema, "%s", path );
771 if ( rc != 0 )
772 {
773 ReportRc ( "VSchemaAddIncludePath", rc );
774 }
775 }
776
777 const KFile *
OpenIncludeFile(const Token::Location & p_loc,const char * p_fmt,...)778 ASTBuilder :: OpenIncludeFile ( const Token :: Location & p_loc, const char * p_fmt, ... )
779 {
780 const KFile * ret = 0;
781 va_list args;
782 va_start ( args, p_fmt );
783
784 char path [ 4096 ];
785 rc_t rc = 0;
786 /* open file using include paths */
787 rc = VSchemaOpenFile ( m_schema, & ret, path, sizeof path, p_fmt, args );
788
789 if ( rc != 0 )
790 { /* try to open the file according to current directory */
791 KDirectory *wd;
792 rc = KDirectoryNativeDir ( & wd );
793 if ( rc == 0 )
794 {
795 rc = VSchemaTryOpenFile ( m_schema, wd, & ret, path, sizeof path, p_fmt, args );
796 // ret == 0 if was included previously
797 KDirectoryRelease ( wd );
798 }
799 else
800 {
801 ReportRc ( "KDirectoryNativeDir", rc );
802 }
803 }
804
805 // if the file was found ...
806 if ( rc == 0 )
807 {
808 if ( ret != 0 ) // file was included for the 1st time
809 {
810 const KMMap *mm;
811 rc = KMMapMakeRead ( & mm, ret );
812 if ( rc == 0 )
813 {
814 size_t size;
815 const void *addr;
816 rc = KMMapAddrRead ( mm, & addr );
817 if ( rc == 0 )
818 {
819 rc = KMMapSize ( mm, & size );
820 if ( rc == 0 )
821 {
822 rc = VIncludedPathMake ( & m_schema -> paths, & m_schema -> file_count, path );
823 if ( rc != 0 )
824 {
825 ReportRc ( "VIncludedPathMake", rc );
826 }
827 }
828 else
829 {
830 ReportRc ( "KMMapSize", rc );
831 }
832 }
833 else
834 {
835 ReportRc ( "KMMapAddrRead", rc );
836 }
837
838 KMMapRelease ( mm );
839 }
840 else
841 {
842 ReportRc ( "KMMapMakeRead", rc );
843 }
844 }
845 // else: file was included previously, now ignored
846 }
847 else
848 {
849 ReportError ( p_loc, "Could not open include file", path );
850 }
851
852 va_end ( args );
853 return ret;
854 }
855
856 AST *
Include(const Token * p_token,const Token * p_filename)857 ASTBuilder :: Include ( const Token * p_token, const Token * p_filename )
858 {
859 AST * ret = new AST ( p_token );
860 assert ( p_filename != 0 );
861 ret -> AddNode ( p_filename );
862
863 const char * quoted = p_filename -> GetValue ();
864 char * unquoted = string_dup ( quoted + 1, string_size ( quoted ) - 2 );
865 if ( unquoted != 0 )
866 {
867 const KFile * f = OpenIncludeFile ( p_token -> GetLocation (), "%s", unquoted );
868 if ( f != 0 )
869 {
870 SchemaParser parser;
871 if ( parser . ParseFile ( f, unquoted ) )
872 {
873 delete Build ( * parser . GetParseTree (), unquoted, false );
874 }
875 KFileRelease ( f );
876 }
877 free ( unquoted );
878 }
879 else
880 {
881 ReportInternalError ( "ASTBuilder :: Include () : string_dup() failed" );
882 }
883
884 return ret;
885 }