1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * rasqal_expr_evaluate.c - Rasqal expression evaluation
4  *
5  * Copyright (C) 2003-2010, David Beckett http://www.dajobe.org/
6  * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
7  *
8  * This package is Free Software and part of Redland http://librdf.org/
9  *
10  * It is licensed under the following three licenses as alternatives:
11  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12  *   2. GNU General Public License (GPL) V2 or any newer version
13  *   3. Apache License, V2.0 or any newer version
14  *
15  * You may not use this file except in compliance with at least one of
16  * the above three licenses.
17  *
18  * See LICENSE.html or LICENSE.txt at the top of this package for the
19  * complete terms and further detail along with the license texts for
20  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21  *
22  *
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <rasqal_config.h>
27 #endif
28 
29 #ifdef WIN32
30 #include <win32_rasqal_config.h>
31 #endif
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 #include <stdarg.h>
40 
41 #include "rasqal.h"
42 #include "rasqal_internal.h"
43 
44 
45 #define DEBUG_FH stderr
46 
47 /* Enable evaluation debugging by defining RASQAL_DEBUG_EVAL */
48 /* #define RASQAL_DEBUG_EVAL 1 */
49 
50 
51 /*
52  * rasqal_language_matches:
53  * @lang_tag: language tag such as "en" or "en-US" or "ab-cd-ef"
54  * @lang_range: language range such as "*" (SPARQL) or "en" or "ab-cd"
55  *
56  * INTERNAL - Match a language tag against a language range
57  *
58  * Returns true if @lang_range matches @lang_tag per
59  *   Matching of Language Tags [RFC4647] section 2.1
60  * RFC4647 defines a case-insensitive, hierarchical matching
61  * algorithm which operates on ISO-defined subtags for language and
62  * country codes, and user defined subtags.
63  *
64  * (Note: RFC3066 section 2.5 matching is identical to
65  * RFC4647 section 3.3.1 Basic Filtering )
66  *
67  * In SPARQL, a language-range of "*" matches any non-empty @lang_tag string.
68  * See http://www.w3.org/TR/2007/WD-rdf-sparql-query-20070326/#func-langMatches
69  *
70  * Return value: non-0 if true
71  */
72 int
rasqal_language_matches(const unsigned char * lang_tag,const unsigned char * lang_range)73 rasqal_language_matches(const unsigned char* lang_tag,
74                         const unsigned char* lang_range)
75 {
76   int b= 0;
77 
78   if(!(lang_tag && lang_range && *lang_tag && *lang_range)) {
79     /* One of the arguments is NULL or the empty string */
80     return 0;
81   }
82 
83   /* Now have two non-empty arguments */
84 
85   /* Simple range string "*" matches anything excluding NULL/empty
86    * lang_tag (checked above)
87    */
88   if(lang_range[0] == '*') {
89     if(!lang_range[1])
90       b = 1;
91     return b;
92   }
93 
94   while (1) {
95     char tag_c   = RASQAL_GOOD_CAST(char, tolower(*lang_tag++));
96     char range_c = RASQAL_GOOD_CAST(char, tolower(*lang_range++));
97     if ((!tag_c && !range_c) || (!range_c && tag_c == '-')) {
98       /* EITHER
99        *   The end of both strings (thus everything previous matched
100        *   such as e.g. tag "fr-CA" matching range "fr-ca")
101        * OR
102        *   The end of the range and end of the tag prefix (e.g. tag
103        *   "en-US" matching range "en")
104        * means a match
105        */
106       b = 1;
107       break;
108     }
109     if (range_c != tag_c) {
110       /* If a difference was found - including one of the
111        * strings being shorter than the other, it means no match
112        * (b is set to 0 above)
113        */
114       break;
115     }
116   }
117 
118   return b;
119 }
120 
121 
122 /*
123  * rasqal_expression_evaluate_strdt:
124  * @e: The expression to evaluate.
125  * @eval_context: Evaluation context
126  *
127  * INTERNAL - Evaluate RASQAL_EXPR_STRDT(expr) expression.
128  *
129  * Return value: A #rasqal_literal string value or NULL on failure.
130  */
131 static rasqal_literal*
rasqal_expression_evaluate_strdt(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)132 rasqal_expression_evaluate_strdt(rasqal_expression *e,
133                                  rasqal_evaluation_context *eval_context,
134                                  int *error_p)
135 {
136   rasqal_world* world = eval_context->world;
137   rasqal_literal *l1 = NULL;
138   rasqal_literal *l2 = NULL;
139   const unsigned char* s = NULL;
140   unsigned char* new_s = NULL;
141   size_t len;
142   raptor_uri* dt_uri = NULL;
143 
144   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
145   if((error_p && *error_p) || !l1)
146     goto failed;
147 
148   if(l1->language || l1->datatype) {
149     /* not a simple literal so return NULL success */
150     rasqal_free_literal(l1);
151     return NULL;
152   }
153 
154   s = rasqal_literal_as_counted_string(l1, &len, eval_context->flags, error_p);
155   if(error_p && *error_p)
156     goto failed;
157 
158   l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
159   if((error_p && *error_p) || !l2)
160     goto failed;
161 
162   dt_uri = rasqal_literal_as_uri(l2);
163   if(dt_uri) {
164     dt_uri = raptor_uri_copy(dt_uri);
165   } else {
166     const unsigned char *uri_string;
167 
168     uri_string = rasqal_literal_as_string_flags(l2, eval_context->flags,
169                                                 error_p);
170     if(error_p && *error_p)
171       goto failed;
172 
173     dt_uri = raptor_new_uri(world->raptor_world_ptr, uri_string);
174     if(!dt_uri)
175       goto failed;
176   }
177 
178   new_s =RASQAL_MALLOC(unsigned char*, len + 1);
179   if(!new_s)
180     goto failed;
181   memcpy(new_s, s, len + 1);
182 
183   rasqal_free_literal(l1);
184   rasqal_free_literal(l2);
185 
186   /* after this new_s and dt_uri become owned by result */
187   return rasqal_new_string_literal(world, new_s, /* language */ NULL,
188                                    dt_uri, /* qname */ NULL);
189 
190 
191   failed:
192   if(error_p)
193     *error_p = 1;
194 
195   if(new_s)
196     RASQAL_FREE(char*, new_s);
197   if(l1)
198     rasqal_free_literal(l1);
199   if(l2)
200     rasqal_free_literal(l2);
201 
202   return NULL;
203 }
204 
205 
206 /*
207  * rasqal_expression_evaluate_strlang:
208  * @e: The expression to evaluate.
209  * @eval_context: Evaluation context
210  *
211  * INTERNAL - Evaluate RASQAL_EXPR_STRLANG(expr) expression.
212  *
213  * Return value: A #rasqal_literal string value or NULL on failure.
214  */
215 static rasqal_literal*
rasqal_expression_evaluate_strlang(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)216 rasqal_expression_evaluate_strlang(rasqal_expression *e,
217                                    rasqal_evaluation_context *eval_context,
218                                    int *error_p)
219 {
220   rasqal_world* world = eval_context->world;
221   rasqal_literal *l1 = NULL;
222   rasqal_literal *l2 = NULL;
223   const unsigned char* s = NULL;
224   const unsigned char* lang = NULL;
225   unsigned char* new_s = NULL;
226   unsigned char* new_lang = NULL;
227   size_t len;
228   size_t lang_len;
229 
230   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
231   if((error_p && *error_p) || !l1)
232     goto failed;
233 
234   if(l1->language || l1->datatype) {
235     /* not a simple literal so return NULL success */
236     rasqal_free_literal(l1);
237     return NULL;
238   }
239 
240   s = rasqal_literal_as_counted_string(l1, &len, eval_context->flags, error_p);
241   if(error_p && *error_p)
242     goto failed;
243 
244   l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
245   if((error_p && *error_p) || !l2)
246     goto failed;
247 
248   lang = rasqal_literal_as_counted_string(l2, &lang_len, eval_context->flags,
249                                           error_p);
250   if(error_p && *error_p)
251     goto failed;
252 
253   new_s = RASQAL_MALLOC(unsigned char*, len + 1);
254   if(!new_s)
255     goto failed;
256   memcpy(new_s, s, len + 1);
257 
258   new_lang = RASQAL_MALLOC(unsigned char*, lang_len + 1);
259   if(!new_lang)
260     goto failed;
261   memcpy(new_lang, lang, lang_len + 1);
262 
263   rasqal_free_literal(l1);
264   rasqal_free_literal(l2);
265 
266   /* after this new_s and new_lang become owned by result */
267   return rasqal_new_string_literal(world, new_s,
268                                    RASQAL_GOOD_CAST(const char*, new_lang),
269                                    /*datatype */ NULL, /* qname */ NULL);
270 
271 
272   failed:
273   if(error_p)
274     *error_p = 1;
275 
276   if(new_s)
277     RASQAL_FREE(char*, new_s);
278   if(l1)
279     rasqal_free_literal(l1);
280   if(l2)
281     rasqal_free_literal(l2);
282 
283   return NULL;
284 }
285 
286 
287 /*
288  * rasqal_expression_evaluate_istype:
289  * @e: The expression to evaluate.
290  * @eval_context: Evaluation context
291  *
292  * INTERNAL - Evaluate RASQAL_EXPR_ISBLANK, RASQAL_EXPR_ISURI,
293  * RASQAL_EXPR_ISLITERAL and RASQAL_EXPR_ISNUMERIC (expr)
294  * expressions.
295  *
296  * Return value: A #rasqal_literal boolean value or NULL on failure.
297  */
298 static rasqal_literal*
rasqal_expression_evaluate_istype(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)299 rasqal_expression_evaluate_istype(rasqal_expression *e,
300                                   rasqal_evaluation_context *eval_context,
301                                   int *error_p)
302 {
303   rasqal_world* world = eval_context->world;
304   rasqal_literal* l1;
305   int free_literal = 1;
306   rasqal_variable *v;
307   int b;
308 
309   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
310   if((error_p && *error_p) || !l1)
311     goto failed;
312 
313   v = rasqal_literal_as_variable(l1);
314   if(v) {
315     rasqal_free_literal(l1);
316 
317     l1 = v->value; /* don't need v after this */
318 
319     free_literal = 0;
320     if(!l1)
321       goto failed;
322   }
323 
324   if(e->op == RASQAL_EXPR_ISBLANK)
325     b = (l1->type == RASQAL_LITERAL_BLANK);
326   else if(e->op == RASQAL_EXPR_ISLITERAL)
327     b = (rasqal_literal_get_rdf_term_type(l1) == RASQAL_LITERAL_STRING);
328   else if(e->op == RASQAL_EXPR_ISURI)
329     b =(l1->type == RASQAL_LITERAL_URI);
330   else
331     b = (rasqal_literal_is_numeric(l1));
332 
333   if(free_literal)
334     rasqal_free_literal(l1);
335 
336   return rasqal_new_boolean_literal(world, b);
337 
338 failed:
339   if(error_p)
340     *error_p = 1;
341 
342   if(free_literal && l1)
343     rasqal_free_literal(l1);
344 
345   return NULL;
346 }
347 
348 
349 /*
350  * rasqal_expression_evaluate_bound:
351  * @e: The expression to evaluate.
352  * @eval_context: Evaluation context
353  *
354  * INTERNAL - Evaluate RASQAL_EXPR_BOUND (variable) expressions.
355  *
356  * Return value: A #rasqal_literal boolean value or NULL on failure.
357  */
358 static rasqal_literal*
rasqal_expression_evaluate_bound(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)359 rasqal_expression_evaluate_bound(rasqal_expression *e,
360                                  rasqal_evaluation_context *eval_context,
361                                  int *error_p)
362 {
363   rasqal_world* world = eval_context->world;
364   rasqal_literal* l1;
365   rasqal_variable* v;
366 
367   /* Do not use rasqal_expression_evaluate() here since
368    * we need to check the argument is a variable, and
369    * that function will flatten such thing to literals
370    * as early as possible. See (FLATTEN_LITERAL) below
371    */
372   if(!e->arg1 || e->arg1->op != RASQAL_EXPR_LITERAL)
373     goto failed;
374 
375   l1 = e->arg1->literal;
376   if(!l1 || l1->type != RASQAL_LITERAL_VARIABLE)
377     goto failed;
378 
379   v = rasqal_literal_as_variable(l1);
380   if(!v)
381     goto failed;
382 
383   return rasqal_new_boolean_literal(world, (v->value != NULL));
384 
385   failed:
386   if(error_p)
387     *error_p = 1;
388 
389   return NULL;
390 }
391 
392 
393 /*
394  * rasqal_expression_evaluate_if:
395  * @e: The expression to evaluate.
396  * @eval_context: Evaluation context
397  *
398  * INTERNAL - Evaluate RASQAL_EXPR_IF (condition, true expr, false expr) expressions.
399  *
400  * Return value: A #rasqal_literal value or NULL on failure.
401  */
402 static rasqal_literal*
rasqal_expression_evaluate_if(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)403 rasqal_expression_evaluate_if(rasqal_expression *e,
404                               rasqal_evaluation_context *eval_context,
405                               int *error_p)
406 {
407   rasqal_literal* l1;
408   int b;
409 
410   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
411   if((error_p && *error_p) || !l1)
412     goto failed;
413 
414   /* IF condition */
415   b = rasqal_literal_as_boolean(l1, error_p);
416   rasqal_free_literal(l1);
417 
418   if(error_p && *error_p)
419     goto failed;
420 
421   /* condition is true: evaluate arg2 or false: evaluate arg3 */
422   return rasqal_expression_evaluate2(b ? e->arg2 : e->arg3, eval_context,
423                                      error_p);
424 
425   failed:
426   if(error_p)
427     *error_p = 1;
428 
429   return NULL;
430 }
431 
432 
433 /*
434  * rasqal_expression_evaluate_sameterm:
435  * @e: The expression to evaluate.
436  * @eval_context: Evaluation context
437  *
438  * INTERNAL - Evaluate RASQAL_EXPR_SAMETERM (expr1, expr2) expressions.
439  *
440  * Return value: A #rasqal_literal boolean value or NULL on failure.
441  */
442 static rasqal_literal*
rasqal_expression_evaluate_sameterm(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)443 rasqal_expression_evaluate_sameterm(rasqal_expression *e,
444                                     rasqal_evaluation_context *eval_context,
445                                     int *error_p)
446 {
447   rasqal_world* world = eval_context->world;
448   rasqal_literal* l1;
449   rasqal_literal* l2;
450   int b;
451 
452   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
453   if((error_p && *error_p) || !l1)
454     goto failed;
455 
456   l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
457   if((error_p && *error_p) || !l2)
458     goto failed;
459 
460   b = rasqal_literal_same_term(l1, l2);
461 #ifdef RASQAL_DEBUG_EVAL
462   RASQAL_DEBUG2("rasqal_literal_same_term() returned: %d\n", b);
463 #endif
464 
465   rasqal_free_literal(l1);
466   rasqal_free_literal(l2);
467 
468   return rasqal_new_boolean_literal(world, b);
469 
470   failed:
471   if(error_p)
472     *error_p = 1;
473 
474   if(l1)
475     rasqal_free_literal(l1);
476 
477   return NULL;
478 }
479 
480 
481 /*
482  * rasqal_expression_evaluate_in_set:
483  * @e: The expression to evaluate.
484  * @eval_context: Evaluation context
485  *
486  * INTERNAL - Evaluate RASQAL_EXPR_IN and RASQAL_EXPR_NOT_IN (expr,
487  * expr list) expression.
488  *
489  * Return value: A #rasqal_literal boolean value or NULL on failure.
490  */
491 static rasqal_literal*
rasqal_expression_evaluate_in_set(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)492 rasqal_expression_evaluate_in_set(rasqal_expression *e,
493                                   rasqal_evaluation_context *eval_context,
494                                   int *error_p)
495 {
496   rasqal_world* world = eval_context->world;
497   int size = raptor_sequence_size(e->args);
498   int i;
499   rasqal_literal* l1;
500   int found = 0;
501 
502   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
503   if((error_p && *error_p) || !l1)
504     goto failed;
505 
506   for(i = 0; i < size; i++) {
507     rasqal_expression* arg_e;
508     rasqal_literal* arg_literal;
509 
510     arg_e = (rasqal_expression*)raptor_sequence_get_at(e->args, i);
511     arg_literal = rasqal_expression_evaluate2(arg_e, eval_context, error_p);
512     if(!arg_literal)
513       goto failed;
514 
515     found = (rasqal_literal_equals_flags(l1, arg_literal,
516                                          eval_context->flags, error_p) != 0);
517 #ifdef RASQAL_DEBUG_EVAL
518     if(error_p && *error_p)
519       RASQAL_DEBUG1("rasqal_literal_equals_flags() returned: FAILURE\n");
520     else
521       RASQAL_DEBUG2("rasqal_literal_equals_flags() returned: %d\n", found);
522 #endif
523     rasqal_free_literal(arg_literal);
524 
525     if(error_p && *error_p)
526       goto failed;
527 
528     if(found)
529       /* found - terminate search */
530       break;
531   }
532   rasqal_free_literal(l1);
533 
534   if(e->op == RASQAL_EXPR_NOT_IN)
535     found = !found;
536   return rasqal_new_boolean_literal(world, found);
537 
538   failed:
539   if(error_p)
540     *error_p = 1;
541 
542   if(l1)
543     rasqal_free_literal(l1);
544 
545   return NULL;
546 }
547 
548 
549 /*
550  * rasqal_expression_evaluate_coalesce:
551  * @e: The expression to evaluate.
552  * @eval_context: Evaluation context
553  *
554  * INTERNAL - Evaluate RASQAL_EXPR_COALESCE (expr list) expressions.
555  *
556  * Return value: A #rasqal_literal value or NULL on failure.
557  */
558 static rasqal_literal*
rasqal_expression_evaluate_coalesce(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)559 rasqal_expression_evaluate_coalesce(rasqal_expression *e,
560                                     rasqal_evaluation_context *eval_context,
561                                     int *error_p)
562 {
563   int size = raptor_sequence_size(e->args);
564   int i;
565 
566   for(i = 0; i < size; i++) {
567     rasqal_expression* arg_e;
568 
569     arg_e = (rasqal_expression*)raptor_sequence_get_at(e->args, i);
570     if(arg_e) {
571       int my_error = 0;
572       rasqal_literal* result;
573       result = rasqal_expression_evaluate2(arg_e, eval_context, &my_error);
574       if(!my_error && result)
575         return result;
576     }
577   }
578 
579   /* No arguments evaluated to an RDF term, return an error (NULL) */
580   return NULL;
581 }
582 
583 
584 /*
585  * rasqal_expression_evaluate_str:
586  * @e: The expression to evaluate.
587  * @eval_context: Evaluation context
588  *
589  * INTERNAL - Evaluate RASQAL_EXPR_STR (literal expr) expression.
590  *
591  * Return value: A #rasqal_literal value or NULL on failure.
592  */
593 static rasqal_literal*
rasqal_expression_evaluate_str(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)594 rasqal_expression_evaluate_str(rasqal_expression *e,
595                                rasqal_evaluation_context *eval_context,
596                                int *error_p)
597 {
598   rasqal_world* world = eval_context->world;
599   rasqal_literal* l1 = NULL;
600   rasqal_literal* result = NULL;
601   const unsigned char *s;
602   size_t len;
603   unsigned char *new_s;
604 
605   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
606   if((error_p && *error_p) || !l1)
607     goto failed;
608 
609   /* Note: flags removes RASQAL_COMPARE_XQUERY as this is the
610    * explicit stringify operation and we want URIs as strings.
611    */
612   s = rasqal_literal_as_counted_string(l1, &len,
613                                        (eval_context->flags & ~RASQAL_COMPARE_XQUERY),
614                                        error_p);
615   if((error_p && *error_p) || !s)
616     goto failed;
617 
618   new_s = RASQAL_MALLOC(unsigned char*, len + 1);
619   if(!new_s)
620     goto failed;
621 
622   memcpy(RASQAL_GOOD_CAST(char*, new_s), RASQAL_GOOD_CAST(const char*, s), len + 1);
623 
624   /* after this new_s is owned by result */
625   result = rasqal_new_string_literal(world, new_s, NULL, NULL, NULL);
626 
627   if(l1)
628     rasqal_free_literal(l1);
629 
630   return result;
631 
632   failed:
633   if(error_p)
634     *error_p = 1;
635 
636   if(l1)
637     rasqal_free_literal(l1);
638 
639   return NULL;
640 }
641 
642 
643 /*
644  * rasqal_expression_evaluate_lang:
645  * @e: The expression to evaluate.
646  * @eval_context: Evaluation context
647  *
648  * INTERNAL - Evaluate RASQAL_EXPR_LANG (literal expr) expression.
649  *
650  * Return value: A #rasqal_literal value or NULL on failure.
651  */
652 static rasqal_literal*
rasqal_expression_evaluate_lang(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)653 rasqal_expression_evaluate_lang(rasqal_expression *e,
654                                 rasqal_evaluation_context *eval_context,
655                                 int *error_p)
656 {
657   rasqal_world* world = eval_context->world;
658   rasqal_literal* l1;
659   int free_literal = 1;
660   rasqal_variable* v = NULL;
661   unsigned char* new_s;
662 
663   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
664   if((error_p && *error_p) || !l1)
665     goto failed;
666 
667   v = rasqal_literal_as_variable(l1);
668   if(v) {
669     rasqal_free_literal(l1);
670 
671     l1 = v->value; /* don't need v after this */
672 
673     free_literal = 0;
674     if(!l1)
675       goto failed;
676   }
677 
678   if(rasqal_literal_get_rdf_term_type(l1) != RASQAL_LITERAL_STRING)
679     goto failed;
680 
681   if(l1->language) {
682     size_t len = strlen(l1->language);
683     new_s = RASQAL_MALLOC(unsigned char*, len + 1);
684     if(!new_s)
685       goto failed;
686 
687     memcpy(RASQAL_GOOD_CAST(char*, new_s), l1->language, len + 1);
688   } else  {
689     new_s = RASQAL_MALLOC(unsigned char*, 1);
690     if(!new_s)
691       goto failed;
692 
693     *new_s = '\0';
694   }
695 
696   if(free_literal)
697     rasqal_free_literal(l1);
698 
699   /* after this new_s is owned by result */
700   return rasqal_new_string_literal(world, new_s, NULL, NULL, NULL);
701 
702   failed:
703   if(error_p)
704     *error_p = 1;
705 
706   if(free_literal)
707     rasqal_free_literal(l1);
708 
709   return NULL;
710 }
711 
712 
713 /*
714  * rasqal_expression_evaluate_datatype:
715  * @e: The expression to evaluate.
716  * @eval_context: Evaluation context
717  *
718  * INTERNAL - Evaluate RASQAL_EXPR_DATATYPE (string literal) expression.
719  *
720  * Return value: A #rasqal_literal URI value or NULL on failure.
721  */
722 static rasqal_literal*
rasqal_expression_evaluate_datatype(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)723 rasqal_expression_evaluate_datatype(rasqal_expression *e,
724                                     rasqal_evaluation_context *eval_context,
725                                     int *error_p)
726 {
727   rasqal_world* world = eval_context->world;
728   rasqal_literal* l1;
729   int free_literal = 1;
730   rasqal_variable* v = NULL;
731   raptor_uri* dt_uri = NULL;
732 
733   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
734   if((error_p && *error_p) || !l1)
735     goto failed;
736 
737   v = rasqal_literal_as_variable(l1);
738   if(v) {
739     rasqal_free_literal(l1);
740 
741     l1 = v->value; /* don't need v after this */
742 
743     free_literal = 0;
744     if(!l1)
745       goto failed;
746   }
747 
748   if(rasqal_literal_get_rdf_term_type(l1) != RASQAL_LITERAL_STRING)
749     goto failed;
750 
751   if(l1->language)
752     goto failed;
753 
754   /* The datatype of a plain literal is xsd:string */
755   dt_uri = l1->datatype;
756   if(!dt_uri && l1->type == RASQAL_LITERAL_STRING)
757     dt_uri = rasqal_xsd_datatype_type_to_uri(l1->world,
758                                              RASQAL_LITERAL_XSD_STRING);
759 
760   if(!dt_uri)
761     goto failed;
762 
763   dt_uri = raptor_uri_copy(dt_uri);
764 
765   if(free_literal)
766     rasqal_free_literal(l1);
767 
768   /* after this dt_uri is owned by result */
769   return rasqal_new_uri_literal(world, dt_uri);
770 
771   failed:
772   if(error_p)
773     *error_p = 1;
774 
775   if(free_literal)
776     rasqal_free_literal(l1);
777 
778   return NULL;
779 }
780 
781 
782 /*
783  * rasqal_expression_evaluate_uri_constructor:
784  * @e: The expression to evaluate.
785  * @eval_context: Evaluation context
786  *
787  * INTERNAL - Evaluate RASQAL_EXPR_URI and RASQAL_EXPR_IRI (string)
788  * expressions.
789  *
790  * Return value: A #rasqal_literal URI value or NULL on failure.
791  */
792 static rasqal_literal*
rasqal_expression_evaluate_uri_constructor(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)793 rasqal_expression_evaluate_uri_constructor(rasqal_expression *e,
794                                            rasqal_evaluation_context *eval_context,
795                                            int *error_p)
796 {
797   rasqal_world* world = eval_context->world;
798   rasqal_literal* l1;
799   raptor_uri* dt_uri;
800   const unsigned char *s;
801 
802   l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
803   if((error_p && *error_p) || !l1)
804     goto failed;
805 
806   s = rasqal_literal_as_string_flags(l1, eval_context->flags, error_p);
807   if(error_p && *error_p)
808     goto failed;
809 
810   dt_uri = raptor_new_uri_relative_to_base(world->raptor_world_ptr,
811                                            eval_context->base_uri,
812                                            s);
813   rasqal_free_literal(l1); l1 = NULL;
814 
815   if(!dt_uri)
816     goto failed;
817 
818   /* after this dt_uri is owned by the result literal */
819   return rasqal_new_uri_literal(world, dt_uri);
820 
821   failed:
822   if(error_p)
823     *error_p = 1;
824 
825   if(l1)
826     rasqal_free_literal(l1);
827 
828   return NULL;
829 }
830 
831 
832 /*
833  * rasqal_expression_evaluate_bnode_constructor:
834  * @e: The expression to evaluate.
835  * @eval_context: Evaluation context
836  *
837  * INTERNAL - Evaluate RASQAL_EXPR_BNODE (string) expression.
838  *
839  * Return value: A #rasqal_literal blank node value or NULL on failure.
840  */
841 static rasqal_literal*
rasqal_expression_evaluate_bnode_constructor(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)842 rasqal_expression_evaluate_bnode_constructor(rasqal_expression *e,
843                                              rasqal_evaluation_context *eval_context,
844                                              int *error_p)
845 {
846   rasqal_world* world = eval_context->world;
847   rasqal_literal *l1 = NULL;
848   unsigned char *new_s = NULL;
849 
850   if(e->arg1) {
851     const unsigned char *s;
852     size_t len;
853 
854     l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
855     if((error_p && *error_p) || !l1)
856       goto failed;
857 
858     s = rasqal_literal_as_counted_string(l1, &len, eval_context->flags,
859                                          error_p);
860     if(error_p && *error_p)
861       goto failed;
862 
863     new_s = RASQAL_MALLOC(unsigned char*, len + 1);
864     if(!new_s)
865       goto failed;
866 
867     memcpy(RASQAL_GOOD_CAST(char*, new_s), s, len + 1);
868 
869     rasqal_free_literal(l1);
870   } else {
871     new_s = rasqal_world_generate_bnodeid(world, NULL);
872     if(!new_s)
873       goto failed;
874   }
875 
876   /* after this new_s is owned by the result */
877   return rasqal_new_simple_literal(world, RASQAL_LITERAL_BLANK, new_s);
878 
879   failed:
880   if(error_p)
881     *error_p = 1;
882 
883   if(l1)
884     rasqal_free_literal(l1);
885 
886   return NULL;
887 }
888 
889 
890 /**
891  * rasqal_expression_evaluate2:
892  * @e: The expression to evaluate.
893  * @eval_context: expression context
894  * @error_p: pointer to error return flag
895  *
896  * Evaluate a #rasqal_expression tree in the context of a
897  * #rasqal_evaluation_context to give a #rasqal_literal result or error.
898  *
899  * Return value: a #rasqal_literal value or NULL (a valid value).  @error_p is set to non-0 on failure.
900  **/
901 rasqal_literal*
rasqal_expression_evaluate2(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)902 rasqal_expression_evaluate2(rasqal_expression* e,
903                             rasqal_evaluation_context* eval_context,
904                             int *error_p)
905 {
906   rasqal_world *world;
907   int flags;
908   rasqal_literal* result = NULL;
909   rasqal_literal *l1;
910   rasqal_literal *l2;
911 
912   /* pack vars from different switch cases in unions to save some stack space */
913   union {
914     struct { int e1; int e2; } errs;
915     struct { int dummy_do_not_mask_e; int free_literal; } flags;
916     int e;
917   } errs;
918   union {
919     struct { int b1; int b2; } bools;
920     int b;
921     int i;
922     raptor_uri *dt_uri;
923     const unsigned char *s;
924     unsigned char *new_s;
925     rasqal_variable *v;
926     rasqal_expression *e;
927     struct { void *dummy_do_not_mask; int found; } flags;
928     rasqal_xsd_datetime* dt;
929     struct timeval *tv;
930     raptor_stringbuffer* sb;
931   } vars;
932 
933   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(e, rasqal_expression, NULL);
934   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(eval_context, rasqal_evaluation_context, NULL);
935   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(error_p, intp, NULL);
936 
937   world = eval_context->world;
938   flags = eval_context->flags;
939 
940   errs.e = 0;
941 
942 #ifdef RASQAL_DEBUG_EVAL
943   RASQAL_DEBUG2("evaluating expression %p: ", e);
944   rasqal_expression_print(e, stderr);
945   fprintf(stderr, "\n");
946 #endif
947 
948   switch(e->op) {
949     case RASQAL_EXPR_AND:
950       errs.errs.e1 = 0;
951       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, &errs.errs.e1);
952       if(errs.errs.e1) {
953         vars.bools.b1 = 0;
954       } else {
955         vars.bools.b1 = rasqal_literal_as_boolean(l1, &errs.errs.e1);
956         rasqal_free_literal(l1);
957       }
958 
959       errs.errs.e2 = 0;
960       l1 = rasqal_expression_evaluate2(e->arg2, eval_context, &errs.errs.e2);
961       if(errs.errs.e2) {
962         vars.bools.b2 = 0;
963       } else {
964         vars.bools.b2 = rasqal_literal_as_boolean(l1, &errs.errs.e2);
965         rasqal_free_literal(l1);
966       }
967 
968       /* See http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/#truthTable */
969       if(!errs.errs.e1 && !errs.errs.e2) {
970         /* No type error, answer is A && B */
971         vars.b = vars.bools.b1 && vars.bools.b2; /* don't need b1,b2 anymore */
972       } else {
973         if((!vars.bools.b1 && errs.errs.e2) || (errs.errs.e1 && vars.bools.b2))
974           /* F && E => F.   E && F => F. */
975           vars.b = 0;
976         else
977           /* Otherwise E */
978           goto failed;
979       }
980 
981       result = rasqal_new_boolean_literal(world, vars.b);
982       break;
983 
984     case RASQAL_EXPR_OR:
985       errs.errs.e1 = 0;
986       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, &errs.errs.e1);
987       if(errs.errs.e1) {
988         vars.bools.b1 = 0;
989       } else {
990         vars.bools.b1 = rasqal_literal_as_boolean(l1, &errs.errs.e1);
991         rasqal_free_literal(l1);
992       }
993 
994       errs.errs.e2 = 0;
995       l1 = rasqal_expression_evaluate2(e->arg2, eval_context, &errs.errs.e2);
996       if(errs.errs.e2) {
997         vars.bools.b2 = 0;
998       } else {
999         vars.bools.b2 = rasqal_literal_as_boolean(l1, &errs.errs.e2);
1000         rasqal_free_literal(l1);
1001       }
1002 
1003       /* See http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/#truthTable */
1004       if(!errs.errs.e1 && !errs.errs.e2) {
1005         /* No type error, answer is A || B */
1006         vars.b = vars.bools.b1 || vars.bools.b2; /* don't need b1,b2 anymore */
1007       } else {
1008         if((vars.bools.b1 && errs.errs.e2) || (errs.errs.e1 && vars.bools.b2))
1009           /* T || E => T.   E || T => T */
1010           vars.b = 1;
1011         else
1012           /* Otherwise E */
1013           goto failed;
1014       }
1015 
1016       result = rasqal_new_boolean_literal(world, vars.b);
1017       break;
1018 
1019     case RASQAL_EXPR_EQ:
1020       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1021       if((error_p && *error_p) || !l1)
1022         goto failed;
1023 
1024       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1025       if((error_p && *error_p) || !l2) {
1026         rasqal_free_literal(l1);
1027         goto failed;
1028       }
1029 
1030       /* FIXME - this should probably be checked at literal creation
1031        * time
1032        */
1033       if(!rasqal_xsd_datatype_check(l1->type, l1->string, flags) ||
1034          !rasqal_xsd_datatype_check(l2->type, l2->string, flags)) {
1035 #ifdef RASQAL_DEBUG_EVAL
1036         RASQAL_DEBUG1("One of the literals was invalid\n");
1037 #endif
1038         goto failed;
1039       }
1040 
1041       vars.b = (rasqal_literal_equals_flags(l1, l2, flags, &errs.e) != 0);
1042 #ifdef RASQAL_DEBUG_EVAL
1043       if(errs.e)
1044         RASQAL_DEBUG1("rasqal_literal_equals_flags returned: FAILURE\n");
1045       else
1046         RASQAL_DEBUG2("rasqal_literal_equals_flags returned: %d\n", vars.b);
1047 #endif
1048       rasqal_free_literal(l1);
1049       rasqal_free_literal(l2);
1050       if(errs.e)
1051         goto failed;
1052 
1053       result = rasqal_new_boolean_literal(world, vars.b);
1054       break;
1055 
1056     case RASQAL_EXPR_NEQ:
1057       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1058       if((error_p && *error_p) || !l1)
1059         goto failed;
1060 
1061       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1062       if((error_p && *error_p) || !l2) {
1063         rasqal_free_literal(l1);
1064         goto failed;
1065       }
1066 
1067       vars.b = (rasqal_literal_not_equals_flags(l1, l2, flags, &errs.e) != 0);
1068 #ifdef RASQAL_DEBUG_EVAL
1069       if(errs.e)
1070         RASQAL_DEBUG1("rasqal_literal_not_equals_flags returned: FAILURE\n");
1071       else
1072         RASQAL_DEBUG2("rasqal_literal_not_equals_flags returned: %d\n", vars.b);
1073 #endif
1074       rasqal_free_literal(l1);
1075       rasqal_free_literal(l2);
1076       if(errs.e)
1077         goto failed;
1078 
1079       result = rasqal_new_boolean_literal(world, vars.b);
1080       break;
1081 
1082     case RASQAL_EXPR_LT:
1083       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1084       if((error_p && *error_p) || !l1)
1085         goto failed;
1086 
1087       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1088       if((error_p && *error_p) || !l2) {
1089         rasqal_free_literal(l1);
1090         goto failed;
1091       }
1092 
1093       vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) < 0);
1094       rasqal_free_literal(l1);
1095       rasqal_free_literal(l2);
1096       if(errs.e)
1097         goto failed;
1098 
1099       result = rasqal_new_boolean_literal(world, vars.b);
1100       break;
1101 
1102     case RASQAL_EXPR_GT:
1103       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1104       if((error_p && *error_p) || !l1)
1105         goto failed;
1106 
1107       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1108       if((error_p && *error_p) || !l2) {
1109         rasqal_free_literal(l1);
1110         goto failed;
1111       }
1112 
1113       vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) > 0);
1114       rasqal_free_literal(l1);
1115       rasqal_free_literal(l2);
1116       if(errs.e)
1117         goto failed;
1118 
1119       result = rasqal_new_boolean_literal(world, vars.b);
1120       break;
1121 
1122     case RASQAL_EXPR_LE:
1123       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1124       if((error_p && *error_p) || !l1)
1125         goto failed;
1126 
1127       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1128       if((error_p && *error_p) || !l2) {
1129         rasqal_free_literal(l1);
1130         goto failed;
1131       }
1132 
1133       vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) <= 0);
1134       rasqal_free_literal(l1);
1135       rasqal_free_literal(l2);
1136       if(errs.e)
1137         goto failed;
1138 
1139       result = rasqal_new_boolean_literal(world, vars.b);
1140       break;
1141 
1142     case RASQAL_EXPR_GE:
1143       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1144       if((error_p && *error_p) || !l1)
1145         goto failed;
1146 
1147       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1148       if((error_p && *error_p) || !l2) {
1149         rasqal_free_literal(l1);
1150         goto failed;
1151       }
1152 
1153       vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) >= 0);
1154       rasqal_free_literal(l1);
1155       rasqal_free_literal(l2);
1156       if(errs.e)
1157         goto failed;
1158 
1159       result = rasqal_new_boolean_literal(world, vars.b);
1160       break;
1161 
1162     case RASQAL_EXPR_UMINUS:
1163       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1164       if((error_p && *error_p) || !l1)
1165         goto failed;
1166 
1167       result = rasqal_literal_negate(l1, &errs.e);
1168       rasqal_free_literal(l1);
1169       if(errs.e)
1170         goto failed;
1171       break;
1172 
1173     case RASQAL_EXPR_BOUND:
1174       result = rasqal_expression_evaluate_bound(e, eval_context, error_p);
1175       break;
1176 
1177     case RASQAL_EXPR_STR:
1178       result = rasqal_expression_evaluate_str(e, eval_context, error_p);
1179       break;
1180 
1181     case RASQAL_EXPR_LANG:
1182       result = rasqal_expression_evaluate_lang(e, eval_context, error_p);
1183       break;
1184 
1185     case RASQAL_EXPR_LANGMATCHES:
1186       result = rasqal_expression_evaluate_langmatches(e, eval_context, error_p);
1187       break;
1188 
1189     case RASQAL_EXPR_DATATYPE:
1190       result = rasqal_expression_evaluate_datatype(e, eval_context, error_p);
1191       break;
1192 
1193     case RASQAL_EXPR_ISURI:
1194     case RASQAL_EXPR_ISBLANK:
1195     case RASQAL_EXPR_ISLITERAL:
1196     case RASQAL_EXPR_ISNUMERIC:
1197       result = rasqal_expression_evaluate_istype(e, eval_context, error_p);
1198       break;
1199 
1200     case RASQAL_EXPR_PLUS:
1201       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1202       if((error_p && *error_p) || !l1)
1203         goto failed;
1204 
1205       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1206       if((error_p && *error_p) || !l2) {
1207         rasqal_free_literal(l1);
1208         goto failed;
1209       }
1210 
1211       result = rasqal_literal_add(l1, l2, &errs.e);
1212       rasqal_free_literal(l1);
1213       rasqal_free_literal(l2);
1214       if(errs.e)
1215         goto failed;
1216 
1217       break;
1218 
1219     case RASQAL_EXPR_MINUS:
1220       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1221       if((error_p && *error_p) || !l1)
1222         goto failed;
1223 
1224       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1225       if((error_p && *error_p) || !l2) {
1226         rasqal_free_literal(l1);
1227         goto failed;
1228       }
1229 
1230       result = rasqal_literal_subtract(l1, l2, &errs.e);
1231       rasqal_free_literal(l1);
1232       rasqal_free_literal(l2);
1233       if(errs.e)
1234         goto failed;
1235 
1236       break;
1237 
1238     case RASQAL_EXPR_STAR:
1239       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1240       if((error_p && *error_p) || !l1)
1241         goto failed;
1242 
1243       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1244       if((error_p && *error_p) || !l2) {
1245         rasqal_free_literal(l1);
1246         goto failed;
1247       }
1248 
1249       result = rasqal_literal_multiply(l1, l2, &errs.e);
1250       rasqal_free_literal(l1);
1251       rasqal_free_literal(l2);
1252       if(errs.e)
1253         goto failed;
1254 
1255       break;
1256 
1257     case RASQAL_EXPR_SLASH:
1258       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1259       if((error_p && *error_p) || !l1)
1260         goto failed;
1261 
1262       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1263       if((error_p && *error_p) || !l2) {
1264         rasqal_free_literal(l1);
1265         goto failed;
1266       }
1267 
1268       result = rasqal_literal_divide(l1, l2, &errs.e);
1269       rasqal_free_literal(l1);
1270       rasqal_free_literal(l2);
1271       if(errs.e)
1272         goto failed;
1273 
1274       break;
1275 
1276     case RASQAL_EXPR_REM:
1277       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1278       if((error_p && *error_p) || !l1)
1279         goto failed;
1280 
1281       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1282       if((error_p && *error_p) || !l2) {
1283         rasqal_free_literal(l1);
1284         goto failed;
1285       }
1286 
1287       vars.i = rasqal_literal_as_integer(l2, &errs.errs.e2);
1288       /* error if divisor is zero */
1289       if(!vars.i)
1290         errs.errs.e2 = 1;
1291       else
1292         vars.i = rasqal_literal_as_integer(l1, &errs.errs.e1) % vars.i;
1293 
1294       rasqal_free_literal(l1);
1295       rasqal_free_literal(l2);
1296       if(errs.errs.e1 || errs.errs.e2)
1297         goto failed;
1298 
1299       result = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, vars.i);
1300       break;
1301 
1302     case RASQAL_EXPR_STR_EQ:
1303       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1304       if((error_p && *error_p) || !l1)
1305         goto failed;
1306 
1307       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1308       if((error_p && *error_p) || !l2) {
1309         rasqal_free_literal(l1);
1310         goto failed;
1311       }
1312 
1313       vars.b = (rasqal_literal_compare(l1, l2, flags | RASQAL_COMPARE_NOCASE,
1314                                        &errs.e) == 0);
1315       rasqal_free_literal(l1);
1316       rasqal_free_literal(l2);
1317       if(errs.e)
1318         goto failed;
1319 
1320       result = rasqal_new_boolean_literal(world, vars.b);
1321       break;
1322 
1323     case RASQAL_EXPR_STR_NEQ:
1324       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1325       if((error_p && *error_p) || !l1)
1326         goto failed;
1327 
1328       l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p);
1329       if((error_p && *error_p) || !l2) {
1330         rasqal_free_literal(l1);
1331         goto failed;
1332       }
1333 
1334       vars.b = (rasqal_literal_compare(l1, l2, flags | RASQAL_COMPARE_NOCASE,
1335                                        &errs.e) != 0);
1336       rasqal_free_literal(l1);
1337       rasqal_free_literal(l2);
1338       if(errs.e)
1339         goto failed;
1340 
1341       result = rasqal_new_boolean_literal(world, vars.b);
1342       break;
1343 
1344     case RASQAL_EXPR_TILDE:
1345       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1346       if((error_p && *error_p) || !l1)
1347         goto failed;
1348 
1349       vars.i= ~ rasqal_literal_as_integer(l1, &errs.e);
1350       rasqal_free_literal(l1);
1351       if(errs.e)
1352         goto failed;
1353 
1354       result = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, vars.i);
1355       break;
1356 
1357     case RASQAL_EXPR_BANG:
1358       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1359       if((error_p && *error_p) || !l1)
1360         goto failed;
1361 
1362       vars.b = ! rasqal_literal_as_boolean(l1, &errs.e);
1363       rasqal_free_literal(l1);
1364       if(errs.e)
1365         goto failed;
1366 
1367       result = rasqal_new_boolean_literal(world, vars.b);
1368       break;
1369 
1370     case RASQAL_EXPR_STR_MATCH:
1371     case RASQAL_EXPR_STR_NMATCH:
1372     case RASQAL_EXPR_REGEX:
1373       result = rasqal_expression_evaluate_strmatch(e, eval_context, error_p);
1374       break;
1375 
1376     case RASQAL_EXPR_LITERAL:
1377       /* flatten any literal to a value as soon as possible - this
1378        * removes variables from expressions the first time they are seen.
1379        * (FLATTEN_LITERAL)
1380        */
1381       result = rasqal_new_literal_from_literal(rasqal_literal_value(e->literal));
1382       break;
1383 
1384     case RASQAL_EXPR_FUNCTION:
1385       rasqal_log_warning_simple(world, RASQAL_WARNING_LEVEL_NOT_IMPLEMENTED,
1386                                 eval_context->locator,
1387                                 "No function expressions support at present.  Returning false.");
1388       result = rasqal_new_boolean_literal(world, 0);
1389       break;
1390 
1391     case RASQAL_EXPR_CAST:
1392       l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1393       if((error_p && *error_p) || !l1)
1394         goto failed;
1395 
1396       result = rasqal_literal_cast(l1, e->name, flags, &errs.e);
1397 
1398       rasqal_free_literal(l1);
1399       if(errs.e)
1400         goto failed;
1401 
1402       break;
1403 
1404     case RASQAL_EXPR_ORDER_COND_ASC:
1405     case RASQAL_EXPR_ORDER_COND_DESC:
1406     case RASQAL_EXPR_GROUP_COND_ASC:
1407     case RASQAL_EXPR_GROUP_COND_DESC:
1408       result = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
1409       break;
1410 
1411     case RASQAL_EXPR_COUNT:
1412     case RASQAL_EXPR_SUM:
1413     case RASQAL_EXPR_AVG:
1414     case RASQAL_EXPR_MIN:
1415     case RASQAL_EXPR_MAX:
1416     case RASQAL_EXPR_SAMPLE:
1417     case RASQAL_EXPR_GROUP_CONCAT:
1418       rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR,
1419                               eval_context->locator,
1420                               "Aggregate expressions cannot be evaluated in a general scalar expression.");
1421       errs.e = 1;
1422       goto failed;
1423 
1424     case RASQAL_EXPR_VARSTAR:
1425       /* constants */
1426       break;
1427 
1428     case RASQAL_EXPR_SAMETERM:
1429       result = rasqal_expression_evaluate_sameterm(e, eval_context, error_p);
1430       break;
1431 
1432     case RASQAL_EXPR_CONCAT:
1433       result = rasqal_expression_evaluate_concat(e, eval_context, error_p);
1434       break;
1435 
1436     case RASQAL_EXPR_COALESCE:
1437       result = rasqal_expression_evaluate_coalesce(e, eval_context, error_p);
1438       break;
1439 
1440     case RASQAL_EXPR_IF:
1441       result = rasqal_expression_evaluate_if(e, eval_context, error_p);
1442       break;
1443 
1444     case RASQAL_EXPR_URI:
1445     case RASQAL_EXPR_IRI:
1446       result = rasqal_expression_evaluate_uri_constructor(e, eval_context, error_p);
1447       break;
1448 
1449     case RASQAL_EXPR_STRLANG:
1450       result = rasqal_expression_evaluate_strlang(e, eval_context, error_p);
1451       break;
1452 
1453     case RASQAL_EXPR_STRDT:
1454       result = rasqal_expression_evaluate_strdt(e, eval_context, error_p);
1455       break;
1456 
1457     case RASQAL_EXPR_BNODE:
1458       result = rasqal_expression_evaluate_bnode_constructor(e, eval_context, error_p);
1459       break;
1460 
1461     case RASQAL_EXPR_IN:
1462       result = rasqal_expression_evaluate_in_set(e, eval_context, error_p);
1463       break;
1464 
1465     case RASQAL_EXPR_NOT_IN:
1466       result = rasqal_expression_evaluate_in_set(e, eval_context, error_p);
1467       break;
1468 
1469     case RASQAL_EXPR_YEAR:
1470     case RASQAL_EXPR_MONTH:
1471     case RASQAL_EXPR_DAY:
1472     case RASQAL_EXPR_HOURS:
1473     case RASQAL_EXPR_MINUTES:
1474     case RASQAL_EXPR_SECONDS:
1475       result = rasqal_expression_evaluate_datetime_part(e, eval_context, error_p);
1476       break;
1477 
1478     case RASQAL_EXPR_CURRENT_DATETIME:
1479     case RASQAL_EXPR_NOW:
1480       result = rasqal_expression_evaluate_now(e, eval_context, error_p);
1481       break;
1482 
1483     case RASQAL_EXPR_TO_UNIXTIME:
1484       result = rasqal_expression_evaluate_to_unixtime(e, eval_context, error_p);
1485       break;
1486 
1487     case RASQAL_EXPR_FROM_UNIXTIME:
1488       result = rasqal_expression_evaluate_from_unixtime(e, eval_context, error_p);
1489       break;
1490 
1491     case RASQAL_EXPR_RAND:
1492       result = rasqal_expression_evaluate_rand(e, eval_context, error_p);
1493       break;
1494 
1495     case RASQAL_EXPR_STRLEN:
1496       result = rasqal_expression_evaluate_strlen(e, eval_context, error_p);
1497       break;
1498 
1499     case RASQAL_EXPR_UCASE:
1500     case RASQAL_EXPR_LCASE:
1501       result = rasqal_expression_evaluate_set_case(e, eval_context, error_p);
1502       break;
1503 
1504     case RASQAL_EXPR_STRSTARTS:
1505     case RASQAL_EXPR_STRENDS:
1506     case RASQAL_EXPR_CONTAINS:
1507       result = rasqal_expression_evaluate_str_prefix_suffix(e, eval_context, error_p);
1508       break;
1509 
1510     case RASQAL_EXPR_TIMEZONE:
1511       result = rasqal_expression_evaluate_datetime_timezone(e, eval_context, error_p);
1512       break;
1513 
1514     case RASQAL_EXPR_TZ:
1515       result = rasqal_expression_evaluate_datetime_tz(e, eval_context, error_p);
1516       break;
1517 
1518     case RASQAL_EXPR_ENCODE_FOR_URI:
1519       result = rasqal_expression_evaluate_encode_for_uri(e, eval_context, error_p);
1520       break;
1521 
1522     case RASQAL_EXPR_SUBSTR:
1523       result = rasqal_expression_evaluate_substr(e, eval_context, error_p);
1524       break;
1525 
1526     case RASQAL_EXPR_STRBEFORE:
1527       result = rasqal_expression_evaluate_strbefore(e, eval_context, error_p);
1528       break;
1529 
1530     case RASQAL_EXPR_STRAFTER:
1531       result = rasqal_expression_evaluate_strafter(e, eval_context, error_p);
1532       break;
1533 
1534     case RASQAL_EXPR_REPLACE:
1535       result = rasqal_expression_evaluate_replace(e, eval_context, error_p);
1536       break;
1537 
1538     case RASQAL_EXPR_ABS:
1539       result = rasqal_expression_evaluate_abs(e, eval_context, error_p);
1540       break;
1541 
1542     case RASQAL_EXPR_ROUND:
1543       result = rasqal_expression_evaluate_round(e, eval_context, error_p);
1544       break;
1545 
1546     case RASQAL_EXPR_CEIL:
1547       result = rasqal_expression_evaluate_ceil(e, eval_context, error_p);
1548       break;
1549 
1550     case RASQAL_EXPR_FLOOR:
1551       result = rasqal_expression_evaluate_floor(e, eval_context, error_p);
1552       break;
1553 
1554     case RASQAL_EXPR_MD5:
1555     case RASQAL_EXPR_SHA1:
1556     case RASQAL_EXPR_SHA224:
1557     case RASQAL_EXPR_SHA256:
1558     case RASQAL_EXPR_SHA384:
1559     case RASQAL_EXPR_SHA512:
1560       result = rasqal_expression_evaluate_digest(e, eval_context, error_p);
1561       break;
1562 
1563     case RASQAL_EXPR_UUID:
1564       result = rasqal_expression_evaluate_uriuuid(e, eval_context, error_p);
1565       break;
1566 
1567     case RASQAL_EXPR_STRUUID:
1568       result = rasqal_expression_evaluate_struuid(e, eval_context, error_p);
1569       break;
1570 
1571     case RASQAL_EXPR_UNKNOWN:
1572     default:
1573       RASQAL_FATAL3("Unknown operation %s (%u)",
1574                     rasqal_expression_op_label(e->op), e->op);
1575   }
1576 
1577   got_result:
1578 
1579 #ifdef RASQAL_DEBUG_EVAL
1580   RASQAL_DEBUG2("result of %p: ", e);
1581   rasqal_expression_print(e, stderr);
1582   fputs( ": ", stderr);
1583   if(error_p && *error_p)
1584     fputs("FAILURE",stderr);
1585   else
1586     rasqal_literal_print(result, stderr);
1587   fputc('\n', stderr);
1588 #endif
1589 
1590   return result;
1591 
1592   failed:
1593   *error_p = 1;
1594 
1595   if(result) {
1596     rasqal_free_literal(result);
1597     result = NULL;
1598   }
1599   goto got_result;
1600 }
1601 
1602 
1603 #ifndef RASQAL_DISABLE_DEPRECATED
1604 /**
1605  * rasqal_expression_evaluate:
1606  * @world: #rasqal_world
1607  * @locator: error locator (or NULL)
1608  * @e: The expression to evaluate.
1609  * @flags: Flags for rasqal_literal_compare() and RASQAL_COMPARE_NOCASE for string matches.
1610  *
1611  * Evaluate a #rasqal_expression tree to give a #rasqal_literal result
1612  * or error.
1613  *
1614  * @Deprecated: use rasqal_expression_evaluate2() using a #rasqal_evaluation_context
1615  *
1616  * Return value: a #rasqal_literal value or NULL on failure.
1617  **/
1618 rasqal_literal*
rasqal_expression_evaluate(rasqal_world * world,raptor_locator * locator,rasqal_expression * e,int flags)1619 rasqal_expression_evaluate(rasqal_world *world, raptor_locator *locator,
1620                            rasqal_expression* e, int flags)
1621 {
1622   rasqal_evaluation_context context; /* static */
1623   int error = 0;
1624   rasqal_literal* l;
1625 
1626   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
1627   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(e, rasqal_expression, NULL);
1628 
1629   memset(&context, '\0', sizeof(context));
1630   context.world = world;
1631   context.locator = locator;
1632   context.flags = flags;
1633 
1634   l = rasqal_expression_evaluate2(e, &context, &error);
1635   if(error)
1636     return NULL;
1637 
1638   return l;
1639 }
1640 #endif
1641