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 
33 #include <klib/symbol.h>
34 #include <klib/symtab.h>
35 #include <klib/rc.h>
36 #include <sysalloc.h>
37 #include <bitstr.h>
38 #include <atomic32.h>
39 
40 #include <stdlib.h>
41 #include <string.h>
42 #include <assert.h>
43 
44 
45 /*--------------------------------------------------------------------------
46  * VSchema
47  */
48 
49 
50 /* CacheIntrinsicTypeId
51  *  for id-caching
52  *
53  *  reads id atomically from "cache" and returns if non-zero
54  *
55  *  otherwise retrieves type id by name lookup, and sets
56  *  value atomically in "cache" before returning.
57  */
VSchemaCacheIntrinsicTypeId(const VSchema * self,atomic32_t * cache,const char * type_name)58 uint32_t VSchemaCacheIntrinsicTypeId ( const VSchema *self,
59     atomic32_t *cache, const char *type_name )
60 {
61     uint32_t id;
62 
63     assert ( self != NULL );
64     assert ( cache != NULL );
65     assert ( type_name != NULL && type_name [ 0 ] != 0 );
66 
67     /* retrieve cached value */
68     id = atomic32_read ( cache );
69     if ( id == 0 )
70     {
71         String name;
72         uint32_t prev;
73         const KSymbol *sym;
74         const SDatatype *dt;
75 
76         /* find intrinsic schema */
77         const VSchema *intrinsic = self;
78         while ( intrinsic -> dad != NULL )
79             intrinsic = intrinsic -> dad;
80 
81         /* find datatype U32 */
82         StringInitCString ( & name, type_name );
83         sym = ( const KSymbol* )
84             BSTreeFind ( & intrinsic -> scope, & name, KSymbolCmp );
85         assert ( sym != NULL );
86         dt = sym -> u . obj;
87 
88         /* this SHOULD be idempotent */
89         prev = atomic32_test_and_set ( cache, ( int ) dt -> id, id );
90         assert ( prev == id || prev == dt -> id );
91 
92         id = dt -> id;
93     }
94 
95     return id;
96 }
97 
98 
99 /*--------------------------------------------------------------------------
100  * constant numeric expressions
101  *
102  *  built-in typecasting allows for the chain
103  *    bool => uint => int => float
104  *
105  *  built-in size promotion is automatic from 8 => 16 => 32 => 64 bits
106  *
107  *  constant size-demotion is allowed due to knowledge of constant value
108  *
109  *  explicit casts may reverse type promotion rules
110  */
111 
112 
113 /* 64 bit interchange union
114  */
115 typedef union nx nx;
116 union nx
117 {
118     uint64_t u64;
119     int64_t i64;
120     double f64;
121 };
122 
123 
124 /* readers
125  *  access data in 8, 16, 32 or 64 bit form
126  *  return data in 64 bit form
127  *  advance data pointer
128  */
129 static
read_bool(nx * data,const void * p)130 const void *read_bool ( nx *data, const void *p )
131 {
132     const bool *src = p;
133     data -> u64 = src [ 0 ];
134     return src + 1;
135 }
136 
137 static
read_U8(nx * data,const void * p)138 const void *read_U8 ( nx *data, const void *p )
139 {
140     const uint8_t *src = p;
141     data -> u64 = src [ 0 ];
142     return src + 1;
143 }
144 
145 static
read_U16(nx * data,const void * p)146 const void *read_U16 ( nx *data, const void *p )
147 {
148     const uint16_t *src = p;
149     data -> u64 = src [ 0 ];
150     return src + 1;
151 }
152 
153 static
read_U32(nx * data,const void * p)154 const void *read_U32 ( nx *data, const void *p )
155 {
156     const uint32_t *src = p;
157     data -> u64 = src [ 0 ];
158     return src + 1;
159 }
160 
161 static
read_U64(nx * data,const void * p)162 const void *read_U64 ( nx *data, const void *p )
163 {
164     const uint64_t *src = p;
165     data -> u64 = src [ 0 ];
166     return src + 1;
167 }
168 
169 static
read_I8(nx * data,const void * p)170 const void *read_I8 ( nx *data, const void *p )
171 {
172     const int8_t *src = p;
173     data -> i64 = src [ 0 ];
174     return src + 1;
175 }
176 
177 static
read_I16(nx * data,const void * p)178 const void *read_I16 ( nx *data, const void *p )
179 {
180     const int16_t *src = p;
181     data -> i64 = src [ 0 ];
182     return src + 1;
183 }
184 
185 static
read_I32(nx * data,const void * p)186 const void *read_I32 ( nx *data, const void *p )
187 {
188     const int32_t *src = p;
189     data -> i64 = src [ 0 ];
190     return src + 1;
191 }
192 
193 static
read_I64(nx * data,const void * p)194 const void *read_I64 ( nx *data, const void *p )
195 {
196     const int64_t *src = p;
197     data -> i64 = src [ 0 ];
198     return src + 1;
199 }
200 
201 static
read_F32(nx * data,const void * p)202 const void *read_F32 ( nx *data, const void *p )
203 {
204     const float *src = p;
205     data -> f64 = src [ 0 ];
206     return src + 1;
207 }
208 
209 static
read_F64(nx * data,const void * p)210 const void *read_F64 ( nx *data, const void *p )
211 {
212     const double *src = p;
213     data -> f64 = src [ 0 ];
214     return src + 1;
215 }
216 
217 /* writers
218  *  write data in 8, 16, 32, or 64 bit form
219  *  receive data in 64 bit form
220  *  advance pointers
221  */
222 static
write_bool(void * p,const nx * data)223 void *write_bool ( void *p, const nx *data )
224 {
225     bool *dst = p;
226     dst [ 0 ] = data -> u64 ? true : false;
227     return dst + 1;
228 }
229 
230 static
write_U8(void * p,const nx * data)231 void *write_U8 ( void *p, const nx *data )
232 {
233     uint8_t *dst = p;
234     dst [ 0 ] = ( uint8_t ) data -> u64;
235     if ( ( uint64_t ) dst [ 0 ] != data -> u64 )
236         return NULL;
237     return dst + 1;
238 }
239 
240 static
write_U16(void * p,const nx * data)241 void *write_U16 ( void *p, const nx *data )
242 {
243     uint16_t *dst = p;
244     dst [ 0 ] = ( uint16_t ) data -> u64;
245     if ( ( uint64_t ) dst [ 0 ] != data -> u64 )
246         return NULL;
247     return dst + 1;
248 }
249 
250 static
write_U32(void * p,const nx * data)251 void *write_U32 ( void *p, const nx *data )
252 {
253     uint32_t *dst = p;
254     dst [ 0 ] = ( uint32_t ) data -> u64;
255     if ( ( uint64_t ) dst [ 0 ] != data -> u64 )
256         return NULL;
257     return dst + 1;
258 }
259 
260 static
write_U64(void * p,const nx * data)261 void *write_U64 ( void *p, const nx *data )
262 {
263     uint64_t *dst = p;
264     dst [ 0 ] = data -> u64;
265     return dst + 1;
266 }
267 
268 static
write_I8(void * p,const nx * data)269 void *write_I8 ( void *p, const nx *data )
270 {
271     int8_t *dst = p;
272     dst [ 0 ] = ( int8_t ) data -> i64;
273     if ( ( int64_t ) dst [ 0 ] != data -> i64 )
274         return NULL;
275     return dst + 1;
276 }
277 
278 static
write_I16(void * p,const nx * data)279 void *write_I16 ( void *p, const nx *data )
280 {
281     int16_t *dst = p;
282     dst [ 0 ] = ( int16_t ) data -> i64;
283     if ( ( int64_t ) dst [ 0 ] != data -> i64 )
284         return NULL;
285     return dst + 1;
286 }
287 
288 static
write_I32(void * p,const nx * data)289 void *write_I32 ( void *p, const nx *data )
290 {
291     int32_t *dst = p;
292     dst [ 0 ] = ( int32_t ) data -> i64;
293     if ( ( int64_t ) dst [ 0 ] != data -> i64 )
294         return NULL;
295     return dst + 1;
296 }
297 
298 static
write_I64(void * p,const nx * data)299 void *write_I64 ( void *p, const nx *data )
300 {
301     int64_t *dst = p;
302     dst [ 0 ] = data -> i64;
303     return dst + 1;
304 }
305 
306 static
write_F32(void * p,const nx * data)307 void *write_F32 ( void *p, const nx *data )
308 {
309     double e;
310     float *dst = p;
311     dst [ 0 ] = ( float ) data -> f64;
312     e = ( double ) dst [ 0 ] - data -> f64;
313     if ( -1.0 < e || e > 1.0 )
314         return NULL;
315     return dst + 1;
316 }
317 
318 static
write_F64(void * p,const nx * data)319 void *write_F64 ( void *p, const nx *data )
320 {
321     double *dst = p;
322     dst [ 0 ] = data -> f64;
323     return dst + 1;
324 }
325 
326 
327 /* converters
328  *  convert from one data type to another
329  */
330 static
null_cvt(nx * data)331 nx *null_cvt ( nx *data )
332 {
333     return data;
334 }
335 
336 static
uint_int(nx * data)337 nx *uint_int ( nx *data )
338 {
339     if ( data -> i64 < 0 )
340         return NULL;
341     return data;
342 }
343 
344 static
uint_float(nx * data)345 nx *uint_float ( nx *data )
346 {
347     if ( data -> i64 < 0 )
348         return NULL;
349     data -> f64 = (double)data -> i64;
350     return data;
351 }
352 
353 static
int_float(nx * data)354 nx *int_float ( nx *data )
355 {
356     data -> f64 = (double)data -> i64;
357     return data;
358 }
359 
360 static
float_int(nx * data)361 nx *float_int ( nx *data )
362 {
363     data -> i64 = ( int64_t ) data -> f64;
364     return data;
365 }
366 
367 static
float_uint(nx * data)368 nx *float_uint ( nx *data )
369 {
370     data -> i64 = ( int64_t ) data -> f64;
371     if ( data -> i64 < 0 )
372         return NULL;
373     return data;
374 }
375 
376 static
int_uint(nx * data)377 nx *int_uint ( nx *data )
378 {
379     if ( data -> i64 < 0 )
380         return NULL;
381     return data;
382 }
383 
384 /* eval-numeric-expr
385  *  tries to evaluate a constant numeric expression against type
386  *  returns non-zero error code if failed
387  */
388 #if SLVL >= 1
eval_numeric_expr(const VSchema * self,const VTypedecl * td,const SConstExpr * expr,SConstExpr ** xp,bool force)389 LIB_EXPORT rc_t CC eval_numeric_expr ( const VSchema *self, const VTypedecl *td,
390     const SConstExpr *expr, SConstExpr **xp, bool force )
391 {
392     SConstExpr *x;
393     uint32_t sbits, sdim;
394     uint32_t i, dbits, ddim;
395 
396     void *dst;
397     const void *src;
398 
399     const void* ( * reader ) ( nx*, const void* );
400     void* ( * writer ) ( void*, const nx* );
401     nx* ( * cvt ) ( nx* );
402 
403     /* source and destination types of constant vector */
404     const SDatatype *sdt = VSchemaFindTypeid ( self, expr -> td . type_id );
405     const SDatatype *ddt = VSchemaFindTypeid ( self, td -> type_id );
406     if ( sdt == NULL || ddt == NULL )
407         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcNotFound );
408 
409     /* size of source and destination types */
410     sbits = sdt -> size;
411     dbits = ddt -> size;
412 
413     /* regardless of how derived the specified types may be,
414        get their dimensions in terms of intrinsic types */
415     sdim = SDatatypeIntrinsicDim ( sdt );
416     ddim = SDatatypeIntrinsicDim ( ddt );
417 
418     /* convert stated sizes to intrinsic element size */
419     assert ( sdim != 0 && ( sbits % sdim ) == 0 );
420     sbits /= sdim;
421     assert ( ddim != 0 && ( dbits % ddim ) == 0 );
422     dbits /= ddim;
423 
424     /* test for cast compatibility */
425     if ( ! force ) switch ( ddt -> domain )
426     {
427     case ddBool:
428         /* only bool casts to bool */
429         if ( sdt -> domain != ddBool )
430             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
431         break;
432     case ddUint: case ddInt: case ddFloat:
433         if ( sdt -> domain > ddt -> domain )
434             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
435         break;
436     default:
437         return SILENT_RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
438     }
439 
440     /* reset dimensions to account for explicit values */
441     sdim *= expr -> td . dim;
442     i = ddim * td -> dim;
443 
444     /* destination dim must divide source dim evenly */
445     if ( i == 0 || sdim < i || ( sdim % i ) != 0 )
446         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
447 
448     /* determine reader */
449     switch ( sdt -> domain )
450     {
451     case ddBool:
452         reader = read_bool; break;
453     case ddUint:
454         switch ( sbits )
455         {
456         case 8:  reader = read_U8; break;
457         case 16: reader = read_U16; break;
458         case 32: reader = read_U32; break;
459         case 64: reader = read_U64; break;
460         default:
461             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
462         }
463         break;
464     case ddInt:
465         switch ( sbits )
466         {
467         case 8:  reader = read_I8; break;
468         case 16: reader = read_I16; break;
469         case 32: reader = read_I32; break;
470         case 64: reader = read_I64; break;
471         default:
472             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
473         }
474         break;
475     case ddFloat:
476         switch ( sbits )
477         {
478         case 32: reader = read_F32; break;
479         case 64: reader = read_F64; break;
480         default:
481             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
482         }
483         break;
484     default:
485         /* here to quiet compiler complaints */
486         reader = NULL;
487     }
488 
489     /* determine writer */
490     switch ( ddt -> domain )
491     {
492     case ddBool:
493         writer = write_bool; break;
494     case ddUint:
495         switch ( dbits )
496         {
497         case 8:  writer = write_U8; break;
498         case 16: writer = write_U16; break;
499         case 32: writer = write_U32; break;
500         case 64: writer = write_U64; break;
501         default:
502             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
503         }
504         break;
505     case ddInt:
506         switch ( dbits )
507         {
508         case 8:  writer = write_I8; break;
509         case 16: writer = write_I16; break;
510         case 32: writer = write_I32; break;
511         case 64: writer = write_I64; break;
512         default:
513             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
514         }
515         break;
516     case ddFloat:
517         switch ( dbits )
518         {
519         case 32: writer = write_F32; break;
520         case 64: writer = write_F64; break;
521         default:
522             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
523         }
524         break;
525     default:
526         writer = NULL;
527     }
528 
529     /* determine converter */
530     if ( sdt -> domain == ddt -> domain )
531         cvt = null_cvt;
532     else switch ( ddt -> domain )
533     {
534     case ddBool:
535     case ddUint:
536         switch ( sdt -> domain )
537         {
538         case ddInt:
539             cvt = int_uint; break;
540         case ddFloat:
541             cvt = float_uint; break;
542         default:
543             cvt = null_cvt;
544         }
545         break;
546     case ddInt:
547         switch ( sdt -> domain )
548         {
549         case ddFloat:
550             cvt = float_int; break;
551         default:
552             cvt = uint_int; break;
553         }
554         break;
555     case ddFloat:
556         switch ( sdt -> domain )
557         {
558         case ddInt:
559             cvt = int_float; break;
560         default:
561             cvt = uint_float; break;
562         }
563         break;
564     default:
565         cvt = null_cvt;
566     }
567 
568     /* create output object */
569     {
570 	unsigned int alloc_size;
571 
572 	alloc_size=(((size_t)dbits * sdim + 7) >> 3);
573 	if(alloc_size < sizeof(x->u)){ /** don't go below size of union ***/
574 		alloc_size=sizeof(*x);
575 	} else { /** overallocate here ***/
576 		alloc_size+=sizeof(*x)-sizeof(x->u);
577 	}
578 	alloc_size = (alloc_size+3)&~3; /** align to 4 bytes **/
579     	x = malloc ( alloc_size );
580 	if ( x == NULL )
581             return RC ( rcVDB, rcExpression, rcEvaluating, rcMemory, rcExhausted );
582 	memset(x,0,alloc_size);
583     }
584 
585     /* copy, and perform type conversion */
586     src = & expr -> u;
587     dst = & x -> u;
588     for ( i = 0; i < sdim; ++ i )
589     {
590         nx data;
591         const nx *dp;
592 
593         /* read element */
594         src = ( * reader ) ( & data, src );
595 
596         /* type-promote */
597         dp = ( * cvt ) ( & data );
598         if ( dp == NULL )
599         {
600             free ( x );
601             return RC ( rcVDB, rcExpression, rcEvaluating, rcConstraint, rcViolated );
602         }
603 
604         /* write element */
605         dst = ( * writer ) ( dst, dp );
606         if ( dst == NULL )
607         {
608             free ( x );
609             return RC ( rcVDB, rcExpression, rcEvaluating, rcConstraint, rcViolated );
610         }
611     }
612 
613     /* it is done */
614     x -> dad . var = eConstExpr;
615     atomic32_set ( & x -> dad . refcount, 1 );
616     x -> td . type_id = td -> type_id;
617     x -> td . dim = sdim / ddim;
618     * xp = x;
619     return 0;
620 }
621 #endif
622 
623 
624 /*--------------------------------------------------------------------------
625  * constant textual expressions
626  *
627  *  built-in typecasting allows for the chain
628  *    ascii => unicode
629  *
630  *  built-in size promotion is automatic from 8 => 16 => 32 bits
631  *
632  *  constant size-demotion is allowed due to knowledge of constant value
633  *
634  *  explicit casts may reverse type promotion rules
635  */
636 
637 
638 static
read_ascii(uint32_t * ch,const void * p,const void * end)639 const void *read_ascii ( uint32_t *ch, const void *p, const void *end )
640 {
641     const char *src = p;
642     if ( src [ 0 ] < 0 )
643         return NULL;
644     * ch = src [ 0 ];
645     return src + 1;
646 }
647 
648 static
read_utf8(uint32_t * ch,const void * p,const void * end)649 const void *read_utf8 ( uint32_t *ch, const void *p, const void *end )
650 {
651     const char *src = p;
652     int len = utf8_utf32 ( ch, src, end );
653     if ( len <= 0 )
654         return NULL;
655     return src + len;
656 }
657 
658 static
read_utf16(uint32_t * ch,const void * p,const void * end)659 const void *read_utf16 ( uint32_t *ch, const void *p, const void *end )
660 {
661     const uint16_t *src = p;
662     * ch = src [ 0 ];
663     return src + 1;
664 }
665 
666 static
read_utf32(uint32_t * ch,const void * p,const void * end)667 const void *read_utf32 ( uint32_t *ch, const void *p, const void *end )
668 {
669     const uint32_t *src = p;
670     * ch = src [ 0 ];
671     return src + 1;
672 }
673 
674 static
write_ascii(void * p,void * end,uint32_t ch)675 void *write_ascii ( void *p, void *end, uint32_t ch )
676 {
677     char *dst = p;
678     if ( ch >= 128 )
679         ch = '?';
680     dst [ 0 ] = ( char ) ch;
681     return dst + 1;
682 }
683 
684 static
write_utf8(void * p,void * end,uint32_t ch)685 void *write_utf8 ( void *p, void *end, uint32_t ch )
686 {
687     char *dst = p;
688     int len = utf32_utf8 ( dst, end, ch );
689     if ( len <= 0 )
690         return NULL;
691     return dst + len;
692 }
693 
694 static
write_utf16(void * p,void * end,uint32_t ch)695 void *write_utf16 ( void *p, void *end, uint32_t ch )
696 {
697     uint16_t *dst = p;
698     if ( ch > 0x10000 )
699         ch = '?';
700     dst [ 0 ] = ( uint16_t ) ch;
701     return dst + 1;
702 }
703 
704 static
write_utf32(void * p,void * end,uint32_t ch)705 void *write_utf32 ( void *p, void *end, uint32_t ch )
706 {
707     uint32_t *dst = p;
708     dst [ 0 ] = ch;
709     return dst + 1;
710 }
711 
712 #if SLVL >= 1
eval_text_expr(const VSchema * self,const VTypedecl * td,const SConstExpr * expr,SConstExpr ** xp,bool force)713 LIB_EXPORT rc_t CC eval_text_expr ( const VSchema *self, const VTypedecl *td,
714     const SConstExpr *expr, SConstExpr **xp, bool force )
715 {
716     size_t size;
717     uint32_t len;
718     SConstExpr *x;
719     uint32_t sbits, sdim;
720     uint32_t i, dbits, ddim;
721 
722     void *dst, *dend;
723     const void *src, *send;
724     void* ( * writer ) ( void*, void*, uint32_t );
725     const void* ( * reader ) ( uint32_t*, const void*, const void* );
726 
727     /* source and destination types of constant vector */
728     const SDatatype *sdt = VSchemaFindTypeid ( self, expr -> td . type_id );
729     const SDatatype *ddt = VSchemaFindTypeid ( self, td -> type_id );
730     if ( sdt == NULL || ddt == NULL )
731         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcNotFound );
732 
733     /* size of source and destination types */
734     sbits = sdt -> size;
735     dbits = ddt -> size;
736 
737     /* regardless of how derived the specified types may be,
738        get their dimensions in terms of intrinsic types */
739     sdim = SDatatypeIntrinsicDim ( sdt );
740     ddim = SDatatypeIntrinsicDim ( ddt );
741 
742     /* convert stated sizes to intrinsic element size */
743     assert ( sdim != 0 && ( sbits % sdim ) == 0 );
744     sbits /= sdim;
745     assert ( ddim != 0 && ( dbits % ddim ) == 0 );
746     dbits /= ddim;
747 
748     /* test for cast compatibility */
749     if ( ! force ) switch ( ddt -> domain )
750     {
751     case ddAscii:
752         /* only ascii casts to ascii */
753         if ( sdt -> domain != ddAscii )
754             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
755         break;
756     case ddUnicode:
757         if ( sdt -> domain < ddAscii || sdt -> domain > ddt -> domain )
758             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
759         break;
760     default:
761         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
762     }
763 
764     /* restore source dimension */
765     sdim *= expr -> td . dim;
766 
767     /* determine reader and length */
768     len = sdim;
769     switch ( sdt -> domain )
770     {
771     case ddAscii:
772         reader = read_ascii; break;
773     default:
774         switch ( sbits )
775         {
776         case 8:
777             reader = read_utf8;
778             len = string_len ( expr -> u . utf8, sdim );
779             break;
780         case 16:
781             reader = read_utf16;
782             break;
783         case 32:
784             reader = read_utf32;
785             break;
786         default:
787             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
788         }
789     }
790 
791     /* determine writer and size */
792     ddim = len;
793     switch ( ddt -> domain )
794     {
795     case ddAscii:
796         writer = write_ascii;
797         size = len;
798         break;
799     default:
800         switch ( sbits )
801         {
802         case 8:
803             writer = write_utf8;
804             switch ( dbits )
805             {
806             case 16:
807                 utf16_cvt_string_len ( expr -> u . utf16, len << 1, & size );
808                 break;
809             case 32:
810                 utf32_cvt_string_len ( expr -> u . utf32, len << 2, & size );
811                 break;
812             default:
813                 size = sdim;
814             }
815             ddim = ( uint32_t ) size;
816             break;
817         case 16:
818             writer = write_utf16;
819             size = len << 1;
820             break;
821         case 32:
822             writer = write_utf32;
823             size = len << 2;
824             break;
825         default:
826             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
827         }
828     }
829 
830     /* create output object */
831     {
832 	unsigned int alloc_size;
833 
834 	alloc_size=size;
835 	if(alloc_size < sizeof(x->u)){ /** don't go below size of union ***/
836 		alloc_size=sizeof(*x);
837 	} else { /** overallocate here ***/
838 		alloc_size+=sizeof(*x)-sizeof(x->u);
839 	}
840 	alloc_size = (alloc_size+3)&~3; /** align to 4 bytes **/
841     	x = malloc ( alloc_size );
842 	if ( x == NULL )
843 		return RC ( rcVDB, rcExpression, rcEvaluating, rcMemory, rcExhausted );
844 	memset(x,0,alloc_size);
845     }
846 
847 
848     /* copy, and perform type conversion */
849     src = expr -> u . utf8;
850     send = & expr -> u . utf8 [ sdim ];
851     dst = x -> u . utf8;
852     dend = & x -> u . utf8 [ size ];
853     for ( i = 0; i < len; ++ i )
854     {
855         uint32_t ch;
856 
857         /* read character */
858         src = ( * reader ) ( & ch, src, send );
859         if ( src == NULL )
860         {
861             free ( x );
862             return RC ( rcVDB, rcExpression, rcEvaluating, rcData, rcCorrupt );
863         }
864 
865         /* write character */
866         dst = ( * writer ) ( dst, dend, ch );
867         if ( dst == NULL )
868         {
869             free ( x );
870             return RC ( rcVDB, rcExpression, rcEvaluating, rcData, rcCorrupt );
871         }
872     }
873 
874     /* it is done */
875     x -> dad . var = eConstExpr;
876     atomic32_set ( & x -> dad . refcount, 1 );
877     x -> td . type_id = td -> type_id;
878     x -> td . dim = ddim;
879     * xp = x;
880     return 0;
881 }
882 #endif
883 
884 
885 /*--------------------------------------------------------------------------
886  * SConstExpr
887  */
888 
889 
890 /* Resolve
891  *  return constant expression as a vector of indicated type
892  */
893 rc_t SConstExprResolveAsBool ( const SConstExpr *self,
894     const VSchema *schema, bool *b, uint32_t capacity );
895 rc_t SConstExprResolveAsI8 ( const SConstExpr *self,
896     const VSchema *schema, int8_t *i8, uint32_t capacity );
897 rc_t SConstExprResolveAsI16 ( const SConstExpr *self,
898     const VSchema *schema, int16_t *i16, uint32_t capacity );
899 rc_t SConstExprResolveAsI32 ( const SConstExpr *self,
900     const VSchema *schema, int32_t *i32, uint32_t capacity );
901 rc_t SConstExprResolveAsI64 ( const SConstExpr *self,
902     const VSchema *schema, int64_t *i64, uint32_t capacity );
903 rc_t SConstExprResolveAsU8 ( const SConstExpr *self,
904     const VSchema *schema, uint8_t *u8, uint32_t capacity );
905 rc_t SConstExprResolveAsU16 ( const SConstExpr *self,
906     const VSchema *schema, uint16_t *u16, uint32_t capacity );
907 
SConstExprResolveAsU32(const SConstExpr * self,const VSchema * schema,uint32_t * u32,uint32_t capacity,Vector * cx_bind)908 rc_t SConstExprResolveAsU32 ( const SConstExpr *self,
909     const VSchema *schema, uint32_t *u32, uint32_t capacity, Vector *cx_bind )
910 {
911     if ( capacity != 1 )
912         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnsupported );
913     return eval_uint_expr ( schema, ( const SExpression* ) self, u32, cx_bind );
914 }
915 
916 rc_t SConstExprResolveAsU64 ( const SConstExpr *self,
917     const VSchema *schema, uint32_t *u64, uint32_t capacity );
918 rc_t SConstExprResolveAsF32 ( const SConstExpr *self,
919     const VSchema *schema, float *f32, uint32_t capacity );
920 rc_t SConstExprResolveAsF64 ( const SConstExpr *self,
921     const VSchema *schema, double *f64, uint32_t capacity );
922 rc_t SConstExprResolveAsAscii ( const SConstExpr *self,
923     const VSchema *schema, char *ascii, size_t capacity );
924 rc_t SConstExprResolveAsUTF8 ( const SConstExpr *self,
925     const VSchema *schema, char *utf8, size_t bytes );
926 rc_t SConstExprResolveAsUTF16 ( const SConstExpr *self,
927     const VSchema *schema, uint16_t *utf16, uint32_t capacity );
928 rc_t SConstExprResolveAsUTF32 ( const SConstExpr *self,
929     const VSchema *schema, uint32_t *utf32, uint32_t capacity );
930 
931 
932 /*--------------------------------------------------------------------------
933  * STypeExpr
934  */
935 
936 /* Resolve
937  *  resolve type expression to either a VTypedecl or VFormatdecl
938  */
STypeExprResolveAsFormatdecl(const STypeExpr * self,const VSchema * schema,VFormatdecl * fd,Vector * cx_bind)939 rc_t STypeExprResolveAsFormatdecl ( const STypeExpr *self,
940     const VSchema *schema, VFormatdecl *fd, Vector *cx_bind )
941 {
942     rc_t rc;
943     uint32_t dim;
944 
945     /* if self is resolved, then the format, type
946        and dimension are completely resolved */
947     if ( self -> resolved )
948     {
949         * fd = self -> fd;
950         return 0;
951     }
952 
953 #if SLVL < 3
954     return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
955 #else
956     /* the format is always completely resolved,
957        this leaves type and/or dimension */
958 
959     if ( self -> id != NULL )
960     {
961         /* the type needs to be resolved */
962         const STypeExpr *type = ( const STypeExpr* ) VectorGet ( cx_bind, self -> id -> type_id );
963         if ( type == NULL )
964             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUndefined );
965         if ( type -> dad . var != eTypeExpr )
966             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
967         rc = STypeExprResolveAsFormatdecl ( type, schema, fd, cx_bind );
968         if ( rc != 0 )
969             return rc;
970 
971         /* at this point, "fd" has some format - which we'll clobber,
972            a type and dim from the indirect type just resolved */
973     }
974     else
975     {
976         /* take known type and default dimension */
977         fd -> td . type_id = self -> fd . td . type_id;
978         fd -> td . dim = 1;
979     }
980 
981     /* always take our format */
982     fd -> fmt = self -> fd . fmt;
983 
984     /* test for unresolved dimension */
985     dim = self -> fd . td . dim;
986     if ( dim == 0 && self -> dim != NULL )
987     {
988         const SExpression *dx = self -> dim;
989         while ( dx != NULL )
990         {
991             const SIndirectConst *ic;
992 
993             if ( dx -> var == eConstExpr )
994             {
995                 rc = SConstExprResolveAsU32 ( ( const SConstExpr* ) dx, schema, & dim, 1, cx_bind );
996                 if ( rc != 0 )
997                     return rc;
998                 break;
999             }
1000 
1001             if ( dx -> var != eIndirectExpr )
1002                 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1003 
1004             ic = ( ( const SSymExpr* ) dx ) -> _sym -> u . obj;
1005             assert ( ic != NULL );
1006 
1007             dx = ( const SExpression* ) VectorGet ( cx_bind, ic -> expr_id );
1008         }
1009 
1010         /* must have non-zero dim */
1011         if ( dim == 0 )
1012             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUndefined );
1013     }
1014 
1015     /* factor in our dimension */
1016     fd -> td . dim *= dim;
1017     return 0;
1018 #endif
1019 }
1020 
STypeExprResolveAsTypedecl(const STypeExpr * self,const VSchema * schema,VTypedecl * td,Vector * cx_bind)1021 rc_t STypeExprResolveAsTypedecl ( const STypeExpr *self,
1022     const VSchema *schema, VTypedecl *td, Vector *cx_bind )
1023 {
1024     VFormatdecl fd;
1025     rc_t rc = STypeExprResolveAsFormatdecl ( self, schema, & fd, cx_bind );
1026     if ( rc == 0 )
1027     {
1028         if ( fd . fmt != 0 )
1029             return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1030         * td = fd . td;
1031     }
1032     return rc;
1033 }
1034 
1035 
1036 /*--------------------------------------------------------------------------
1037  * general constant expression evaluation
1038  */
1039 #if SLVL >= 1
1040 
1041 /* eval-type-expr
1042  *  should be able to boil things down to defined type vector
1043  */
1044 static
eval_type_expr(const VSchema * self,const VTypedecl * td,const STypeExpr * expr,SExpression ** xp)1045 rc_t eval_type_expr ( const VSchema *self, const VTypedecl *td,
1046     const STypeExpr *expr, SExpression **xp )
1047 {
1048     PLOGMSG( klogWarn, ( klogWarn, "TDB: $(msg)", "msg=handle type expression" ));
1049     return -1;
1050 }
1051 
1052 /* eval-indirect-expr
1053  */
1054 static
eval_indirect_expr(const VSchema * self,const VTypedecl * td,const SSymExpr * expr,SExpression ** xp,Vector * cx_bind)1055 rc_t eval_indirect_expr ( const VSchema *self, const VTypedecl *td,
1056     const SSymExpr *expr, SExpression **xp, Vector *cx_bind )
1057 {
1058     const SIndirectConst *ic = expr -> _sym -> u . obj;
1059 
1060     /* if the expression is there */
1061     if ( ic -> expr_id != 0 )
1062     {
1063         const SExpression *ic_expr = ( const SExpression* ) VectorGet ( cx_bind, ic -> expr_id );
1064         if ( ic_expr != NULL )
1065             return eval_const_expr ( self, td, ic_expr, xp, cx_bind );
1066     }
1067 
1068     /* just return self */
1069     * xp = & ( ( SSymExpr* ) expr ) -> dad;
1070     atomic32_inc ( & ( ( SSymExpr* ) expr ) -> dad . refcount );
1071     return 0;
1072 }
1073 
1074 
1075 /* eval-const-cast-expr
1076  */
1077 static
eval_const_cast_expr(const VSchema * self,const VTypedecl * td,const SExpression * expr,SExpression ** xp)1078 rc_t eval_const_cast_expr ( const VSchema *self, const VTypedecl *td,
1079     const SExpression *expr, SExpression **xp )
1080 {
1081     PLOGMSG( klogWarn, ( klogWarn, "TDB: $(msg)", "msg=handle const cast expression" ));
1082     return -1;
1083 }
1084 
1085 
1086 /* eval-func-param-expr
1087  */
1088 static
eval_func_param_expr(const VSchema * self,const VTypedecl * td,const SExpression * expr,SExpression ** xp)1089 rc_t eval_func_param_expr ( const VSchema *self, const VTypedecl *td,
1090     const SExpression *expr, SExpression **xp )
1091 {
1092     PLOGMSG( klogWarn, ( klogWarn, "TDB: $(msg)", "msg=handle function expression" ));
1093     return -1;
1094 }
1095 
1096 struct eval_vector_param_expr_pb
1097 {
1098     rc_t rc;
1099     const VSchema *self;
1100     const VTypedecl *td;
1101     Vector *cx_bind;
1102     Vector v;
1103 };
1104 
1105 static
vector_free(void * item,void * data)1106 void CC vector_free ( void *item, void *data )
1107 {
1108     free ( item );
1109 }
1110 
1111 static
do_eval_vector_param_expr(void * item,void * data)1112 bool CC do_eval_vector_param_expr ( void *item, void *data )
1113 {
1114     struct eval_vector_param_expr_pb *pb = data;
1115     SExpression *rslt = NULL;
1116 
1117     pb -> rc = eval_const_expr ( pb -> self, pb -> td, item, & rslt, pb -> cx_bind );
1118     if ( pb -> rc != 0 )
1119         return true;
1120 
1121     switch ( rslt -> var )
1122     {
1123     case eConstExpr:
1124         VectorAppend ( & pb -> v, NULL, rslt );
1125         break;
1126     case eVectorExpr:
1127         free ( rslt );
1128         break;
1129     default:
1130         free ( rslt );
1131         pb -> rc = RC ( rcVDB, rcExpression, rcEvaluating, rcExpression, rcUnexpected );
1132         return true;
1133     }
1134 
1135     return false;
1136 }
1137 
1138 /* eval-vector-param-expr
1139  */
1140 static
eval_vector_param_expr(const VSchema * self,const VTypedecl * td,const SVectExpr * expr,SExpression ** xp,Vector * cx_bind)1141 rc_t eval_vector_param_expr ( const VSchema *self, const VTypedecl *td,
1142     const SVectExpr *expr, SExpression **xp, Vector *cx_bind )
1143 {
1144     struct eval_vector_param_expr_pb pb;
1145 
1146     *xp = NULL;
1147 
1148     pb . rc = 0;
1149     pb . self = self;
1150     pb . td = td;
1151     pb . cx_bind = cx_bind;
1152     VectorInit ( & pb . v, 0, 32 );
1153 
1154     VectorDoUntil ( & expr -> expr, 0, do_eval_vector_param_expr, & pb );
1155     if ( pb . rc == 0 )
1156     {
1157         SConstExpr *rslt;
1158         uint32_t elem_count = VectorLength ( & pb . v );
1159         uint32_t elem_bits;
1160         size_t alloc_size;
1161 
1162         {
1163             const SDatatype *dt = VSchemaFindTypeid ( self, td -> type_id );
1164             elem_bits = dt -> size;
1165         }
1166 
1167         alloc_size = ( ( ( size_t ) elem_bits * elem_count + 7 ) >> 3 );
1168 
1169         /** don't go below size of union ***/
1170         if ( alloc_size < sizeof rslt -> u )
1171             alloc_size = sizeof * rslt;
1172         /** overallocate here ***/
1173         else
1174             alloc_size += sizeof * rslt - sizeof rslt -> u ;
1175 
1176         /** align to 4 bytes **/
1177         alloc_size = ( alloc_size + 3 ) & ~ 3;
1178         rslt = calloc ( alloc_size, 1 );
1179         if ( rslt == NULL )
1180             pb . rc = RC ( rcVDB, rcExpression, rcEvaluating, rcMemory, rcExhausted );
1181         else
1182         {
1183             uint32_t i;
1184 
1185             rslt -> dad . var = eConstExpr;
1186             atomic32_set ( & rslt -> dad . refcount, 1 );
1187             rslt -> td = *td;
1188             rslt -> td . dim = elem_count;
1189 
1190             for ( i = 0; i != elem_count; ++i )
1191             {
1192                 const SConstExpr *y = VectorGet ( & pb . v, i );
1193                 bitcpy ( & rslt -> u, i * elem_bits, & y -> u, 0, elem_bits );
1194             }
1195 
1196             *xp = & rslt -> dad;
1197         }
1198     }
1199 
1200     VectorWhack( & pb . v, vector_free, 0 );
1201 
1202     return pb . rc;
1203 }
1204 
1205 
1206 /* eval-const-expr
1207  *  tries to evaluate a constant expression against type
1208  *  returns non-zero error code if failed
1209  */
eval_const_expr(const VSchema * self,const VTypedecl * td,const SExpression * expr,SExpression ** xp,Vector * cx_bind)1210 rc_t eval_const_expr ( const VSchema *self, const VTypedecl *td,
1211     const SExpression *expr, SExpression **xp, Vector *cx_bind )
1212 {
1213     rc_t rc;
1214     const SConstExpr *s;
1215 
1216     switch ( expr -> var )
1217     {
1218     case eTypeExpr:
1219         return eval_type_expr ( self, td, ( const STypeExpr* ) expr, xp );
1220     case eConstExpr:
1221         s = ( const SConstExpr* ) expr;
1222         break;
1223 #if SLVL >= 3
1224     case eIndirectExpr:
1225         return eval_indirect_expr ( self, td, ( const SSymExpr* ) expr, xp, cx_bind );
1226 #endif
1227 #if SLVL >= 4
1228     case eFuncParamExpr:
1229         return eval_func_param_expr ( self, td, expr, xp );
1230 #endif
1231     case eCastExpr:
1232         return eval_const_cast_expr ( self, td, expr, xp );
1233     case eVectorExpr:
1234         return eval_vector_param_expr(self, td, ( const SVectExpr* ) expr, xp, cx_bind );
1235     default:
1236         *xp = NULL;
1237         return RC ( rcVDB, rcExpression, rcEvaluating, rcExpression, rcUnexpected );
1238     }
1239 
1240     /* try to evaluate as numeric */
1241     rc = eval_numeric_expr ( self, td, s, ( SConstExpr** ) xp, false );
1242 
1243     /* fall over to text */
1244     if ( rc != 0 && GetRCState ( rc ) == rcUnexpected && GetRCObject ( rc ) == (enum RCObject)rcType )
1245         rc = eval_text_expr ( self, td, s, ( SConstExpr** ) xp, false );
1246 
1247     return rc;
1248 }
1249 
1250 /* eval-uint-expr
1251  *  special const expression evaluator for uint32_t
1252  */
eval_uint_expr(const VSchema * self,const SExpression * expr,uint32_t * value,Vector * cx_bind)1253 rc_t eval_uint_expr ( const VSchema *self,
1254     const SExpression *expr, uint32_t *value, Vector *cx_bind )
1255 {
1256     rc_t rc;
1257     VTypedecl td;
1258     SConstExpr *x;
1259 
1260     /* capture runtime value for U32 */
1261     static atomic32_t s_U32_id;
1262     uint32_t U32_id = VSchemaCacheIntrinsicTypeId ( self, & s_U32_id, "U32" );
1263 
1264     /* evaluate expression against type */
1265     td . type_id = U32_id;
1266     td . dim = 1;
1267     rc = eval_const_expr ( self, & td, expr, ( SExpression** ) & x, cx_bind );
1268     if ( rc != 0 )
1269         return rc;
1270 
1271     /* verify dimensionality */
1272     assert ( x -> dad . var == eConstExpr );
1273     if ( x -> td . dim != 1 )
1274         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1275 
1276     /* got it */
1277     * value = x -> u . u32 [ 0 ];
1278     free ( x );
1279     return 0;
1280 }
1281 
1282 
1283 /* eval-uint64-expr
1284  *  special const expression evaluator for uint32_t
1285  */
eval_uint64_expr(const VSchema * self,const SExpression * expr,uint64_t * value,Vector * cx_bind)1286 rc_t eval_uint64_expr ( const VSchema *self,
1287     const SExpression *expr, uint64_t *value, Vector *cx_bind )
1288 {
1289     rc_t rc;
1290     VTypedecl td;
1291     SConstExpr *x;
1292 
1293     /* capture runtime value for U64 */
1294     static atomic32_t s_U64_id;
1295     uint64_t U64_id = VSchemaCacheIntrinsicTypeId ( self, & s_U64_id, "U64" );
1296 
1297     /* evaluate expression against type */
1298     td . type_id = U64_id;
1299     td . dim = 1;
1300     rc = eval_const_expr ( self, & td, expr, ( SExpression** ) & x, cx_bind );
1301     if ( rc != 0 )
1302         return rc;
1303 
1304     /* verify dimensionality */
1305     assert ( x -> dad . var == eConstExpr );
1306     if ( x -> td . dim != 1 )
1307         return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1308 
1309     /* got it */
1310     * value = x -> u . u64 [ 0 ];
1311     free ( x );
1312     return 0;
1313 }
1314 
1315 
1316 /* eval-expr-syntax
1317  *  examine expression syntax
1318  *  fixes forward references
1319  */
1320 static
eval_vect_expr_syntax(void * item,void * data)1321 bool CC eval_vect_expr_syntax ( void *item, void *data )
1322 {
1323     rc_t *rc = data;
1324     SExpression *x = item;
1325     * rc = eval_expr_syntax ( x );
1326     return ( * rc != 0 ) ? true : false;
1327 }
1328 
1329 static
eval_type_expr_syntax(const STypeExpr * expr)1330 rc_t eval_type_expr_syntax ( const STypeExpr *expr )
1331 {
1332     if ( expr -> dad . var != eTypeExpr )
1333         return RC ( rcVDB, rcExpression, rcValidating, rcExpression, rcIncorrect );
1334     return 0;
1335 }
1336 
1337 static
eval_fwd_expr_syntax(SSymExpr * expr)1338 rc_t eval_fwd_expr_syntax ( SSymExpr *expr )
1339 {
1340     const KSymbol *sym = expr -> _sym;
1341     assert ( sym != NULL );
1342     switch ( sym -> type )
1343     {
1344     case eFuncParam:
1345         expr -> dad . var = eParamExpr;
1346         break;
1347     case eProduction:
1348         expr -> dad . var = eProdExpr;
1349         break;
1350     case eColumn:
1351         expr -> dad . var = eColExpr;
1352         break;
1353     case ePhysMember:
1354         expr -> dad . var = ePhysExpr;
1355         break;
1356     case eForward:
1357         return RC ( rcVDB, rcSchema, rcValidating, rcName, rcUndefined );
1358     case eVirtual:
1359         break;
1360 
1361     default:
1362         return RC ( rcVDB, rcSchema, rcValidating, rcExpression, rcInvalid );
1363     }
1364 
1365     return 0;
1366 }
1367 
eval_expr_syntax(const SExpression * expr)1368 rc_t eval_expr_syntax ( const SExpression *expr )
1369 {
1370     rc_t rc;
1371 
1372     if ( expr == NULL )
1373         rc = RC ( rcVDB, rcExpression, rcValidating, rcSelf, rcNull );
1374     else switch ( expr -> var )
1375     {
1376     case eFwdExpr:
1377         rc = eval_fwd_expr_syntax ( ( SSymExpr* ) expr );
1378         break;
1379     case eCastExpr:
1380         rc = eval_type_expr_syntax ( ( const STypeExpr* ) ( ( const SBinExpr* ) expr ) -> left );
1381         if ( rc == 0 )
1382             rc = eval_expr_syntax ( ( ( const SBinExpr* ) expr ) -> right );
1383         break;
1384     case eVectorExpr:
1385         rc = 0;
1386         VectorDoUntil ( & ( ( const SVectExpr* ) expr ) -> expr, false, eval_vect_expr_syntax, & rc );
1387         break;
1388     case eCondExpr:
1389         rc = eval_expr_syntax ( ( ( const SBinExpr* ) expr ) -> left );
1390         if ( rc == 0 )
1391             rc = eval_expr_syntax ( ( ( const SBinExpr* ) expr ) -> right );
1392         break;
1393     default:
1394         rc = 0;
1395     }
1396 
1397     return rc;
1398 }
1399 
1400 #endif
1401