aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2001-07-30 21:41:37 +0000
committerandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2001-07-30 21:41:37 +0000
commitc6312c270adf0ecceac516c1a3b647eb79229a73 (patch)
treef54a28df9cd460c1da85e13e6fe1b387199f92df /libbb
parent792fe8e7657642423a55f937d53b190e54d553a5 (diff)
downloadbusybox-w32-c6312c270adf0ecceac516c1a3b647eb79229a73.tar.gz
busybox-w32-c6312c270adf0ecceac516c1a3b647eb79229a73.tar.bz2
busybox-w32-c6312c270adf0ecceac516c1a3b647eb79229a73.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 git-svn-id: svn://busybox.net/trunk/busybox@3165 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'libbb')
-rw-r--r--libbb/arith.c250
-rw-r--r--libbb/libbb.h2
2 files changed, 252 insertions, 0 deletions
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;