VirtualBox

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

Last change on this file since 2074 was 2022, checked in by bird, 16 years ago

exprval.c: fixed bug parsing unqoted variable references ($(VAR) == $(VAR)). Converted ifcond testcases to the GNU Make tests and supplemented it with tests for this bug.

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