@@ -34,6 +34,7 @@
#include <inttypes.h>
#include <stdlib.h>
+#include <string.h>
#include "arith_yacc.h"
#include "expand.h"
#include "shell.h"
@@ -134,6 +135,50 @@
static intmax_t assignment(int var, int noeval);
+typedef struct CHK_VAR_RECURSIVE_LOOPED {
+ const char *name;
+ struct CHK_VAR_RECURSIVE_LOOPED *next;
+} chk_var_recursive_looped_t;
+
+static chk_var_recursive_looped_t *prev_chk_var_recursive;
+
+static intmax_t arith_lookup_val(const char *name)
+{
+ const char * p = lookupvar(name);
+
+ if(p) {
+ intmax_t ret;
+
+ /* recursive try as expression */
+ chk_var_recursive_looped_t *cur;
+ chk_var_recursive_looped_t cur_save;
+ const char *arith_buf_s;
+ int lt;
+
+ for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
+ if(!strcmp(cur->name, name))
+ yyerror("expression recursion loop detected");
+ }
+ /* save current lookuped var name */
+ cur = prev_chk_var_recursive;
+ cur_save.name = name;
+ cur_save.next = cur;
+ prev_chk_var_recursive = &cur_save;
+
+ arith_buf_s = arith_buf;
+ lt = last_token;
+ ret = arith (p, 1);
+ /* restore previous after recursiving */
+ prev_chk_var_recursive = cur;
+ arith_buf = arith_buf_s;
+ last_token = lt;
+ return ret;
+ } else {
+ /* allow undefined var as 0 */
+ return 0;
+ }
+}
+
static intmax_t primary(int token, union yystype *val, int op, int noeval)
{
intmax_t result;
@@ -151,7 +196,7 @@
return val->val;
case ARITH_VAR:
last_token = op;
- return noeval ? val->val : lookupvarint(val->name);
+ return noeval ? val->val : arith_lookup_val(val->name);
case ARITH_ADD:
token = op;
*val = yylval;
@@ -286,16 +331,27 @@
return setvarint(val.name,
op == ARITH_ASS ? result :
- do_binop(op - 11, lookupvarint(val.name), result), 0);
+ do_binop(op - 11, arith_lookup_val(val.name), result), 0);
}
-intmax_t arith(const char *s)
+intmax_t arith(const char *s, int r)
{
intmax_t result;
+ int l0;
- arith_buf = arith_startbuf = s;
+ arith_buf = s;
+ last_token = 0;
- result = assignment(yylex(), 0);
+ if(!r) {
+ prev_chk_var_recursive = (chk_var_recursive_looped_t *)0;
+ arith_startbuf = s;
+ }
+ l0 = yylex();
+ if (l0 == 0) {
+ /* $(( )) */
+ return 0;
+ }
+ result = assignment(l0, 0);
if (last_token)
yyerror("expecting EOF");
@@ -460,7 +460,7 @@
rmescapes(start);
pushstackmark(&sm, endoff);
- result = arith(start);
+ result = arith(start, 0);
popstackmark(&sm);
len = cvtnum(result, flag);
@@ -73,7 +73,7 @@
void ifsfree(void);
/* From arith.y */
-intmax_t arith(const char *);
+intmax_t arith(const char *, int r);
int expcmd(int , char **);
#ifdef USE_LEX
void arith_lex_reset(void);
@@ -322,12 +322,6 @@
return NULL;
}
-intmax_t lookupvarint(const char *name)
-{
- return atomax(lookupvar(name) ?: nullstr, 0);
-}
-
-
/*
@@ -140,7 +140,6 @@
struct var *setvareq(char *s, int flags);
struct strlist;
char *lookupvar(const char *);
-intmax_t lookupvarint(const char *);
char **listvars(int, int, char ***);
#define environment() listvars(VEXPORT, VUNSET, 0)
int showvars(const char *, int, int);