This incorporates Posix math support into ash. The Posix math support
was written by Aaron Lehmann <aaronl@vitelus.com> for busybox. This patch makes a few trivial changes to Aaron's code so that it can be used (in theory) by the other shells as well... -Erik
This commit is contained in:
parent
dc6647201d
commit
74bcd16425
2
Makefile
2
Makefile
@ -247,7 +247,7 @@ safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \
|
|||||||
trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
|
trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
|
||||||
xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
|
xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
|
||||||
copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
|
copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
|
||||||
dirname.c make_directory.c create_icmp_socket.c
|
dirname.c make_directory.c create_icmp_socket.c arith.c
|
||||||
LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
|
LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
|
||||||
LIBBB_CFLAGS = -I$(LIBBB)
|
LIBBB_CFLAGS = -I$(LIBBB)
|
||||||
ifneq ($(strip $(BB_SRC_DIR)),)
|
ifneq ($(strip $(BB_SRC_DIR)),)
|
||||||
|
105
ash.c
105
ash.c
@ -51,9 +51,8 @@
|
|||||||
#define ASH_ALIAS
|
#define ASH_ALIAS
|
||||||
|
|
||||||
/* If you need ash to act as a full Posix shell, with full math
|
/* If you need ash to act as a full Posix shell, with full math
|
||||||
* support, enable this. This option needs some work, since it
|
* support, enable this. This adds a bit over 2k an x86 system. */
|
||||||
* doesn't compile right now... */
|
#define ASH_MATH_SUPPORT
|
||||||
#undef ASH_MATH_SUPPORT
|
|
||||||
|
|
||||||
/* Getopts is used by shell procedures to parse positional parameters.
|
/* Getopts is used by shell procedures to parse positional parameters.
|
||||||
* You probably want to leave this disabled, and use the busybox getopt
|
* You probably want to leave this disabled, and use the busybox getopt
|
||||||
@ -80,6 +79,7 @@
|
|||||||
#undef FNMATCH_BROKEN
|
#undef FNMATCH_BROKEN
|
||||||
#undef GLOB_BROKEN
|
#undef GLOB_BROKEN
|
||||||
#undef _GNU_SOURCE
|
#undef _GNU_SOURCE
|
||||||
|
#undef __USE_GNU
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -1562,8 +1562,10 @@ __lookupalias(const char *name) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ASH_MATH_SUPPORT
|
#ifdef ASH_MATH_SUPPORT
|
||||||
/* The generated file arith.c has been snipped. If you want this
|
/* The generated file arith.c has been replaced with a custom hand
|
||||||
* stuff back in, feel free to add it to your own copy. */
|
* written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
|
||||||
|
* This is now part of libbb, so that it can be used by all the shells
|
||||||
|
* in busybox. */
|
||||||
#define ARITH_NUM 257
|
#define ARITH_NUM 257
|
||||||
#define ARITH_LPAREN 258
|
#define ARITH_LPAREN 258
|
||||||
#define ARITH_RPAREN 259
|
#define ARITH_RPAREN 259
|
||||||
@ -1592,11 +1594,8 @@ __lookupalias(const char *name) {
|
|||||||
|
|
||||||
static void expari (int);
|
static void expari (int);
|
||||||
/* From arith.y */
|
/* From arith.y */
|
||||||
static int arith (const char *);
|
static long ash_arith(const char *p);
|
||||||
static int expcmd (int , char **);
|
static int expcmd (int , char **);
|
||||||
static void arith_lex_reset (void);
|
|
||||||
static int yylex (void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *trap[NSIG]; /* trap handler commands */
|
static char *trap[NSIG]; /* trap handler commands */
|
||||||
@ -2173,52 +2172,22 @@ exverror(int cond, const char *msg, va_list ap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
static void
|
||||||
static void
|
|
||||||
error(const char *msg, ...)
|
error(const char *msg, ...)
|
||||||
#else
|
|
||||||
static void
|
|
||||||
error(va_alist)
|
|
||||||
va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
#ifndef __STDC__
|
|
||||||
const char *msg;
|
|
||||||
#endif
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
msg = va_arg(ap, const char *);
|
|
||||||
#endif
|
|
||||||
exverror(EXERROR, msg, ap);
|
exverror(EXERROR, msg, ap);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
static void
|
static void
|
||||||
exerror(int cond, const char *msg, ...)
|
exerror(int cond, const char *msg, ...)
|
||||||
#else
|
|
||||||
static void
|
|
||||||
exerror(va_alist)
|
|
||||||
va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
#ifndef __STDC__
|
|
||||||
int cond;
|
|
||||||
const char *msg;
|
|
||||||
#endif
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
cond = va_arg(ap, int);
|
|
||||||
msg = va_arg(ap, const char *);
|
|
||||||
#endif
|
|
||||||
exverror(cond, msg, ap);
|
exverror(cond, msg, ap);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@ -4914,7 +4883,7 @@ expari(int flag)
|
|||||||
removerecordregions(begoff);
|
removerecordregions(begoff);
|
||||||
if (quotes)
|
if (quotes)
|
||||||
rmescapes(p+2);
|
rmescapes(p+2);
|
||||||
result = arith(p+2);
|
result = ash_arith(p+2);
|
||||||
snprintf(p, 12, "%d", result);
|
snprintf(p, 12, "%d", result);
|
||||||
|
|
||||||
while (*p++)
|
while (*p++)
|
||||||
@ -11952,13 +11921,7 @@ static void
|
|||||||
trace(const char *fmt, ...)
|
trace(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
#else
|
|
||||||
char *fmt;
|
|
||||||
va_start(va);
|
|
||||||
fmt = va_arg(va, char *);
|
|
||||||
#endif
|
|
||||||
if (tracefile != NULL) {
|
if (tracefile != NULL) {
|
||||||
(void) vfprintf(tracefile, fmt, va);
|
(void) vfprintf(tracefile, fmt, va);
|
||||||
if (strchr(fmt, '\n'))
|
if (strchr(fmt, '\n'))
|
||||||
@ -12657,7 +12620,6 @@ found:;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "local" command.
|
* The "local" command.
|
||||||
*/
|
*/
|
||||||
@ -12916,7 +12878,7 @@ findvar(struct var **vpp, const char *name)
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999 Herbert Xu <herbert@debian.org>
|
* Copyright (c) 1999 Herbert Xu <herbert@debian.org>
|
||||||
* This file contains code for the times builtin.
|
* This file contains code for the times builtin.
|
||||||
* $Id: ash.c,v 1.13 2001/07/26 05:58:40 russ Exp $
|
* $Id: ash.c,v 1.14 2001/07/30 21:41:37 andersen Exp $
|
||||||
*/
|
*/
|
||||||
static int timescmd (int argc, char **argv)
|
static int timescmd (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -12937,6 +12899,51 @@ static int timescmd (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ASH_MATH_SUPPORT
|
||||||
|
/* The exp(1) builtin. */
|
||||||
|
int expcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char *concat;
|
||||||
|
char **ap;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
p = argv[1];
|
||||||
|
if (argc > 2) {
|
||||||
|
/* concatenate arguments */
|
||||||
|
STARTSTACKSTR(concat);
|
||||||
|
ap = argv + 2;
|
||||||
|
for (;;) {
|
||||||
|
while (*p)
|
||||||
|
STPUTC(*p++, concat);
|
||||||
|
if ((p = *ap++) == NULL)
|
||||||
|
break;
|
||||||
|
STPUTC(' ', concat);
|
||||||
|
}
|
||||||
|
STPUTC('\0', concat);
|
||||||
|
p = grabstackstr(concat);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
p = "";
|
||||||
|
|
||||||
|
i = ash_arith(p);
|
||||||
|
|
||||||
|
printf("%ld\n", i);
|
||||||
|
return (! i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long ash_arith(const char *p)
|
||||||
|
{
|
||||||
|
long i = arith(p);
|
||||||
|
if (i <0)
|
||||||
|
error("arith: syntax error: \"%s\"\n", p);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1989, 1991, 1993, 1994
|
* Copyright (c) 1989, 1991, 1993, 1994
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -212,6 +212,8 @@ char *xreadlink(const char *path);
|
|||||||
char *concat_path_file(const char *path, const char *filename);
|
char *concat_path_file(const char *path, const char *filename);
|
||||||
char *last_char_is(const char *s, int c);
|
char *last_char_is(const char *s, int c);
|
||||||
|
|
||||||
|
extern long arith (const char *startbuf);
|
||||||
|
|
||||||
typedef struct file_headers_s {
|
typedef struct file_headers_s {
|
||||||
char *name;
|
char *name;
|
||||||
char *link_name;
|
char *link_name;
|
||||||
|
250
libbb/arith.c
Normal file
250
libbb/arith.c
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
/* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is my infix parser/evaluator. It is optimized for size, intended
|
||||||
|
* as a replacement for yacc-based parsers. However, it may well be faster
|
||||||
|
* than a comparable parser writen in yacc. The supported operators are
|
||||||
|
* listed in #defines below. Parens, order of operations, and error handling
|
||||||
|
* are supported. This code is threadsafe. */
|
||||||
|
|
||||||
|
/* To use the routine, call it with an expression string. It returns an
|
||||||
|
* integer result. You will also need to define an "error" function
|
||||||
|
* that takes printf arguments and _does not return_, or modify the code
|
||||||
|
* to use another error mechanism. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "libbb.h"
|
||||||
|
|
||||||
|
typedef char operator;
|
||||||
|
|
||||||
|
#define tok_decl(prec,id) (((id)<<5)|(prec))
|
||||||
|
#define PREC(op) ((op)&0x1F)
|
||||||
|
|
||||||
|
#define TOK_LPAREN tok_decl(0,0)
|
||||||
|
|
||||||
|
#define TOK_OR tok_decl(1,0)
|
||||||
|
|
||||||
|
#define TOK_AND tok_decl(2,0)
|
||||||
|
|
||||||
|
#define TOK_BOR tok_decl(3,0)
|
||||||
|
|
||||||
|
#define TOK_BXOR tok_decl(4,0)
|
||||||
|
|
||||||
|
#define TOK_BAND tok_decl(5,0)
|
||||||
|
|
||||||
|
#define TOK_EQ tok_decl(6,0)
|
||||||
|
#define TOK_NE tok_decl(6,1)
|
||||||
|
|
||||||
|
#define TOK_LT tok_decl(7,0)
|
||||||
|
#define TOK_GT tok_decl(7,1)
|
||||||
|
#define TOK_GE tok_decl(7,2)
|
||||||
|
#define TOK_LE tok_decl(7,3)
|
||||||
|
|
||||||
|
#define TOK_LSHIFT tok_decl(8,0)
|
||||||
|
#define TOK_RSHIFT tok_decl(8,1)
|
||||||
|
|
||||||
|
#define TOK_ADD tok_decl(9,0)
|
||||||
|
#define TOK_SUB tok_decl(9,1)
|
||||||
|
|
||||||
|
#define TOK_MUL tok_decl(10,0)
|
||||||
|
#define TOK_DIV tok_decl(10,1)
|
||||||
|
#define TOK_REM tok_decl(10,2)
|
||||||
|
|
||||||
|
#define UNARYPREC 14
|
||||||
|
#define TOK_BNOT tok_decl(UNARYPREC,0)
|
||||||
|
#define TOK_NOT tok_decl(UNARYPREC,1)
|
||||||
|
#define TOK_UMINUS tok_decl(UNARYPREC,2)
|
||||||
|
|
||||||
|
#define TOK_NUM tok_decl(15,0)
|
||||||
|
|
||||||
|
#define ARITH_APPLY(op) arith_apply(op, numstack, &numstackptr)
|
||||||
|
#define NUMPTR (*numstackptr)
|
||||||
|
static short arith_apply(operator op, long *numstack, long **numstackptr)
|
||||||
|
{
|
||||||
|
if (NUMPTR == numstack) goto err;
|
||||||
|
if (op == TOK_UMINUS)
|
||||||
|
NUMPTR[-1] *= -1;
|
||||||
|
else if (op == TOK_NOT)
|
||||||
|
NUMPTR[-1] = !(NUMPTR[-1]);
|
||||||
|
else if (op == TOK_BNOT)
|
||||||
|
NUMPTR[-1] = ~(NUMPTR[-1]);
|
||||||
|
|
||||||
|
/* Binary operators */
|
||||||
|
else {
|
||||||
|
if (NUMPTR-1 == numstack) goto err;
|
||||||
|
--NUMPTR;
|
||||||
|
if (op == TOK_BOR)
|
||||||
|
NUMPTR[-1] |= *NUMPTR;
|
||||||
|
else if (op == TOK_OR)
|
||||||
|
NUMPTR[-1] = *NUMPTR || NUMPTR[-1];
|
||||||
|
else if (op == TOK_BAND)
|
||||||
|
NUMPTR[-1] &= *NUMPTR;
|
||||||
|
else if (op == TOK_AND)
|
||||||
|
NUMPTR[-1] = NUMPTR[-1] && *NUMPTR;
|
||||||
|
else if (op == TOK_EQ)
|
||||||
|
NUMPTR[-1] = (NUMPTR[-1] == *NUMPTR);
|
||||||
|
else if (op == TOK_NE)
|
||||||
|
NUMPTR[-1] = (NUMPTR[-1] != *NUMPTR);
|
||||||
|
else if (op == TOK_GE)
|
||||||
|
NUMPTR[-1] = (NUMPTR[-1] >= *NUMPTR);
|
||||||
|
else if (op == TOK_RSHIFT)
|
||||||
|
NUMPTR[-1] >>= *NUMPTR;
|
||||||
|
else if (op == TOK_LSHIFT)
|
||||||
|
NUMPTR[-1] <<= *NUMPTR;
|
||||||
|
else if (op == TOK_GT)
|
||||||
|
NUMPTR[-1] = (NUMPTR[-1] > *NUMPTR);
|
||||||
|
else if (op == TOK_LT)
|
||||||
|
NUMPTR[-1] = (NUMPTR[-1] < *NUMPTR);
|
||||||
|
else if (op == TOK_LE)
|
||||||
|
NUMPTR[-1] = (NUMPTR[-1] <= *NUMPTR);
|
||||||
|
else if (op == TOK_MUL)
|
||||||
|
NUMPTR[-1] *= *NUMPTR;
|
||||||
|
else if (op == TOK_DIV)
|
||||||
|
NUMPTR[-1] /= *NUMPTR;
|
||||||
|
else if (op == TOK_REM)
|
||||||
|
NUMPTR[-1] %= *NUMPTR;
|
||||||
|
else if (op == TOK_ADD)
|
||||||
|
NUMPTR[-1] += *NUMPTR;
|
||||||
|
else if (op == TOK_SUB)
|
||||||
|
NUMPTR[-1] -= *NUMPTR;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
err: return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern long arith (const char *startbuf)
|
||||||
|
{
|
||||||
|
register char arithval;
|
||||||
|
const char *expr = startbuf;
|
||||||
|
|
||||||
|
operator lasttok = TOK_MUL, op;
|
||||||
|
size_t datasizes = strlen(startbuf);
|
||||||
|
unsigned char prec;
|
||||||
|
|
||||||
|
long *numstack, *numstackptr;
|
||||||
|
|
||||||
|
operator *stack = alloca(datasizes * sizeof(operator)), *stackptr = stack;
|
||||||
|
numstack = alloca((datasizes/2+1)*sizeof(long)), numstackptr = numstack;
|
||||||
|
|
||||||
|
while ((arithval = *expr)) {
|
||||||
|
if (arithval == ' ' || arithval == '\n' || arithval == '\t')
|
||||||
|
goto prologue;
|
||||||
|
if ((unsigned)arithval-'0' <= 9) /* isdigit */ {
|
||||||
|
*numstackptr++ = strtol(expr, (char **) &expr, 10);
|
||||||
|
lasttok = TOK_NUM;
|
||||||
|
continue;
|
||||||
|
} if (arithval == '(') {
|
||||||
|
*stackptr++ = TOK_LPAREN;
|
||||||
|
lasttok = TOK_LPAREN;
|
||||||
|
goto prologue;
|
||||||
|
} if (arithval == ')') {
|
||||||
|
lasttok = TOK_NUM;
|
||||||
|
while (stackptr != stack) {
|
||||||
|
op = *--stackptr;
|
||||||
|
if (op == TOK_LPAREN)
|
||||||
|
goto prologue;
|
||||||
|
if(ARITH_APPLY(op)) goto err;
|
||||||
|
}
|
||||||
|
goto err; /* Mismatched parens */
|
||||||
|
} if (arithval == '|') {
|
||||||
|
if (*++expr == '|')
|
||||||
|
op = TOK_OR;
|
||||||
|
else {
|
||||||
|
--expr;
|
||||||
|
op = TOK_BOR;
|
||||||
|
}
|
||||||
|
} else if (arithval == '&') {
|
||||||
|
if (*++expr == '&')
|
||||||
|
op = TOK_AND;
|
||||||
|
else {
|
||||||
|
--expr;
|
||||||
|
op = TOK_BAND;
|
||||||
|
}
|
||||||
|
} else if (arithval == '=') {
|
||||||
|
if (*++expr != '=') goto err; /* Unknown token */
|
||||||
|
op = TOK_EQ;
|
||||||
|
} else if (arithval == '!') {
|
||||||
|
if (*++expr == '=')
|
||||||
|
op = TOK_NE;
|
||||||
|
else {
|
||||||
|
--expr;
|
||||||
|
op = TOK_NOT;
|
||||||
|
}
|
||||||
|
} else if (arithval == '>') {
|
||||||
|
switch (*++expr) {
|
||||||
|
case '=':
|
||||||
|
op = TOK_GE;
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
op = TOK_RSHIFT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
--expr;
|
||||||
|
op = TOK_GT;
|
||||||
|
}
|
||||||
|
} else if (arithval == '<') {
|
||||||
|
switch (*++expr) {
|
||||||
|
case '=':
|
||||||
|
op = TOK_LE;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
op = TOK_LSHIFT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
--expr;
|
||||||
|
op = TOK_LT;
|
||||||
|
}
|
||||||
|
} else if (arithval == '*')
|
||||||
|
op = TOK_MUL;
|
||||||
|
else if (arithval == '/')
|
||||||
|
op = TOK_DIV;
|
||||||
|
else if (arithval == '%')
|
||||||
|
op = TOK_REM;
|
||||||
|
else if (arithval == '+') {
|
||||||
|
if (lasttok != TOK_NUM) goto prologue; /* Unary plus */
|
||||||
|
op = TOK_ADD;
|
||||||
|
} else if (arithval == '-')
|
||||||
|
op = (lasttok == TOK_NUM) ? TOK_SUB : TOK_UMINUS;
|
||||||
|
else if (arithval == '~')
|
||||||
|
op = TOK_BNOT;
|
||||||
|
else goto err; /* Unknown token */
|
||||||
|
|
||||||
|
prec = PREC(op);
|
||||||
|
if (prec != UNARYPREC)
|
||||||
|
while (stackptr != stack && PREC(stackptr[-1]) >= prec)
|
||||||
|
if(ARITH_APPLY(*--stackptr)) goto err;
|
||||||
|
*stackptr++ = op;
|
||||||
|
lasttok = op;
|
||||||
|
prologue: ++expr;
|
||||||
|
} /* yay */
|
||||||
|
|
||||||
|
while (stackptr != stack)
|
||||||
|
if(ARITH_APPLY(*--stackptr)) goto err;
|
||||||
|
if (numstackptr != numstack+1) {
|
||||||
|
err:
|
||||||
|
return -1;
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
return *numstack;
|
||||||
|
}
|
@ -212,6 +212,8 @@ char *xreadlink(const char *path);
|
|||||||
char *concat_path_file(const char *path, const char *filename);
|
char *concat_path_file(const char *path, const char *filename);
|
||||||
char *last_char_is(const char *s, int c);
|
char *last_char_is(const char *s, int c);
|
||||||
|
|
||||||
|
extern long arith (const char *startbuf);
|
||||||
|
|
||||||
typedef struct file_headers_s {
|
typedef struct file_headers_s {
|
||||||
char *name;
|
char *name;
|
||||||
char *link_name;
|
char *link_name;
|
||||||
|
105
shell/ash.c
105
shell/ash.c
@ -51,9 +51,8 @@
|
|||||||
#define ASH_ALIAS
|
#define ASH_ALIAS
|
||||||
|
|
||||||
/* If you need ash to act as a full Posix shell, with full math
|
/* If you need ash to act as a full Posix shell, with full math
|
||||||
* support, enable this. This option needs some work, since it
|
* support, enable this. This adds a bit over 2k an x86 system. */
|
||||||
* doesn't compile right now... */
|
#define ASH_MATH_SUPPORT
|
||||||
#undef ASH_MATH_SUPPORT
|
|
||||||
|
|
||||||
/* Getopts is used by shell procedures to parse positional parameters.
|
/* Getopts is used by shell procedures to parse positional parameters.
|
||||||
* You probably want to leave this disabled, and use the busybox getopt
|
* You probably want to leave this disabled, and use the busybox getopt
|
||||||
@ -80,6 +79,7 @@
|
|||||||
#undef FNMATCH_BROKEN
|
#undef FNMATCH_BROKEN
|
||||||
#undef GLOB_BROKEN
|
#undef GLOB_BROKEN
|
||||||
#undef _GNU_SOURCE
|
#undef _GNU_SOURCE
|
||||||
|
#undef __USE_GNU
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -1562,8 +1562,10 @@ __lookupalias(const char *name) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ASH_MATH_SUPPORT
|
#ifdef ASH_MATH_SUPPORT
|
||||||
/* The generated file arith.c has been snipped. If you want this
|
/* The generated file arith.c has been replaced with a custom hand
|
||||||
* stuff back in, feel free to add it to your own copy. */
|
* written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
|
||||||
|
* This is now part of libbb, so that it can be used by all the shells
|
||||||
|
* in busybox. */
|
||||||
#define ARITH_NUM 257
|
#define ARITH_NUM 257
|
||||||
#define ARITH_LPAREN 258
|
#define ARITH_LPAREN 258
|
||||||
#define ARITH_RPAREN 259
|
#define ARITH_RPAREN 259
|
||||||
@ -1592,11 +1594,8 @@ __lookupalias(const char *name) {
|
|||||||
|
|
||||||
static void expari (int);
|
static void expari (int);
|
||||||
/* From arith.y */
|
/* From arith.y */
|
||||||
static int arith (const char *);
|
static long ash_arith(const char *p);
|
||||||
static int expcmd (int , char **);
|
static int expcmd (int , char **);
|
||||||
static void arith_lex_reset (void);
|
|
||||||
static int yylex (void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *trap[NSIG]; /* trap handler commands */
|
static char *trap[NSIG]; /* trap handler commands */
|
||||||
@ -2173,52 +2172,22 @@ exverror(int cond, const char *msg, va_list ap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
static void
|
||||||
static void
|
|
||||||
error(const char *msg, ...)
|
error(const char *msg, ...)
|
||||||
#else
|
|
||||||
static void
|
|
||||||
error(va_alist)
|
|
||||||
va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
#ifndef __STDC__
|
|
||||||
const char *msg;
|
|
||||||
#endif
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
msg = va_arg(ap, const char *);
|
|
||||||
#endif
|
|
||||||
exverror(EXERROR, msg, ap);
|
exverror(EXERROR, msg, ap);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
static void
|
static void
|
||||||
exerror(int cond, const char *msg, ...)
|
exerror(int cond, const char *msg, ...)
|
||||||
#else
|
|
||||||
static void
|
|
||||||
exerror(va_alist)
|
|
||||||
va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
#ifndef __STDC__
|
|
||||||
int cond;
|
|
||||||
const char *msg;
|
|
||||||
#endif
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
cond = va_arg(ap, int);
|
|
||||||
msg = va_arg(ap, const char *);
|
|
||||||
#endif
|
|
||||||
exverror(cond, msg, ap);
|
exverror(cond, msg, ap);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@ -4914,7 +4883,7 @@ expari(int flag)
|
|||||||
removerecordregions(begoff);
|
removerecordregions(begoff);
|
||||||
if (quotes)
|
if (quotes)
|
||||||
rmescapes(p+2);
|
rmescapes(p+2);
|
||||||
result = arith(p+2);
|
result = ash_arith(p+2);
|
||||||
snprintf(p, 12, "%d", result);
|
snprintf(p, 12, "%d", result);
|
||||||
|
|
||||||
while (*p++)
|
while (*p++)
|
||||||
@ -11952,13 +11921,7 @@ static void
|
|||||||
trace(const char *fmt, ...)
|
trace(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
#else
|
|
||||||
char *fmt;
|
|
||||||
va_start(va);
|
|
||||||
fmt = va_arg(va, char *);
|
|
||||||
#endif
|
|
||||||
if (tracefile != NULL) {
|
if (tracefile != NULL) {
|
||||||
(void) vfprintf(tracefile, fmt, va);
|
(void) vfprintf(tracefile, fmt, va);
|
||||||
if (strchr(fmt, '\n'))
|
if (strchr(fmt, '\n'))
|
||||||
@ -12657,7 +12620,6 @@ found:;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "local" command.
|
* The "local" command.
|
||||||
*/
|
*/
|
||||||
@ -12916,7 +12878,7 @@ findvar(struct var **vpp, const char *name)
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999 Herbert Xu <herbert@debian.org>
|
* Copyright (c) 1999 Herbert Xu <herbert@debian.org>
|
||||||
* This file contains code for the times builtin.
|
* This file contains code for the times builtin.
|
||||||
* $Id: ash.c,v 1.13 2001/07/26 05:58:40 russ Exp $
|
* $Id: ash.c,v 1.14 2001/07/30 21:41:37 andersen Exp $
|
||||||
*/
|
*/
|
||||||
static int timescmd (int argc, char **argv)
|
static int timescmd (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -12937,6 +12899,51 @@ static int timescmd (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ASH_MATH_SUPPORT
|
||||||
|
/* The exp(1) builtin. */
|
||||||
|
int expcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char *concat;
|
||||||
|
char **ap;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
p = argv[1];
|
||||||
|
if (argc > 2) {
|
||||||
|
/* concatenate arguments */
|
||||||
|
STARTSTACKSTR(concat);
|
||||||
|
ap = argv + 2;
|
||||||
|
for (;;) {
|
||||||
|
while (*p)
|
||||||
|
STPUTC(*p++, concat);
|
||||||
|
if ((p = *ap++) == NULL)
|
||||||
|
break;
|
||||||
|
STPUTC(' ', concat);
|
||||||
|
}
|
||||||
|
STPUTC('\0', concat);
|
||||||
|
p = grabstackstr(concat);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
p = "";
|
||||||
|
|
||||||
|
i = ash_arith(p);
|
||||||
|
|
||||||
|
printf("%ld\n", i);
|
||||||
|
return (! i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long ash_arith(const char *p)
|
||||||
|
{
|
||||||
|
long i = arith(p);
|
||||||
|
if (i <0)
|
||||||
|
error("arith: syntax error: \"%s\"\n", p);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1989, 1991, 1993, 1994
|
* Copyright (c) 1989, 1991, 1993, 1994
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
Loading…
Reference in New Issue
Block a user