dash.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Vladimir N. Oleynik" <dzo@simtreas.ru>
To: dash@vger.kernel.org
Cc: "Vladimir N. Oleynik" <dzo@simtreas.ru>
Subject: [PATCH]: allow recursive variable inderection in arith
Date: Sun, 31 Jan 2021 13:29:36 +0400	[thread overview]
Message-ID: <ecf90382-e5b9-9b0c-c73b-c564a660ee20@simtreas.ru> (raw)
In-Reply-To: <08178d03-1912-76e7-0733-75e8f1d691af@simtreas.ru>

[-- Attachment #1: Type: text/plain, Size: 344 bytes --]

Hello.


My patch for allow recursive variable inderection in arith
and simplify allow $(( )). Originaly from my arith in busybox

Before patch:
$ a=b b=2; echo $((a))
dash: 1: Illegal number: b

After patch:
$ a=b b=2; echo $((a))
2
a=b b="a*2"; echo $((a))
./dash: 4: arithmetic expression: expression recursion loop detected: "a"


--w
vodz

[-- Attachment #2: arith_diff.txt --]
[-- Type: text/plain, Size: 4102 bytes --]

--- arith_yacc.c.orig   2020-12-23 11:58:12.000000000 +0400
+++ arith_yacc.c        2021-01-31 13:19:00.790119536 +0400
@@ -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");
--- expand.c.orig       2020-12-23 11:58:12.000000000 +0400
+++ expand.c    2021-01-31 12:39:07.083194412 +0400
@@ -460,7 +460,7 @@
		rmescapes(start);

	pushstackmark(&sm, endoff);
-       result = arith(start);
+       result = arith(start, 0);
	popstackmark(&sm);

	len = cvtnum(result, flag);
--- expand.h.orig       2020-12-23 11:58:12.000000000 +0400
+++ expand.h    2021-01-31 12:39:09.435194338 +0400
@@ -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);
--- var.c.orig  2020-12-23 11:58:12.000000000 +0400
+++ var.c       2021-01-31 12:30:38.894210308 +0400
@@ -322,12 +322,6 @@
	return NULL;
 }

-intmax_t lookupvarint(const char *name)
-{
-       return atomax(lookupvar(name) ?: nullstr, 0);
-}
-
-

 /*
--- var.h.orig  2020-12-23 11:58:12.000000000 +0400
+++ var.h       2021-01-31 12:30:45.150210113 +0400
@@ -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);

      reply	other threads:[~2021-01-31  9:33 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-29 19:49 [PATCH]: allow $(()) Vladimir N. Oleynik
2021-01-31  9:29 ` Vladimir N. Oleynik [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ecf90382-e5b9-9b0c-c73b-c564a660ee20@simtreas.ru \
    --to=dzo@simtreas.ru \
    --cc=dash@vger.kernel.org \
    --subject='Re: [PATCH]: allow recursive variable inderection in arith' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).