aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-07-30 21:41:37 +0000
committerEric Andersen <andersen@codepoet.org>2001-07-30 21:41:37 +0000
commit74bcd1642597109661543d25304c551a2e39acbc (patch)
treef54a28df9cd460c1da85e13e6fe1b387199f92df
parentdc6647201da6d5cf044f4b54fe9826c89068b782 (diff)
downloadbusybox-w32-74bcd1642597109661543d25304c551a2e39acbc.tar.gz
busybox-w32-74bcd1642597109661543d25304c551a2e39acbc.tar.bz2
busybox-w32-74bcd1642597109661543d25304c551a2e39acbc.zip
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
-rw-r--r--Makefile2
-rw-r--r--ash.c105
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/arith.c250
-rw-r--r--libbb/libbb.h2
-rw-r--r--shell/ash.c105
6 files changed, 367 insertions, 99 deletions
diff --git a/Makefile b/Makefile
index 7ee55f857..88a7aa0df 100644
--- a/Makefile
+++ b/Makefile
@@ -247,7 +247,7 @@ safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \
247trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \ 247trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
248xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ 248xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
249copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \ 249copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
250dirname.c make_directory.c create_icmp_socket.c 250dirname.c make_directory.c create_icmp_socket.c arith.c
251LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC)) 251LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
252LIBBB_CFLAGS = -I$(LIBBB) 252LIBBB_CFLAGS = -I$(LIBBB)
253ifneq ($(strip $(BB_SRC_DIR)),) 253ifneq ($(strip $(BB_SRC_DIR)),)
diff --git a/ash.c b/ash.c
index bb5bf3601..9a5435e8b 100644
--- a/ash.c
+++ b/ash.c
@@ -51,9 +51,8 @@
51#define ASH_ALIAS 51#define ASH_ALIAS
52 52
53/* If you need ash to act as a full Posix shell, with full math 53/* If you need ash to act as a full Posix shell, with full math
54 * support, enable this. This option needs some work, since it 54 * support, enable this. This adds a bit over 2k an x86 system. */
55 * doesn't compile right now... */ 55#define ASH_MATH_SUPPORT
56#undef ASH_MATH_SUPPORT
57 56
58/* Getopts is used by shell procedures to parse positional parameters. 57/* Getopts is used by shell procedures to parse positional parameters.
59 * You probably want to leave this disabled, and use the busybox getopt 58 * You probably want to leave this disabled, and use the busybox getopt
@@ -80,6 +79,7 @@
80#undef FNMATCH_BROKEN 79#undef FNMATCH_BROKEN
81#undef GLOB_BROKEN 80#undef GLOB_BROKEN
82#undef _GNU_SOURCE 81#undef _GNU_SOURCE
82#undef __USE_GNU
83 83
84#include <assert.h> 84#include <assert.h>
85#include <ctype.h> 85#include <ctype.h>
@@ -1562,8 +1562,10 @@ __lookupalias(const char *name) {
1562#endif 1562#endif
1563 1563
1564#ifdef ASH_MATH_SUPPORT 1564#ifdef ASH_MATH_SUPPORT
1565/* The generated file arith.c has been snipped. If you want this 1565/* The generated file arith.c has been replaced with a custom hand
1566 * stuff back in, feel free to add it to your own copy. */ 1566 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1567 * This is now part of libbb, so that it can be used by all the shells
1568 * in busybox. */
1567#define ARITH_NUM 257 1569#define ARITH_NUM 257
1568#define ARITH_LPAREN 258 1570#define ARITH_LPAREN 258
1569#define ARITH_RPAREN 259 1571#define ARITH_RPAREN 259
@@ -1592,11 +1594,8 @@ __lookupalias(const char *name) {
1592 1594
1593static void expari (int); 1595static void expari (int);
1594/* From arith.y */ 1596/* From arith.y */
1595static int arith (const char *); 1597static long ash_arith(const char *p);
1596static int expcmd (int , char **); 1598static int expcmd (int , char **);
1597static void arith_lex_reset (void);
1598static int yylex (void);
1599
1600#endif 1599#endif
1601 1600
1602static char *trap[NSIG]; /* trap handler commands */ 1601static char *trap[NSIG]; /* trap handler commands */
@@ -2173,52 +2172,22 @@ exverror(int cond, const char *msg, va_list ap)
2173} 2172}
2174 2173
2175 2174
2176#ifdef __STDC__ 2175static void
2177static void
2178error(const char *msg, ...) 2176error(const char *msg, ...)
2179#else
2180static void
2181error(va_alist)
2182 va_dcl
2183#endif
2184{ 2177{
2185#ifndef __STDC__
2186 const char *msg;
2187#endif
2188 va_list ap; 2178 va_list ap;
2189#ifdef __STDC__
2190 va_start(ap, msg); 2179 va_start(ap, msg);
2191#else
2192 va_start(ap);
2193 msg = va_arg(ap, const char *);
2194#endif
2195 exverror(EXERROR, msg, ap); 2180 exverror(EXERROR, msg, ap);
2196 /* NOTREACHED */ 2181 /* NOTREACHED */
2197 va_end(ap); 2182 va_end(ap);
2198} 2183}
2199 2184
2200 2185
2201#ifdef __STDC__
2202static void 2186static void
2203exerror(int cond, const char *msg, ...) 2187exerror(int cond, const char *msg, ...)
2204#else
2205static void
2206exerror(va_alist)
2207 va_dcl
2208#endif
2209{ 2188{
2210#ifndef __STDC__
2211 int cond;
2212 const char *msg;
2213#endif
2214 va_list ap; 2189 va_list ap;
2215#ifdef __STDC__
2216 va_start(ap, msg); 2190 va_start(ap, msg);
2217#else
2218 va_start(ap);
2219 cond = va_arg(ap, int);
2220 msg = va_arg(ap, const char *);
2221#endif
2222 exverror(cond, msg, ap); 2191 exverror(cond, msg, ap);
2223 /* NOTREACHED */ 2192 /* NOTREACHED */
2224 va_end(ap); 2193 va_end(ap);
@@ -4914,7 +4883,7 @@ expari(int flag)
4914 removerecordregions(begoff); 4883 removerecordregions(begoff);
4915 if (quotes) 4884 if (quotes)
4916 rmescapes(p+2); 4885 rmescapes(p+2);
4917 result = arith(p+2); 4886 result = ash_arith(p+2);
4918 snprintf(p, 12, "%d", result); 4887 snprintf(p, 12, "%d", result);
4919 4888
4920 while (*p++) 4889 while (*p++)
@@ -11952,13 +11921,7 @@ static void
11952trace(const char *fmt, ...) 11921trace(const char *fmt, ...)
11953{ 11922{
11954 va_list va; 11923 va_list va;
11955#ifdef __STDC__
11956 va_start(va, fmt); 11924 va_start(va, fmt);
11957#else
11958 char *fmt;
11959 va_start(va);
11960 fmt = va_arg(va, char *);
11961#endif
11962 if (tracefile != NULL) { 11925 if (tracefile != NULL) {
11963 (void) vfprintf(tracefile, fmt, va); 11926 (void) vfprintf(tracefile, fmt, va);
11964 if (strchr(fmt, '\n')) 11927 if (strchr(fmt, '\n'))
@@ -12657,7 +12620,6 @@ found:;
12657 return 0; 12620 return 0;
12658} 12621}
12659 12622
12660
12661/* 12623/*
12662 * The "local" command. 12624 * The "local" command.
12663 */ 12625 */
@@ -12916,7 +12878,7 @@ findvar(struct var **vpp, const char *name)
12916/* 12878/*
12917 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12879 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12918 * This file contains code for the times builtin. 12880 * This file contains code for the times builtin.
12919 * $Id: ash.c,v 1.13 2001/07/26 05:58:40 russ Exp $ 12881 * $Id: ash.c,v 1.14 2001/07/30 21:41:37 andersen Exp $
12920 */ 12882 */
12921static int timescmd (int argc, char **argv) 12883static int timescmd (int argc, char **argv)
12922{ 12884{
@@ -12937,6 +12899,51 @@ static int timescmd (int argc, char **argv)
12937} 12899}
12938 12900
12939 12901
12902#ifdef ASH_MATH_SUPPORT
12903/* The exp(1) builtin. */
12904int expcmd(int argc, char **argv)
12905{
12906 const char *p;
12907 char *concat;
12908 char **ap;
12909 long i;
12910
12911 if (argc > 1) {
12912 p = argv[1];
12913 if (argc > 2) {
12914 /* concatenate arguments */
12915 STARTSTACKSTR(concat);
12916 ap = argv + 2;
12917 for (;;) {
12918 while (*p)
12919 STPUTC(*p++, concat);
12920 if ((p = *ap++) == NULL)
12921 break;
12922 STPUTC(' ', concat);
12923 }
12924 STPUTC('\0', concat);
12925 p = grabstackstr(concat);
12926 }
12927 } else
12928 p = "";
12929
12930 i = ash_arith(p);
12931
12932 printf("%ld\n", i);
12933 return (! i);
12934}
12935
12936static long ash_arith(const char *p)
12937{
12938 long i = arith(p);
12939 if (i <0)
12940 error("arith: syntax error: \"%s\"\n", p);
12941 return i;
12942}
12943#endif
12944
12945
12946
12940/*- 12947/*-
12941 * Copyright (c) 1989, 1991, 1993, 1994 12948 * Copyright (c) 1989, 1991, 1993, 1994
12942 * The Regents of the University of California. All rights reserved. 12949 * The Regents of the University of California. All rights reserved.
diff --git a/include/libbb.h b/include/libbb.h
index 3cf932dc4..66acc2278 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -212,6 +212,8 @@ char *xreadlink(const char *path);
212char *concat_path_file(const char *path, const char *filename); 212char *concat_path_file(const char *path, const char *filename);
213char *last_char_is(const char *s, int c); 213char *last_char_is(const char *s, int c);
214 214
215extern long arith (const char *startbuf);
216
215typedef struct file_headers_s { 217typedef struct file_headers_s {
216 char *name; 218 char *name;
217 char *link_name; 219 char *link_name;
diff --git a/libbb/arith.c b/libbb/arith.c
new file mode 100644
index 000000000..c7a3cf98b
--- /dev/null
+++ b/libbb/arith.c
@@ -0,0 +1,250 @@
1/* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
2
3 Permission is hereby granted, free of charge, to any person obtaining
4 a copy of this software and associated documentation files (the
5 "Software"), to deal in the Software without restriction, including
6 without limitation the rights to use, copy, modify, merge, publish,
7 distribute, sublicense, and/or sell copies of the Software, and to
8 permit persons to whom the Software is furnished to do so, subject to
9 the following conditions:
10
11 The above copyright notice and this permission notice shall be
12 included in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*/
22
23/* This is my infix parser/evaluator. It is optimized for size, intended
24 * as a replacement for yacc-based parsers. However, it may well be faster
25 * than a comparable parser writen in yacc. The supported operators are
26 * listed in #defines below. Parens, order of operations, and error handling
27 * are supported. This code is threadsafe. */
28
29/* To use the routine, call it with an expression string. It returns an
30 * integer result. You will also need to define an "error" function
31 * that takes printf arguments and _does not return_, or modify the code
32 * to use another error mechanism. */
33
34#include <stdlib.h>
35#include <string.h>
36#include "libbb.h"
37
38typedef char operator;
39
40#define tok_decl(prec,id) (((id)<<5)|(prec))
41#define PREC(op) ((op)&0x1F)
42
43#define TOK_LPAREN tok_decl(0,0)
44
45#define TOK_OR tok_decl(1,0)
46
47#define TOK_AND tok_decl(2,0)
48
49#define TOK_BOR tok_decl(3,0)
50
51#define TOK_BXOR tok_decl(4,0)
52
53#define TOK_BAND tok_decl(5,0)
54
55#define TOK_EQ tok_decl(6,0)
56#define TOK_NE tok_decl(6,1)
57
58#define TOK_LT tok_decl(7,0)
59#define TOK_GT tok_decl(7,1)
60#define TOK_GE tok_decl(7,2)
61#define TOK_LE tok_decl(7,3)
62
63#define TOK_LSHIFT tok_decl(8,0)
64#define TOK_RSHIFT tok_decl(8,1)
65
66#define TOK_ADD tok_decl(9,0)
67#define TOK_SUB tok_decl(9,1)
68
69#define TOK_MUL tok_decl(10,0)
70#define TOK_DIV tok_decl(10,1)
71#define TOK_REM tok_decl(10,2)
72
73#define UNARYPREC 14
74#define TOK_BNOT tok_decl(UNARYPREC,0)
75#define TOK_NOT tok_decl(UNARYPREC,1)
76#define TOK_UMINUS tok_decl(UNARYPREC,2)
77
78#define TOK_NUM tok_decl(15,0)
79
80#define ARITH_APPLY(op) arith_apply(op, numstack, &numstackptr)
81#define NUMPTR (*numstackptr)
82static short arith_apply(operator op, long *numstack, long **numstackptr)
83{
84 if (NUMPTR == numstack) goto err;
85 if (op == TOK_UMINUS)
86 NUMPTR[-1] *= -1;
87 else if (op == TOK_NOT)
88 NUMPTR[-1] = !(NUMPTR[-1]);
89 else if (op == TOK_BNOT)
90 NUMPTR[-1] = ~(NUMPTR[-1]);
91
92 /* Binary operators */
93 else {
94 if (NUMPTR-1 == numstack) goto err;
95 --NUMPTR;
96 if (op == TOK_BOR)
97 NUMPTR[-1] |= *NUMPTR;
98 else if (op == TOK_OR)
99 NUMPTR[-1] = *NUMPTR || NUMPTR[-1];
100 else if (op == TOK_BAND)
101 NUMPTR[-1] &= *NUMPTR;
102 else if (op == TOK_AND)
103 NUMPTR[-1] = NUMPTR[-1] && *NUMPTR;
104 else if (op == TOK_EQ)
105 NUMPTR[-1] = (NUMPTR[-1] == *NUMPTR);
106 else if (op == TOK_NE)
107 NUMPTR[-1] = (NUMPTR[-1] != *NUMPTR);
108 else if (op == TOK_GE)
109 NUMPTR[-1] = (NUMPTR[-1] >= *NUMPTR);
110 else if (op == TOK_RSHIFT)
111 NUMPTR[-1] >>= *NUMPTR;
112 else if (op == TOK_LSHIFT)
113 NUMPTR[-1] <<= *NUMPTR;
114 else if (op == TOK_GT)
115 NUMPTR[-1] = (NUMPTR[-1] > *NUMPTR);
116 else if (op == TOK_LT)
117 NUMPTR[-1] = (NUMPTR[-1] < *NUMPTR);
118 else if (op == TOK_LE)
119 NUMPTR[-1] = (NUMPTR[-1] <= *NUMPTR);
120 else if (op == TOK_MUL)
121 NUMPTR[-1] *= *NUMPTR;
122 else if (op == TOK_DIV)
123 NUMPTR[-1] /= *NUMPTR;
124 else if (op == TOK_REM)
125 NUMPTR[-1] %= *NUMPTR;
126 else if (op == TOK_ADD)
127 NUMPTR[-1] += *NUMPTR;
128 else if (op == TOK_SUB)
129 NUMPTR[-1] -= *NUMPTR;
130 }
131 return 0;
132err: return(1);
133}
134
135extern long arith (const char *startbuf)
136{
137 register char arithval;
138 const char *expr = startbuf;
139
140 operator lasttok = TOK_MUL, op;
141 size_t datasizes = strlen(startbuf);
142 unsigned char prec;
143
144 long *numstack, *numstackptr;
145
146 operator *stack = alloca(datasizes * sizeof(operator)), *stackptr = stack;
147 numstack = alloca((datasizes/2+1)*sizeof(long)), numstackptr = numstack;
148
149 while ((arithval = *expr)) {
150 if (arithval == ' ' || arithval == '\n' || arithval == '\t')
151 goto prologue;
152 if ((unsigned)arithval-'0' <= 9) /* isdigit */ {
153 *numstackptr++ = strtol(expr, (char **) &expr, 10);
154 lasttok = TOK_NUM;
155 continue;
156 } if (arithval == '(') {
157 *stackptr++ = TOK_LPAREN;
158 lasttok = TOK_LPAREN;
159 goto prologue;
160 } if (arithval == ')') {
161 lasttok = TOK_NUM;
162 while (stackptr != stack) {
163 op = *--stackptr;
164 if (op == TOK_LPAREN)
165 goto prologue;
166 if(ARITH_APPLY(op)) goto err;
167 }
168 goto err; /* Mismatched parens */
169 } if (arithval == '|') {
170 if (*++expr == '|')
171 op = TOK_OR;
172 else {
173 --expr;
174 op = TOK_BOR;
175 }
176 } else if (arithval == '&') {
177 if (*++expr == '&')
178 op = TOK_AND;
179 else {
180 --expr;
181 op = TOK_BAND;
182 }
183 } else if (arithval == '=') {
184 if (*++expr != '=') goto err; /* Unknown token */
185 op = TOK_EQ;
186 } else if (arithval == '!') {
187 if (*++expr == '=')
188 op = TOK_NE;
189 else {
190 --expr;
191 op = TOK_NOT;
192 }
193 } else if (arithval == '>') {
194 switch (*++expr) {
195 case '=':
196 op = TOK_GE;
197 break;
198 case '>':
199 op = TOK_RSHIFT;
200 break;
201 default:
202 --expr;
203 op = TOK_GT;
204 }
205 } else if (arithval == '<') {
206 switch (*++expr) {
207 case '=':
208 op = TOK_LE;
209 break;
210 case '<':
211 op = TOK_LSHIFT;
212 break;
213 default:
214 --expr;
215 op = TOK_LT;
216 }
217 } else if (arithval == '*')
218 op = TOK_MUL;
219 else if (arithval == '/')
220 op = TOK_DIV;
221 else if (arithval == '%')
222 op = TOK_REM;
223 else if (arithval == '+') {
224 if (lasttok != TOK_NUM) goto prologue; /* Unary plus */
225 op = TOK_ADD;
226 } else if (arithval == '-')
227 op = (lasttok == TOK_NUM) ? TOK_SUB : TOK_UMINUS;
228 else if (arithval == '~')
229 op = TOK_BNOT;
230 else goto err; /* Unknown token */
231
232 prec = PREC(op);
233 if (prec != UNARYPREC)
234 while (stackptr != stack && PREC(stackptr[-1]) >= prec)
235 if(ARITH_APPLY(*--stackptr)) goto err;
236 *stackptr++ = op;
237 lasttok = op;
238prologue: ++expr;
239 } /* yay */
240
241 while (stackptr != stack)
242 if(ARITH_APPLY(*--stackptr)) goto err;
243 if (numstackptr != numstack+1) {
244err:
245 return -1;
246 /* NOTREACHED */
247 }
248
249 return *numstack;
250}
diff --git a/libbb/libbb.h b/libbb/libbb.h
index 3cf932dc4..66acc2278 100644
--- a/libbb/libbb.h
+++ b/libbb/libbb.h
@@ -212,6 +212,8 @@ char *xreadlink(const char *path);
212char *concat_path_file(const char *path, const char *filename); 212char *concat_path_file(const char *path, const char *filename);
213char *last_char_is(const char *s, int c); 213char *last_char_is(const char *s, int c);
214 214
215extern long arith (const char *startbuf);
216
215typedef struct file_headers_s { 217typedef struct file_headers_s {
216 char *name; 218 char *name;
217 char *link_name; 219 char *link_name;
diff --git a/shell/ash.c b/shell/ash.c
index bb5bf3601..9a5435e8b 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -51,9 +51,8 @@
51#define ASH_ALIAS 51#define ASH_ALIAS
52 52
53/* If you need ash to act as a full Posix shell, with full math 53/* If you need ash to act as a full Posix shell, with full math
54 * support, enable this. This option needs some work, since it 54 * support, enable this. This adds a bit over 2k an x86 system. */
55 * doesn't compile right now... */ 55#define ASH_MATH_SUPPORT
56#undef ASH_MATH_SUPPORT
57 56
58/* Getopts is used by shell procedures to parse positional parameters. 57/* Getopts is used by shell procedures to parse positional parameters.
59 * You probably want to leave this disabled, and use the busybox getopt 58 * You probably want to leave this disabled, and use the busybox getopt
@@ -80,6 +79,7 @@
80#undef FNMATCH_BROKEN 79#undef FNMATCH_BROKEN
81#undef GLOB_BROKEN 80#undef GLOB_BROKEN
82#undef _GNU_SOURCE 81#undef _GNU_SOURCE
82#undef __USE_GNU
83 83
84#include <assert.h> 84#include <assert.h>
85#include <ctype.h> 85#include <ctype.h>
@@ -1562,8 +1562,10 @@ __lookupalias(const char *name) {
1562#endif 1562#endif
1563 1563
1564#ifdef ASH_MATH_SUPPORT 1564#ifdef ASH_MATH_SUPPORT
1565/* The generated file arith.c has been snipped. If you want this 1565/* The generated file arith.c has been replaced with a custom hand
1566 * stuff back in, feel free to add it to your own copy. */ 1566 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1567 * This is now part of libbb, so that it can be used by all the shells
1568 * in busybox. */
1567#define ARITH_NUM 257 1569#define ARITH_NUM 257
1568#define ARITH_LPAREN 258 1570#define ARITH_LPAREN 258
1569#define ARITH_RPAREN 259 1571#define ARITH_RPAREN 259
@@ -1592,11 +1594,8 @@ __lookupalias(const char *name) {
1592 1594
1593static void expari (int); 1595static void expari (int);
1594/* From arith.y */ 1596/* From arith.y */
1595static int arith (const char *); 1597static long ash_arith(const char *p);
1596static int expcmd (int , char **); 1598static int expcmd (int , char **);
1597static void arith_lex_reset (void);
1598static int yylex (void);
1599
1600#endif 1599#endif
1601 1600
1602static char *trap[NSIG]; /* trap handler commands */ 1601static char *trap[NSIG]; /* trap handler commands */
@@ -2173,52 +2172,22 @@ exverror(int cond, const char *msg, va_list ap)
2173} 2172}
2174 2173
2175 2174
2176#ifdef __STDC__ 2175static void
2177static void
2178error(const char *msg, ...) 2176error(const char *msg, ...)
2179#else
2180static void
2181error(va_alist)
2182 va_dcl
2183#endif
2184{ 2177{
2185#ifndef __STDC__
2186 const char *msg;
2187#endif
2188 va_list ap; 2178 va_list ap;
2189#ifdef __STDC__
2190 va_start(ap, msg); 2179 va_start(ap, msg);
2191#else
2192 va_start(ap);
2193 msg = va_arg(ap, const char *);
2194#endif
2195 exverror(EXERROR, msg, ap); 2180 exverror(EXERROR, msg, ap);
2196 /* NOTREACHED */ 2181 /* NOTREACHED */
2197 va_end(ap); 2182 va_end(ap);
2198} 2183}
2199 2184
2200 2185
2201#ifdef __STDC__
2202static void 2186static void
2203exerror(int cond, const char *msg, ...) 2187exerror(int cond, const char *msg, ...)
2204#else
2205static void
2206exerror(va_alist)
2207 va_dcl
2208#endif
2209{ 2188{
2210#ifndef __STDC__
2211 int cond;
2212 const char *msg;
2213#endif
2214 va_list ap; 2189 va_list ap;
2215#ifdef __STDC__
2216 va_start(ap, msg); 2190 va_start(ap, msg);
2217#else
2218 va_start(ap);
2219 cond = va_arg(ap, int);
2220 msg = va_arg(ap, const char *);
2221#endif
2222 exverror(cond, msg, ap); 2191 exverror(cond, msg, ap);
2223 /* NOTREACHED */ 2192 /* NOTREACHED */
2224 va_end(ap); 2193 va_end(ap);
@@ -4914,7 +4883,7 @@ expari(int flag)
4914 removerecordregions(begoff); 4883 removerecordregions(begoff);
4915 if (quotes) 4884 if (quotes)
4916 rmescapes(p+2); 4885 rmescapes(p+2);
4917 result = arith(p+2); 4886 result = ash_arith(p+2);
4918 snprintf(p, 12, "%d", result); 4887 snprintf(p, 12, "%d", result);
4919 4888
4920 while (*p++) 4889 while (*p++)
@@ -11952,13 +11921,7 @@ static void
11952trace(const char *fmt, ...) 11921trace(const char *fmt, ...)
11953{ 11922{
11954 va_list va; 11923 va_list va;
11955#ifdef __STDC__
11956 va_start(va, fmt); 11924 va_start(va, fmt);
11957#else
11958 char *fmt;
11959 va_start(va);
11960 fmt = va_arg(va, char *);
11961#endif
11962 if (tracefile != NULL) { 11925 if (tracefile != NULL) {
11963 (void) vfprintf(tracefile, fmt, va); 11926 (void) vfprintf(tracefile, fmt, va);
11964 if (strchr(fmt, '\n')) 11927 if (strchr(fmt, '\n'))
@@ -12657,7 +12620,6 @@ found:;
12657 return 0; 12620 return 0;
12658} 12621}
12659 12622
12660
12661/* 12623/*
12662 * The "local" command. 12624 * The "local" command.
12663 */ 12625 */
@@ -12916,7 +12878,7 @@ findvar(struct var **vpp, const char *name)
12916/* 12878/*
12917 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12879 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12918 * This file contains code for the times builtin. 12880 * This file contains code for the times builtin.
12919 * $Id: ash.c,v 1.13 2001/07/26 05:58:40 russ Exp $ 12881 * $Id: ash.c,v 1.14 2001/07/30 21:41:37 andersen Exp $
12920 */ 12882 */
12921static int timescmd (int argc, char **argv) 12883static int timescmd (int argc, char **argv)
12922{ 12884{
@@ -12937,6 +12899,51 @@ static int timescmd (int argc, char **argv)
12937} 12899}
12938 12900
12939 12901
12902#ifdef ASH_MATH_SUPPORT
12903/* The exp(1) builtin. */
12904int expcmd(int argc, char **argv)
12905{
12906 const char *p;
12907 char *concat;
12908 char **ap;
12909 long i;
12910
12911 if (argc > 1) {
12912 p = argv[1];
12913 if (argc > 2) {
12914 /* concatenate arguments */
12915 STARTSTACKSTR(concat);
12916 ap = argv + 2;
12917 for (;;) {
12918 while (*p)
12919 STPUTC(*p++, concat);
12920 if ((p = *ap++) == NULL)
12921 break;
12922 STPUTC(' ', concat);
12923 }
12924 STPUTC('\0', concat);
12925 p = grabstackstr(concat);
12926 }
12927 } else
12928 p = "";
12929
12930 i = ash_arith(p);
12931
12932 printf("%ld\n", i);
12933 return (! i);
12934}
12935
12936static long ash_arith(const char *p)
12937{
12938 long i = arith(p);
12939 if (i <0)
12940 error("arith: syntax error: \"%s\"\n", p);
12941 return i;
12942}
12943#endif
12944
12945
12946
12940/*- 12947/*-
12941 * Copyright (c) 1989, 1991, 1993, 1994 12948 * Copyright (c) 1989, 1991, 1993, 1994
12942 * The Regents of the University of California. All rights reserved. 12949 * The Regents of the University of California. All rights reserved.