VirtualBox

source: kBuild/trunk/src/kmk/expreval.c@ 2016

Last change on this file since 2016 was 1729, checked in by bird, 16 years ago

kmk/expreval.c: Added conversion operators: num, string and bool. Consoliated some assertions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 52.5 KB
Line 
1#ifdef CONFIG_WITH_IF_CONDITIONALS
2/* $Id: expreval.c 1729 2008-09-05 03:50:10Z bird $ */
3/** @file
4 * expreval - Expressions evaluator, C / BSD make / nmake style.
5 */
6
7/*
8 * Copyright (c) 2008 knut st. osmundsen <[email protected]>
9 *
10 * This file is part of kBuild.
11 *
12 * kBuild is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * kBuild is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with kBuild; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "make.h"
32#include <assert.h>
33
34#include <glob.h>
35
36#include "dep.h"
37#include "filedef.h"
38#include "job.h"
39#include "commands.h"
40#include "variable.h"
41#include "rule.h"
42#include "debug.h"
43#include "hash.h"
44#include <ctype.h>
45#ifndef _MSC_VER
46# include <stdint.h>
47#endif
48#include <stdarg.h>
49
50
51/*******************************************************************************
52* Defined Constants And Macros *
53*******************************************************************************/
54/** The max length of a string representation of a number. */
55#define EXPR_NUM_LEN ((sizeof("-9223372036854775802") + 4) & ~3)
56
57/** The max operator stack depth. */
58#define EXPR_MAX_OPERATORS 72
59/** The max operand depth. */
60#define EXPR_MAX_OPERANDS 128
61
62
63/*******************************************************************************
64* Structures and Typedefs *
65*******************************************************************************/
66/** The 64-bit signed integer type we're using. */
67#ifdef _MSC_VER
68typedef __int64 EXPRINT64;
69#else
70# include <stdint.h>
71typedef int64_t EXPRINT64;
72#endif
73
74/** Pointer to a evaluator instance. */
75typedef struct EXPR *PEXPR;
76
77
78/**
79 * Operand variable type.
80 */
81typedef enum
82{
83 /** Invalid zero entry. */
84 kExprVar_Invalid = 0,
85 /** A number. */
86 kExprVar_Num,
87 /** A string in need of expanding (perhaps). */
88 kExprVar_String,
89 /** A simple string that doesn't need expanding. */
90 kExprVar_SimpleString,
91 /** A quoted string in need of expanding (perhaps). */
92 kExprVar_QuotedString,
93 /** A simple quoted string that doesn't need expanding. */
94 kExprVar_QuotedSimpleString,
95 /** The end of the valid variable types. */
96 kExprVar_End
97} EXPRVARTYPE;
98
99/**
100 * Operand variable.
101 */
102typedef struct
103{
104 /** The variable type. */
105 EXPRVARTYPE enmType;
106 /** The variable. */
107 union
108 {
109 /** Pointer to the string. */
110 char *psz;
111 /** The variable. */
112 EXPRINT64 i;
113 } uVal;
114} EXPRVAR;
115/** Pointer to a operand variable. */
116typedef EXPRVAR *PEXPRVAR;
117/** Pointer to a const operand variable. */
118typedef EXPRVAR const *PCEXPRVAR;
119
120/**
121 * Operator return statuses.
122 */
123typedef enum
124{
125 kExprRet_Error = -1,
126 kExprRet_Ok = 0,
127 kExprRet_Operator,
128 kExprRet_Operand,
129 kExprRet_EndOfExpr,
130 kExprRet_End
131} EXPRRET;
132
133/**
134 * Operator.
135 */
136typedef struct
137{
138 /** The operator. */
139 char szOp[11];
140 /** The length of the operator string. */
141 char cchOp;
142 /** The pair operator.
143 * This is used with '(' and '?'. */
144 char chPair;
145 /** The precedence. Higher means higher. */
146 char iPrecedence;
147 /** The number of arguments it takes. */
148 signed char cArgs;
149 /** Pointer to the method implementing the operator. */
150 EXPRRET (*pfn)(PEXPR pThis);
151} EXPROP;
152/** Pointer to a const operator. */
153typedef EXPROP const *PCEXPROP;
154
155/**
156 * Expression evaluator instance.
157 */
158typedef struct EXPR
159{
160 /** The full expression. */
161 const char *pszExpr;
162 /** The current location. */
163 const char *psz;
164 /** The current file location, used for errors. */
165 const struct floc *pFileLoc;
166 /** Pending binary operator. */
167 PCEXPROP pPending;
168 /** Top of the operator stack. */
169 int iOp;
170 /** Top of the operand stack. */
171 int iVar;
172 /** The operator stack. */
173 PCEXPROP apOps[EXPR_MAX_OPERATORS];
174 /** The operand stack. */
175 EXPRVAR aVars[EXPR_MAX_OPERANDS];
176} EXPR;
177
178
179/*******************************************************************************
180* Global Variables *
181*******************************************************************************/
182/** Operator start character map.
183 * This indicates which characters that are starting operators and which aren't. */
184static char g_auchOpStartCharMap[256];
185/** Whether we've initialized the map. */
186static int g_fExprInitializedMap = 0;
187
188
189/*******************************************************************************
190* Internal Functions *
191*******************************************************************************/
192static void expr_unget_op(PEXPR pThis);
193static EXPRRET expr_get_binary_or_eoe_or_rparen(PEXPR pThis);
194
195
196
197
198/**
199 * Displays an error message.
200 *
201 * The total string length must not exceed 256 bytes.
202 *
203 * @param pThis The evaluator instance.
204 * @param pszError The message format string.
205 * @param ... The message format args.
206 */
207static void expr_error(PEXPR pThis, const char *pszError, ...)
208{
209 char szTmp[256];
210 va_list va;
211
212 va_start(va, pszError);
213 vsprintf(szTmp, pszError, va);
214 va_end(va);
215
216 fatal(pThis->pFileLoc, "%s", szTmp);
217}
218
219
220/**
221 * Converts a number to a string.
222 *
223 * @returns pszDst.
224 * @param pszDst The string buffer to write into. Assumes length of EXPR_NUM_LEN.
225 * @param iSrc The number to convert.
226 */
227static char *expr_num_to_string(char *pszDst, EXPRINT64 iSrc)
228{
229 static const char s_szDigits[17] = "0123456789abcdef";
230 char szTmp[EXPR_NUM_LEN];
231 char *psz = &szTmp[EXPR_NUM_LEN - 1];
232 int fNegative;
233
234 fNegative = iSrc < 0;
235 if (fNegative)
236 {
237 /** @todo this isn't right for INT64_MIN. */
238 iSrc = -iSrc;
239 }
240
241 *psz = '\0';
242 do
243 {
244#if 0
245 *--psz = s_szDigits[iSrc & 0xf];
246 iSrc >>= 4;
247#else
248 *--psz = s_szDigits[iSrc % 10];
249 iSrc /= 10;
250#endif
251 } while (iSrc);
252
253#if 0
254 *--psz = 'x';
255 *--psz = '0';
256#endif
257
258 if (fNegative)
259 *--psz = '-';
260
261 /* copy it into the output buffer. */
262 return (char *)memcpy(pszDst, psz, &szTmp[EXPR_NUM_LEN] - psz);
263}
264
265
266/**
267 * Attempts to convert a (simple) string into a number.
268 *
269 * @returns status code.
270 * @param pThis The evaluator instance. This is optional when fQuiet is true.
271 * @param piSrc Where to store the numeric value on success.
272 * @param pszSrc The string to try convert.
273 * @param fQuiet Whether we should be quiet or grumpy on failure.
274 */
275static EXPRRET expr_string_to_num(PEXPR pThis, EXPRINT64 *piDst, const char *pszSrc, int fQuiet)
276{
277 EXPRRET rc = kExprRet_Ok;
278 char const *psz = pszSrc;
279 EXPRINT64 i;
280 unsigned uBase;
281 int fNegative;
282
283
284 /*
285 * Skip blanks.
286 */
287 while (isblank(*psz))
288 psz++;
289
290 /*
291 * Check for '-'.
292 *
293 * At this point we will not need to deal with operators, this is
294 * just an indicator of negative numbers. If some operator ends up
295 * here it's because it came from a string expansion and thus shall
296 * not be interpreted. If this turns out to be an stupid restriction
297 * it can be fixed, but for now it stays like this.
298 */
299 fNegative = *psz == '-';
300 if (fNegative)
301 psz++;
302
303 /*
304 * Determin base .
305 * .
306 * Recognize some exsotic prefixes here in addition to the two standard ones.
307 */
308 if (*psz != '0' || psz[1] == '\0' || isblank((unsigned int)psz[1]))
309 uBase = 10;
310 else if (psz[1] == 'x' || psz[1] == 'X')
311 {
312 uBase = 16;
313 psz += 2;
314 }
315 else if (psz[1] == 'b' || psz[1] == 'B')
316 {
317 uBase = 2;
318 psz += 2;
319 }
320 else if (psz[1] == 'd' || psz[1] == 'D')
321 {
322 uBase = 10;
323 psz += 2;
324 }
325 else if (psz[1] == 'o' || psz[1] == 'O')
326 {
327 uBase = 8;
328 psz += 2;
329 }
330 else if (isdigit(psz[1]) && psz[1] != '9' && psz[1] != '8')
331 {
332 uBase = 8;
333 psz++;
334 }
335 else
336 uBase = 10;
337
338 /*
339 * Convert until we hit a non-digit.
340 */
341 i = 0;
342 for (;;)
343 {
344 unsigned iDigit;
345 int ch = *psz;
346 switch (ch)
347 {
348 case '0': iDigit = 0; break;
349 case '1': iDigit = 1; break;
350 case '2': iDigit = 2; break;
351 case '3': iDigit = 3; break;
352 case '4': iDigit = 4; break;
353 case '5': iDigit = 5; break;
354 case '6': iDigit = 6; break;
355 case '7': iDigit = 7; break;
356 case '8': iDigit = 8; break;
357 case '9': iDigit = 9; break;
358 case 'a':
359 case 'A': iDigit = 10; break;
360 case 'b':
361 case 'B': iDigit = 11; break;
362 case 'c':
363 case 'C': iDigit = 12; break;
364 case 'd':
365 case 'D': iDigit = 13; break;
366 case 'e':
367 case 'E': iDigit = 14; break;
368 case 'f':
369 case 'F': iDigit = 15; break;
370
371 default:
372 /* is the rest white space? */
373 while (isspace((unsigned int)*psz))
374 psz++;
375 if (*psz != '\0')
376 {
377 iDigit = uBase;
378 break;
379 }
380 /* fall thru */
381
382 case '\0':
383 if (fNegative)
384 i = -i;
385 *piDst = i;
386 return rc;
387 }
388 if (iDigit >= uBase)
389 {
390 if (fNegative)
391 i = -i;
392 *piDst = i;
393 if (!fQuiet)
394 expr_error(pThis, "Invalid a number \"%.80s\"", pszSrc);
395 return kExprRet_Error;
396 }
397
398 /* add the digit and advance */
399 i *= uBase;
400 i += iDigit;
401 psz++;
402 }
403 /* not reached */
404}
405
406
407/**
408 * Checks if the variable is a string or not.
409 *
410 * @returns 1 if it's a string, 0 otherwise.
411 * @param pVar The variable.
412 */
413static int expr_var_is_string(PCEXPRVAR pVar)
414{
415 return pVar->enmType >= kExprVar_String;
416}
417
418
419/**
420 * Checks if the variable contains a string that was quoted
421 * in the expression.
422 *
423 * @returns 1 if if was a quoted string, otherwise 0.
424 * @param pVar The variable.
425 */
426static int expr_var_was_quoted(PCEXPRVAR pVar)
427{
428 return pVar->enmType >= kExprVar_QuotedString;
429}
430
431
432/**
433 * Deletes a variable.
434 *
435 * @param pVar The variable.
436 */
437static void expr_var_delete(PEXPRVAR pVar)
438{
439 if (expr_var_is_string(pVar))
440 {
441 free(pVar->uVal.psz);
442 pVar->uVal.psz = NULL;
443 }
444 pVar->enmType = kExprVar_Invalid;
445}
446
447
448/**
449 * Initializes a new variables with a sub-string value.
450 *
451 * @param pVar The new variable.
452 * @param psz The start of the string value.
453 * @param cch The number of chars to copy.
454 * @param enmType The string type.
455 */
456static void expr_var_init_substring(PEXPRVAR pVar, const char *psz, size_t cch, EXPRVARTYPE enmType)
457{
458 /* convert string needing expanding into simple ones if possible. */
459 if ( enmType == kExprVar_String
460 && !memchr(psz, '$', cch))
461 enmType = kExprVar_SimpleString;
462 else if ( enmType == kExprVar_QuotedString
463 && !memchr(psz, '$', cch))
464 enmType = kExprVar_QuotedSimpleString;
465
466 pVar->enmType = enmType;
467 pVar->uVal.psz = xmalloc(cch + 1);
468 memcpy(pVar->uVal.psz, psz, cch);
469 pVar->uVal.psz[cch] = '\0';
470}
471
472
473#if 0 /* unused */
474/**
475 * Initializes a new variables with a string value.
476 *
477 * @param pVar The new variable.
478 * @param psz The string value.
479 * @param enmType The string type.
480 */
481static void expr_var_init_string(PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
482{
483 expr_var_init_substring(pVar, psz, strlen(psz), enmType);
484}
485
486
487/**
488 * Assigns a sub-string value to a variable.
489 *
490 * @param pVar The new variable.
491 * @param psz The start of the string value.
492 * @param cch The number of chars to copy.
493 * @param enmType The string type.
494 */
495static void expr_var_assign_substring(PEXPRVAR pVar, const char *psz, size_t cch, EXPRVARTYPE enmType)
496{
497 expr_var_delete(pVar);
498 expr_var_init_substring(pVar, psz, cch, enmType);
499}
500
501
502/**
503 * Assignes a string value to a variable.
504 *
505 * @param pVar The variable.
506 * @param psz The string value.
507 * @param enmType The string type.
508 */
509static void expr_var_assign_string(PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
510{
511 expr_var_delete(pVar);
512 expr_var_init_string(pVar, psz, enmType);
513}
514#endif /* unused */
515
516
517/**
518 * Simplifies a string variable.
519 *
520 * @param pVar The variable.
521 */
522static void expr_var_make_simple_string(PEXPRVAR pVar)
523{
524 switch (pVar->enmType)
525 {
526 case kExprVar_Num:
527 {
528 char *psz = (char *)xmalloc(EXPR_NUM_LEN);
529 expr_num_to_string(psz, pVar->uVal.i);
530 pVar->uVal.psz = psz;
531 pVar->enmType = kExprVar_SimpleString;
532 break;
533 }
534
535 case kExprVar_String:
536 case kExprVar_QuotedString:
537 {
538 char *psz;
539 assert(strchr(pVar->uVal.psz, '$'));
540
541 psz = allocated_variable_expand(pVar->uVal.psz);
542 free(pVar->uVal.psz);
543 pVar->uVal.psz = psz;
544
545 pVar->enmType = pVar->enmType == kExprVar_String
546 ? kExprVar_SimpleString
547 : kExprVar_QuotedSimpleString;
548 break;
549 }
550
551 case kExprVar_SimpleString:
552 case kExprVar_QuotedSimpleString:
553 /* nothing to do. */
554 break;
555
556 default:
557 assert(0);
558 }
559}
560
561
562#if 0 /* unused */
563/**
564 * Turns a variable into a string value.
565 *
566 * @param pVar The variable.
567 */
568static void expr_var_make_string(PEXPRVAR pVar)
569{
570 switch (pVar->enmType)
571 {
572 case kExprVar_Num:
573 expr_var_make_simple_string(pVar);
574 break;
575
576 case kExprVar_String:
577 case kExprVar_SimpleString:
578 case kExprVar_QuotedString:
579 case kExprVar_QuotedSimpleString:
580 /* nothing to do. */
581 break;
582
583 default:
584 assert(0);
585 }
586}
587#endif /* unused */
588
589
590/**
591 * Initializes a new variables with a integer value.
592 *
593 * @param pVar The new variable.
594 * @param i The integer value.
595 */
596static void expr_var_init_num(PEXPRVAR pVar, EXPRINT64 i)
597{
598 pVar->enmType = kExprVar_Num;
599 pVar->uVal.i = i;
600}
601
602
603/**
604 * Assigns a integer value to a variable.
605 *
606 * @param pVar The variable.
607 * @param i The integer value.
608 */
609static void expr_var_assign_num(PEXPRVAR pVar, EXPRINT64 i)
610{
611 expr_var_delete(pVar);
612 expr_var_init_num(pVar, i);
613}
614
615
616/**
617 * Turns the variable into a number.
618 *
619 * @returns status code.
620 * @param pThis The evaluator instance.
621 * @param pVar The variable.
622 */
623static EXPRRET expr_var_make_num(PEXPR pThis, PEXPRVAR pVar)
624{
625 switch (pVar->enmType)
626 {
627 case kExprVar_Num:
628 /* nothing to do. */
629 break;
630
631 case kExprVar_String:
632 expr_var_make_simple_string(pVar);
633 /* fall thru */
634 case kExprVar_SimpleString:
635 {
636 EXPRINT64 i;
637 EXPRRET rc = expr_string_to_num(pThis, &i, pVar->uVal.psz, 0 /* fQuiet */);
638 if (rc < kExprRet_Ok)
639 return rc;
640 expr_var_assign_num(pVar, i);
641 break;
642 }
643
644 case kExprVar_QuotedString:
645 case kExprVar_QuotedSimpleString:
646 expr_error(pThis, "Cannot convert a quoted string to a number");
647 return kExprRet_Error;
648
649 default:
650 assert(0);
651 return kExprRet_Error;
652 }
653
654 return kExprRet_Ok;
655}
656
657
658/**
659 * Try to turn the variable into a number.
660 *
661 * @returns status code.
662 * @param pVar The variable.
663 */
664static EXPRRET expr_var_try_make_num(PEXPRVAR pVar)
665{
666 switch (pVar->enmType)
667 {
668 case kExprVar_Num:
669 /* nothing to do. */
670 break;
671
672 case kExprVar_String:
673 expr_var_make_simple_string(pVar);
674 /* fall thru */
675 case kExprVar_SimpleString:
676 {
677 EXPRINT64 i;
678 EXPRRET rc = expr_string_to_num(NULL, &i, pVar->uVal.psz, 1 /* fQuiet */);
679 if (rc < kExprRet_Ok)
680 return rc;
681 expr_var_assign_num(pVar, i);
682 break;
683 }
684
685 default:
686 assert(0);
687 case kExprVar_QuotedString:
688 case kExprVar_QuotedSimpleString:
689 /* can't do this */
690 return kExprRet_Error;
691 }
692
693 return kExprRet_Ok;
694}
695
696
697/**
698 * Initializes a new variables with a boolean value.
699 *
700 * @param pVar The new variable.
701 * @param f The boolean value.
702 */
703static void expr_var_init_bool(PEXPRVAR pVar, int f)
704{
705 pVar->enmType = kExprVar_Num;
706 pVar->uVal.i = !!f;
707}
708
709
710/**
711 * Assigns a boolean value to a variable.
712 *
713 * @param pVar The variable.
714 * @param f The boolean value.
715 */
716static void expr_var_assign_bool(PEXPRVAR pVar, int f)
717{
718 expr_var_delete(pVar);
719 expr_var_init_bool(pVar, f);
720}
721
722
723/**
724 * Turns the variable into an boolean.
725 *
726 * @returns the boolean interpretation.
727 * @param pVar The variable.
728 */
729static int expr_var_make_bool(PEXPRVAR pVar)
730{
731 switch (pVar->enmType)
732 {
733 case kExprVar_Num:
734 pVar->uVal.i = !!pVar->uVal.i;
735 break;
736
737 case kExprVar_String:
738 expr_var_make_simple_string(pVar);
739 /* fall thru */
740 case kExprVar_SimpleString:
741 {
742 /*
743 * Try convert it to a number. If that fails, use the
744 * GNU make boolean logic - not empty string means true.
745 */
746 EXPRINT64 iVal;
747 char const *psz = pVar->uVal.psz;
748 while (isblank((unsigned char)*psz))
749 psz++;
750 if ( *psz
751 && expr_string_to_num(NULL, &iVal, psz, 1 /* fQuiet */) >= kExprRet_Ok)
752 expr_var_assign_bool(pVar, iVal != 0);
753 else
754 expr_var_assign_bool(pVar, *psz != '\0');
755 break;
756 }
757
758 case kExprVar_QuotedString:
759 expr_var_make_simple_string(pVar);
760 /* fall thru */
761 case kExprVar_QuotedSimpleString:
762 /*
763 * Use GNU make boolean logic (not empty string means true).
764 * No stripping here, the string is quoted.
765 */
766 expr_var_assign_bool(pVar, *pVar->uVal.psz != '\0');
767 break;
768
769 default:
770 assert(0);
771 break;
772 }
773
774 return pVar->uVal.i;
775}
776
777
778/**
779 * Pops a varable off the stack and deletes it.
780 * @param pThis The evaluator instance.
781 */
782static void expr_pop_and_delete_var(PEXPR pThis)
783{
784 expr_var_delete(&pThis->aVars[pThis->iVar]);
785 pThis->iVar--;
786}
787
788
789
790/**
791 * Tries to make the variables the same type.
792 *
793 * This will not convert numbers to strings, unless one of them
794 * is a quoted string.
795 *
796 * this will try convert both to numbers if neither is quoted. Both
797 * conversions will have to suceed for this to be commited.
798 *
799 * All strings will be simplified.
800 *
801 * @returns status code. Done complaining on failure.
802 *
803 * @param pThis The evaluator instance.
804 * @param pVar1 The first variable.
805 * @param pVar2 The second variable.
806 */
807static EXPRRET expr_var_unify_types(PEXPR pThis, PEXPRVAR pVar1, PEXPRVAR pVar2, const char *pszOp)
808{
809 /*
810 * Try make the variables the same type before comparing.
811 */
812 if ( !expr_var_was_quoted(pVar1)
813 && !expr_var_was_quoted(pVar2))
814 {
815 if ( expr_var_is_string(pVar1)
816 || expr_var_is_string(pVar2))
817 {
818 if (!expr_var_is_string(pVar1))
819 expr_var_try_make_num(pVar2);
820 else if (!expr_var_is_string(pVar2))
821 expr_var_try_make_num(pVar1);
822 else
823 {
824 /*
825 * Both are strings, simplify them then see if both can be made into numbers.
826 */
827 EXPRINT64 iVar1;
828 EXPRINT64 iVar2;
829
830 expr_var_make_simple_string(pVar1);
831 expr_var_make_simple_string(pVar2);
832
833 if ( expr_string_to_num(NULL, &iVar1, pVar1->uVal.psz, 1 /* fQuiet */) >= kExprRet_Ok
834 && expr_string_to_num(NULL, &iVar2, pVar2->uVal.psz, 1 /* fQuiet */) >= kExprRet_Ok)
835 {
836 expr_var_assign_num(pVar1, iVar1);
837 expr_var_assign_num(pVar2, iVar2);
838 }
839 }
840 }
841 }
842 else
843 {
844 expr_var_make_simple_string(pVar1);
845 expr_var_make_simple_string(pVar2);
846 }
847
848 /*
849 * Complain if they aren't the same type now.
850 */
851 if (expr_var_is_string(pVar1) != expr_var_is_string(pVar2))
852 {
853 expr_error(pThis, "Unable to unify types for \"%s\"", pszOp);
854 return kExprRet_Error;
855 }
856 return kExprRet_Ok;
857}
858
859
860/**
861 * Is variable defined, unary.
862 *
863 * @returns Status code.
864 * @param pThis The instance.
865 */
866static EXPRRET expr_op_defined(PEXPR pThis)
867{
868 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
869 struct variable *pMakeVar;
870
871 expr_var_make_simple_string(pVar);
872 pMakeVar = lookup_variable(pVar->uVal.psz, strlen(pVar->uVal.psz));
873 expr_var_assign_bool(pVar, pMakeVar && *pMakeVar->value != '\0');
874
875 return kExprRet_Ok;
876}
877
878
879/**
880 * Is target defined, unary.
881 *
882 * @returns Status code.
883 * @param pThis The instance.
884 */
885static EXPRRET expr_op_target(PEXPR pThis)
886{
887 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
888 struct file *pFile = NULL;
889
890 /*
891 * Because of secondary target expansion, lookup the unexpanded
892 * name first.
893 */
894#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
895 if ( pVar->enmType == kExprVar_String
896 || pVar->enmType == kExprVar_QuotedString)
897 {
898 pFile = lookup_file(pVar->uVal.psz);
899 if ( pFile
900 && !pFile->need_2nd_target_expansion)
901 pFile = NULL;
902 }
903 if (!pFile)
904#endif
905 {
906 expr_var_make_simple_string(pVar);
907 pFile = lookup_file(pVar->uVal.psz);
908 }
909
910 /*
911 * Always inspect the head of a multiple target rule
912 * and look for a file with commands.
913 */
914#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
915 if (pFile && pFile->multi_head)
916 pFile = pFile->multi_head;
917#endif
918
919 while (pFile && !pFile->cmds)
920 pFile = pFile->prev;
921
922 expr_var_assign_bool(pVar, pFile != NULL && pFile->is_target);
923
924 return kExprRet_Ok;
925}
926
927
928/**
929 * Convert to boolean.
930 *
931 * @returns Status code.
932 * @param pThis The instance.
933 */
934static EXPRRET expr_op_bool(PEXPR pThis)
935{
936 expr_var_make_bool(&pThis->aVars[pThis->iVar]);
937 return kExprRet_Ok;
938}
939
940
941/**
942 * Convert to number, works on quoted strings too.
943 *
944 * @returns Status code.
945 * @param pThis The instance.
946 */
947static EXPRRET expr_op_num(PEXPR pThis)
948{
949 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
950
951 /* unquote the string */
952 if (pVar->enmType == kExprVar_QuotedSimpleString)
953 pVar->enmType = kExprVar_SimpleString;
954 else if (pVar->enmType == kExprVar_QuotedString)
955 pVar->enmType = kExprVar_String;
956
957 return expr_var_make_num(pThis, pVar);
958}
959
960
961/**
962 * Convert to string (simplified and quoted)
963 *
964 * @returns Status code.
965 * @param pThis The instance.
966 */
967static EXPRRET expr_op_str(PEXPR pThis)
968{
969 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
970
971 expr_var_make_simple_string(pVar);
972 pVar->enmType = kExprVar_QuotedSimpleString;
973
974 return kExprRet_Ok;
975}
976
977
978/**
979 * Pluss (dummy / make_integer)
980 *
981 * @returns Status code.
982 * @param pThis The instance.
983 */
984static EXPRRET expr_op_pluss(PEXPR pThis)
985{
986 return expr_var_make_num(pThis, &pThis->aVars[pThis->iVar]);
987}
988
989
990/**
991 * Minus (negate)
992 *
993 * @returns Status code.
994 * @param pThis The instance.
995 */
996static EXPRRET expr_op_minus(PEXPR pThis)
997{
998 EXPRRET rc;
999 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
1000
1001 rc = expr_var_make_num(pThis, pVar);
1002 if (rc >= kExprRet_Ok)
1003 pVar->uVal.i = -pVar->uVal.i;
1004
1005 return rc;
1006}
1007
1008
1009
1010/**
1011 * Bitwise NOT.
1012 *
1013 * @returns Status code.
1014 * @param pThis The instance.
1015 */
1016static EXPRRET expr_op_bitwise_not(PEXPR pThis)
1017{
1018 EXPRRET rc;
1019 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
1020
1021 rc = expr_var_make_num(pThis, pVar);
1022 if (rc >= kExprRet_Ok)
1023 pVar->uVal.i = ~pVar->uVal.i;
1024
1025 return rc;
1026}
1027
1028
1029/**
1030 * Logical NOT.
1031 *
1032 * @returns Status code.
1033 * @param pThis The instance.
1034 */
1035static EXPRRET expr_op_logical_not(PEXPR pThis)
1036{
1037 PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
1038
1039 expr_var_make_bool(pVar);
1040 pVar->uVal.i = !pVar->uVal.i;
1041
1042 return kExprRet_Ok;
1043}
1044
1045
1046/**
1047 * Multiplication.
1048 *
1049 * @returns Status code.
1050 * @param pThis The instance.
1051 */
1052static EXPRRET expr_op_multiply(PEXPR pThis)
1053{
1054 EXPRRET rc = kExprRet_Ok;
1055 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1056 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1057
1058 rc = expr_var_make_num(pThis, pVar1);
1059 if (rc >= kExprRet_Ok)
1060 {
1061 rc = expr_var_make_num(pThis, pVar2);
1062 if (rc >= kExprRet_Ok)
1063 pVar1->uVal.i *= pVar2->uVal.i;
1064 }
1065
1066 expr_pop_and_delete_var(pThis);
1067 return rc;
1068}
1069
1070
1071
1072/**
1073 * Division.
1074 *
1075 * @returns Status code.
1076 * @param pThis The instance.
1077 */
1078static EXPRRET expr_op_divide(PEXPR pThis)
1079{
1080 EXPRRET rc = kExprRet_Ok;
1081 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1082 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1083
1084 rc = expr_var_make_num(pThis, pVar1);
1085 if (rc >= kExprRet_Ok)
1086 {
1087 rc = expr_var_make_num(pThis, pVar2);
1088 if (rc >= kExprRet_Ok)
1089 pVar1->uVal.i /= pVar2->uVal.i;
1090 }
1091
1092 expr_pop_and_delete_var(pThis);
1093 return rc;
1094}
1095
1096
1097
1098/**
1099 * Modulus.
1100 *
1101 * @returns Status code.
1102 * @param pThis The instance.
1103 */
1104static EXPRRET expr_op_modulus(PEXPR pThis)
1105{
1106 EXPRRET rc = kExprRet_Ok;
1107 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1108 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1109
1110 rc = expr_var_make_num(pThis, pVar1);
1111 if (rc >= kExprRet_Ok)
1112 {
1113 rc = expr_var_make_num(pThis, pVar2);
1114 if (rc >= kExprRet_Ok)
1115 pVar1->uVal.i %= pVar2->uVal.i;
1116 }
1117
1118 expr_pop_and_delete_var(pThis);
1119 return rc;
1120}
1121
1122
1123
1124/**
1125 * Addition (numeric).
1126 *
1127 * @returns Status code.
1128 * @param pThis The instance.
1129 */
1130static EXPRRET expr_op_add(PEXPR pThis)
1131{
1132 EXPRRET rc = kExprRet_Ok;
1133 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1134 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1135
1136 rc = expr_var_make_num(pThis, pVar1);
1137 if (rc >= kExprRet_Ok)
1138 {
1139 rc = expr_var_make_num(pThis, pVar2);
1140 if (rc >= kExprRet_Ok)
1141 pVar1->uVal.i += pVar2->uVal.i;
1142 }
1143
1144 expr_pop_and_delete_var(pThis);
1145 return rc;
1146}
1147
1148
1149/**
1150 * Subtract (numeric).
1151 *
1152 * @returns Status code.
1153 * @param pThis The instance.
1154 */
1155static EXPRRET expr_op_sub(PEXPR pThis)
1156{
1157 EXPRRET rc = kExprRet_Ok;
1158 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1159 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1160
1161 rc = expr_var_make_num(pThis, pVar1);
1162 if (rc >= kExprRet_Ok)
1163 {
1164 rc = expr_var_make_num(pThis, pVar2);
1165 if (rc >= kExprRet_Ok)
1166 pVar1->uVal.i -= pVar2->uVal.i;
1167 }
1168
1169 expr_pop_and_delete_var(pThis);
1170 return rc;
1171}
1172
1173/**
1174 * Bitwise left shift.
1175 *
1176 * @returns Status code.
1177 * @param pThis The instance.
1178 */
1179static EXPRRET expr_op_shift_left(PEXPR pThis)
1180{
1181 EXPRRET rc = kExprRet_Ok;
1182 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1183 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1184
1185 rc = expr_var_make_num(pThis, pVar1);
1186 if (rc >= kExprRet_Ok)
1187 {
1188 rc = expr_var_make_num(pThis, pVar2);
1189 if (rc >= kExprRet_Ok)
1190 pVar1->uVal.i <<= pVar2->uVal.i;
1191 }
1192
1193 expr_pop_and_delete_var(pThis);
1194 return rc;
1195}
1196
1197
1198/**
1199 * Bitwise right shift.
1200 *
1201 * @returns Status code.
1202 * @param pThis The instance.
1203 */
1204static EXPRRET expr_op_shift_right(PEXPR pThis)
1205{
1206 EXPRRET rc = kExprRet_Ok;
1207 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1208 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1209
1210 rc = expr_var_make_num(pThis, pVar1);
1211 if (rc >= kExprRet_Ok)
1212 {
1213 rc = expr_var_make_num(pThis, pVar2);
1214 if (rc >= kExprRet_Ok)
1215 pVar1->uVal.i >>= pVar2->uVal.i;
1216 }
1217
1218 expr_pop_and_delete_var(pThis);
1219 return rc;
1220}
1221
1222
1223/**
1224 * Less than or equal
1225 *
1226 * @returns Status code.
1227 * @param pThis The instance.
1228 */
1229static EXPRRET expr_op_less_or_equal_than(PEXPR pThis)
1230{
1231 EXPRRET rc = kExprRet_Ok;
1232 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1233 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1234
1235 rc = expr_var_unify_types(pThis, pVar1, pVar2, "<=");
1236 if (rc >= kExprRet_Ok)
1237 {
1238 if (!expr_var_is_string(pVar1))
1239 expr_var_assign_bool(pVar1, pVar1->uVal.i <= pVar2->uVal.i);
1240 else
1241 expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) <= 0);
1242 }
1243
1244 expr_pop_and_delete_var(pThis);
1245 return rc;
1246}
1247
1248
1249/**
1250 * Less than.
1251 *
1252 * @returns Status code.
1253 * @param pThis The instance.
1254 */
1255static EXPRRET expr_op_less_than(PEXPR pThis)
1256{
1257 EXPRRET rc = kExprRet_Ok;
1258 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1259 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1260
1261 rc = expr_var_unify_types(pThis, pVar1, pVar2, "<");
1262 if (rc >= kExprRet_Ok)
1263 {
1264 if (!expr_var_is_string(pVar1))
1265 expr_var_assign_bool(pVar1, pVar1->uVal.i < pVar2->uVal.i);
1266 else
1267 expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) < 0);
1268 }
1269
1270 expr_pop_and_delete_var(pThis);
1271 return rc;
1272}
1273
1274
1275/**
1276 * Greater or equal than
1277 *
1278 * @returns Status code.
1279 * @param pThis The instance.
1280 */
1281static EXPRRET expr_op_greater_or_equal_than(PEXPR pThis)
1282{
1283 EXPRRET rc = kExprRet_Ok;
1284 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1285 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1286
1287 rc = expr_var_unify_types(pThis, pVar1, pVar2, ">=");
1288 if (rc >= kExprRet_Ok)
1289 {
1290 if (!expr_var_is_string(pVar1))
1291 expr_var_assign_bool(pVar1, pVar1->uVal.i >= pVar2->uVal.i);
1292 else
1293 expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) >= 0);
1294 }
1295
1296 expr_pop_and_delete_var(pThis);
1297 return rc;
1298}
1299
1300
1301/**
1302 * Greater than.
1303 *
1304 * @returns Status code.
1305 * @param pThis The instance.
1306 */
1307static EXPRRET expr_op_greater_than(PEXPR pThis)
1308{
1309 EXPRRET rc = kExprRet_Ok;
1310 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1311 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1312
1313 rc = expr_var_unify_types(pThis, pVar1, pVar2, ">");
1314 if (rc >= kExprRet_Ok)
1315 {
1316 if (!expr_var_is_string(pVar1))
1317 expr_var_assign_bool(pVar1, pVar1->uVal.i > pVar2->uVal.i);
1318 else
1319 expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) > 0);
1320 }
1321
1322 expr_pop_and_delete_var(pThis);
1323 return rc;
1324}
1325
1326
1327/**
1328 * Equal.
1329 *
1330 * @returns Status code.
1331 * @param pThis The instance.
1332 */
1333static EXPRRET expr_op_equal(PEXPR pThis)
1334{
1335 EXPRRET rc = kExprRet_Ok;
1336 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1337 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1338
1339 /*
1340 * The same type?
1341 */
1342 if (expr_var_is_string(pVar1) == expr_var_is_string(pVar2))
1343 {
1344 if (!expr_var_is_string(pVar1))
1345 /* numbers are simple */
1346 expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
1347 else
1348 {
1349 /* try a normal string compare. */
1350 expr_var_make_simple_string(pVar1);
1351 expr_var_make_simple_string(pVar2);
1352 if (!strcmp(pVar1->uVal.psz, pVar2->uVal.psz))
1353 expr_var_assign_bool(pVar1, 1);
1354 /* try convert and compare as number instead. */
1355 else if ( expr_var_try_make_num(pVar1) >= kExprRet_Ok
1356 && expr_var_try_make_num(pVar2) >= kExprRet_Ok)
1357 expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
1358 /* ok, they really aren't equal. */
1359 else
1360 expr_var_assign_bool(pVar1, 0);
1361 }
1362 }
1363 else
1364 {
1365 /*
1366 * If the type differs, there are now two options:
1367 * 1. Convert the string to a valid number and compare the numbers.
1368 * 2. Convert an empty string to a 'false' boolean value and compare
1369 * numerically. This one is a bit questionable, so we don't try this.
1370 */
1371 if ( expr_var_try_make_num(pVar1) >= kExprRet_Ok
1372 && expr_var_try_make_num(pVar2) >= kExprRet_Ok)
1373 expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
1374 else
1375 {
1376 expr_error(pThis, "Cannot compare strings and numbers");
1377 rc = kExprRet_Error;
1378 }
1379 }
1380
1381 expr_pop_and_delete_var(pThis);
1382 return kExprRet_Ok;
1383}
1384
1385
1386/**
1387 * Not equal.
1388 *
1389 * @returns Status code.
1390 * @param pThis The instance.
1391 */
1392static EXPRRET expr_op_not_equal(PEXPR pThis)
1393{
1394 EXPRRET rc = expr_op_equal(pThis);
1395 if (rc >= kExprRet_Ok)
1396 rc = expr_op_logical_not(pThis);
1397 return rc;
1398}
1399
1400
1401/**
1402 * Bitwise AND.
1403 *
1404 * @returns Status code.
1405 * @param pThis The instance.
1406 */
1407static EXPRRET expr_op_bitwise_and(PEXPR pThis)
1408{
1409 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1410 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1411 EXPRRET rc;
1412
1413 rc = expr_var_make_num(pThis, pVar1);
1414 if (rc >= kExprRet_Ok)
1415 {
1416 rc = expr_var_make_num(pThis, pVar2);
1417 if (rc >= kExprRet_Ok)
1418 pVar1->uVal.i &= pVar2->uVal.i;
1419 }
1420
1421 expr_pop_and_delete_var(pThis);
1422 return kExprRet_Ok;
1423}
1424
1425
1426/**
1427 * Bitwise XOR.
1428 *
1429 * @returns Status code.
1430 * @param pThis The instance.
1431 */
1432static EXPRRET expr_op_bitwise_xor(PEXPR pThis)
1433{
1434 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1435 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1436 EXPRRET rc;
1437
1438 rc = expr_var_make_num(pThis, pVar1);
1439 if (rc >= kExprRet_Ok)
1440 {
1441 rc = expr_var_make_num(pThis, pVar2);
1442 if (rc >= kExprRet_Ok)
1443 pVar1->uVal.i ^= pVar2->uVal.i;
1444 }
1445
1446 expr_pop_and_delete_var(pThis);
1447 return kExprRet_Ok;
1448}
1449
1450
1451/**
1452 * Bitwise OR.
1453 *
1454 * @returns Status code.
1455 * @param pThis The instance.
1456 */
1457static EXPRRET expr_op_bitwise_or(PEXPR pThis)
1458{
1459 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1460 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1461 EXPRRET rc;
1462
1463 rc = expr_var_make_num(pThis, pVar1);
1464 if (rc >= kExprRet_Ok)
1465 {
1466 rc = expr_var_make_num(pThis, pVar2);
1467 if (rc >= kExprRet_Ok)
1468 pVar1->uVal.i |= pVar2->uVal.i;
1469 }
1470
1471 expr_pop_and_delete_var(pThis);
1472 return kExprRet_Ok;
1473}
1474
1475
1476/**
1477 * Logical AND.
1478 *
1479 * @returns Status code.
1480 * @param pThis The instance.
1481 */
1482static EXPRRET expr_op_logical_and(PEXPR pThis)
1483{
1484 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1485 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1486
1487 if ( expr_var_make_bool(pVar1)
1488 && expr_var_make_bool(pVar2))
1489 expr_var_assign_bool(pVar1, 1);
1490 else
1491 expr_var_assign_bool(pVar1, 0);
1492
1493 expr_pop_and_delete_var(pThis);
1494 return kExprRet_Ok;
1495}
1496
1497
1498/**
1499 * Logical OR.
1500 *
1501 * @returns Status code.
1502 * @param pThis The instance.
1503 */
1504static EXPRRET expr_op_logical_or(PEXPR pThis)
1505{
1506 PEXPRVAR pVar1 = &pThis->aVars[pThis->iVar - 1];
1507 PEXPRVAR pVar2 = &pThis->aVars[pThis->iVar];
1508
1509 if ( expr_var_make_bool(pVar1)
1510 || expr_var_make_bool(pVar2))
1511 expr_var_assign_bool(pVar1, 1);
1512 else
1513 expr_var_assign_bool(pVar1, 0);
1514
1515 expr_pop_and_delete_var(pThis);
1516 return kExprRet_Ok;
1517}
1518
1519
1520/**
1521 * Left parenthesis.
1522 *
1523 * @returns Status code.
1524 * @param pThis The instance.
1525 */
1526static EXPRRET expr_op_left_parenthesis(PEXPR pThis)
1527{
1528 /*
1529 * There should be a right parenthesis operator lined up for us now,
1530 * eat it. If not found there is an inbalance.
1531 */
1532 EXPRRET rc = expr_get_binary_or_eoe_or_rparen(pThis);
1533 if ( rc == kExprRet_Operator
1534 && pThis->apOps[pThis->iOp]->szOp[0] == ')')
1535 {
1536 /* pop it and get another one which we can leave pending. */
1537 pThis->iOp--;
1538 rc = expr_get_binary_or_eoe_or_rparen(pThis);
1539 if (rc >= kExprRet_Ok)
1540 expr_unget_op(pThis);
1541 }
1542 else
1543 {
1544 expr_error(pThis, "Missing ')'");
1545 rc = kExprRet_Error;
1546 }
1547
1548 return rc;
1549}
1550
1551
1552/**
1553 * Right parenthesis, dummy that's never actually called.
1554 *
1555 * @returns Status code.
1556 * @param pThis The instance.
1557 */
1558static EXPRRET expr_op_right_parenthesis(PEXPR pThis)
1559{
1560 assert(0);
1561 (void)pThis;
1562 return kExprRet_Ok;
1563}
1564
1565
1566
1567
1568
1569/**
1570 * The operator table.
1571 *
1572 * This table is NOT ordered by precedence, but for linear search
1573 * allowing for first match to return the correct operator. This
1574 * means that || must come before |, or else | will match all.
1575 */
1576static const EXPROP g_aExprOps[] =
1577{
1578#define EXPR_OP(szOp, iPrecedence, cArgs, pfn) { szOp, sizeof(szOp) - 1, '\0', iPrecedence, cArgs, pfn }
1579 /* Name, iPrecedence, cArgs, pfn */
1580 EXPR_OP("defined", 90, 1, expr_op_defined),
1581 EXPR_OP("target", 90, 1, expr_op_target),
1582 EXPR_OP("bool", 90, 1, expr_op_bool),
1583 EXPR_OP("num", 90, 1, expr_op_num),
1584 EXPR_OP("str", 90, 1, expr_op_str),
1585 EXPR_OP("+", 80, 1, expr_op_pluss),
1586 EXPR_OP("-", 80, 1, expr_op_minus),
1587 EXPR_OP("~", 80, 1, expr_op_bitwise_not),
1588 EXPR_OP("*", 75, 2, expr_op_multiply),
1589 EXPR_OP("/", 75, 2, expr_op_divide),
1590 EXPR_OP("%", 75, 2, expr_op_modulus),
1591 EXPR_OP("+", 70, 2, expr_op_add),
1592 EXPR_OP("-", 70, 2, expr_op_sub),
1593 EXPR_OP("<<", 65, 2, expr_op_shift_left),
1594 EXPR_OP(">>", 65, 2, expr_op_shift_right),
1595 EXPR_OP("<=", 60, 2, expr_op_less_or_equal_than),
1596 EXPR_OP("<", 60, 2, expr_op_less_than),
1597 EXPR_OP(">=", 60, 2, expr_op_greater_or_equal_than),
1598 EXPR_OP(">", 60, 2, expr_op_greater_than),
1599 EXPR_OP("==", 55, 2, expr_op_equal),
1600 EXPR_OP("!=", 55, 2, expr_op_not_equal),
1601 EXPR_OP("!", 80, 1, expr_op_logical_not),
1602 EXPR_OP("^", 45, 2, expr_op_bitwise_xor),
1603 EXPR_OP("&&", 35, 2, expr_op_logical_and),
1604 EXPR_OP("&", 50, 2, expr_op_bitwise_and),
1605 EXPR_OP("||", 30, 2, expr_op_logical_or),
1606 EXPR_OP("|", 40, 2, expr_op_bitwise_or),
1607 { "(", 1, ')', 10, 1, expr_op_left_parenthesis },
1608 { ")", 1, '(', 10, 0, expr_op_right_parenthesis },
1609 /* { "?", 1, ':', 5, 2, expr_op_question },
1610 { ":", 1, '?', 5, 2, expr_op_colon }, -- too weird for now. */
1611#undef EXPR_OP
1612};
1613
1614/** Dummy end of expression fake. */
1615static const EXPROP g_ExprEndOfExpOp =
1616{
1617 "", 0, '\0', 0, 0, NULL
1618};
1619
1620
1621/**
1622 * Initializes the opcode character map if necessary.
1623 */
1624static void expr_map_init(void)
1625{
1626 unsigned i;
1627 if (g_fExprInitializedMap)
1628 return;
1629
1630 /*
1631 * Initialize it.
1632 */
1633 memset(&g_auchOpStartCharMap, 0, sizeof(g_auchOpStartCharMap));
1634 for (i = 0; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
1635 {
1636 unsigned int ch = (unsigned int)g_aExprOps[i].szOp[0];
1637 if (!g_auchOpStartCharMap[ch])
1638 g_auchOpStartCharMap[ch] = (i << 1) | 1;
1639 }
1640
1641 g_fExprInitializedMap = 1;
1642}
1643
1644
1645/**
1646 * Looks up a character in the map.
1647 *
1648 * @returns the value for that char.
1649 * @retval 0 if not a potential opcode start char.
1650 * @retval non-zero if it's a potential operator. The low bit is always set
1651 * while the remaining 7 bits is the index into the operator table
1652 * of the first match.
1653 *
1654 * @param ch The character.
1655 */
1656static unsigned char expr_map_get(char ch)
1657{
1658 return g_auchOpStartCharMap[(unsigned int)ch];
1659}
1660
1661
1662/**
1663 * Searches the operator table given a potential operator start char.
1664 *
1665 * @returns Pointer to the matching operator. NULL if not found.
1666 * @param psz Pointer to what can be an operator.
1667 * @param uchVal The expr_map_get value.
1668 * @param fUnary Whether it must be an unary operator or not.
1669 */
1670static PCEXPROP expr_lookup_op(char const *psz, unsigned char uchVal, int fUnary)
1671{
1672 char ch = *psz;
1673 unsigned i;
1674
1675 for (i = uchVal >> 1; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
1676 {
1677 /* compare the string... */
1678 switch (g_aExprOps[i].cchOp)
1679 {
1680 case 1:
1681 if (g_aExprOps[i].szOp[0] != ch)
1682 continue;
1683 break;
1684 case 2:
1685 if ( g_aExprOps[i].szOp[0] != ch
1686 || g_aExprOps[i].szOp[1] != psz[1])
1687 continue;
1688 break;
1689 default:
1690 if ( g_aExprOps[i].szOp[0] != ch
1691 || strncmp(&g_aExprOps[i].szOp[1], psz + 1, g_aExprOps[i].cchOp - 1))
1692 continue;
1693 break;
1694 }
1695
1696 /* ... and the operator type. */
1697 if (fUnary == (g_aExprOps[i].cArgs == 1))
1698 {
1699 /* got a match! */
1700 return &g_aExprOps[i];
1701 }
1702 }
1703
1704 return NULL;
1705}
1706
1707
1708/**
1709 * Ungets a binary operator.
1710 *
1711 * The operator is poped from the stack and put in the pending position.
1712 *
1713 * @param pThis The evaluator instance.
1714 */
1715static void expr_unget_op(PEXPR pThis)
1716{
1717 assert(pThis->pPending == NULL);
1718 assert(pThis->iOp >= 0);
1719
1720 pThis->pPending = pThis->apOps[pThis->iOp];
1721 pThis->apOps[pThis->iOp] = NULL;
1722 pThis->iOp--;
1723}
1724
1725
1726
1727/**
1728 * Get the next token, it should be a binary operator, or the end of
1729 * the expression, or a right parenthesis.
1730 *
1731 * The operator is pushed onto the stack and the status code indicates
1732 * which of the two we found.
1733 *
1734 * @returns status code. Will grumble on failure.
1735 * @retval kExprRet_EndOfExpr if we encountered the end of the expression.
1736 * @retval kExprRet_Operator if we encountered a binary operator or right
1737 * parenthesis. It's on the operator stack.
1738 *
1739 * @param pThis The evaluator instance.
1740 */
1741static EXPRRET expr_get_binary_or_eoe_or_rparen(PEXPR pThis)
1742{
1743 /*
1744 * See if there is anything pending first.
1745 */
1746 PCEXPROP pOp = pThis->pPending;
1747 if (pOp)
1748 pThis->pPending = NULL;
1749 else
1750 {
1751 /*
1752 * Eat more of the expression.
1753 */
1754 char const *psz = pThis->psz;
1755
1756 /* spaces */
1757 while (isspace((unsigned int)*psz))
1758 psz++;
1759 /* see what we've got. */
1760 if (*psz)
1761 {
1762 unsigned char uchVal = expr_map_get(*psz);
1763 if (uchVal)
1764 pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
1765 if (!pOp)
1766 {
1767 expr_error(pThis, "Expected binary operator, found \"%.42s\"...", psz);
1768 return kExprRet_Error;
1769 }
1770 psz += pOp->cchOp;
1771 }
1772 else
1773 pOp = &g_ExprEndOfExpOp;
1774 pThis->psz = psz;
1775 }
1776
1777 /*
1778 * Push it.
1779 */
1780 if (pThis->iOp >= EXPR_MAX_OPERATORS - 1)
1781 {
1782 expr_error(pThis, "Operator stack overflow");
1783 return kExprRet_Error;
1784 }
1785 pThis->apOps[++pThis->iOp] = pOp;
1786
1787 return pOp->iPrecedence
1788 ? kExprRet_Operator
1789 : kExprRet_EndOfExpr;
1790}
1791
1792
1793
1794/**
1795 * Get the next token, it should be an unary operator or an operand.
1796 *
1797 * This will fail if encountering the end of the expression since
1798 * it is implied that there should be something more.
1799 *
1800 * The token is pushed onto the respective stack and the status code
1801 * indicates which it is.
1802 *
1803 * @returns status code. On failure we'll be done bitching already.
1804 * @retval kExprRet_Operator if we encountered an unary operator.
1805 * It's on the operator stack.
1806 * @retval kExprRet_Operand if we encountered an operand operator.
1807 * It's on the operand stack.
1808 *
1809 * @param This The evaluator instance.
1810 */
1811static EXPRRET expr_get_unary_or_operand(PEXPR pThis)
1812{
1813 EXPRRET rc;
1814 unsigned char uchVal;
1815 PCEXPROP pOp;
1816 char const *psz = pThis->psz;
1817
1818 /*
1819 * Eat white space and make sure there is something after it.
1820 */
1821 while (isspace((unsigned int)*psz))
1822 psz++;
1823 if (!*psz)
1824 {
1825 expr_error(pThis, "Unexpected end of expression");
1826 return kExprRet_Error;
1827 }
1828
1829 /*
1830 * Is it an operator?
1831 */
1832 pOp = NULL;
1833 uchVal = expr_map_get(*psz);
1834 if (uchVal)
1835 pOp = expr_lookup_op(psz, uchVal, 1 /* fUnary */);
1836 if (pOp)
1837 {
1838 /*
1839 * Push the operator onto the stack.
1840 */
1841 if (pThis->iVar < EXPR_MAX_OPERANDS - 1)
1842 {
1843 pThis->apOps[++pThis->iOp] = pOp;
1844 rc = kExprRet_Operator;
1845 }
1846 else
1847 {
1848 expr_error(pThis, "Operator stack overflow");
1849 rc = kExprRet_Error;
1850 }
1851 psz += pOp->cchOp;
1852 }
1853 else if (pThis->iVar < EXPR_MAX_OPERANDS - 1)
1854 {
1855 /*
1856 * It's an operand. Figure out where it ends and
1857 * push it onto the stack.
1858 */
1859 const char *pszStart;
1860
1861 rc = kExprRet_Ok;
1862 if (*psz == '"')
1863 {
1864 pszStart = ++psz;
1865 while (*psz && *psz != '"')
1866 psz++;
1867 expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedString);
1868 if (*psz)
1869 psz++;
1870 }
1871 else if (*psz == '\'')
1872 {
1873 pszStart = ++psz;
1874 while (*psz && *psz != '\'')
1875 psz++;
1876 expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedSimpleString);
1877 if (*psz)
1878 psz++;
1879 }
1880 else
1881 {
1882 char achPars[20];
1883 int iPar = -1;
1884 char chEndPar = '\0';
1885 char ch;
1886
1887 pszStart = psz;
1888 while ((ch = *psz) != '\0')
1889 {
1890 /* $(adsf) or ${asdf} needs special handling. */
1891 if ( ch == '$'
1892 && ( psz[1] == '('
1893 || psz[1] == '{'))
1894 {
1895 psz++;
1896 if (iPar > (int)(sizeof(achPars) / sizeof(achPars[0])))
1897 {
1898 expr_error(pThis, "Too deep nesting of variable expansions");
1899 rc = kExprRet_Error;
1900 break;
1901 }
1902 achPars[++iPar] = chEndPar = ch == '(' ? ')' : '}';
1903 }
1904 else if (ch == chEndPar)
1905 {
1906 iPar--;
1907 chEndPar = iPar >= 0 ? achPars[iPar] : '\0';
1908 }
1909 else if (!chEndPar)
1910 {
1911 /** @todo combine isspace and expr_map_get! */
1912 unsigned chVal = expr_map_get(ch);
1913 if (chVal)
1914 {
1915 PCEXPROP pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
1916 if (pOp)
1917 break;
1918 }
1919 if (isspace((unsigned char)ch))
1920 break;
1921 }
1922
1923 /* next */
1924 psz++;
1925 }
1926
1927 if (rc == kExprRet_Ok)
1928 expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_String);
1929 }
1930 }
1931 else
1932 {
1933 expr_error(pThis, "Operand stack overflow");
1934 rc = kExprRet_Error;
1935 }
1936 pThis->psz = psz;
1937
1938 return rc;
1939}
1940
1941
1942/**
1943 * Evaluates the current expression.
1944 *
1945 * @returns status code.
1946 *
1947 * @param pThis The instance.
1948 */
1949static EXPRRET expr_eval(PEXPR pThis)
1950{
1951 EXPRRET rc;
1952 PCEXPROP pOp;
1953
1954 /*
1955 * The main loop.
1956 */
1957 for (;;)
1958 {
1959 /*
1960 * Eat unary operators until we hit an operand.
1961 */
1962 do rc = expr_get_unary_or_operand(pThis);
1963 while (rc == kExprRet_Operator);
1964 if (rc < kExprRet_Error)
1965 break;
1966
1967 /*
1968 * Look for a binary operator, right parenthesis or end of expression.
1969 */
1970 rc = expr_get_binary_or_eoe_or_rparen(pThis);
1971 if (rc < kExprRet_Error)
1972 break;
1973 expr_unget_op(pThis);
1974
1975 /*
1976 * Pop operators and apply them.
1977 *
1978 * Parenthesis will be handed via precedence, where the left parenthesis
1979 * will go pop the right one and make another operator pending.
1980 */
1981 while ( pThis->iOp >= 0
1982 && pThis->apOps[pThis->iOp]->iPrecedence >= pThis->pPending->iPrecedence)
1983 {
1984 pOp = pThis->apOps[pThis->iOp--];
1985 assert(pThis->iVar + 1 >= pOp->cArgs);
1986 rc = pOp->pfn(pThis);
1987 if (rc < kExprRet_Error)
1988 break;
1989 }
1990 if (rc < kExprRet_Error)
1991 break;
1992
1993 /*
1994 * Get the next binary operator or end of expression.
1995 * There should be no right parenthesis here.
1996 */
1997 rc = expr_get_binary_or_eoe_or_rparen(pThis);
1998 if (rc < kExprRet_Error)
1999 break;
2000 pOp = pThis->apOps[pThis->iOp];
2001 if (!pOp->iPrecedence)
2002 break; /* end of expression */
2003 if (!pOp->cArgs)
2004 {
2005 expr_error(pThis, "Unexpected \"%s\"", pOp->szOp);
2006 rc = kExprRet_Error;
2007 break;
2008 }
2009 }
2010
2011 return rc;
2012}
2013
2014
2015/**
2016 * Destroys the given instance.
2017 *
2018 * @param pThis The instance to destroy.
2019 */
2020static void expr_destroy(PEXPR pThis)
2021{
2022 while (pThis->iVar >= 0)
2023 {
2024 expr_var_delete(pThis->aVars);
2025 pThis->iVar--;
2026 }
2027 free(pThis);
2028}
2029
2030
2031/**
2032 * Instantiates an expression evaluator.
2033 *
2034 * @returns The instance.
2035 *
2036 * @param pszExpr What to parse.
2037 * This must stick around until expr_destroy.
2038 */
2039static PEXPR expr_create(char const *pszExpr)
2040{
2041 PEXPR pThis = (PEXPR)xmalloc(sizeof(*pThis));
2042 pThis->pszExpr = pszExpr;
2043 pThis->psz = pszExpr;
2044 pThis->pFileLoc = NULL;
2045 pThis->pPending = NULL;
2046 pThis->iVar = -1;
2047 pThis->iOp = -1;
2048
2049 expr_map_init();
2050 return pThis;
2051}
2052
2053
2054/**
2055 * Evaluates the given if expression.
2056 *
2057 * @returns -1, 0 or 1.
2058 * @retval -1 if the expression is invalid.
2059 * @retval 0 if the expression is true
2060 * @retval 1 if the expression is false.
2061 *
2062 * @param line The expression. Can modify this as we like.
2063 * @param flocp The file location, used for errors.
2064 */
2065int expr_eval_if_conditionals(char *line, const struct floc *flocp)
2066{
2067 /*
2068 * Instantiate the expression evaluator and let
2069 * it have a go at it.
2070 */
2071 int rc = -1;
2072 PEXPR pExpr = expr_create(line);
2073 pExpr->pFileLoc = flocp;
2074 if (expr_eval(pExpr) >= kExprRet_Ok)
2075 {
2076 /*
2077 * Convert the result (on top of the stack) to boolean and
2078 * set our return value accordingly.
2079 */
2080 if (expr_var_make_bool(&pExpr->aVars[0]))
2081 rc = 0;
2082 else
2083 rc = 1;
2084 }
2085 expr_destroy(pExpr);
2086
2087 return rc;
2088}
2089
2090
2091/**
2092 * Evaluates the given expression and returns the result as a string.
2093 *
2094 * @returns variable buffer position.
2095 *
2096 * @param o The current variable buffer position.
2097 * @param expr The expression.
2098 */
2099char *expr_eval_to_string(char *o, char *expr)
2100{
2101 /*
2102 * Instantiate the expression evaluator and let
2103 * it have a go at it.
2104 */
2105 PEXPR pExpr = expr_create(expr);
2106 if (expr_eval(pExpr) >= kExprRet_Ok)
2107 {
2108 /*
2109 * Convert the result (on top of the stack) to a string
2110 * and copy it out the variable buffer.
2111 */
2112 PEXPRVAR pVar = &pExpr->aVars[0];
2113 expr_var_make_simple_string(pVar);
2114 o = variable_buffer_output(o, pVar->uVal.psz, strlen(pVar->uVal.psz));
2115 }
2116 else
2117 o = variable_buffer_output(o, "<expression evaluation failed>", sizeof("<expression evaluation failed>") - 1);
2118 expr_destroy(pExpr);
2119
2120 return o;
2121}
2122
2123
2124#endif /* CONFIG_WITH_IF_CONDITIONALS */
2125
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette