summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschweikh <schweikh@FreeBSD.org>2003-08-30 12:31:44 +0000
committerschweikh <schweikh@FreeBSD.org>2003-08-30 12:31:44 +0000
commit70a2b506d0394f7e4718d8cf08ad3ccfa2112637 (patch)
tree6e23a9b62c546da89fbc5cc397c8c2045f56efc3
parente8c434f7c55809a53a64211ba5234f1f59e72df8 (diff)
downloadFreeBSD-src-70a2b506d0394f7e4718d8cf08ad3ccfa2112637.zip
FreeBSD-src-70a2b506d0394f7e4718d8cf08ad3ccfa2112637.tar.gz
Implement missing shell arithmetic operators in $(()) expansion
and variable recognition. PR: standards/52972 Submitted by: Wartan Hachaturow <wart@tepkom.ru> Reviewed by: tjr (improved on original patch) Tested by: buildworld on CURRENT. MFC after: 6 weeks
-rw-r--r--bin/sh/arith.h1
-rw-r--r--bin/sh/arith.y230
-rw-r--r--bin/sh/arith_lex.l46
-rw-r--r--bin/sh/shell.h8
4 files changed, 236 insertions, 49 deletions
diff --git a/bin/sh/arith.h b/bin/sh/arith.h
index ba8134e..45161c1 100644
--- a/bin/sh/arith.h
+++ b/bin/sh/arith.h
@@ -34,5 +34,6 @@
* $FreeBSD$
*/
+int arith_assign(char *, arith_t);
int arith(char *);
int expcmd(int , char **);
diff --git a/bin/sh/arith.y b/bin/sh/arith.y
index 1ced626..87a027c 100644
--- a/bin/sh/arith.y
+++ b/bin/sh/arith.y
@@ -1,5 +1,65 @@
-%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+%{
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include "shell.h"
+#include "var.h"
+%}
+%union {
+ arith_t l_value;
+ char* s_value;
+}
+%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+%token <s_value> ARITH_VAR
+%type <l_value> expr
+%right ARITH_ASSIGN
+%right ARITH_ADDASSIGN ARITH_SUBASSIGN
+%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
+%right ARITH_RSHASSIGN ARITH_LSHASSIGN
+%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
%left ARITH_OR
%left ARITH_AND
%left ARITH_BOR
@@ -18,7 +78,6 @@ exp: expr = {
}
;
-
expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
| expr ARITH_OR expr = { $$ = $1 ? $1 : $3 ? $3 : 0; }
| expr ARITH_AND expr = { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
@@ -51,57 +110,122 @@ expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
| ARITH_SUB expr %prec ARITH_UNARYMINUS = { $$ = -($2); }
| ARITH_ADD expr %prec ARITH_UNARYPLUS = { $$ = $2; }
| ARITH_NUM
- ;
-%%
-/*-
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+ | ARITH_VAR {
+ char *p;
+ arith_t arith_val;
+ char *str_val;
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
-#endif
-#endif /* not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+ if (lookupvar($1) == NULL)
+ setvarsafe($1, "0", 0);
+ str_val = lookupvar($1);
+ arith_val = strtoarith_t(str_val, &p, 0);
+ /*
+ * Conversion is successful only in case
+ * we've converted _all_ characters.
+ */
+ if (*p != '\0')
+ yyerror("variable conversion error");
+ $$ = arith_val;
+ }
+ | ARITH_VAR ARITH_ASSIGN expr {
+ if (arith_assign($1, $3) != 1)
+ yyerror("variable assignment error");
+ $$ = $3;
+ }
+ | ARITH_VAR ARITH_ADDASSIGN expr {
+ arith_t value;
-#include "shell.h"
+ value = atoarith_t(lookupvar($1)) + $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_SUBASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) - $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_MULASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) * $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_DIVASSIGN expr {
+ arith_t value;
+
+ if ($3 == 0)
+ yyerror("division by zero");
+
+ value = atoarith_t(lookupvar($1)) / $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_REMASSIGN expr {
+ arith_t value;
+
+ if ($3 == 0)
+ yyerror("division by zero");
+
+ value = atoarith_t(lookupvar($1)) % $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_RSHASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) >> $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_LSHASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) << $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_BANDASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) & $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_BXORASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) ^ $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_BORASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) | $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ ;
+%%
#include "error.h"
#include "output.h"
#include "memalloc.h"
+#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
+
char *arith_buf, *arith_startbuf;
extern void arith_lex_reset();
@@ -109,6 +233,18 @@ int yylex(void);
int yyparse(void);
int
+arith_assign(char *name, arith_t value) {
+ char *str;
+ int ret;
+
+ str = (char *)ckmalloc(lstrlen(value));
+ sprintf(str, ARITH_FORMAT_STR, value);
+ ret = setvarsafe(name, str, 0);
+ free(str);
+ return ret;
+}
+
+int
arith(char *s)
{
long result;
diff --git a/bin/sh/arith_lex.l b/bin/sh/arith_lex.l
index 6bbbfaf..cad1846 100644
--- a/bin/sh/arith_lex.l
+++ b/bin/sh/arith_lex.l
@@ -43,10 +43,12 @@ static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "shell.h"
#include "y.tab.h"
#include "error.h"
+#include "var.h"
+#include "memalloc.h"
-extern int yylval;
extern char *arith_buf, *arith_startbuf;
#undef YY_INPUT
#define YY_INPUT(buf,result,max) \
@@ -56,7 +58,36 @@ extern char *arith_buf, *arith_startbuf;
%%
[ \t\n] { ; }
-[0-9]+ { yylval = atol(yytext); return(ARITH_NUM); }
+
+0x[a-fA-F0-9]+ {
+ yylval.l_value = strtoarith_t(yytext, NULL, 16);
+ return(ARITH_NUM);
+ }
+
+0[0-7]+ {
+ yylval.l_value = strtoarith_t(yytext, NULL, 8);
+ return(ARITH_NUM);
+ }
+
+[0-9]+ {
+ yylval.l_value = strtoarith_t(yytext, NULL, 10);
+ return(ARITH_NUM);
+ }
+
+
+[A-Za-z][A-Za-z0-9_]* {
+ /*
+ * If variable doesn't exist, we should initialize
+ * it to zero.
+ */
+ char *temp;
+ if (lookupvar(yytext) == NULL)
+ setvarsafe(yytext, "0", 0);
+ temp = (char *)ckmalloc(strlen(yytext) + 1);
+ yylval.s_value = strcpy(temp, yytext);
+
+ return(ARITH_VAR);
+ }
"(" { return(ARITH_LPAREN); }
")" { return(ARITH_RPAREN); }
"||" { return(ARITH_OR); }
@@ -79,6 +110,17 @@ extern char *arith_buf, *arith_startbuf;
"-" { return(ARITH_SUB); }
"~" { return(ARITH_BNOT); }
"!" { return(ARITH_NOT); }
+"=" { return(ARITH_ASSIGN); }
+"+=" { return(ARITH_ADDASSIGN); }
+"-=" { return(ARITH_SUBASSIGN); }
+"*=" { return(ARITH_MULASSIGN); }
+"/=" { return(ARITH_DIVASSIGN); }
+"%=" { return(ARITH_REMASSIGN); }
+">>=" { return(ARITH_RSHASSIGN); }
+"<<=" { return(ARITH_LSHASSIGN); }
+"&=" { return(ARITH_BANDASSIGN); }
+"^=" { return(ARITH_BXORASSIGN); }
+"|=" { return(ARITH_BORASSIGN); }
. { error("arith: syntax error: \"%s\"\n", arith_startbuf); }
%%
diff --git a/bin/sh/shell.h b/bin/sh/shell.h
index 1de36f3..eaf2755 100644
--- a/bin/sh/shell.h
+++ b/bin/sh/shell.h
@@ -51,6 +51,14 @@
#define JOBS 1
/* #define DEBUG 1 */
+/*
+ * Type of used arithmetics. SUSv3 requires us to have at least signed long.
+ */
+typedef long arith_t;
+#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
+#define atoarith_t(arg) strtol(arg, NULL, 0)
+#define ARITH_FORMAT_STR "%ld"
+
typedef void *pointer;
#define STATIC static
#define MKINIT /* empty */
OpenPOWER on IntegriCloud