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 <vdb/extern.h>
28 
29 #include "schema-priv.h"
30 #include "schema-parse.h"
31 #include "schema-expr.h"
32 #include "schema-dump.h"
33 
34 #include <klib/symbol.h>
35 #include <klib/symtab.h>
36 #include <klib/rc.h>
37 #include <sysalloc.h>
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <os-native.h>
44 #include <assert.h>
45 
46 
47 /*--------------------------------------------------------------------------
48  * SExpression
49  */
50 #if SLVL >= 1
SExpressionWhack(const SExpression * cself)51 void SExpressionWhack ( const SExpression *cself )
52 {
53     SExpression *self = ( SExpression* ) cself;
54     if ( self != NULL && atomic32_dec_and_test ( & self -> refcount ) )
55     {
56         switch ( self -> var )
57         {
58             case eTypeExpr:
59             {
60                 STypeExpr *x = ( STypeExpr* ) self;
61                 SExpressionWhack ( x -> dim );
62                 break;
63             }
64             case eFuncExpr:
65             case eScriptExpr:
66             {
67                 SFuncExpr *x = ( SFuncExpr* ) self;
68                 VectorWhack ( & x -> schem, SExpressionVWhack, NULL );
69                 VectorWhack ( & x -> pfact, SExpressionVWhack, NULL );
70                 VectorWhack ( & x -> pfunc, SExpressionVWhack, NULL );
71                 break;
72             }
73             case ePhysEncExpr:
74             {
75                 SPhysEncExpr *x = ( SPhysEncExpr* ) self;
76                 VectorWhack ( & x -> schem, SExpressionVWhack, NULL );
77                 VectorWhack ( & x -> pfact, SExpressionVWhack, NULL );
78                 break;
79             }
80             case eNegateExpr:
81             {
82                 SUnaryExpr *x = ( SUnaryExpr* ) self;
83                 SExpressionWhack ( x -> expr );
84                 break;
85             }
86             case eCastExpr:
87             case eCondExpr:
88             {
89                 SBinExpr *x = ( SBinExpr* ) self;
90                 SExpressionWhack ( x -> left );
91                 SExpressionWhack ( x -> right );
92                 break;
93             }
94             case eVectorExpr:
95             {
96                 SVectExpr *x = ( SVectExpr* ) self;
97                 VectorWhack ( & x -> expr, SExpressionVWhack, NULL );
98                 break;
99             }
100             case eMembExpr:
101             {
102                 SMembExpr *x = ( SMembExpr* ) self;
103                 SExpressionWhack ( x -> rowId );
104                 break;
105             }
106         }
107 
108         free ( self );
109     }
110 }
111 
SExpressionVWhack(void * item,void * ignore)112 void CC SExpressionVWhack ( void *item, void *ignore )
113 {
114     SExpression *self = item;
115     SExpressionWhack ( self );
116 }
117 #endif
118 
119 /* Mark
120  */
121 #if SLVL >= 1
SExpressionMark(void * item,void * data)122 void CC SExpressionMark ( void * item, void * data )
123 {
124     const SExpression * self = item;
125     const VSchema * schema = data;
126     if ( self != NULL ) switch ( self -> var )
127     {
128     case eTypeExpr:
129         STypeExprMark ( ( const STypeExpr* ) self, schema );
130         break;
131     case eConstExpr:
132         VSchemaTypeMark ( schema, ( ( const SConstExpr* ) self ) -> td . type_id );
133         break;
134     case eIndirectExpr:
135     case eParamExpr:
136     case eProdExpr:
137     case eFwdExpr:
138     case eFuncParamExpr:
139     case eColExpr:
140     case ePhysExpr:
141         SSymExprMark ( ( const SSymExpr* ) self, schema );
142         break;
143     case eFuncExpr:
144     case eScriptExpr:
145         SFuncExprMark ( ( const SFuncExpr* ) self, schema );
146         break;
147     case ePhysEncExpr:
148         SPhysEncExprMark ( ( const SPhysEncExpr* ) self, schema );
149         break;
150     case eNegateExpr:
151         SExpressionMark ( ( void * )( ( const SUnaryExpr* ) self ) -> expr, data );
152         break;
153     case eCastExpr:
154     case eCondExpr:
155         SExpressionMark ( ( void * )( ( const SBinExpr* ) self ) -> left, data );
156         SExpressionMark ( ( void * )( ( const SBinExpr* ) self ) -> right, data );
157         break;
158     case eVectorExpr:
159         VectorForEach ( & ( ( const SVectExpr* ) self ) -> expr, false,
160                         SExpressionMark, data );
161         break;
162     case eMembExpr:
163         assert (false); //TODO SMembExprMark
164         break;
165     }
166 }
167 #endif
168 
169 /* Dump
170  */
171 #if SLVL >= 1
SExpressionListDump(void * item,void * data)172 bool CC SExpressionListDump ( void *item, void *data )
173 {
174     SDumper *b = data;
175     const SExpression *self = ( const void* ) item;
176 
177     SDumperSep ( b );
178     b -> rc = SExpressionDump ( self, b );
179     SDumperSepString ( b, SDumperMode ( b ) == sdmCompact ? "," : ", " );
180 
181     return ( b -> rc != 0 ) ? true : false;
182 }
183 
SExpressionBracketListDump(const Vector * expr,SDumper * b,const char * begin,const char * end)184 rc_t SExpressionBracketListDump ( const Vector *expr, SDumper *b,
185     const char *begin, const char *end )
186 {
187     SDumperSepString ( b, begin );
188     if ( VectorDoUntil ( expr, false, SExpressionListDump, b ) )
189         return b -> rc;
190     return SDumperPrint ( b, end );
191 }
192 
193 static
STypeExprDump(const STypeExpr * self,SDumper * b)194 rc_t STypeExprDump ( const STypeExpr *self, SDumper *b )
195 {
196     rc_t rc;
197     if ( self -> fmt != NULL )
198     {
199         rc = SFormatDump ( self -> fmt, b );
200         if ( rc != 0 )
201             return rc;
202 
203         if ( self -> dt == NULL && self -> ts == NULL && self -> id == NULL )
204             return 0;
205 
206         rc = SDumperWrite ( b, "/", 1 );
207         if ( rc != 0 )
208             return rc;
209     }
210 
211     if ( self -> dt != NULL )
212         rc = SDatatypeDump ( self -> dt, b );
213     else if ( self -> ts != NULL )
214         rc = STypesetDump ( self -> ts, b );
215 #if SLVL >= 3
216     else if ( self -> id != NULL )
217         rc = SIndirectTypeDump ( self -> id, b );
218 #endif
219     else
220         rc = SDumperWrite ( b, "NULL", 4 );
221 
222     if ( rc == 0 )
223     {
224         if ( SDumperMode ( b ) == sdmCompact )
225         {
226             if ( self -> dim != NULL )
227                 rc = SDumperPrint ( b, "[%E]", self -> dim );
228             else if ( self -> fd . td . dim == 0 )
229                 rc = SDumperPrint ( b, "[*]" );
230         }
231         else
232         {
233             if ( self -> dim != NULL )
234                 rc = SDumperPrint ( b, " [ %E ]", self -> dim );
235             else if ( self -> fd . td . dim == 0 )
236                 rc = SDumperPrint ( b, " [ * ]" );
237         }
238     }
239 
240     return rc;
241 }
242 
243 static
SConstExprDump(const SConstExpr * self,SDumper * b)244 rc_t SConstExprDump ( const SConstExpr *self, SDumper *b )
245 {
246     rc_t rc = 0;
247     bool compact = SDumperMode ( b ) == sdmCompact ? true : false;
248     const SDatatype *dt = VSchemaFindTypeid ( b -> schema, self -> td . type_id );
249     uint32_t bits = dt -> size;
250     uint32_t i, dim = SDatatypeIntrinsicDim ( dt );
251     assert ( dim != 0 && ( bits % dim ) == 0 );
252     bits /= dim;
253     dim *= self -> td . dim;
254 
255     /* open a vector expression */
256     if ( dt -> domain < ddAscii && dim > 1 )
257     {
258         rc = SDumperPrint ( b, compact ? "[" : "[ " );
259         if ( rc != 0 )
260             return rc;
261     }
262 
263     SDumperSepString ( b, "" );
264 
265     switch ( dt -> domain )
266     {
267     case ddBool:
268         for ( i = 0; i < dim; ++ i )
269         {
270             rc = SDumperPrint ( b, "\v%s", self -> u . b [ i ] ? "true" : "false" );
271             if ( rc != 0 )
272                 return rc;
273             SDumperSepString ( b, compact ? "," : ", " );
274         }
275         break;
276     case ddUint:
277         switch ( bits )
278         {
279         case 8:
280             for ( i = 0; i < dim; ++ i )
281             {
282                 rc = SDumperPrint ( b, "\v%u", self -> u . u8 [ i ] );
283                 if ( rc != 0 )
284                     return rc;
285                 SDumperSepString ( b, compact ? "," : ", " );
286             }
287             break;
288         case 16:
289             for ( i = 0; i < dim; ++ i )
290             {
291                 rc = SDumperPrint ( b, "\v%u", self -> u . u16 [ i ] );
292                 if ( rc != 0 )
293                     return rc;
294                 SDumperSepString ( b, compact ? "," : ", " );
295             }
296             break;
297         case 32:
298             for ( i = 0; i < dim; ++ i )
299             {
300                 rc = SDumperPrint ( b, "\v%u", self -> u . u32 [ i ] );
301                 if ( rc != 0 )
302                     return rc;
303                 SDumperSepString ( b, compact ? "," : ", " );
304             }
305             break;
306         case 64:
307             for ( i = 0; i < dim; ++ i )
308             {
309                 rc = SDumperPrint ( b, "\v%lu", self -> u . u64 [ i ] );
310                 if ( rc != 0 )
311                     return rc;
312                 SDumperSepString ( b, compact ? "," : ", " );
313             }
314             break;
315         }
316         break;
317     case ddInt:
318         switch ( bits )
319         {
320         case 8:
321             for ( i = 0; i < dim; ++ i )
322             {
323                 rc = SDumperPrint ( b, "\v%d", self -> u . i8 [ i ] );
324                 if ( rc != 0 )
325                     return rc;
326                 SDumperSepString ( b, compact ? "," : ", " );
327             }
328             break;
329         case 16:
330             for ( i = 0; i < dim; ++ i )
331             {
332                 rc = SDumperPrint ( b, "\v%d", self -> u . i16 [ i ] );
333                 if ( rc != 0 )
334                     return rc;
335                 SDumperSepString ( b, compact ? "," : ", " );
336             }
337             break;
338         case 32:
339             for ( i = 0; i < dim; ++ i )
340             {
341                 rc = SDumperPrint ( b, "\v%d", self -> u . i32 [ i ] );
342                 if ( rc != 0 )
343                     return rc;
344                 SDumperSepString ( b, compact ? "," : ", " );
345             }
346             break;
347         case 64:
348             for ( i = 0; i < dim; ++ i )
349             {
350                 rc = SDumperPrint ( b, "\v%ld", self -> u . i64 [ i ] );
351                 if ( rc != 0 )
352                     return rc;
353                 SDumperSepString ( b, compact ? "," : ", " );
354             }
355             break;
356         }
357         break;
358     case ddFloat:
359         switch ( bits )
360         {
361         case 32:
362             for ( i = 0; i < dim; ++ i )
363             {
364                 rc = SDumperPrint ( b, "\v%f", ( double ) self -> u . f32 [ i ] );
365                 if ( rc != 0 )
366                     return rc;
367                 SDumperSepString ( b, compact ? "," : ", " );
368             }
369             break;
370         case 64:
371             for ( i = 0; i < dim; ++ i )
372             {
373                 rc = SDumperPrint ( b, "\v%f", self -> u . f64 [ i ] );
374                 if ( rc != 0 )
375                     return rc;
376                 SDumperSepString ( b, compact ? "," : ", " );
377             }
378             break;
379         }
380         break;
381     case ddAscii:
382     {
383         const char *end, *p;
384 
385         rc = SDumperWrite ( b, "'", 1 );
386 
387     do_ascii:
388         for ( p = self -> u . ascii, end = p + dim; rc == 0 && p < end; )
389         {
390             const char *start = p;
391             while ( p < end && isprint ( * p ) )
392                 ++ p;
393             rc = SDumperWrite ( b, start, p - start );
394             if ( p == end )
395                 break;
396 
397             switch ( * p )
398             {
399             case '\n':
400                 rc = SDumperWrite ( b, "\\n", 2 );
401                 break;
402             case '\r':
403                 rc = SDumperWrite ( b, "\\", 2 );
404                 break;
405             case '\t':
406                 rc = SDumperWrite ( b, "\\t", 2 );
407                 break;
408             default:
409                 rc = SDumperPrint ( b, "\\x%x%x", ( * ( uint8_t* ) p ) / 16, * p & 15 );
410             }
411             ++ p;
412         }
413         if ( rc == 0 )
414             rc = SDumperWrite ( b, "'", 1 );
415         return rc;
416     }
417     case ddUnicode:
418     {
419         rc = SDumperWrite ( b, "'", 1 );
420         if ( rc != 0 )
421             return rc;
422 
423         if ( bits == 8 )
424             goto do_ascii;
425 
426         for ( i = 0; i < dim; ++ i )
427         {
428             char buff [ 8 ];
429             uint32_t ch = ( bits == 16 ) ?
430                 ( uint32_t )  self -> u . utf16 [ i ] :
431                 self -> u . utf32 [ i ];
432 
433             if ( ch >= 128 )
434                 sprintf ( buff, "\\u%04x", ch );
435             else if ( isprint ( ( int ) ch ) )
436                 buff [ 0 ] = ( char ) ch, buff [ 1 ] = 0;
437             else switch ( ch )
438             {
439             case '\n':
440                 sprintf ( buff, "\\n" );
441                 break;
442             case '\r':
443                 sprintf ( buff, "\\r" );
444                 break;
445             case '\t':
446                 sprintf ( buff, "\\t" );
447                 break;
448             default:
449                 sprintf ( buff, "\\x%02x", ch );
450             }
451 
452             rc = SDumperPrint ( b, buff );
453             if ( rc != 0 )
454                 return rc;
455         }
456         if ( rc == 0 )
457             rc = SDumperWrite ( b, "'", 1 );
458         return rc;
459     }}
460 
461     if ( rc == 0 && dim > 1 )
462         rc = SDumperPrint ( b, compact ? "]" : " ]" );
463 
464     return rc;
465 }
466 
467 #if SLVL >= 3
468 static
SFuncExprDump(const SFuncExpr * self,SDumper * b)469 rc_t SFuncExprDump ( const SFuncExpr *self, SDumper *b )
470 {
471     rc_t rc;
472     bool compact = SDumperMode ( b ) == sdmCompact ? true : false;
473 
474     if ( VectorLength ( & self -> schem ) != 0 )
475     {
476         if ( compact )
477             rc = SExpressionBracketListDump ( & self -> schem, b, "<", ">" );
478         else
479             rc = SExpressionBracketListDump ( & self -> schem, b, "< ", " > " );
480         if ( rc != 0 )
481             return rc;
482     }
483 
484     rc = SFunctionDump ( self -> func, b );
485     if ( rc != 0 )
486         return rc;
487 
488     rc = SDumperVersion ( b, self -> version_requested ?
489         self -> version : self -> func -> version );
490     if ( rc != 0 )
491         return rc;
492 
493     if ( VectorLength ( & self -> pfact ) != 0 )
494     {
495         if ( compact )
496             rc = SExpressionBracketListDump ( & self -> pfact, b, "<", ">" );
497         else
498             rc = SExpressionBracketListDump ( & self -> pfact, b, " < ", " >" );
499         if ( rc != 0 )
500             return rc;
501     }
502 
503     if ( VectorLength ( & self -> pfunc ) == 0 )
504         rc = SDumperPrint ( b, compact ? "()" : " ()" );
505     else if ( compact )
506         rc = SExpressionBracketListDump ( & self -> pfunc, b, "(", ")" );
507     else
508         rc = SExpressionBracketListDump ( & self -> pfunc, b, " ( ", " )" );
509 
510     return rc;
511 }
512 #endif
513 
514 #if SLVL >= 7
515 static
SPhysEncExprDump(const SPhysEncExpr * self,SDumper * b)516 rc_t SPhysEncExprDump ( const SPhysEncExpr *self, SDumper *b )
517 {
518     rc_t rc;
519     bool compact = SDumperMode ( b ) == sdmCompact ? true : false;
520 
521     if ( VectorLength ( & self -> schem ) != 0 )
522     {
523         if ( compact )
524             rc = SExpressionBracketListDump ( & self -> schem, b, "<", ">" );
525         else
526             rc = SExpressionBracketListDump ( & self -> schem, b, "< ", " > " );
527         if ( rc != 0 )
528             return rc;
529     }
530 
531     rc = SPhysicalDump ( self -> phys, b );
532     if ( rc != 0 )
533         return rc;
534 
535     if ( self -> version_requested )
536         rc = SDumperVersion ( b, self -> version );
537     else
538         rc = SDumperVersion ( b, self -> phys -> version );
539     if ( rc != 0 )
540         return rc;
541 
542     if ( VectorLength ( & self -> pfact ) != 0 )
543     {
544         if ( compact )
545             rc = SExpressionBracketListDump ( & self -> pfact, b, "<", ">" );
546         else
547             rc = SExpressionBracketListDump ( & self -> pfact, b, " < ", " >" );
548         if ( rc != 0 )
549             return rc;
550     }
551 
552     return rc;
553 }
554 #endif
555 
SExpressionDump(const SExpression * self,SDumper * b)556 rc_t SExpressionDump ( const SExpression *self, SDumper *b )
557 {
558     bool compact = SDumperMode ( b ) == sdmCompact ? true : false;
559 
560     if ( self == NULL )
561         return SDumperWrite ( b, "NULL", 4 );
562 
563     switch ( self -> var )
564     {
565     case eTypeExpr:
566         return STypeExprDump ( ( const STypeExpr* ) self, b );
567     case eConstExpr:
568         return SConstExprDump ( ( const SConstExpr* ) self, b );
569 #if SLVL >= 3
570     case eIndirectExpr:
571     case eParamExpr:
572     case eProdExpr:
573     case eFwdExpr:
574     case eFuncParamExpr:
575     case eColExpr:
576     case ePhysExpr:
577     {
578         const SSymExpr *x = ( const SSymExpr* ) self;
579         if ( x -> alt )
580             return SDumperPrint ( b, "@%N", x -> _sym );
581         return KSymbolDump ( x -> _sym, b );
582     }
583     case eFuncExpr:
584 #if SLVL >= 4
585     case eScriptExpr:
586 #endif
587         return SFuncExprDump ( ( const SFuncExpr* ) self, b );
588 #endif
589 #if SLVL >= 7
590     case ePhysEncExpr:
591         return SPhysEncExprDump ( ( const SPhysEncExpr* ) self, b );
592 #endif
593     case eNegateExpr:
594     {
595         const SUnaryExpr *x = ( const SUnaryExpr* ) self;
596         return SDumperPrint ( b, "-%E", x -> expr );
597     }
598     case eCastExpr:
599     {
600         const SBinExpr *x = ( const SBinExpr* ) self;
601         return SDumperPrint ( b, compact ? "(%E)%E" : "( %E ) %E", x -> left, x -> right );
602     }
603     case eCondExpr:
604     {
605         const SBinExpr *x = ( const SBinExpr* ) self;
606         return SDumperPrint ( b, compact ? "%E|%E" : "%E | %E", x -> left, x -> right );
607     }
608     case eVectorExpr:
609     {
610         const SVectExpr *x = ( const SVectExpr* ) self;
611         if ( compact )
612             return SExpressionBracketListDump ( & x -> expr, b, "[", "]" );
613         return SExpressionBracketListDump ( & x -> expr, b, "[ ", " ]" );
614     }
615     case eMembExpr:
616         assert (false); //TODO: SMembExprDump
617         break;
618     }
619 
620     return SDumperPrint ( b, "EXPR-UNKNOWN" );
621 
622 }
623 
SExpressionVDump(void * item,void * data)624 bool SExpressionVDump ( void *item, void *data )
625 {
626     SDumper *b = data;
627     const SExpression *self = ( const void* ) item;
628 
629     b -> rc = SExpressionDump ( self, b );
630 
631     return ( b -> rc != 0 ) ? true : false;
632 }
633 #endif /* SLVL >= 1 */
634 
635 
636 /*--------------------------------------------------------------------------
637  * STypeExpr
638  */
639 
640 /* Mark
641  */
STypeExprMark(const STypeExpr * self,const VSchema * schema)642 void STypeExprMark ( const STypeExpr *self, const VSchema *schema )
643 {
644     if ( self -> fmt != NULL )
645         SFormatMark ( self -> fmt );
646     if ( self -> dt != NULL )
647         SDatatypeMark ( self -> dt );
648     if ( self -> ts != NULL )
649         STypesetMark ( self -> ts, schema );
650     if ( self -> dim )
651         SExpressionMark ( ( void * ) self -> dim, ( void * ) schema );
652 }
653 
654 
655 /*--------------------------------------------------------------------------
656  * SSymExpr
657  */
658 
659 /* Make
660  *  used when creating implicit expressions
661  */
SSymExprMake(const SExpression ** xp,const KSymbol * sym,uint32_t var)662 rc_t SSymExprMake ( const SExpression **xp, const KSymbol *sym, uint32_t var )
663 {
664     SSymExpr *x = malloc ( sizeof * x );
665     if ( x == NULL )
666         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
667 
668     x -> dad . var = var;
669     atomic32_set ( & x -> dad . refcount, 1 );
670     x -> _sym = sym;
671     x -> alt = false;
672 
673     * xp = & x -> dad;
674     return 0;
675 }
676 
677 /* Mark
678  */
SSymExprMark(const SSymExpr * self,const VSchema * schema)679 void SSymExprMark ( const SSymExpr *self, const VSchema *schema )
680 {
681     switch ( self -> _sym -> type )
682     {
683     case eConstant:
684         SConstantMark ( self -> _sym -> u . obj );
685         break;
686     }
687 }
688 
689 
690 /*--------------------------------------------------------------------------
691  * SFuncExpr
692  */
693 
694 /* Mark
695  */
SFuncExprMark(const SFuncExpr * self,const VSchema * schema)696 void SFuncExprMark ( const SFuncExpr *self, const VSchema *schema )
697 {
698     SFunctionMark ( ( void * )self -> func, ( void * )schema );
699 }
700 
701 
702 /*--------------------------------------------------------------------------
703  * SPhysEncExpr
704  */
705 
706 /* ImplicitPhysEncExpr
707  *  create expression object
708  */
VSchemaImplicitPhysEncExpr(VSchema * self,VTypedecl * td,const SExpression ** expr,const char * text,const char * ctx)709 rc_t VSchemaImplicitPhysEncExpr ( VSchema *self,
710     VTypedecl *td, const SExpression **expr, const char *text, const char *ctx )
711 {
712     KSymTable tbl;
713     rc_t rc = init_symtab ( & tbl, self );
714     if ( rc == 0 )
715     {
716         KToken t;
717         KTokenText tt;
718         KTokenSource src;
719 
720         SchemaEnv env;
721         SchemaEnvInit ( & env, EXT_SCHEMA_LANG_VERSION );
722 
723         KTokenTextInitCString ( & tt, text, ctx );
724         KTokenSourceInit ( & src, & tt );
725         next_token ( & tbl, & src, & t );
726 
727         rc = phys_encoding_expr ( & tbl, & src, & t, & env, self, td, expr );
728 
729         KSymTableWhack ( & tbl );
730     }
731     return rc;
732 }
733 
734 /* Mark
735  */
SPhysEncExprMark(const SPhysEncExpr * self,const VSchema * schema)736 void SPhysEncExprMark ( const SPhysEncExpr *self, const VSchema *schema )
737 {
738     SPhysicalMark ( ( void * )self -> phys, ( void * )schema );
739 }
740 
741 
742 /*--------------------------------------------------------------------------
743  * VSchema
744  */
745 
746 #if SLVL >= 1
747 static
const_vect_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SVectExpr ** xp)748 rc_t const_vect_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
749     const SchemaEnv *env, const VSchema *self, const SVectExpr **xp )
750 {
751     rc_t rc;
752     SVectExpr *x = malloc ( sizeof * x );
753     if ( x == NULL )
754         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
755 
756     x -> dad . var = eVectorExpr;
757     atomic32_set ( & x -> dad . refcount, 1 );
758     VectorInit ( & x -> expr, 0, 16 );
759 
760     do
761     {
762         SExpression *vx;
763         rc = const_expr ( tbl, src, next_token ( tbl, src, t ),
764             env, self, ( const SExpression** ) & vx );
765         if ( rc != 0 )
766             break;
767 
768         if ( vx -> var == eVectorExpr )
769         {
770             SExpressionWhack ( vx );
771             rc = KTokenExpected ( t, klogErr, "scalar constant" );
772             break;
773         }
774 
775         rc = VectorAppend ( & x -> expr, NULL, vx );
776         if ( rc != 0 )
777         {
778             SExpressionWhack ( vx );
779             break;
780         }
781     }
782     while ( t -> id == eComma );
783 
784     if ( rc != 0 )
785         SExpressionWhack ( & x -> dad );
786     else
787     {
788         * xp = x;
789         rc = expect ( tbl, src, t, eRightSquare, "]", true );
790     }
791 
792     return rc;
793 }
794 #endif
795 
796 /*
797  * const-expr         = <constname>
798  *                    | CONST-VALUE
799  */
800 #if SLVL >= 1
801 static
negate_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SExpression ** xp)802 rc_t negate_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
803     const SchemaEnv *env, const VSchema *self, const SExpression **xp )
804 {
805     rc_t rc = const_expr ( tbl, src, next_token ( tbl, src, t ), env, self, xp );
806     if ( rc == 0 )
807     {
808         SUnaryExpr *x;
809         SConstExpr *cx;
810         const SSymExpr *sx;
811         const SExpression *td;
812         const SDatatype *dt;
813 
814         static atomic32_t s_I8_id;
815         static atomic32_t s_I16_id;
816         static atomic32_t s_I32_id;
817         static atomic32_t s_I64_id;
818 
819         switch ( ( * xp ) -> var )
820         {
821         case eConstExpr:
822             cx = * ( SConstExpr** ) xp;
823             if ( cx -> td . dim < 2 )
824             {
825                 dt = VSchemaFindTypeid ( self, cx -> td . type_id );
826                 if ( dt != NULL ) switch ( dt -> domain )
827                 {
828                 case vtdUint:
829                     switch ( dt -> size )
830                     {
831                     case 8:
832                         cx -> td . type_id  = VSchemaCacheIntrinsicTypeId ( self, & s_I8_id, "I8" );
833                         break;
834                     case 16:
835                         cx -> td . type_id  = VSchemaCacheIntrinsicTypeId ( self, & s_I16_id, "I16" );
836                         break;
837                     case 32:
838                         cx -> td . type_id  = VSchemaCacheIntrinsicTypeId ( self, & s_I32_id, "I32" );
839                         break;
840                     case 64:
841                         cx -> td . type_id  = VSchemaCacheIntrinsicTypeId ( self, & s_I64_id, "I64" );
842                         break;
843                     }
844                     /* no break */
845                 case vtdInt:
846                     switch ( dt -> size )
847                     {
848                     case 8:
849                         cx -> u . i8 [ 0 ] = - cx -> u . i8 [ 0 ];
850                         return 0;
851                     case 16:
852                         cx -> u . i16 [ 0 ] = - cx -> u . i16 [ 0 ];
853                         return 0;
854                     case 32:
855                         cx -> u . i32 [ 0 ] = - cx -> u . i32 [ 0 ];
856                         return 0;
857                     case 64:
858                         cx -> u . i64 [ 0 ] = - cx -> u . i64 [ 0 ];
859                         return 0;
860                     }
861                     break;
862                 case vtdFloat:
863                     switch ( dt -> size )
864                     {
865                     case 32:
866                         cx -> u . f32 [ 0 ] = - cx -> u . f32 [ 0 ];
867                         return 0;
868                     case 64:
869                         cx -> u . f64 [ 0 ] = - cx -> u . f64 [ 0 ];
870                         return 0;
871                     }
872                     break;
873                 }
874             }
875             break;
876 
877         case eIndirectExpr:
878             /* if type is known, at least verify domain */
879             sx = * ( const SSymExpr** ) xp;
880             td = ( ( const SIndirectConst* ) sx -> _sym -> u . obj ) -> td;
881             if ( td != NULL )
882             {
883                 const STypeExpr *tx = ( const STypeExpr* ) td;
884                 if ( tx-> dad . var == eTypeExpr && tx -> resolved )
885                 {
886                     /* cannot have formats, but this is verified elsewhere */
887                     if ( tx -> fd . fmt == 0 && tx -> fd . td . dim < 2 )
888                     {
889                         /* determine domain */
890                         dt = VSchemaFindTypeid ( self, tx -> fd . td . type_id );
891                         if ( dt != NULL ) switch ( dt -> domain )
892                         {
893                         case vtdUint:
894                             KTokenExpected ( t, klogWarn, "signed integer" );
895                         case vtdInt:
896                         case vtdFloat:
897                             goto introduce_negate_expr;
898                         }
899                     }
900                 }
901 
902                 break;
903             }
904 
905         introduce_negate_expr:
906             x = malloc ( sizeof * x );
907             if ( x == NULL )
908             {
909                 SExpressionWhack ( & sx -> dad );
910                 return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
911             }
912 
913             x -> dad . var = eNegateExpr;
914             atomic32_set ( & x -> dad . refcount, 1 );
915             x -> expr = & sx -> dad;
916             * xp = & x -> dad;
917             return 0;
918 
919         case eNegateExpr:
920             /* double negate */
921             x = * ( SUnaryExpr** ) xp;
922             * xp = x -> expr;
923             free ( x );
924             return 0;
925 
926         default:
927             SExpressionWhack ( * xp );
928             return KTokenExpected ( t, klogErr, "integer or floating point constant" );
929         }
930 
931         rc = RC ( rcVDB, rcSchema, rcParsing, rcType, rcIncorrect );
932         KTokenRCExplain ( t, klogErr, rc );
933     }
934 
935     return rc;
936 }
937 
938 static
bool_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SConstExpr ** xp)939 rc_t bool_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
940     const SchemaEnv *env, const VSchema *self, const SConstExpr **xp )
941 {
942     static atomic32_t s_bool_id;
943 
944     SConstExpr *x = malloc ( sizeof * x - sizeof x -> u + sizeof x -> u . b [ 0 ] );
945     if ( x == NULL )
946         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
947 
948     assert ( t -> id == kw_true || t -> id == kw_false );
949     x -> u . b [ 0 ] = ( t -> id == kw_true );
950 
951     x -> dad . var = eConstExpr;
952     atomic32_set ( & x -> dad . refcount, 1 );
953     x -> td . type_id = VSchemaCacheIntrinsicTypeId ( self, & s_bool_id, "bool" );
954     x -> td . dim = 1;
955 
956     * xp = x;
957 
958     next_token ( tbl, src, t );
959     return 0;
960 }
961 
962 static
uint_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SConstExpr ** xp)963 rc_t uint_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
964     const SchemaEnv *env, const VSchema *self, const SConstExpr **xp )
965 {
966     rc_t rc;
967     static atomic32_t s_U64_id;
968 
969     SConstExpr *x = malloc ( sizeof * x - sizeof x -> u + sizeof x -> u . u64 [ 0 ] );
970     if ( x == NULL )
971         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
972 
973     rc = KTokenToU64 ( t, & x -> u . u64 [ 0 ] );
974     if ( rc != 0 )
975     {
976         free ( x );
977         return rc;
978     }
979 
980     x -> dad . var = eConstExpr;
981     atomic32_set ( & x -> dad . refcount, 1 );
982     x -> td . type_id = VSchemaCacheIntrinsicTypeId ( self, & s_U64_id, "U64" );
983     x -> td . dim = 1;
984 
985     * xp = x;
986 
987     next_token ( tbl, src, t );
988     return 0;
989 }
990 
991 static
float_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SConstExpr ** xp)992 rc_t float_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
993     const SchemaEnv *env, const VSchema *self, const SConstExpr **xp )
994 {
995     rc_t rc;
996     static atomic32_t s_F64_id;
997 
998     SConstExpr *x = malloc ( sizeof * x - sizeof x -> u + sizeof x -> u . f64 [ 0 ] );
999     if ( x == NULL )
1000         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1001 
1002     rc = KTokenToF64 ( t, & x -> u . f64 [ 0 ] );
1003     if ( rc != 0 )
1004     {
1005         free ( x );
1006         return rc;
1007     }
1008 
1009     x -> dad . var = eConstExpr;
1010     atomic32_set ( & x -> dad . refcount, 1 );
1011     x -> td . type_id = VSchemaCacheIntrinsicTypeId ( self, & s_F64_id, "F64" );
1012     x -> td . dim = 1;
1013 
1014     * xp = x;
1015 
1016     next_token ( tbl, src, t );
1017     return 0;
1018 }
1019 
1020 static
string_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SConstExpr ** xp)1021 rc_t string_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1022     const SchemaEnv *env, const VSchema *self, const SConstExpr **xp )
1023 {
1024     rc_t rc;
1025 
1026     size_t size = t -> str . size + 1;
1027     SConstExpr *x = malloc ( sizeof * x - sizeof x -> u + size );
1028     if ( x == NULL )
1029         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1030 
1031     rc = KTokenToString ( t, x -> u . utf8, size, & size );
1032     if ( rc != 0 )
1033     {
1034         free ( x );
1035         return rc;
1036     }
1037 
1038     x -> dad . var = eConstExpr;
1039     atomic32_set ( & x -> dad . refcount, 1 );
1040     x -> td . dim = ( uint32_t ) size;
1041 
1042     if ( t -> id == eString || ( size_t ) string_len ( x -> u . utf8, size ) == size )
1043     {
1044         static atomic32_t s_ascii_id;
1045         x -> td . type_id = VSchemaCacheIntrinsicTypeId ( self, & s_ascii_id, "ascii" );
1046     }
1047     else
1048     {
1049         static atomic32_t s_utf8_id;
1050         x -> td . type_id = VSchemaCacheIntrinsicTypeId ( self, & s_utf8_id, "utf8" );
1051     }
1052 
1053     * xp = x;
1054 
1055     next_token ( tbl, src, t );
1056     return 0;
1057 }
1058 
1059 static
sym_const_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SConstExpr ** xp)1060 rc_t sym_const_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1061     const SchemaEnv *env, const VSchema *self, const SConstExpr **xp )
1062 {
1063     const KSymbol *sym = t -> sym;
1064     const SConstant *cnst = sym -> u . obj;
1065 
1066     assert ( cnst -> expr != NULL );
1067     atomic32_inc ( & ( ( SExpression* ) cnst -> expr ) -> refcount );
1068     * xp = ( SConstExpr* ) cnst -> expr;
1069 
1070     next_token ( tbl, src, t );
1071     return 0;
1072 }
1073 #endif /* SLVL >= 1 */
1074 
1075 
1076 #if SLVL >= 3
indirect_const_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SExpression ** xp)1077 LIB_EXPORT rc_t CC indirect_const_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1078     const SchemaEnv *env, const VSchema *self, const SExpression **xp )
1079 {
1080     SSymExpr *x = malloc ( sizeof *x );
1081     if ( x == NULL )
1082         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1083 
1084     x -> dad . var = eIndirectExpr;
1085     atomic32_set ( & x -> dad . refcount, 1 );
1086     x -> _sym = t -> sym;
1087     x -> alt = false;
1088     * xp = & x -> dad;
1089 
1090     next_token ( tbl, src, t );
1091     return 0;
1092 }
1093 #endif /* SLVL >= 1 */
1094 
1095 /*
1096  * type-expr          = <typeset>
1097  *                    | <fmtdecl>
1098  *                    | <fmtname> '/' <typeset>
1099  */
1100 #if SLVL >= 1
1101 static
type_expr_impl(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SExpression ** fd,bool vardim)1102 rc_t type_expr_impl ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1103     const SchemaEnv *env, const VSchema *self, const SExpression **fd, bool vardim )
1104 {
1105     STypeExpr *x;
1106 
1107     rc_t rc = next_fqn ( tbl, src, t, env );
1108     if ( rc != 0 )
1109         return rc;
1110 
1111     x = malloc ( sizeof *x );
1112     if ( x == NULL )
1113         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1114 
1115     x -> dad . var = eTypeExpr;
1116     atomic32_set ( & x -> dad . refcount, 1 );
1117     x -> fmt = NULL;
1118     x -> dt = NULL;
1119     x -> ts = NULL;
1120     x -> id = NULL;
1121     x -> dim = NULL;
1122     x -> fd . fmt = 0;
1123     x -> fd . td . type_id = 0;
1124     x -> fd . td . dim = 0;
1125     x -> resolved = true;
1126 
1127     if ( t -> id == eFormat )
1128     {
1129         x -> fmt = t -> sym -> u . obj;
1130         x -> fd . fmt = x -> fmt -> id;
1131         if ( next_token ( tbl, src, t ) -> id != eFwdSlash )
1132         {
1133             * fd = & x -> dad;
1134             return 0;
1135         }
1136 
1137         rc = next_fqn ( tbl, src, next_token ( tbl, src, t ), env );
1138         if ( rc != 0 )
1139         {
1140             free ( x );
1141             return rc;
1142         }
1143     }
1144 
1145     switch ( t -> id )
1146     {
1147     case eDatatype:
1148         x -> dt = t -> sym -> u . obj;
1149         x -> fd . td . type_id = x -> dt -> id;
1150         break;
1151     case eTypeset:
1152         x -> ts = t -> sym -> u . obj;
1153         x -> fd . td . type_id = x -> ts -> id;
1154         break;
1155 #if SLVL >= 3
1156     case eSchemaType:
1157         x -> id = t -> sym -> u . obj;
1158         x -> resolved = false;
1159         break;
1160 #endif
1161     default:
1162         free ( x );
1163         return KTokenExpected ( t, klogErr, "datatype or typeset" );
1164     }
1165 
1166     if ( next_token ( tbl, src, t ) -> id != eLeftSquare )
1167         x -> fd . td . dim = 1;
1168     else
1169     {
1170         if ( next_token ( tbl, src, t ) -> id == eAsterisk && vardim )
1171             next_token ( tbl, src, t );
1172         else
1173         {
1174             const SConstExpr *cx;
1175 
1176             rc = const_expr ( tbl, src, t, env, self, & x -> dim );
1177             if ( rc != 0 )
1178             {
1179                 free ( x );
1180                 return rc;
1181             }
1182 
1183             switch ( x -> dim -> var )
1184             {
1185             case eConstExpr:
1186                 cx =  ( const SConstExpr* ) x -> dim;
1187                 if ( cx -> td . dim == 1 )
1188                 {
1189                     const SDatatype *dt = VSchemaFindTypeid ( self, cx -> td . type_id );
1190                     if ( dt != NULL && SDatatypeIntrinsicDim ( dt ) == 1 )
1191                     {
1192                         if ( dt -> domain == vtdUint )
1193                         {
1194                             switch ( dt -> size )
1195                             {
1196                             case 64:
1197                                 if ( cx -> u . u64 [ 0 ] <= 0xFFFFFFFF )
1198                                     x -> fd . td . dim = ( uint32_t ) cx -> u . u64 [ 0 ];
1199                                 break;
1200                             case 32:
1201                                 x -> fd . td . dim = cx -> u . u32 [ 0 ];
1202                                 break;
1203                             case 16:
1204                                 x -> fd . td . dim = cx -> u . u16 [ 0 ];
1205                                 break;
1206                             case 8:
1207                                 x -> fd . td . dim = cx -> u . u8 [ 0 ];
1208                                 break;
1209                             }
1210                         }
1211                         else if ( dt -> domain ==  vtdInt )
1212                         {
1213                             switch ( dt -> size )
1214                             {
1215                             case 64:
1216                                 if ( cx -> u . i64 [ 0 ] > 0 && cx -> u . i64 [ 0 ] <= 0xFFFFFFFF )
1217                                     x -> fd . td . dim = ( uint32_t ) cx -> u . i64 [ 0 ];
1218                                 break;
1219                             case 32:
1220                                 if ( cx -> u . i32 [ 0 ] > 0 )
1221                                     x -> fd . td . dim = cx -> u . i32 [ 0 ];
1222                                 break;
1223                             case 16:
1224                                 if ( cx -> u . i16 [ 0 ] > 0 )
1225                                     x -> fd . td . dim = cx -> u . i16 [ 0 ];
1226                                 break;
1227                             case 8:
1228                                 if ( cx -> u . i8 [ 0 ] > 0 )
1229                                     x -> fd . td . dim = cx -> u . i8 [ 0 ];
1230                                 break;
1231                             }
1232                         }
1233 
1234                         if ( x -> fd . td . dim > 0 )
1235                             break;
1236                     }
1237                 }
1238 
1239                 SExpressionWhack ( & x -> dad );
1240                 return KTokenExpected ( t, klogErr, "constant integer expression" );
1241 
1242             case eIndirectExpr:
1243                 x -> resolved = false;
1244                 break;
1245             default:
1246                 SExpressionWhack ( & x -> dad );
1247                 return KTokenExpected ( t, klogErr, "constant integer expression" );
1248             }
1249         }
1250 
1251         rc = expect ( tbl, src, t, eRightSquare, "]", true );
1252         if ( rc != 0 )
1253         {
1254             SExpressionWhack ( & x -> dad );
1255             return rc;
1256         }
1257     }
1258 
1259     * fd = & x -> dad;
1260     return 0;
1261 }
1262 
type_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SExpression ** fd)1263 rc_t type_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1264     const SchemaEnv *env, const VSchema *self, const SExpression **fd )
1265 {
1266     return type_expr_impl ( tbl, src, t, env, self, fd, false );
1267 }
1268 
vardim_type_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SExpression ** fd)1269 rc_t vardim_type_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1270     const SchemaEnv *env, const VSchema *self, const SExpression **fd )
1271 {
1272     return type_expr_impl ( tbl, src, t, env, self, fd, true );
1273 }
1274 #endif /* SLVL >= 1 */
1275 
1276 
1277 /*
1278  * cast_expr          = '(' <type-expr> ')' <expression>
1279  */
1280 #if SLVL >= 1
1281 static
cast_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SBinExpr ** xp,rc_t (* expr)(KSymTable *,KTokenSource *,KToken *,const SchemaEnv *,VSchema *,const SExpression **))1282 rc_t cast_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
1283     const SchemaEnv *env, VSchema *self, const SBinExpr **xp,
1284     rc_t ( * expr ) ( KSymTable*, KTokenSource*, KToken*,
1285         const SchemaEnv*, VSchema*, const SExpression** ) )
1286 {
1287     rc_t rc;
1288     SBinExpr *x = malloc ( sizeof * x );
1289     if ( x == NULL )
1290         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1291 
1292     rc = type_expr ( tbl, src, next_token ( tbl, src, t ), env, self, & x -> left );
1293     if ( rc == 0 )
1294     {
1295         rc = expect ( tbl, src, t, eRightParen, ")", true );
1296         if ( rc == 0 )
1297         {
1298             rc = ( * expr ) ( tbl, src, t, env, self, & x -> right );
1299             if ( rc == 0 )
1300             {
1301                 x -> dad . var = eCastExpr;
1302                 atomic32_set ( & x -> dad . refcount, 1 );
1303                 * xp = x;
1304                 return 0;
1305             }
1306         }
1307 
1308         SExpressionWhack ( x -> left );
1309     }
1310 
1311     free ( x );
1312     return rc;
1313 }
1314 
1315 
const_expr(const KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,const VSchema * self,const SExpression ** xp)1316 rc_t const_expr ( const KSymTable *tbl, KTokenSource *src, KToken *t,
1317     const SchemaEnv *env, const VSchema *self, const SExpression **xp )
1318 {
1319     switch ( t -> id )
1320     {
1321     case eDecimal:
1322     case eHex:
1323     case eOctal:
1324         return uint_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1325     case eFloat:
1326     case eExpFloat:
1327         return float_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1328     case eString:
1329     case eEscapedString:
1330         return string_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1331     case eConstant:
1332         return sym_const_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1333 #if SLVL >= 4
1334     case eFactParam:
1335 #endif
1336 #if SLVL >= 3
1337     case eSchemaParam:
1338         return indirect_const_expr ( tbl, src, t, env, self, xp );
1339 #endif
1340     case eLeftSquare:
1341         return const_vect_expr ( tbl, src, t, env, self, ( const SVectExpr** ) xp );
1342     case kw_false:
1343     case kw_true:
1344         return bool_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1345     case eLeftParen:
1346         return cast_expr ( ( KSymTable* ) tbl, src, t, env,
1347             ( VSchema* ) self, ( const SBinExpr** ) xp,
1348             ( rc_t ( * ) ( KSymTable*, KTokenSource*, KToken*,
1349               const SchemaEnv*, VSchema*, const SExpression** ) ) const_expr );
1350     case eMinus:
1351         /* unary minus sign */
1352         return negate_expr ( tbl, src, t, env, self, xp );
1353     case ePlus:
1354         /* unary plus sign */
1355         return const_expr ( tbl, src, next_token ( tbl, src, t ), env, self, xp );
1356     }
1357 
1358     return KTokenExpected ( t, klogErr, "boolean, integer, float, string or symbolic constant" );
1359 }
1360 #endif /* SLVL >= 1 */
1361 
1362 
1363 /*
1364  * func-param-expr    = <funcname>
1365  */
1366 #if SLVL >= 4
1367 static
sym_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SSymExpr ** xp,uint32_t var,bool alt)1368 rc_t sym_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
1369     const SchemaEnv *env, VSchema *self, const SSymExpr **xp, uint32_t var, bool alt )
1370 {
1371     SSymExpr *x = malloc ( sizeof * x );
1372     if ( x == NULL )
1373         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1374 
1375     x -> dad . var = var;
1376     atomic32_set ( & x -> dad . refcount, 1 );
1377     x -> _sym = t -> sym;
1378     x -> alt = alt;
1379     * xp = x;
1380 
1381     next_token ( tbl, src, t );
1382     return 0;
1383 }
1384 
1385 #define func_param_expr( tbl, src, t, env, self, xp ) \
1386     sym_expr ( tbl, src, t, env, self, xp, eFuncParamExpr, false )
1387 
1388 #endif
1389 
1390 
1391 /*
1392  * param-expr         = <func-param>
1393  *
1394  */
1395 #if SLVL >= 4
1396 
1397 #define param_expr( tbl, src, t, env, self, xp ) \
1398     sym_expr ( tbl, src, t, env, self, xp, eParamExpr, false )
1399 
1400 #endif
1401 
1402 
1403 /*
1404  * prod-expr          = <production>
1405  *
1406  */
1407 #if SLVL >= 4
1408 
1409 #define prod_expr( tbl, src, t, env, self, xp ) \
1410     sym_expr ( tbl, src, t, env, self, xp, eProdExpr, false )
1411 
1412 #endif
1413 
1414 
1415 /*
1416  * fwd-expr           = ID
1417  */
1418 #if SLVL >= 4
1419 static
fwd_decl_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SSymExpr ** xp,bool alt)1420 rc_t fwd_decl_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
1421     const SchemaEnv *env, VSchema *self, const SSymExpr **xp, bool alt )
1422 {
1423     rc_t rc;
1424     SSymExpr *x = malloc ( sizeof * x );
1425     if ( x == NULL )
1426         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1427 
1428     rc = KSymTableCreateConstSymbol ( tbl, & x -> _sym, & t -> str, eForward, NULL );
1429     if ( rc != 0 )
1430     {
1431         free ( x );
1432         return rc;
1433     }
1434 
1435     x -> dad . var = eFwdExpr;
1436     atomic32_set ( & x -> dad . refcount, 1 );
1437     x -> alt = alt;
1438     * xp = x;
1439 
1440     next_token ( tbl, src, t );
1441     return 0;
1442 }
1443 
1444 #define fwd_ref_expr( tbl, src, t, env, self, xp, alt ) \
1445     sym_expr ( tbl, src, t, env, self, xp, eFwdExpr, alt )
1446 
1447 #endif
1448 
1449 
1450 /*
1451  * column-expr        = <column>
1452  */
1453 #if SLVL >= 8
1454 
1455 #define column_expr( tbl, src, t, env, self, xp, alt ) \
1456     sym_expr ( tbl, src, t, env, self, xp, eColExpr, alt )
1457 
1458 #endif
1459 
1460 
1461 /*
1462  * physical-expr      = KCOL
1463  */
1464 #if SLVL >= 7
1465 
1466 #define physical_expr( tbl, src, t, env, self, xp ) \
1467     sym_expr ( tbl, src, t, env, self, xp, ePhysExpr, false )
1468 
1469 #endif
1470 
1471 
1472 /*
1473  * schema-parms       = <schema-param> [ ',' <schema-parms> ]
1474  * schema-param       = [ ID '=' ]  <schema-value>
1475  * schema-value       = <fmtdecl>
1476  *                    | <uint-expr>
1477  */
1478 #if SLVL >= 4
1479 static
schema_value(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** v)1480 rc_t schema_value ( KSymTable *tbl, KTokenSource *src, KToken *t,
1481     const SchemaEnv *env, VSchema *self, const SExpression **v )
1482 {
1483     /* could be a typename */
1484     if ( t -> id == eNamespace )
1485     {
1486         rc_t rc = next_fqn ( tbl, src, t, env );
1487         if ( rc != 0 )
1488             return rc;
1489     }
1490 
1491     /* param value */
1492     switch ( t -> id )
1493     {
1494     /* type parameter */
1495     case eFormat:
1496     case eDatatype:
1497     case eTypeset:
1498     case eSchemaType:
1499         return type_expr ( tbl, src, t, env, self, v );
1500 
1501     /* manifest uint constant */
1502     case eDecimal:
1503     case eHex:
1504     case eOctal:
1505         return uint_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1506 
1507     /* symbolic constant must be uint */
1508     case eConstant:
1509         return sym_const_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1510 
1511     /* schema or factory constant must be uint
1512        but may not yet be completely resolved */
1513     case eSchemaParam:
1514     case eFactParam:
1515         return indirect_const_expr ( tbl, src, t, env, self, v );
1516     }
1517 
1518     return KTokenExpected ( t, klogErr, "data type or unsigned int constant" );
1519 }
1520 #endif
1521 
1522 /*
1523  * fact-parms         = <fact-param> [ ',' <fact-parms> ]
1524  * fact-param         = [ ID '=' ] <fact-value>         ( "ID =" not implemented )
1525  * fact-value         = <func-name>
1526  *                    | '[' <fact-const-list> ']'
1527  */
1528 #if SLVL >= 4
1529 static
fact_value(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** v)1530 rc_t fact_value ( KSymTable *tbl, KTokenSource *src, KToken *t,
1531     const SchemaEnv *env, VSchema *self, const SExpression **v )
1532 {
1533     if ( t -> id == eNamespace )
1534     {
1535         rc_t rc = next_fqn ( tbl, src, t, env );
1536         if ( rc != 0 )
1537             return rc;
1538     }
1539 
1540     switch ( t -> id )
1541     {
1542         /* const-expression */
1543     case eDecimal:
1544     case eHex:
1545     case eOctal:
1546         return uint_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1547     case eFloat:
1548     case eExpFloat:
1549         return float_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1550     case eString:
1551     case eEscapedString:
1552         return string_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1553     case eConstant:
1554         return sym_const_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1555     case eSchemaParam:
1556     case eFactParam:
1557         return indirect_const_expr ( tbl, src, t, env, self, v );
1558     case eLeftSquare:
1559         return const_vect_expr ( tbl, src, t, env, self, ( const SVectExpr** ) v );
1560     case kw_false:
1561     case kw_true:
1562         return bool_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1563 
1564         /* cast expression */
1565     case eLeftParen:
1566         return cast_expr ( tbl, src, t, env, self, ( const SBinExpr** ) v, fact_value );
1567 
1568         /* function name */
1569     case eFunction:
1570         return func_param_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v );
1571 
1572     case eMinus:
1573         /* unary minus sign */
1574         return negate_expr ( tbl, src, t, env, self, v );
1575     case ePlus:
1576         /* unary plus sign */
1577         return const_expr ( tbl, src, next_token ( tbl, src, t ), env, self, v );
1578     }
1579 
1580     return KTokenExpected ( t, klogErr, "constant, function param or cast operator" );
1581 }
1582 
1583 static
old_fact_value(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** v)1584 rc_t old_fact_value ( KSymTable *tbl, KTokenSource *src, KToken *t,
1585     const SchemaEnv *env, VSchema *self, const SExpression **v )
1586 {
1587     switch ( t -> id )
1588     {
1589         /* const-expression */
1590     case eDecimal:
1591     case eHex:
1592     case eOctal:
1593         return uint_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1594     case eFloat:
1595     case eExpFloat:
1596         return float_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1597     case eString:
1598     case eEscapedString:
1599         return string_expr ( tbl, src, t, env, self, ( const SConstExpr** ) v );
1600     case eMinus:
1601         return negate_expr ( tbl, src, t, env, self, v );
1602     case ePlus:
1603         return old_fact_value ( tbl, src, next_token ( tbl, src, t ), env, self, v );
1604     }
1605 
1606     return RC ( rcVDB, rcSchema, rcParsing, rcNoObj, rcNoErr );
1607 }
1608 #endif
1609 
1610 /*
1611  *    func-parms         = <func-param> [ ',' <func-parms> ]
1612  *    func-param         = <colname>
1613  *                       | <physname>
1614  *                       | <production>
1615  *                       | <parmname>
1616  */
1617 #if SLVL >= 4
1618 static
param_value(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** v)1619 rc_t param_value ( KSymTable *tbl, KTokenSource *src, KToken *t,
1620     const SchemaEnv *env, VSchema *self, const SExpression **v )
1621 {
1622     KToken t2;
1623     bool alt = false;
1624 
1625     /* look for special modifiers */
1626     switch ( t -> id )
1627     {
1628 #if SLVL >= 7
1629     case ePeriod:
1630         /* detect special syntax for physical column names */
1631         physical_name ( tbl, src, t, env );
1632         break;
1633 #endif
1634     case eAtSign:
1635 
1636         /* detect alternate column source */
1637         switch ( next_token ( tbl, src, & t2 ) -> id )
1638         {
1639 #if SLVL >= 8
1640         case eColumn:
1641 #endif
1642         case eIdent:
1643         case eForward:
1644         case eVirtual:
1645             * t = t2;
1646             alt = true;
1647             break;
1648 
1649         default:
1650             KTokenSourceReturn ( src, & t2 );
1651         }
1652         break;
1653     }
1654 
1655     switch ( t -> id )
1656     {
1657     /* handle function or script params, named productions */
1658 #if SLVL >= 5
1659     case eAtSign:
1660         t -> sym = KSymTableFind ( tbl, & t -> str );
1661         if ( t -> sym == NULL )
1662             break;
1663         t -> id = t -> sym -> type;
1664         /* no break */
1665 #endif
1666     case eFuncParam:
1667         return param_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v );
1668     case eProduction:
1669         return prod_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v );
1670 
1671     /* forward reference */
1672     case eIdent:
1673         return fwd_decl_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v, alt );
1674     case eForward:
1675     case eVirtual:
1676         return fwd_ref_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v, alt );
1677 #if SLVL >= 8
1678     /* column expression */
1679     case eColumn:
1680         return column_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v, alt );
1681 #endif
1682 #if SLVL >= 7
1683     /* physical column expression */
1684     case ePhysMember:
1685         return physical_expr ( tbl, src, t, env, self, ( const SSymExpr** ) v );
1686 #endif
1687     /* cast expression */
1688     case eLeftParen:
1689         return cast_expr ( tbl, src, t, env, self, ( const SBinExpr** ) v, param_value );
1690     }
1691 
1692     return KTokenExpected ( t, klogErr, "column or production name or cast operator" );
1693 }
1694 
1695 static
param_list(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,Vector * v,rc_t (* value)(KSymTable *,KTokenSource *,KToken *,const SchemaEnv *,VSchema *,const SExpression **))1696 rc_t param_list ( KSymTable *tbl, KTokenSource *src, KToken *t,
1697     const SchemaEnv *env, VSchema *self, Vector *v,
1698     rc_t ( * value ) ( KSymTable*, KTokenSource*, KToken*,
1699         const SchemaEnv*, VSchema*, const SExpression** ) )
1700 {
1701     rc_t rc;
1702     const SExpression *x;
1703 
1704     while ( 1 )
1705     {
1706         /* param value */
1707         rc = ( * value ) ( tbl, src, t, env, self, & x );
1708         if ( rc != 0 )
1709             return rc;
1710 
1711         /* record parameter */
1712         rc = VectorAppend ( v, NULL, x );
1713         if ( rc != 0 )
1714         {
1715             SExpressionWhack ( x );
1716             return KTokenRCExplain ( t, klogInt, rc );
1717         }
1718 
1719         if ( t -> id != eComma )
1720             break;
1721 
1722         next_token ( tbl, src, t );
1723     }
1724 
1725     return 0;
1726 }
1727 
1728 static
func_expression(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,SFuncExpr * fx,const KSymbol ** sym)1729 rc_t func_expression ( KSymTable *tbl, KTokenSource *src, KToken *t,
1730     const SchemaEnv *env, VSchema *self, SFuncExpr *fx, const KSymbol **sym )
1731 {
1732     rc_t rc;
1733 
1734     /* schema-parms */
1735     if ( t -> id == eLeftAngle )
1736     {
1737         next_token ( tbl, src, t );
1738         rc = param_list ( tbl, src, t, env, self, & fx -> schem, schema_value );
1739         if ( rc == 0 )
1740             rc = expect ( tbl, src, t, eRightAngle, ">", true );
1741         if ( rc != 0 )
1742             return rc;
1743     }
1744 
1745     /* locate function or schema */
1746     rc = next_fqn ( tbl, src, t, env );
1747     if ( rc != 0 )
1748         return rc;
1749 
1750     if ( t -> id != eScriptFunc && t -> id != eFunction )
1751         return KTokenExpected ( t, klogErr, "function" );
1752     * sym = t -> sym;
1753 
1754     /* look for requested version */
1755     if ( next_token ( tbl, src, t ) -> id == eHash )
1756     {
1757         fx -> version_requested = true;
1758         rc = maj_min_rel ( tbl, src, next_token ( tbl, src, t ),
1759             env, self,  & fx -> version, false );
1760         if ( rc != 0 )
1761             return rc;
1762     }
1763 
1764     /* look for factory params */
1765     if ( t -> id == eLeftAngle && ! env -> mixed_fact_param_list )
1766     {
1767         next_token ( tbl, src, t );
1768         rc = param_list ( tbl, src, t, env, self, & fx -> pfact, fact_value );
1769         if ( rc == 0 )
1770             rc = expect ( tbl, src, t, eRightAngle, ">", true );
1771         if ( rc != 0 )
1772             return rc;
1773     }
1774 
1775     /* function params */
1776     if ( t -> id != eLeftParen )
1777         return KTokenExpected ( t, klogErr, "(" );
1778     if ( next_token ( tbl, src, t ) -> id != eRightParen )
1779     {
1780         /* handle old-style fact params */
1781         if ( env -> mixed_fact_param_list )
1782         {
1783             rc = param_list ( tbl, src, t, env, self, & fx -> pfact, old_fact_value );
1784             if ( GetRCState ( rc ) == rcNoErr )
1785                 rc = 0;
1786         }
1787 
1788         /* handle normal function params */
1789         if ( rc == 0 )
1790             rc = param_list ( tbl, src, t, env, self, & fx -> pfunc, param_value );
1791     }
1792     if ( rc == 0 )
1793         rc = expect ( tbl, src, t, eRightParen, ")", true );
1794 
1795     return rc;
1796 }
1797 
1798 static
func_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SFuncExpr ** xp)1799 rc_t func_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
1800     const SchemaEnv *env, VSchema *self, const SFuncExpr **xp )
1801 {
1802     rc_t rc;
1803     const KSymbol *sym = NULL;
1804 
1805     SFuncExpr *fx = malloc ( sizeof * fx );
1806     if ( fx == NULL )
1807         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1808 
1809     /* initialize */
1810     fx -> dad . var = eFuncExpr;
1811     atomic32_set ( & fx -> dad . refcount, 1 );
1812     fx -> func = NULL;
1813     VectorInit ( & fx -> schem, 0, 4 );
1814     VectorInit ( & fx -> pfact, 0, 8 );
1815     VectorInit ( & fx -> pfunc, 0, 8 );
1816     fx -> version = 0;
1817     fx -> version_requested = false;
1818     fx -> untyped = false;
1819 
1820     /* parse expression */
1821     rc = func_expression ( tbl, src, t, env, self, fx, & sym );
1822     if ( rc == 0 )
1823     {
1824         const SNameOverload *vf = sym -> u . obj;
1825 
1826         /* match expression */
1827         if ( vf -> name -> type == eScriptFunc )
1828             fx -> dad . var = eScriptExpr;
1829 
1830         if ( fx -> version_requested )
1831         {
1832             fx -> func =
1833                 VectorFind ( & vf -> items, & fx -> version, NULL, SFunctionCmp );
1834         }
1835         else
1836         {
1837             fx -> func = VectorLast ( & vf -> items );
1838         }
1839 
1840         * xp = fx;
1841         return 0;
1842     }
1843 
1844     SExpressionWhack ( & fx -> dad );
1845     return rc;
1846 }
1847 #endif /* SLVL >= 4 */
1848 
1849 /*
1850  * expression         = <param-value>
1851  *                    | <func-expr>
1852  *                    | '(' <type-expr> ')' <expression>
1853  */
1854 #if SLVL >= 4
expression(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** xp)1855 rc_t expression ( KSymTable *tbl, KTokenSource *src, KToken *t,
1856     const SchemaEnv *env, VSchema *self, const SExpression **xp )
1857 {
1858     rc_t rc;
1859 
1860     if ( t -> id == eNamespace )
1861     {
1862         rc = next_fqn ( tbl, src, t, env );
1863         if ( rc != 0 )
1864             return rc;
1865     }
1866 
1867 #if SLVL >= 7
1868     /* detect special syntax for physical column names */
1869     if ( t -> id == ePeriod )
1870         physical_name ( tbl, src, t, env );
1871 #endif
1872 
1873     switch ( t -> id )
1874     {
1875     /* handle function or script params, named productions */
1876 #if SLVL >= 5
1877     case eAtSign:
1878         t -> sym = KSymTableFind ( tbl, & t -> str );
1879         if ( t -> sym == NULL )
1880             break;
1881         t -> id = t -> sym -> type;
1882         /* no break */
1883 #endif
1884     case eFuncParam:
1885         return param_expr ( tbl, src, t, env, self, ( const SSymExpr** ) xp );
1886     case eProduction:
1887         return prod_expr ( tbl, src, t, env, self, ( const SSymExpr** ) xp );
1888 
1889     /* forward reference */
1890     case eIdent:
1891         return fwd_decl_expr ( tbl, src, t, env, self, ( const SSymExpr** ) xp, false );
1892     case eForward:
1893     case eVirtual:
1894         return fwd_ref_expr ( tbl, src, t, env, self, ( const SSymExpr** ) xp, false );
1895 #if SLVL >= 8
1896     /* column expression */
1897     case eColumn:
1898         return column_expr ( tbl, src, t, env, self, ( const SSymExpr** ) xp, false );
1899 #endif
1900 #if SLVL >= 7
1901     /* physical column expression */
1902     case ePhysMember:
1903         return physical_expr ( tbl, src, t, env, self, ( const SSymExpr** ) xp );
1904 #endif
1905     /* function expression */
1906     case eLeftAngle:
1907     case eFunction:
1908     case eScriptFunc:
1909         return func_expr ( tbl, src, t, env, self, ( const SFuncExpr** ) xp );
1910 
1911     /* cast expression */
1912     case eLeftParen:
1913         return cast_expr ( tbl, src, t, env, self,
1914             ( const SBinExpr** ) xp, expression );
1915 
1916     /* type expression */
1917     case eFormat:
1918     case eDatatype:
1919     case eTypeset:
1920     case eSchemaType:
1921         return type_expr ( tbl, src, t, env, self, xp );
1922 
1923     /* in case expression gets used for const-expression */
1924     case eDecimal:
1925     case eHex:
1926     case eOctal:
1927         return uint_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1928     case eFloat:
1929     case eExpFloat:
1930         return float_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1931     case eString:
1932     case eEscapedString:
1933         return string_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1934     case eConstant:
1935         return sym_const_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1936     case eSchemaParam:
1937     case eFactParam:
1938         return indirect_const_expr ( tbl, src, t, env, self, xp );
1939     case eLeftSquare:
1940         return const_vect_expr ( tbl, src, t, env, self, ( const SVectExpr** ) xp );
1941     case kw_false:
1942     case kw_true:
1943         return bool_expr ( tbl, src, t, env, self, ( const SConstExpr** ) xp );
1944 
1945     case eMinus:
1946         /* unary minus sign */
1947         return negate_expr ( tbl, src, t, env, self, xp );
1948     case ePlus:
1949         /* unary plus sign */
1950         return const_expr ( tbl, src, next_token ( tbl, src, t ), env, self, xp );
1951     }
1952 
1953     return KTokenExpected ( t, klogErr, "production name, column name, function or cast expression" );
1954 }
1955 #endif /* SLVL >= 4 */
1956 
1957 
1958 /*
1959  * cond-expr          = <expression> [ '|' <cond-expr> ]
1960  */
1961 #if SLVL >= 4
cond_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** xp)1962 rc_t cond_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
1963     const SchemaEnv *env, VSchema *self, const SExpression **xp )
1964 {
1965     rc_t rc = expression ( tbl, src, t, env, self, xp );
1966     if ( rc != 0 )
1967         return rc;
1968 
1969     if ( t -> id == ePipe )
1970     {
1971         SBinExpr *x = malloc ( sizeof * x );
1972         if ( x == NULL )
1973         {
1974             SExpressionWhack ( * xp ), * xp = NULL;
1975             return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
1976         }
1977 
1978         x -> dad . var = eCondExpr;
1979         atomic32_set ( & x -> dad . refcount, 1 );
1980         x -> left = * xp;
1981         x -> right = NULL;
1982         * xp = & x -> dad;
1983 
1984         rc = cond_expr ( tbl, src, next_token ( tbl, src, t ), env, self, & x -> right );
1985         if ( rc != 0 )
1986         {
1987             SExpressionWhack ( & x -> dad );
1988             * xp = NULL;
1989         }
1990     }
1991 
1992     return rc;
1993 }
1994 #endif /* SLVL >= 4 */
1995 
1996 /*
1997  * untyped-expr       = <fmtdecl> | <untyped-func-name> '(' ')'
1998  */
1999 #if SLVL >= 6
2000 static
untyped_func_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SFuncExpr ** xp)2001 rc_t untyped_func_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
2002     const SchemaEnv *env, VSchema *self, const SFuncExpr **xp )
2003 {
2004     rc_t rc;
2005     const KSymbol *sym = t -> sym;
2006 
2007     /* expect empty parameter list */
2008     next_token ( tbl, src, t );
2009     rc = expect ( tbl, src, t, eLeftParen, "(", true );
2010     if ( rc == 0 )
2011         rc = expect ( tbl, src, t, eRightParen, ")", true );
2012     if ( rc == 0 )
2013     {
2014         const SNameOverload *vf = sym -> u . obj;
2015 
2016         SFuncExpr *fx = malloc ( sizeof * fx );
2017         if ( fx == NULL )
2018             return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
2019 
2020         /* initialize */
2021         fx -> dad . var = eFuncExpr;
2022         atomic32_set ( & fx -> dad . refcount, 1 );
2023         VectorInit ( & fx -> schem, 0, 4 );
2024         VectorInit ( & fx -> pfact, 0, 8 );
2025         VectorInit ( & fx -> pfunc, 0, 8 );
2026         fx -> version = 0;
2027         fx -> version_requested = false;
2028         fx -> untyped = true;
2029 
2030         fx -> func = VectorLast ( & vf -> items );
2031 
2032         * xp = fx;
2033         return 0;
2034     }
2035 
2036     return rc;
2037 }
2038 
untyped_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,const SExpression ** xp)2039 LIB_EXPORT rc_t CC untyped_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
2040     const SchemaEnv *env, VSchema *self, const SExpression **xp )
2041 {
2042     rc_t rc;
2043 
2044     if ( t -> id == eNamespace )
2045     {
2046         rc = next_fqn ( tbl, src, t, env );
2047         if ( rc != 0 )
2048             return rc;
2049     }
2050 
2051     switch ( t -> id )
2052     {
2053     /* function expression */
2054     case eUntypedFunc:
2055         return untyped_func_expr ( tbl, src, t, env, self, ( const SFuncExpr** ) xp );
2056 
2057     /* type expression */
2058     case eFormat:
2059         return type_expr ( tbl, src, t, env, self, xp );
2060     }
2061 
2062     return KTokenExpected ( t, klogErr, "type or function expression" );
2063 }
2064 #endif /* SLVL >= 6 */
2065 
2066 
2067 /*
2068  * phys-encoding-expr = [ '<' <schema-parms> '>' ]
2069  *                      <phys-encoding-name> [ '#' <maj-min-rel> ]
2070  *                      [ '<' <fact-params> '>' ]
2071  */
2072 #if SLVL >= 7
2073 static
phys_enc_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,SPhysEncExpr * x,const KSymbol ** sym)2074 rc_t phys_enc_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
2075     const SchemaEnv *env, VSchema *self, SPhysEncExpr *x, const KSymbol **sym )
2076 {
2077     rc_t rc;
2078 
2079     /* schema parms */
2080     if ( t -> id == eLeftAngle )
2081     {
2082         next_token ( tbl, src, t );
2083         rc = param_list ( tbl, src, t, env, self, & x -> schem, schema_value );
2084         if ( rc == 0 )
2085             rc = expect ( tbl, src, t, eRightAngle, ">", true );
2086         if ( rc != 0 )
2087             return rc;
2088     }
2089 
2090     /* phys-encoding-name */
2091     rc = next_fqn ( tbl, src, t, env );
2092     if ( rc != 0 )
2093         return rc;
2094 
2095     if ( t -> id != ePhysical )
2096         return KTokenExpected ( t, klogErr, "physical encoding" );
2097     * sym = t -> sym;
2098 
2099 
2100     /* look for requested version */
2101     if ( next_token ( tbl, src, t ) -> id == eHash )
2102     {
2103         x -> version_requested = true;
2104         rc = maj_min_rel ( tbl, src, next_token ( tbl, src, t ),
2105             env, self,  & x -> version, false );
2106         if ( rc != 0 )
2107             return rc;
2108     }
2109 
2110     /* look for factory params */
2111     if ( t -> id == eLeftAngle )
2112     {
2113         next_token ( tbl, src, t );
2114         rc = param_list ( tbl, src, t, env, self, & x -> pfact, fact_value );
2115         if ( rc == 0 )
2116             rc = expect ( tbl, src, t, eRightAngle, ">", true );
2117     }
2118 
2119     return rc;
2120 }
2121 
phys_encoding_expr(KSymTable * tbl,KTokenSource * src,KToken * t,const SchemaEnv * env,VSchema * self,VTypedecl * td,const SExpression ** xp)2122 rc_t phys_encoding_expr ( KSymTable *tbl, KTokenSource *src, KToken *t,
2123     const SchemaEnv *env, VSchema *self, VTypedecl *td, const SExpression **xp )
2124 {
2125     rc_t rc;
2126     const KSymbol *sym = NULL;
2127 
2128     SPhysEncExpr *x = malloc ( sizeof * x );
2129     if ( x == NULL )
2130         return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
2131 
2132     /* initialize */
2133     x -> dad . var = ePhysEncExpr;
2134     atomic32_set ( & x -> dad . refcount, 1 );
2135     x -> phys = NULL;
2136     VectorInit ( & x -> schem, 0, 4 );
2137     VectorInit ( & x -> pfact, 0, 8 );
2138     x -> version = 0;
2139     x -> version_requested = false;
2140 
2141     /* parse expression */
2142     rc = phys_enc_expr ( tbl, src, t, env, self, x, & sym );
2143     if ( rc == 0 )
2144     {
2145         const SNameOverload *name = sym -> u . obj;
2146 
2147         if ( x -> version_requested )
2148         {
2149             x -> phys =
2150                 VectorFind ( & name -> items, & x -> version, NULL, SPhysicalCmp );
2151         }
2152         else
2153         {
2154             x -> phys = VectorLast ( & name -> items );
2155         }
2156 
2157         /* evaluate type expression */
2158         if ( x -> phys != NULL && td != NULL )
2159         {
2160             /* bind schema parameters */
2161             Vector prior, cx_bind;
2162             VectorInit ( & cx_bind, 1, self -> num_indirect ? self -> num_indirect : 16 );
2163             rc = SPhysicalBindSchemaParms ( x -> phys, & prior, & x -> schem, & cx_bind );
2164             if ( rc == 0 )
2165             {
2166                 const SExpression *tx = x -> phys -> td;
2167                 assert ( tx != NULL );
2168                 rc = STypeExprResolveAsTypedecl ( ( const STypeExpr* ) tx, self, td, & cx_bind );
2169                 SPhysicalRestSchemaParms ( x -> phys, & prior, & cx_bind );
2170             }
2171             VectorWhack ( & cx_bind, NULL, NULL );
2172         }
2173 
2174         if ( rc == 0 )
2175         {
2176             * xp = & x -> dad;
2177             return 0;
2178         }
2179     }
2180 
2181     SExpressionWhack ( & x -> dad );
2182     return rc;
2183 }
2184 #endif
2185