1 #ifdef CONFIG_WITH_IF_CONDITIONALS
2 /* $Id: expreval.c 3065 2017-09-30 12:52:35Z bird $ */
3 /** @file
4  * expreval - Expressions evaluator, C / BSD make / nmake style.
5  */
6 
7 /*
8  * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
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
67 typedef __int64 EXPRINT64;
68 #else
69 # include <stdint.h>
70 typedef int64_t EXPRINT64;
71 #endif
72 
73 /** Pointer to a evaluator instance. */
74 typedef struct EXPR *PEXPR;
75 
76 
77 /**
78  * Operand variable type.
79  */
80 typedef 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  */
101 typedef 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. */
115 typedef EXPRVAR *PEXPRVAR;
116 /** Pointer to a const operand variable. */
117 typedef EXPRVAR const *PCEXPRVAR;
118 
119 /**
120  * Operator return statuses.
121  */
122 typedef 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  */
135 typedef 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. */
152 typedef EXPROP const *PCEXPROP;
153 
154 /**
155  * Expression evaluator instance.
156  */
157 typedef 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. */
183 static char g_auchOpStartCharMap[256];
184 /** Whether we've initialized the map. */
185 static int g_fExprInitializedMap = 0;
186 
187 
188 /*******************************************************************************
189 *   Internal Functions                                                         *
190 *******************************************************************************/
191 static void expr_unget_op(PEXPR pThis);
192 static 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  */
expr_error(PEXPR pThis,const char * pszError,...)206 static 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  */
expr_num_to_string(char * pszDst,EXPRINT64 iSrc)226 static 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  */
expr_string_to_num(PEXPR pThis,EXPRINT64 * piDst,const char * pszSrc,int fQuiet)274 static 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 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  */
expr_var_is_string(PCEXPRVAR pVar)412 static 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  */
expr_var_was_quoted(PCEXPRVAR pVar)425 static 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  */
expr_var_delete(PEXPRVAR pVar)436 static 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  */
expr_var_init_substring(PEXPRVAR pVar,const char * psz,size_t cch,EXPRVARTYPE enmType)455 static 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  */
480 static 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  */
494 static 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  */
508 static 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  */
expr_var_make_simple_string(PEXPRVAR pVar)521 static 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  */
567 static 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  */
expr_var_init_num(PEXPRVAR pVar,EXPRINT64 i)595 static 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  */
expr_var_assign_num(PEXPRVAR pVar,EXPRINT64 i)608 static 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  */
expr_var_make_num(PEXPR pThis,PEXPRVAR pVar)622 static 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  */
expr_var_try_make_num(PEXPRVAR pVar)663 static 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  */
expr_var_init_bool(PEXPRVAR pVar,int f)702 static 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  */
expr_var_assign_bool(PEXPRVAR pVar,int f)715 static 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  */
expr_var_make_bool(PEXPRVAR pVar)728 static 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  */
expr_pop_and_delete_var(PEXPR pThis)781 static 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  */
expr_var_unify_types(PEXPR pThis,PEXPRVAR pVar1,PEXPRVAR pVar2,const char * pszOp)806 static 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  */
expr_op_defined(PEXPR pThis)865 static 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  * Does file(/dir/whatever) exist, unary.
880  *
881  * @returns Status code.
882  * @param   pThis       The instance.
883  */
expr_op_exists(PEXPR pThis)884 static EXPRRET expr_op_exists(PEXPR pThis)
885 {
886     PEXPRVAR            pVar = &pThis->aVars[pThis->iVar];
887     struct stat         st;
888 
889     expr_var_make_simple_string(pVar);
890     expr_var_assign_bool(pVar, stat(pVar->uVal.psz, &st) == 0);
891 
892     return kExprRet_Ok;
893 }
894 
895 
896 /**
897  * Is target defined, unary.
898  *
899  * @returns Status code.
900  * @param   pThis       The instance.
901  */
expr_op_target(PEXPR pThis)902 static EXPRRET expr_op_target(PEXPR pThis)
903 {
904     PEXPRVAR            pVar = &pThis->aVars[pThis->iVar];
905     struct file        *pFile = NULL;
906 
907     /*
908      * Because of secondary target expansion, lookup the unexpanded
909      * name first.
910      */
911 #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
912     if (    pVar->enmType == kExprVar_String
913         ||  pVar->enmType == kExprVar_QuotedString)
914     {
915         pFile = lookup_file(pVar->uVal.psz);
916         if (    pFile
917             &&  !pFile->need_2nd_target_expansion)
918             pFile = NULL;
919     }
920     if (!pFile)
921 #endif
922     {
923         expr_var_make_simple_string(pVar);
924         pFile = lookup_file(pVar->uVal.psz);
925     }
926 
927     /*
928      * Always inspect the head of a multiple target rule
929      * and look for a file with commands.
930      */
931 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
932     if (pFile && pFile->multi_head)
933         pFile = pFile->multi_head;
934 #endif
935 
936     while (pFile && !pFile->cmds)
937         pFile = pFile->prev;
938 
939     expr_var_assign_bool(pVar, pFile != NULL && pFile->is_target);
940 
941     return kExprRet_Ok;
942 }
943 
944 
945 /**
946  * Convert to boolean.
947  *
948  * @returns Status code.
949  * @param   pThis       The instance.
950  */
expr_op_bool(PEXPR pThis)951 static EXPRRET expr_op_bool(PEXPR pThis)
952 {
953     expr_var_make_bool(&pThis->aVars[pThis->iVar]);
954     return kExprRet_Ok;
955 }
956 
957 
958 /**
959  * Convert to number, works on quoted strings too.
960  *
961  * @returns Status code.
962  * @param   pThis       The instance.
963  */
expr_op_num(PEXPR pThis)964 static EXPRRET expr_op_num(PEXPR pThis)
965 {
966     PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
967 
968     /* unquote the string */
969     if (pVar->enmType == kExprVar_QuotedSimpleString)
970         pVar->enmType = kExprVar_SimpleString;
971     else if (pVar->enmType == kExprVar_QuotedString)
972         pVar->enmType = kExprVar_String;
973 
974     return expr_var_make_num(pThis, pVar);
975 }
976 
977 
978 /**
979  * Convert to string (simplified and quoted)
980  *
981  * @returns Status code.
982  * @param   pThis       The instance.
983  */
expr_op_str(PEXPR pThis)984 static EXPRRET expr_op_str(PEXPR pThis)
985 {
986     PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
987 
988     expr_var_make_simple_string(pVar);
989     pVar->enmType = kExprVar_QuotedSimpleString;
990 
991     return kExprRet_Ok;
992 }
993 
994 
995 /**
996  * Pluss (dummy / make_integer)
997  *
998  * @returns Status code.
999  * @param   pThis       The instance.
1000  */
expr_op_pluss(PEXPR pThis)1001 static EXPRRET expr_op_pluss(PEXPR pThis)
1002 {
1003     return expr_var_make_num(pThis, &pThis->aVars[pThis->iVar]);
1004 }
1005 
1006 
1007 /**
1008  * Minus (negate)
1009  *
1010  * @returns Status code.
1011  * @param   pThis       The instance.
1012  */
expr_op_minus(PEXPR pThis)1013 static EXPRRET expr_op_minus(PEXPR pThis)
1014 {
1015     EXPRRET     rc;
1016     PEXPRVAR    pVar = &pThis->aVars[pThis->iVar];
1017 
1018     rc = expr_var_make_num(pThis, pVar);
1019     if (rc >= kExprRet_Ok)
1020         pVar->uVal.i = -pVar->uVal.i;
1021 
1022     return rc;
1023 }
1024 
1025 
1026 
1027 /**
1028  * Bitwise NOT.
1029  *
1030  * @returns Status code.
1031  * @param   pThis       The instance.
1032  */
expr_op_bitwise_not(PEXPR pThis)1033 static EXPRRET expr_op_bitwise_not(PEXPR pThis)
1034 {
1035     EXPRRET     rc;
1036     PEXPRVAR    pVar = &pThis->aVars[pThis->iVar];
1037 
1038     rc = expr_var_make_num(pThis, pVar);
1039     if (rc >= kExprRet_Ok)
1040         pVar->uVal.i = ~pVar->uVal.i;
1041 
1042     return rc;
1043 }
1044 
1045 
1046 /**
1047  * Logical NOT.
1048  *
1049  * @returns Status code.
1050  * @param   pThis       The instance.
1051  */
expr_op_logical_not(PEXPR pThis)1052 static EXPRRET expr_op_logical_not(PEXPR pThis)
1053 {
1054     PEXPRVAR    pVar = &pThis->aVars[pThis->iVar];
1055 
1056     expr_var_make_bool(pVar);
1057     pVar->uVal.i = !pVar->uVal.i;
1058 
1059     return kExprRet_Ok;
1060 }
1061 
1062 
1063 /**
1064  * Multiplication.
1065  *
1066  * @returns Status code.
1067  * @param   pThis       The instance.
1068  */
expr_op_multiply(PEXPR pThis)1069 static EXPRRET expr_op_multiply(PEXPR pThis)
1070 {
1071     EXPRRET     rc = kExprRet_Ok;
1072     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1073     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1074 
1075     rc = expr_var_make_num(pThis, pVar1);
1076     if (rc >= kExprRet_Ok)
1077     {
1078         rc = expr_var_make_num(pThis, pVar2);
1079         if (rc >= kExprRet_Ok)
1080             pVar1->uVal.i *= pVar2->uVal.i;
1081     }
1082 
1083     expr_pop_and_delete_var(pThis);
1084     return rc;
1085 }
1086 
1087 
1088 
1089 /**
1090  * Division.
1091  *
1092  * @returns Status code.
1093  * @param   pThis       The instance.
1094  */
expr_op_divide(PEXPR pThis)1095 static EXPRRET expr_op_divide(PEXPR pThis)
1096 {
1097     EXPRRET     rc = kExprRet_Ok;
1098     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1099     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1100 
1101     rc = expr_var_make_num(pThis, pVar1);
1102     if (rc >= kExprRet_Ok)
1103     {
1104         rc = expr_var_make_num(pThis, pVar2);
1105         if (rc >= kExprRet_Ok)
1106             pVar1->uVal.i /= pVar2->uVal.i;
1107     }
1108 
1109     expr_pop_and_delete_var(pThis);
1110     return rc;
1111 }
1112 
1113 
1114 
1115 /**
1116  * Modulus.
1117  *
1118  * @returns Status code.
1119  * @param   pThis       The instance.
1120  */
expr_op_modulus(PEXPR pThis)1121 static EXPRRET expr_op_modulus(PEXPR pThis)
1122 {
1123     EXPRRET     rc = kExprRet_Ok;
1124     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1125     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1126 
1127     rc = expr_var_make_num(pThis, pVar1);
1128     if (rc >= kExprRet_Ok)
1129     {
1130         rc = expr_var_make_num(pThis, pVar2);
1131         if (rc >= kExprRet_Ok)
1132             pVar1->uVal.i %= pVar2->uVal.i;
1133     }
1134 
1135     expr_pop_and_delete_var(pThis);
1136     return rc;
1137 }
1138 
1139 
1140 
1141 /**
1142  * Addition (numeric).
1143  *
1144  * @returns Status code.
1145  * @param   pThis       The instance.
1146  */
expr_op_add(PEXPR pThis)1147 static EXPRRET expr_op_add(PEXPR pThis)
1148 {
1149     EXPRRET     rc = kExprRet_Ok;
1150     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1151     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1152 
1153     rc = expr_var_make_num(pThis, pVar1);
1154     if (rc >= kExprRet_Ok)
1155     {
1156         rc = expr_var_make_num(pThis, pVar2);
1157         if (rc >= kExprRet_Ok)
1158             pVar1->uVal.i += pVar2->uVal.i;
1159     }
1160 
1161     expr_pop_and_delete_var(pThis);
1162     return rc;
1163 }
1164 
1165 
1166 /**
1167  * Subtract (numeric).
1168  *
1169  * @returns Status code.
1170  * @param   pThis       The instance.
1171  */
expr_op_sub(PEXPR pThis)1172 static EXPRRET expr_op_sub(PEXPR pThis)
1173 {
1174     EXPRRET     rc = kExprRet_Ok;
1175     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1176     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1177 
1178     rc = expr_var_make_num(pThis, pVar1);
1179     if (rc >= kExprRet_Ok)
1180     {
1181         rc = expr_var_make_num(pThis, pVar2);
1182         if (rc >= kExprRet_Ok)
1183             pVar1->uVal.i -= pVar2->uVal.i;
1184     }
1185 
1186     expr_pop_and_delete_var(pThis);
1187     return rc;
1188 }
1189 
1190 /**
1191  * Bitwise left shift.
1192  *
1193  * @returns Status code.
1194  * @param   pThis       The instance.
1195  */
expr_op_shift_left(PEXPR pThis)1196 static EXPRRET expr_op_shift_left(PEXPR pThis)
1197 {
1198     EXPRRET     rc = kExprRet_Ok;
1199     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1200     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1201 
1202     rc = expr_var_make_num(pThis, pVar1);
1203     if (rc >= kExprRet_Ok)
1204     {
1205         rc = expr_var_make_num(pThis, pVar2);
1206         if (rc >= kExprRet_Ok)
1207             pVar1->uVal.i <<= pVar2->uVal.i;
1208     }
1209 
1210     expr_pop_and_delete_var(pThis);
1211     return rc;
1212 }
1213 
1214 
1215 /**
1216  * Bitwise right shift.
1217  *
1218  * @returns Status code.
1219  * @param   pThis       The instance.
1220  */
expr_op_shift_right(PEXPR pThis)1221 static EXPRRET expr_op_shift_right(PEXPR pThis)
1222 {
1223     EXPRRET     rc = kExprRet_Ok;
1224     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1225     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1226 
1227     rc = expr_var_make_num(pThis, pVar1);
1228     if (rc >= kExprRet_Ok)
1229     {
1230         rc = expr_var_make_num(pThis, pVar2);
1231         if (rc >= kExprRet_Ok)
1232             pVar1->uVal.i >>= pVar2->uVal.i;
1233     }
1234 
1235     expr_pop_and_delete_var(pThis);
1236     return rc;
1237 }
1238 
1239 
1240 /**
1241  * Less than or equal
1242  *
1243  * @returns Status code.
1244  * @param   pThis       The instance.
1245  */
expr_op_less_or_equal_than(PEXPR pThis)1246 static EXPRRET expr_op_less_or_equal_than(PEXPR pThis)
1247 {
1248     EXPRRET     rc = kExprRet_Ok;
1249     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1250     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1251 
1252     rc = expr_var_unify_types(pThis, pVar1, pVar2, "<=");
1253     if (rc >= kExprRet_Ok)
1254     {
1255         if (!expr_var_is_string(pVar1))
1256             expr_var_assign_bool(pVar1, pVar1->uVal.i <= pVar2->uVal.i);
1257         else
1258             expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) <= 0);
1259     }
1260 
1261     expr_pop_and_delete_var(pThis);
1262     return rc;
1263 }
1264 
1265 
1266 /**
1267  * Less than.
1268  *
1269  * @returns Status code.
1270  * @param   pThis       The instance.
1271  */
expr_op_less_than(PEXPR pThis)1272 static EXPRRET expr_op_less_than(PEXPR pThis)
1273 {
1274     EXPRRET     rc = kExprRet_Ok;
1275     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1276     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1277 
1278     rc = expr_var_unify_types(pThis, pVar1, pVar2, "<");
1279     if (rc >= kExprRet_Ok)
1280     {
1281         if (!expr_var_is_string(pVar1))
1282             expr_var_assign_bool(pVar1, pVar1->uVal.i < pVar2->uVal.i);
1283         else
1284             expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) < 0);
1285     }
1286 
1287     expr_pop_and_delete_var(pThis);
1288     return rc;
1289 }
1290 
1291 
1292 /**
1293  * Greater or equal than
1294  *
1295  * @returns Status code.
1296  * @param   pThis       The instance.
1297  */
expr_op_greater_or_equal_than(PEXPR pThis)1298 static EXPRRET expr_op_greater_or_equal_than(PEXPR pThis)
1299 {
1300     EXPRRET     rc = kExprRet_Ok;
1301     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1302     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1303 
1304     rc = expr_var_unify_types(pThis, pVar1, pVar2, ">=");
1305     if (rc >= kExprRet_Ok)
1306     {
1307         if (!expr_var_is_string(pVar1))
1308             expr_var_assign_bool(pVar1, pVar1->uVal.i >= pVar2->uVal.i);
1309         else
1310             expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) >= 0);
1311     }
1312 
1313     expr_pop_and_delete_var(pThis);
1314     return rc;
1315 }
1316 
1317 
1318 /**
1319  * Greater than.
1320  *
1321  * @returns Status code.
1322  * @param   pThis       The instance.
1323  */
expr_op_greater_than(PEXPR pThis)1324 static EXPRRET expr_op_greater_than(PEXPR pThis)
1325 {
1326     EXPRRET     rc = kExprRet_Ok;
1327     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1328     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1329 
1330     rc = expr_var_unify_types(pThis, pVar1, pVar2, ">");
1331     if (rc >= kExprRet_Ok)
1332     {
1333         if (!expr_var_is_string(pVar1))
1334             expr_var_assign_bool(pVar1, pVar1->uVal.i > pVar2->uVal.i);
1335         else
1336             expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) > 0);
1337     }
1338 
1339     expr_pop_and_delete_var(pThis);
1340     return rc;
1341 }
1342 
1343 
1344 /**
1345  * Equal.
1346  *
1347  * @returns Status code.
1348  * @param   pThis       The instance.
1349  */
expr_op_equal(PEXPR pThis)1350 static EXPRRET expr_op_equal(PEXPR pThis)
1351 {
1352     EXPRRET     rc = kExprRet_Ok;
1353     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1354     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1355 
1356     /*
1357      * The same type?
1358      */
1359     if (expr_var_is_string(pVar1) == expr_var_is_string(pVar2))
1360     {
1361         if (!expr_var_is_string(pVar1))
1362             /* numbers are simple */
1363             expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
1364         else
1365         {
1366             /* try a normal string compare. */
1367             expr_var_make_simple_string(pVar1);
1368             expr_var_make_simple_string(pVar2);
1369             if (!strcmp(pVar1->uVal.psz, pVar2->uVal.psz))
1370                 expr_var_assign_bool(pVar1, 1);
1371             /* try convert and compare as number instead. */
1372             else if (   expr_var_try_make_num(pVar1) >= kExprRet_Ok
1373                      && expr_var_try_make_num(pVar2) >= kExprRet_Ok)
1374                 expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
1375             /* ok, they really aren't equal. */
1376             else
1377                 expr_var_assign_bool(pVar1, 0);
1378         }
1379     }
1380     else
1381     {
1382         /*
1383          * If the type differs, there are now two options:
1384          *  1. Convert the string to a valid number and compare the numbers.
1385          *  2. Convert an empty string to a 'false' boolean value and compare
1386          *     numerically. This one is a bit questionable, so we don't try this.
1387          */
1388         if (   expr_var_try_make_num(pVar1) >= kExprRet_Ok
1389             && expr_var_try_make_num(pVar2) >= kExprRet_Ok)
1390             expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
1391         else
1392         {
1393             expr_error(pThis, "Cannot compare strings and numbers");
1394             rc = kExprRet_Error;
1395         }
1396     }
1397 
1398     expr_pop_and_delete_var(pThis);
1399     return rc;
1400 }
1401 
1402 
1403 /**
1404  * Not equal.
1405  *
1406  * @returns Status code.
1407  * @param   pThis       The instance.
1408  */
expr_op_not_equal(PEXPR pThis)1409 static EXPRRET expr_op_not_equal(PEXPR pThis)
1410 {
1411     EXPRRET rc = expr_op_equal(pThis);
1412     if (rc >= kExprRet_Ok)
1413         rc = expr_op_logical_not(pThis);
1414     return rc;
1415 }
1416 
1417 
1418 /**
1419  * Bitwise AND.
1420  *
1421  * @returns Status code.
1422  * @param   pThis       The instance.
1423  */
expr_op_bitwise_and(PEXPR pThis)1424 static EXPRRET expr_op_bitwise_and(PEXPR pThis)
1425 {
1426     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1427     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1428     EXPRRET     rc;
1429 
1430     rc = expr_var_make_num(pThis, pVar1);
1431     if (rc >= kExprRet_Ok)
1432     {
1433         rc = expr_var_make_num(pThis, pVar2);
1434         if (rc >= kExprRet_Ok)
1435             pVar1->uVal.i &= pVar2->uVal.i;
1436     }
1437 
1438     expr_pop_and_delete_var(pThis);
1439     return kExprRet_Ok;
1440 }
1441 
1442 
1443 /**
1444  * Bitwise XOR.
1445  *
1446  * @returns Status code.
1447  * @param   pThis       The instance.
1448  */
expr_op_bitwise_xor(PEXPR pThis)1449 static EXPRRET expr_op_bitwise_xor(PEXPR pThis)
1450 {
1451     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1452     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1453     EXPRRET     rc;
1454 
1455     rc = expr_var_make_num(pThis, pVar1);
1456     if (rc >= kExprRet_Ok)
1457     {
1458         rc = expr_var_make_num(pThis, pVar2);
1459         if (rc >= kExprRet_Ok)
1460             pVar1->uVal.i ^= pVar2->uVal.i;
1461     }
1462 
1463     expr_pop_and_delete_var(pThis);
1464     return kExprRet_Ok;
1465 }
1466 
1467 
1468 /**
1469  * Bitwise OR.
1470  *
1471  * @returns Status code.
1472  * @param   pThis       The instance.
1473  */
expr_op_bitwise_or(PEXPR pThis)1474 static EXPRRET expr_op_bitwise_or(PEXPR pThis)
1475 {
1476     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1477     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1478     EXPRRET     rc;
1479 
1480     rc = expr_var_make_num(pThis, pVar1);
1481     if (rc >= kExprRet_Ok)
1482     {
1483         rc = expr_var_make_num(pThis, pVar2);
1484         if (rc >= kExprRet_Ok)
1485             pVar1->uVal.i |= pVar2->uVal.i;
1486     }
1487 
1488     expr_pop_and_delete_var(pThis);
1489     return kExprRet_Ok;
1490 }
1491 
1492 
1493 /**
1494  * Logical AND.
1495  *
1496  * @returns Status code.
1497  * @param   pThis       The instance.
1498  */
expr_op_logical_and(PEXPR pThis)1499 static EXPRRET expr_op_logical_and(PEXPR pThis)
1500 {
1501     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1502     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1503 
1504     if (   expr_var_make_bool(pVar1)
1505         && expr_var_make_bool(pVar2))
1506         expr_var_assign_bool(pVar1, 1);
1507     else
1508         expr_var_assign_bool(pVar1, 0);
1509 
1510     expr_pop_and_delete_var(pThis);
1511     return kExprRet_Ok;
1512 }
1513 
1514 
1515 /**
1516  * Logical OR.
1517  *
1518  * @returns Status code.
1519  * @param   pThis       The instance.
1520  */
expr_op_logical_or(PEXPR pThis)1521 static EXPRRET expr_op_logical_or(PEXPR pThis)
1522 {
1523     PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
1524     PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
1525 
1526     if (   expr_var_make_bool(pVar1)
1527         || expr_var_make_bool(pVar2))
1528         expr_var_assign_bool(pVar1, 1);
1529     else
1530         expr_var_assign_bool(pVar1, 0);
1531 
1532     expr_pop_and_delete_var(pThis);
1533     return kExprRet_Ok;
1534 }
1535 
1536 
1537 /**
1538  * Left parenthesis.
1539  *
1540  * @returns Status code.
1541  * @param   pThis       The instance.
1542  */
expr_op_left_parenthesis(PEXPR pThis)1543 static EXPRRET expr_op_left_parenthesis(PEXPR pThis)
1544 {
1545     /*
1546      * There should be a right parenthesis operator lined up for us now,
1547      * eat it. If not found there is an inbalance.
1548      */
1549     EXPRRET rc = expr_get_binary_or_eoe_or_rparen(pThis);
1550     if (    rc == kExprRet_Operator
1551         &&  pThis->apOps[pThis->iOp]->szOp[0] == ')')
1552     {
1553         /* pop it and get another one which we can leave pending. */
1554         pThis->iOp--;
1555         rc = expr_get_binary_or_eoe_or_rparen(pThis);
1556         if (rc >= kExprRet_Ok)
1557             expr_unget_op(pThis);
1558     }
1559     else
1560     {
1561         expr_error(pThis, "Missing ')'");
1562         rc = kExprRet_Error;
1563     }
1564 
1565     return rc;
1566 }
1567 
1568 
1569 /**
1570  * Right parenthesis, dummy that's never actually called.
1571  *
1572  * @returns Status code.
1573  * @param   pThis       The instance.
1574  */
expr_op_right_parenthesis(PEXPR pThis)1575 static EXPRRET expr_op_right_parenthesis(PEXPR pThis)
1576 {
1577     assert(0);
1578     (void)pThis;
1579     return kExprRet_Ok;
1580 }
1581 
1582 
1583 
1584 
1585 
1586 /**
1587  * The operator table.
1588  *
1589  * This table is NOT ordered by precedence, but for linear search
1590  * allowing for first match to return the correct operator. This
1591  * means that || must come before |, or else | will match all.
1592  */
1593 static const EXPROP g_aExprOps[] =
1594 {
1595 #define EXPR_OP(szOp, iPrecedence, cArgs, pfn)  {  szOp, sizeof(szOp) - 1, '\0', iPrecedence, cArgs, pfn }
1596     /*        Name, iPrecedence,  cArgs,    pfn    */
1597     EXPR_OP("defined",     90,      1,    expr_op_defined),
1598     EXPR_OP("exists",      90,      1,    expr_op_exists),
1599     EXPR_OP("target",      90,      1,    expr_op_target),
1600     EXPR_OP("bool",        90,      1,    expr_op_bool),
1601     EXPR_OP("num",         90,      1,    expr_op_num),
1602     EXPR_OP("str",         90,      1,    expr_op_str),
1603     EXPR_OP("+",           80,      1,    expr_op_pluss),
1604     EXPR_OP("-",           80,      1,    expr_op_minus),
1605     EXPR_OP("~",           80,      1,    expr_op_bitwise_not),
1606     EXPR_OP("*",           75,      2,    expr_op_multiply),
1607     EXPR_OP("/",           75,      2,    expr_op_divide),
1608     EXPR_OP("%",           75,      2,    expr_op_modulus),
1609     EXPR_OP("+",           70,      2,    expr_op_add),
1610     EXPR_OP("-",           70,      2,    expr_op_sub),
1611     EXPR_OP("<<",          65,      2,    expr_op_shift_left),
1612     EXPR_OP(">>",          65,      2,    expr_op_shift_right),
1613     EXPR_OP("<=",          60,      2,    expr_op_less_or_equal_than),
1614     EXPR_OP("<",           60,      2,    expr_op_less_than),
1615     EXPR_OP(">=",          60,      2,    expr_op_greater_or_equal_than),
1616     EXPR_OP(">",           60,      2,    expr_op_greater_than),
1617     EXPR_OP("==",          55,      2,    expr_op_equal),
1618     EXPR_OP("!=",          55,      2,    expr_op_not_equal),
1619     EXPR_OP("!",           80,      1,    expr_op_logical_not),
1620     EXPR_OP("^",           45,      2,    expr_op_bitwise_xor),
1621     EXPR_OP("&&",          35,      2,    expr_op_logical_and),
1622     EXPR_OP("&",           50,      2,    expr_op_bitwise_and),
1623     EXPR_OP("||",          30,      2,    expr_op_logical_or),
1624     EXPR_OP("|",           40,      2,    expr_op_bitwise_or),
1625             { "(", 1, ')',   10,      1,    expr_op_left_parenthesis },
1626             { ")", 1, '(',   10,      0,    expr_op_right_parenthesis },
1627  /*         { "?", 1, ':',    5,      2,    expr_op_question },
1628             { ":", 1, '?',    5,      2,    expr_op_colon }, -- too weird for now. */
1629 #undef EXPR_OP
1630 };
1631 
1632 /** Dummy end of expression fake. */
1633 static const EXPROP g_ExprEndOfExpOp =
1634 {
1635               "", 0, '\0',    0,      0,    NULL
1636 };
1637 
1638 
1639 /**
1640  * Initializes the opcode character map if necessary.
1641  */
expr_map_init(void)1642 static void expr_map_init(void)
1643 {
1644     unsigned i;
1645     if (g_fExprInitializedMap)
1646         return;
1647 
1648     /*
1649      * Initialize it.
1650      */
1651     memset(&g_auchOpStartCharMap, 0, sizeof(g_auchOpStartCharMap));
1652     for (i = 0; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
1653     {
1654         unsigned int ch = (unsigned int)g_aExprOps[i].szOp[0];
1655         if (!g_auchOpStartCharMap[ch])
1656             g_auchOpStartCharMap[ch] = (i << 1) | 1;
1657     }
1658 
1659     g_fExprInitializedMap = 1;
1660 }
1661 
1662 
1663 /**
1664  * Looks up a character in the map.
1665  *
1666  * @returns the value for that char.
1667  * @retval  0 if not a potential opcode start char.
1668  * @retval  non-zero if it's a potential operator. The low bit is always set
1669  *          while the remaining 7 bits is the index into the operator table
1670  *          of the first match.
1671  *
1672  * @param   ch      The character.
1673  */
expr_map_get(char ch)1674 static unsigned char expr_map_get(char ch)
1675 {
1676     return g_auchOpStartCharMap[(unsigned int)ch];
1677 }
1678 
1679 
1680 /**
1681  * Searches the operator table given a potential operator start char.
1682  *
1683  * @returns Pointer to the matching operator. NULL if not found.
1684  * @param   psz     Pointer to what can be an operator.
1685  * @param   uchVal  The expr_map_get value.
1686  * @param   fUnary  Whether it must be an unary operator or not.
1687  */
expr_lookup_op(char const * psz,unsigned char uchVal,int fUnary)1688 static PCEXPROP expr_lookup_op(char const *psz, unsigned char uchVal, int fUnary)
1689 {
1690     char ch = *psz;
1691     unsigned i;
1692 
1693     for (i = uchVal >> 1; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
1694     {
1695         /* compare the string... */
1696         switch (g_aExprOps[i].cchOp)
1697         {
1698             case 1:
1699                 if (g_aExprOps[i].szOp[0] != ch)
1700                     continue;
1701                 break;
1702             case 2:
1703                 if (    g_aExprOps[i].szOp[0] != ch
1704                     ||  g_aExprOps[i].szOp[1] != psz[1])
1705                     continue;
1706                 break;
1707             default:
1708                 if (    g_aExprOps[i].szOp[0] != ch
1709                     ||  strncmp(&g_aExprOps[i].szOp[1], psz + 1, g_aExprOps[i].cchOp - 1))
1710                     continue;
1711                 break;
1712         }
1713 
1714         /* ... and the operator type. */
1715         if (fUnary == (g_aExprOps[i].cArgs == 1))
1716         {
1717             /* got a match! */
1718             return &g_aExprOps[i];
1719         }
1720     }
1721 
1722     return NULL;
1723 }
1724 
1725 
1726 /**
1727  * Ungets a binary operator.
1728  *
1729  * The operator is poped from the stack and put in the pending position.
1730  *
1731  * @param   pThis       The evaluator instance.
1732  */
expr_unget_op(PEXPR pThis)1733 static void expr_unget_op(PEXPR pThis)
1734 {
1735     assert(pThis->pPending == NULL);
1736     assert(pThis->iOp >= 0);
1737 
1738     pThis->pPending = pThis->apOps[pThis->iOp];
1739     pThis->apOps[pThis->iOp] = NULL;
1740     pThis->iOp--;
1741 }
1742 
1743 
1744 
1745 /**
1746  * Get the next token, it should be a binary operator, or the end of
1747  * the expression, or a right parenthesis.
1748  *
1749  * The operator is pushed onto the stack and the status code indicates
1750  * which of the two we found.
1751  *
1752  * @returns status code. Will grumble on failure.
1753  * @retval  kExprRet_EndOfExpr if we encountered the end of the expression.
1754  * @retval  kExprRet_Operator if we encountered a binary operator or right
1755  *          parenthesis. It's on the operator stack.
1756  *
1757  * @param   pThis       The evaluator instance.
1758  */
expr_get_binary_or_eoe_or_rparen(PEXPR pThis)1759 static EXPRRET expr_get_binary_or_eoe_or_rparen(PEXPR pThis)
1760 {
1761     /*
1762      * See if there is anything pending first.
1763      */
1764     PCEXPROP pOp = pThis->pPending;
1765     if (pOp)
1766         pThis->pPending = NULL;
1767     else
1768     {
1769         /*
1770          * Eat more of the expression.
1771          */
1772         char const *psz = pThis->psz;
1773 
1774         /* spaces */
1775         while (isspace((unsigned int)*psz))
1776             psz++;
1777         /* see what we've got. */
1778         if (*psz)
1779         {
1780             unsigned char uchVal = expr_map_get(*psz);
1781             if (uchVal)
1782                 pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
1783             if (!pOp)
1784             {
1785                 expr_error(pThis, "Expected binary operator, found \"%.42s\"...", psz);
1786                 return kExprRet_Error;
1787             }
1788             psz += pOp->cchOp;
1789         }
1790         else
1791             pOp = &g_ExprEndOfExpOp;
1792         pThis->psz = psz;
1793     }
1794 
1795     /*
1796      * Push it.
1797      */
1798     if (pThis->iOp >= EXPR_MAX_OPERATORS - 1)
1799     {
1800         expr_error(pThis, "Operator stack overflow");
1801         return kExprRet_Error;
1802     }
1803     pThis->apOps[++pThis->iOp] = pOp;
1804 
1805     return pOp->iPrecedence
1806          ? kExprRet_Operator
1807          : kExprRet_EndOfExpr;
1808 }
1809 
1810 
1811 
1812 /**
1813  * Get the next token, it should be an unary operator or an operand.
1814  *
1815  * This will fail if encountering the end of the expression since
1816  * it is implied that there should be something more.
1817  *
1818  * The token is pushed onto the respective stack and the status code
1819  * indicates which it is.
1820  *
1821  * @returns status code. On failure we'll be done bitching already.
1822  * @retval  kExprRet_Operator if we encountered an unary operator.
1823  *          It's on the operator stack.
1824  * @retval  kExprRet_Operand if we encountered an operand operator.
1825  *          It's on the operand stack.
1826  *
1827  * @param   This        The evaluator instance.
1828  */
expr_get_unary_or_operand(PEXPR pThis)1829 static EXPRRET expr_get_unary_or_operand(PEXPR pThis)
1830 {
1831     EXPRRET       rc;
1832     unsigned char uchVal;
1833     PCEXPROP      pOp;
1834     char const   *psz = pThis->psz;
1835 
1836     /*
1837      * Eat white space and make sure there is something after it.
1838      */
1839     while (isspace((unsigned int)*psz))
1840         psz++;
1841     if (!*psz)
1842     {
1843         expr_error(pThis, "Unexpected end of expression");
1844         return kExprRet_Error;
1845     }
1846 
1847     /*
1848      * Is it an operator?
1849      */
1850     pOp = NULL;
1851     uchVal = expr_map_get(*psz);
1852     if (uchVal)
1853         pOp = expr_lookup_op(psz, uchVal, 1 /* fUnary */);
1854     if (pOp)
1855     {
1856         /*
1857          * Push the operator onto the stack.
1858          */
1859         if (pThis->iVar < EXPR_MAX_OPERANDS - 1)
1860         {
1861             pThis->apOps[++pThis->iOp] = pOp;
1862             rc = kExprRet_Operator;
1863         }
1864         else
1865         {
1866             expr_error(pThis, "Operator stack overflow");
1867             rc = kExprRet_Error;
1868         }
1869         psz += pOp->cchOp;
1870     }
1871     else if (pThis->iVar < EXPR_MAX_OPERANDS - 1)
1872     {
1873         /*
1874          * It's an operand. Figure out where it ends and
1875          * push it onto the stack.
1876          */
1877         const char *pszStart;
1878 
1879         rc = kExprRet_Ok;
1880         if (*psz == '"')
1881         {
1882             pszStart = ++psz;
1883             while (*psz && *psz != '"')
1884                 psz++;
1885             expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedString);
1886             if (*psz)
1887                 psz++;
1888         }
1889         else if (*psz == '\'')
1890         {
1891             pszStart = ++psz;
1892             while (*psz && *psz != '\'')
1893                 psz++;
1894             expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedSimpleString);
1895             if (*psz)
1896                 psz++;
1897         }
1898         else
1899         {
1900             char    achPars[20];
1901             int     iPar = -1;
1902             char    chEndPar = '\0';
1903             char    ch, ch2;
1904 
1905             pszStart = psz;
1906             while ((ch = *psz) != '\0')
1907             {
1908                 /* $(adsf) or ${asdf} needs special handling. */
1909                 if (    ch == '$'
1910                     &&  (   (ch2 = psz[1]) == '('
1911                          || ch2 == '{'))
1912                 {
1913                     psz++;
1914                     if (iPar > (int)(sizeof(achPars) / sizeof(achPars[0])))
1915                     {
1916                         expr_error(pThis, "Too deep nesting of variable expansions");
1917                         rc = kExprRet_Error;
1918                         break;
1919                     }
1920                     achPars[++iPar] = chEndPar = ch2 == '(' ? ')' : '}';
1921                 }
1922                 else if (ch == chEndPar)
1923                 {
1924                     iPar--;
1925                     chEndPar = iPar >= 0 ? achPars[iPar] : '\0';
1926                 }
1927                 else if (!chEndPar)
1928                 {
1929                     /** @todo combine isspace and expr_map_get! */
1930                     unsigned chVal = expr_map_get(ch);
1931                     if (chVal)
1932                     {
1933                         pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
1934                         if (pOp)
1935                             break;
1936                     }
1937                     if (isspace((unsigned char)ch))
1938                         break;
1939                 }
1940 
1941                 /* next */
1942                 psz++;
1943             }
1944 
1945             if (rc == kExprRet_Ok)
1946                 expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_String);
1947         }
1948     }
1949     else
1950     {
1951         expr_error(pThis, "Operand stack overflow");
1952         rc = kExprRet_Error;
1953     }
1954     pThis->psz = psz;
1955 
1956     return rc;
1957 }
1958 
1959 
1960 /**
1961  * Evaluates the current expression.
1962  *
1963  * @returns status code.
1964  *
1965  * @param   pThis       The instance.
1966  */
expr_eval(PEXPR pThis)1967 static EXPRRET expr_eval(PEXPR pThis)
1968 {
1969     EXPRRET  rc;
1970     PCEXPROP pOp;
1971 
1972     /*
1973      * The main loop.
1974      */
1975     for (;;)
1976     {
1977         /*
1978          * Eat unary operators until we hit an operand.
1979          */
1980         do  rc = expr_get_unary_or_operand(pThis);
1981         while (rc == kExprRet_Operator);
1982         if (rc < kExprRet_Ok)
1983             break;
1984 
1985         /*
1986          * Look for a binary operator, right parenthesis or end of expression.
1987          */
1988         rc = expr_get_binary_or_eoe_or_rparen(pThis);
1989         if (rc < kExprRet_Ok)
1990             break;
1991         expr_unget_op(pThis);
1992 
1993         /*
1994          * Pop operators and apply them.
1995          *
1996          * Parenthesis will be handed via precedence, where the left parenthesis
1997          * will go pop the right one and make another operator pending.
1998          */
1999         while (   pThis->iOp >= 0
2000                && pThis->apOps[pThis->iOp]->iPrecedence >= pThis->pPending->iPrecedence)
2001         {
2002             pOp = pThis->apOps[pThis->iOp--];
2003             assert(pThis->iVar + 1 >= pOp->cArgs);
2004             rc = pOp->pfn(pThis);
2005             if (rc < kExprRet_Ok)
2006                 break;
2007         }
2008         if (rc < kExprRet_Ok)
2009             break;
2010 
2011         /*
2012          * Get the next binary operator or end of expression.
2013          * There should be no right parenthesis here.
2014          */
2015         rc = expr_get_binary_or_eoe_or_rparen(pThis);
2016         if (rc < kExprRet_Ok)
2017             break;
2018         pOp = pThis->apOps[pThis->iOp];
2019         if (!pOp->iPrecedence)
2020             break;  /* end of expression */
2021         if (!pOp->cArgs)
2022         {
2023             expr_error(pThis, "Unexpected \"%s\"", pOp->szOp);
2024             rc = kExprRet_Error;
2025             break;
2026         }
2027     }
2028 
2029     return rc;
2030 }
2031 
2032 
2033 /**
2034  * Destroys the given instance.
2035  *
2036  * @param   pThis       The instance to destroy.
2037  */
expr_destroy(PEXPR pThis)2038 static void expr_destroy(PEXPR pThis)
2039 {
2040     while (pThis->iVar >= 0)
2041     {
2042         expr_var_delete(pThis->aVars);
2043         pThis->iVar--;
2044     }
2045     free(pThis);
2046 }
2047 
2048 
2049 /**
2050  * Instantiates an expression evaluator.
2051  *
2052  * @returns The instance.
2053  *
2054  * @param   pszExpr     What to parse.
2055  *                      This must stick around until expr_destroy.
2056  */
expr_create(char const * pszExpr)2057 static PEXPR expr_create(char const *pszExpr)
2058 {
2059     PEXPR pThis = (PEXPR)xmalloc(sizeof(*pThis));
2060     pThis->pszExpr = pszExpr;
2061     pThis->psz = pszExpr;
2062     pThis->pFileLoc = NULL;
2063     pThis->pPending = NULL;
2064     pThis->iVar = -1;
2065     pThis->iOp = -1;
2066 
2067     expr_map_init();
2068     return pThis;
2069 }
2070 
2071 
2072 /**
2073  * Evaluates the given if expression.
2074  *
2075  * @returns -1, 0 or 1. (GNU make conditional check convention, see read.c.)
2076  * @retval  -1 if the expression is invalid.
2077  * @retval  0 if the expression is true
2078  * @retval  1 if the expression is false.
2079  *
2080  * @param   line    The expression.
2081  * @param   flocp   The file location, used for errors.
2082  */
expr_eval_if_conditionals(const char * line,const struct floc * flocp)2083 int expr_eval_if_conditionals(const char *line, const struct floc *flocp)
2084 {
2085     /*
2086      * Instantiate the expression evaluator and let
2087      * it have a go at it.
2088      */
2089     int rc = -1;
2090     PEXPR pExpr = expr_create(line);
2091     pExpr->pFileLoc = flocp;
2092     if (expr_eval(pExpr) >= kExprRet_Ok)
2093     {
2094         /*
2095          * Convert the result (on top of the stack) to boolean and
2096          * set our return value accordingly.
2097          */
2098         if (expr_var_make_bool(&pExpr->aVars[0]))
2099             rc = 0;
2100         else
2101             rc = 1;
2102     }
2103     expr_destroy(pExpr);
2104 
2105     return rc;
2106 }
2107 
2108 
2109 /**
2110  * Evaluates the given expression and returns the result as a string.
2111  *
2112  * @returns variable buffer position.
2113  *
2114  * @param   o       The current variable buffer position.
2115  * @param   expr    The expression.
2116  */
expr_eval_to_string(char * o,const char * expr)2117 char *expr_eval_to_string(char *o, const char *expr)
2118 {
2119     /*
2120      * Instantiate the expression evaluator and let
2121      * it have a go at it.
2122      */
2123     PEXPR pExpr = expr_create(expr);
2124     if (expr_eval(pExpr) >= kExprRet_Ok)
2125     {
2126         /*
2127          * Convert the result (on top of the stack) to a string
2128          * and copy it out the variable buffer.
2129          */
2130         PEXPRVAR pVar = &pExpr->aVars[0];
2131         expr_var_make_simple_string(pVar);
2132         o = variable_buffer_output(o, pVar->uVal.psz, strlen(pVar->uVal.psz));
2133     }
2134     else
2135         o = variable_buffer_output(o, "<expression evaluation failed>", sizeof("<expression evaluation failed>") - 1);
2136     expr_destroy(pExpr);
2137 
2138     return o;
2139 }
2140 
2141 
2142 #endif /* CONFIG_WITH_IF_CONDITIONALS */
2143 
2144