1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin
22da2e3ebdSchin /*
23da2e3ebdSchin * D. G. Korn
24da2e3ebdSchin * AT&T Labs
25da2e3ebdSchin *
26da2e3ebdSchin * arithmetic expression evaluator
27da2e3ebdSchin *
28da2e3ebdSchin * this version compiles the expression onto a stack
29da2e3ebdSchin * and has a separate executor
30da2e3ebdSchin */
31da2e3ebdSchin
32da2e3ebdSchin #include "streval.h"
33da2e3ebdSchin #include <ctype.h>
34da2e3ebdSchin #include <error.h>
35da2e3ebdSchin #include <stak.h>
36da2e3ebdSchin #include "FEATURE/externs"
37*3e14f97fSRoger A. Faulkner #include "defs.h" /* for sh.decomma */
38da2e3ebdSchin
39da2e3ebdSchin #ifndef ERROR_dictionary
40da2e3ebdSchin # define ERROR_dictionary(s) (s)
41da2e3ebdSchin #endif
42da2e3ebdSchin #ifndef SH_DICT
43da2e3ebdSchin # define SH_DICT "libshell"
44da2e3ebdSchin #endif
45da2e3ebdSchin
46da2e3ebdSchin #define MAXLEVEL 9
47da2e3ebdSchin #define SMALL_STACK 12
48da2e3ebdSchin
49da2e3ebdSchin /*
50da2e3ebdSchin * The following are used with tokenbits() macro
51da2e3ebdSchin */
52da2e3ebdSchin #define T_OP 0x3f /* mask for operator number */
53da2e3ebdSchin #define T_BINARY 0x40 /* binary operators */
54da2e3ebdSchin #define T_NOFLOAT 0x80 /* non floating point operator */
55da2e3ebdSchin #define A_LVALUE (2*MAXPREC+2)
56da2e3ebdSchin
57da2e3ebdSchin #define pow2size(x) ((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64)
58da2e3ebdSchin #define round(x,size) (((x)+(size)-1)&~((size)-1))
59da2e3ebdSchin #define stakpush(v,val,type) ((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\
60da2e3ebdSchin stakseek((v)->offset+sizeof(type)), \
61da2e3ebdSchin *((type*)stakptr((v)->offset)) = (val)),(v)->offset)
62da2e3ebdSchin #define roundptr(ep,cp,type) (((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type))))
63da2e3ebdSchin
64da2e3ebdSchin static int level;
65da2e3ebdSchin
66da2e3ebdSchin struct vars /* vars stacked per invocation */
67da2e3ebdSchin {
68da2e3ebdSchin const char *expr; /* current expression */
69da2e3ebdSchin const char *nextchr; /* next char in current expression */
70da2e3ebdSchin const char *errchr; /* next char after error */
71da2e3ebdSchin const char *errstr; /* error string */
72da2e3ebdSchin struct lval errmsg; /* error message text */
73da2e3ebdSchin int offset; /* offset for pushchr macro */
74da2e3ebdSchin int staksize; /* current stack size needed */
75da2e3ebdSchin int stakmaxsize; /* maximum stack size needed */
76da2e3ebdSchin unsigned char paren; /* parenthesis level */
77da2e3ebdSchin char infun; /* incremented by comma inside function */
78da2e3ebdSchin int emode;
79da2e3ebdSchin Sfdouble_t (*convert)(const char**,struct lval*,int,Sfdouble_t);
80da2e3ebdSchin };
81da2e3ebdSchin
8234f9b3eeSRoland Mainz typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
8334f9b3eeSRoland Mainz typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t);
8434f9b3eeSRoland Mainz typedef int (*Math_1i_f)(Sfdouble_t);
8534f9b3eeSRoland Mainz typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t,Sfdouble_t);
8634f9b3eeSRoland Mainz typedef int (*Math_2i_f)(Sfdouble_t,Sfdouble_t);
8734f9b3eeSRoland Mainz typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
8834f9b3eeSRoland Mainz typedef int (*Math_3i_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
89da2e3ebdSchin
90da2e3ebdSchin #define getchr(vp) (*(vp)->nextchr++)
91da2e3ebdSchin #define peekchr(vp) (*(vp)->nextchr)
92da2e3ebdSchin #define ungetchr(vp) ((vp)->nextchr--)
93da2e3ebdSchin
94da2e3ebdSchin #if ('a'==97) /* ASCII encodings */
95da2e3ebdSchin # define getop(c) (((c) >= sizeof(strval_states))? \
96da2e3ebdSchin ((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\
97da2e3ebdSchin strval_states[(c)])
98da2e3ebdSchin #else
99da2e3ebdSchin # define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \
100da2e3ebdSchin (c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \
101da2e3ebdSchin (c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \
102da2e3ebdSchin (c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \
103da2e3ebdSchin (c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \
104da2e3ebdSchin (c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \
105da2e3ebdSchin (c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \
106da2e3ebdSchin (c=='\''?A_LIT: \
107da2e3ebdSchin (c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG)))))))))))))))))))))))
108da2e3ebdSchin #endif
109da2e3ebdSchin
110da2e3ebdSchin #define seterror(v,msg) _seterror(v,ERROR_dictionary(msg))
111da2e3ebdSchin #define ERROR(vp,msg) return(seterror((vp),msg))
112da2e3ebdSchin
113da2e3ebdSchin /*
114da2e3ebdSchin * set error message string and return(0)
115da2e3ebdSchin */
_seterror(struct vars * vp,const char * msg)116da2e3ebdSchin static int _seterror(struct vars *vp,const char *msg)
117da2e3ebdSchin {
118da2e3ebdSchin if(!vp->errmsg.value)
119da2e3ebdSchin vp->errmsg.value = (char*)msg;
120da2e3ebdSchin vp->errchr = vp->nextchr;
121da2e3ebdSchin vp->nextchr = "";
122da2e3ebdSchin level = 0;
123da2e3ebdSchin return(0);
124da2e3ebdSchin }
125da2e3ebdSchin
126da2e3ebdSchin
arith_error(const char * message,const char * expr,int mode)127da2e3ebdSchin static void arith_error(const char *message,const char *expr, int mode)
128da2e3ebdSchin {
129da2e3ebdSchin level = 0;
130da2e3ebdSchin mode = (mode&3)!=0;
131da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(mode),message,expr);
132da2e3ebdSchin }
133da2e3ebdSchin
134da2e3ebdSchin #if _ast_no_um2fm
U2F(Sfulong_t u)135da2e3ebdSchin static Sfdouble_t U2F(Sfulong_t u)
136da2e3ebdSchin {
137da2e3ebdSchin Sflong_t s = u;
138da2e3ebdSchin Sfdouble_t f;
139da2e3ebdSchin
140da2e3ebdSchin if (s >= 0)
141da2e3ebdSchin return s;
142da2e3ebdSchin s = u / 2;
143da2e3ebdSchin f = s;
144da2e3ebdSchin f *= 2;
145da2e3ebdSchin if (u & 1)
146da2e3ebdSchin f++;
147da2e3ebdSchin return f;
148da2e3ebdSchin }
149da2e3ebdSchin #else
150da2e3ebdSchin #define U2F(x) x
151da2e3ebdSchin #endif
152da2e3ebdSchin
arith_exec(Arith_t * ep)153da2e3ebdSchin Sfdouble_t arith_exec(Arith_t *ep)
154da2e3ebdSchin {
155da2e3ebdSchin register Sfdouble_t num=0,*dp,*sp;
156da2e3ebdSchin register unsigned char *cp = ep->code;
157da2e3ebdSchin register int c,type=0;
158da2e3ebdSchin register char *tp;
159da2e3ebdSchin Sfdouble_t small_stack[SMALL_STACK+1];
160da2e3ebdSchin const char *ptr = "";
16134f9b3eeSRoland Mainz Math_f fun;
162da2e3ebdSchin struct lval node;
163da2e3ebdSchin node.emode = ep->emode;
164da2e3ebdSchin node.expr = ep->expr;
165da2e3ebdSchin node.elen = ep->elen;
166*3e14f97fSRoger A. Faulkner node.value = 0;
167*3e14f97fSRoger A. Faulkner node.nosub = 0;
168da2e3ebdSchin if(level++ >=MAXLEVEL)
169da2e3ebdSchin {
170da2e3ebdSchin arith_error(e_recursive,ep->expr,ep->emode);
171da2e3ebdSchin return(0);
172da2e3ebdSchin }
173da2e3ebdSchin if(ep->staksize < SMALL_STACK)
174da2e3ebdSchin sp = small_stack;
175da2e3ebdSchin else
176da2e3ebdSchin sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1));
177da2e3ebdSchin tp = (char*)(sp+ep->staksize);
178da2e3ebdSchin tp--,sp--;
179da2e3ebdSchin while(c = *cp++)
180da2e3ebdSchin {
181da2e3ebdSchin if(c&T_NOFLOAT)
182da2e3ebdSchin {
183da2e3ebdSchin if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1))
184da2e3ebdSchin arith_error(e_incompatible,ep->expr,ep->emode);
185da2e3ebdSchin }
186da2e3ebdSchin switch(c&T_OP)
187da2e3ebdSchin {
188da2e3ebdSchin case A_JMP: case A_JMPZ: case A_JMPNZ:
189da2e3ebdSchin c &= T_OP;
190da2e3ebdSchin cp = roundptr(ep,cp,short);
191da2e3ebdSchin if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num))
192da2e3ebdSchin cp += sizeof(short);
193da2e3ebdSchin else
194da2e3ebdSchin cp = (unsigned char*)ep + *((short*)cp);
195da2e3ebdSchin continue;
196da2e3ebdSchin case A_NOTNOT:
197da2e3ebdSchin num = (num!=0);
198da2e3ebdSchin type=0;
199da2e3ebdSchin break;
200da2e3ebdSchin case A_PLUSPLUS:
201*3e14f97fSRoger A. Faulkner node.nosub = 1;
202da2e3ebdSchin (*ep->fun)(&ptr,&node,ASSIGN,num+1);
203da2e3ebdSchin break;
204da2e3ebdSchin case A_MINUSMINUS:
205*3e14f97fSRoger A. Faulkner node.nosub = 1;
206da2e3ebdSchin (*ep->fun)(&ptr,&node,ASSIGN,num-1);
207da2e3ebdSchin break;
208da2e3ebdSchin case A_INCR:
209da2e3ebdSchin num = num+1;
210*3e14f97fSRoger A. Faulkner node.nosub = 1;
211da2e3ebdSchin num = (*ep->fun)(&ptr,&node,ASSIGN,num);
212da2e3ebdSchin break;
213da2e3ebdSchin case A_DECR:
214da2e3ebdSchin num = num-1;
215*3e14f97fSRoger A. Faulkner node.nosub = 1;
216da2e3ebdSchin num = (*ep->fun)(&ptr,&node,ASSIGN,num);
217da2e3ebdSchin break;
218da2e3ebdSchin case A_SWAP:
219da2e3ebdSchin num = sp[-1];
220da2e3ebdSchin sp[-1] = *sp;
221da2e3ebdSchin type = tp[-1];
222da2e3ebdSchin tp[-1] = *tp;
223da2e3ebdSchin break;
224da2e3ebdSchin case A_POP:
225da2e3ebdSchin sp--;
226da2e3ebdSchin continue;
227da2e3ebdSchin case A_PUSHV:
228da2e3ebdSchin cp = roundptr(ep,cp,Sfdouble_t*);
229da2e3ebdSchin dp = *((Sfdouble_t**)cp);
230da2e3ebdSchin cp += sizeof(Sfdouble_t*);
231da2e3ebdSchin c = *(short*)cp;
232da2e3ebdSchin cp += sizeof(short);
233da2e3ebdSchin node.value = (char*)dp;
234da2e3ebdSchin node.flag = c;
235da2e3ebdSchin node.isfloat=0;
236da2e3ebdSchin node.level = level;
237da2e3ebdSchin num = (*ep->fun)(&ptr,&node,VALUE,num);
238da2e3ebdSchin if(node.value != (char*)dp)
239da2e3ebdSchin arith_error(node.value,ptr,ep->emode);
240da2e3ebdSchin *++sp = num;
241da2e3ebdSchin type = node.isfloat;
242da2e3ebdSchin if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
243da2e3ebdSchin type = 1;
244da2e3ebdSchin else
245da2e3ebdSchin {
246da2e3ebdSchin Sfdouble_t d=num;
247da2e3ebdSchin if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX)
248da2e3ebdSchin {
249da2e3ebdSchin type = 2;
250da2e3ebdSchin d -= LDBL_LLONG_MAX;
251da2e3ebdSchin }
252da2e3ebdSchin if((Sflong_t)d!=d)
253da2e3ebdSchin type = 1;
254da2e3ebdSchin }
255da2e3ebdSchin *++tp = type;
256da2e3ebdSchin c = 0;
257da2e3ebdSchin break;
258*3e14f97fSRoger A. Faulkner case A_ASSIGNOP:
259*3e14f97fSRoger A. Faulkner node.nosub = 1;
260da2e3ebdSchin case A_STORE:
261da2e3ebdSchin cp = roundptr(ep,cp,Sfdouble_t*);
262da2e3ebdSchin dp = *((Sfdouble_t**)cp);
263da2e3ebdSchin cp += sizeof(Sfdouble_t*);
264da2e3ebdSchin c = *(short*)cp;
265da2e3ebdSchin if(c<0)
266da2e3ebdSchin c = 0;
267da2e3ebdSchin cp += sizeof(short);
268da2e3ebdSchin node.value = (char*)dp;
269da2e3ebdSchin node.flag = c;
270da2e3ebdSchin num = (*ep->fun)(&ptr,&node,ASSIGN,num);
27134f9b3eeSRoland Mainz c=0;
272da2e3ebdSchin break;
273da2e3ebdSchin case A_PUSHF:
27434f9b3eeSRoland Mainz cp = roundptr(ep,cp,Math_f);
275da2e3ebdSchin *++sp = (Sfdouble_t)(cp-ep->code);
27634f9b3eeSRoland Mainz cp += sizeof(Math_f);
277da2e3ebdSchin *++tp = *cp++;
278da2e3ebdSchin continue;
279da2e3ebdSchin case A_PUSHN:
280da2e3ebdSchin cp = roundptr(ep,cp,Sfdouble_t);
281da2e3ebdSchin num = *((Sfdouble_t*)cp);
282da2e3ebdSchin cp += sizeof(Sfdouble_t);
283da2e3ebdSchin *++sp = num;
284da2e3ebdSchin *++tp = type = *cp++;
285da2e3ebdSchin break;
286da2e3ebdSchin case A_NOT:
287da2e3ebdSchin type=0;
288da2e3ebdSchin num = !num;
289da2e3ebdSchin break;
290da2e3ebdSchin case A_UMINUS:
291da2e3ebdSchin num = -num;
292da2e3ebdSchin break;
293da2e3ebdSchin case A_TILDE:
294da2e3ebdSchin num = ~((Sflong_t)(num));
295da2e3ebdSchin break;
296da2e3ebdSchin case A_PLUS:
297da2e3ebdSchin num += sp[-1];
298da2e3ebdSchin break;
299da2e3ebdSchin case A_MINUS:
300da2e3ebdSchin num = sp[-1] - num;
301da2e3ebdSchin break;
302da2e3ebdSchin case A_TIMES:
303da2e3ebdSchin num *= sp[-1];
304da2e3ebdSchin break;
305da2e3ebdSchin case A_POW:
306da2e3ebdSchin num = pow(sp[-1],num);
307da2e3ebdSchin break;
308da2e3ebdSchin case A_MOD:
309da2e3ebdSchin if(!(Sflong_t)num)
310da2e3ebdSchin arith_error(e_divzero,ep->expr,ep->emode);
311da2e3ebdSchin if(type==2 || tp[-1]==2)
312da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
313da2e3ebdSchin else
314da2e3ebdSchin num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
315da2e3ebdSchin break;
316da2e3ebdSchin case A_DIV:
317da2e3ebdSchin if(type==1 || tp[-1]==1)
318da2e3ebdSchin {
319da2e3ebdSchin num = sp[-1]/num;
320da2e3ebdSchin type = 1;
321da2e3ebdSchin }
322da2e3ebdSchin else if((Sfulong_t)(num)==0)
323da2e3ebdSchin arith_error(e_divzero,ep->expr,ep->emode);
324da2e3ebdSchin else if(type==2 || tp[-1]==2)
325da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
326da2e3ebdSchin else
327da2e3ebdSchin num = (Sflong_t)(sp[-1]) / (Sflong_t)(num);
328da2e3ebdSchin break;
329da2e3ebdSchin case A_LSHIFT:
330da2e3ebdSchin if(tp[-1]==2)
331da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
332da2e3ebdSchin else
333da2e3ebdSchin num = (Sflong_t)(sp[-1]) << (long)(num);
334da2e3ebdSchin break;
335da2e3ebdSchin case A_RSHIFT:
336da2e3ebdSchin if(tp[-1]==2)
337da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
338da2e3ebdSchin else
339da2e3ebdSchin num = (Sflong_t)(sp[-1]) >> (long)(num);
340da2e3ebdSchin break;
341da2e3ebdSchin case A_XOR:
342da2e3ebdSchin if(type==2 || tp[-1]==2)
343da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
344da2e3ebdSchin else
345da2e3ebdSchin num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
346da2e3ebdSchin break;
347da2e3ebdSchin case A_OR:
348da2e3ebdSchin if(type==2 || tp[-1]==2)
349da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
350da2e3ebdSchin else
351da2e3ebdSchin num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
352da2e3ebdSchin break;
353da2e3ebdSchin case A_AND:
354da2e3ebdSchin if(type==2 || tp[-1]==2)
355da2e3ebdSchin num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
356da2e3ebdSchin else
357da2e3ebdSchin num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
358da2e3ebdSchin break;
359da2e3ebdSchin case A_EQ:
360da2e3ebdSchin num = (sp[-1]==num);
361da2e3ebdSchin type=0;
362da2e3ebdSchin break;
363da2e3ebdSchin case A_NEQ:
364da2e3ebdSchin num = (sp[-1]!=num);
365da2e3ebdSchin type=0;
366da2e3ebdSchin break;
367da2e3ebdSchin case A_LE:
368da2e3ebdSchin num = (sp[-1]<=num);
369da2e3ebdSchin type=0;
370da2e3ebdSchin break;
371da2e3ebdSchin case A_GE:
372da2e3ebdSchin num = (sp[-1]>=num);
373da2e3ebdSchin type=0;
374da2e3ebdSchin break;
375da2e3ebdSchin case A_GT:
376da2e3ebdSchin num = (sp[-1]>num);
377da2e3ebdSchin type=0;
378da2e3ebdSchin break;
379da2e3ebdSchin case A_LT:
380da2e3ebdSchin num = (sp[-1]<num);
381da2e3ebdSchin type=0;
382da2e3ebdSchin break;
38334f9b3eeSRoland Mainz case A_CALL1F:
384da2e3ebdSchin sp--,tp--;
38534f9b3eeSRoland Mainz fun = *((Math_f*)(ep->code+(int)(*sp)));
386da2e3ebdSchin type = 0;
38734f9b3eeSRoland Mainz num = (*((Math_1f_f)fun))(num);
388da2e3ebdSchin break;
38934f9b3eeSRoland Mainz case A_CALL1I:
390da2e3ebdSchin sp--,tp--;
39134f9b3eeSRoland Mainz fun = *((Math_f*)(ep->code+(int)(*sp)));
392da2e3ebdSchin type = *tp;
39334f9b3eeSRoland Mainz num = (*((Math_1i_f)fun))(num);
394da2e3ebdSchin break;
39534f9b3eeSRoland Mainz case A_CALL2F:
396da2e3ebdSchin sp-=2,tp-=2;
39734f9b3eeSRoland Mainz fun = *((Math_f*)(ep->code+(int)(*sp)));
39834f9b3eeSRoland Mainz type = 0;
39934f9b3eeSRoland Mainz num = (*((Math_2f_f)fun))(sp[1],num);
400da2e3ebdSchin break;
40134f9b3eeSRoland Mainz case A_CALL2I:
40234f9b3eeSRoland Mainz sp-=2,tp-=2;
40334f9b3eeSRoland Mainz fun = *((Math_f*)(ep->code+(int)(*sp)));
404da2e3ebdSchin type = *tp;
40534f9b3eeSRoland Mainz num = (*((Math_2i_f)fun))(sp[1],num);
40634f9b3eeSRoland Mainz break;
40734f9b3eeSRoland Mainz case A_CALL3F:
40834f9b3eeSRoland Mainz sp-=3,tp-=3;
40934f9b3eeSRoland Mainz fun = *((Math_f*)(ep->code+(int)(*sp)));
41034f9b3eeSRoland Mainz type = 0;
41134f9b3eeSRoland Mainz num = (*((Math_3f_f)fun))(sp[1],sp[2],num);
412da2e3ebdSchin break;
413da2e3ebdSchin }
414da2e3ebdSchin if(c&T_BINARY)
415da2e3ebdSchin sp--,tp--;
416da2e3ebdSchin *sp = num;
417da2e3ebdSchin *tp = type;
418da2e3ebdSchin }
419da2e3ebdSchin if(level>0)
420da2e3ebdSchin level--;
421da2e3ebdSchin return(num);
422da2e3ebdSchin }
423da2e3ebdSchin
424da2e3ebdSchin /*
425da2e3ebdSchin * This returns operator tokens or A_REG or A_NUM
426da2e3ebdSchin */
gettok(register struct vars * vp)427da2e3ebdSchin static int gettok(register struct vars *vp)
428da2e3ebdSchin {
429da2e3ebdSchin register int c,op;
430da2e3ebdSchin vp->errchr = vp->nextchr;
431da2e3ebdSchin while(1)
432da2e3ebdSchin {
433da2e3ebdSchin c = getchr(vp);
434da2e3ebdSchin switch(op=getop(c))
435da2e3ebdSchin {
436da2e3ebdSchin case 0:
437da2e3ebdSchin vp->errchr = vp->nextchr;
438da2e3ebdSchin continue;
439da2e3ebdSchin case A_EOF:
440da2e3ebdSchin vp->nextchr--;
441da2e3ebdSchin break;
442*3e14f97fSRoger A. Faulkner case A_COMMA:
443*3e14f97fSRoger A. Faulkner if(sh.decomma && (c=peekchr(vp))>='0' && c<='9')
444da2e3ebdSchin {
445*3e14f97fSRoger A. Faulkner op = A_DIG;
446*3e14f97fSRoger A. Faulkner goto keep;
447*3e14f97fSRoger A. Faulkner }
448*3e14f97fSRoger A. Faulkner break;
449*3e14f97fSRoger A. Faulkner case A_DOT:
450da2e3ebdSchin if((c=peekchr(vp))>='0' && c<='9')
451da2e3ebdSchin op = A_DIG;
452da2e3ebdSchin else
453da2e3ebdSchin op = A_REG;
454*3e14f97fSRoger A. Faulkner /*FALL THRU*/
455*3e14f97fSRoger A. Faulkner case A_DIG: case A_REG: case A_LIT:
456*3e14f97fSRoger A. Faulkner keep:
457da2e3ebdSchin ungetchr(vp);
458da2e3ebdSchin break;
459da2e3ebdSchin case A_QUEST:
460da2e3ebdSchin if(peekchr(vp)==':')
461da2e3ebdSchin {
462da2e3ebdSchin getchr(vp);
463da2e3ebdSchin op = A_QCOLON;
464da2e3ebdSchin }
465da2e3ebdSchin break;
466da2e3ebdSchin case A_LT: case A_GT:
467da2e3ebdSchin if(peekchr(vp)==c)
468da2e3ebdSchin {
469da2e3ebdSchin getchr(vp);
470da2e3ebdSchin op -= 2;
471da2e3ebdSchin break;
472da2e3ebdSchin }
473da2e3ebdSchin /* FALL THRU */
474da2e3ebdSchin case A_NOT: case A_COLON:
475da2e3ebdSchin c = '=';
476da2e3ebdSchin /* FALL THRU */
477da2e3ebdSchin case A_ASSIGN:
478da2e3ebdSchin case A_TIMES:
479da2e3ebdSchin case A_PLUS: case A_MINUS:
480da2e3ebdSchin case A_OR: case A_AND:
481da2e3ebdSchin if(peekchr(vp)==c)
482da2e3ebdSchin {
483da2e3ebdSchin getchr(vp);
484da2e3ebdSchin op--;
485da2e3ebdSchin }
486da2e3ebdSchin }
487da2e3ebdSchin return(op);
488da2e3ebdSchin }
489da2e3ebdSchin }
490da2e3ebdSchin
491da2e3ebdSchin /*
492da2e3ebdSchin * evaluate a subexpression with precedence
493da2e3ebdSchin */
494da2e3ebdSchin
expr(register struct vars * vp,register int precedence)495da2e3ebdSchin static int expr(register struct vars *vp,register int precedence)
496da2e3ebdSchin {
497da2e3ebdSchin register int c, op;
498da2e3ebdSchin int invalid,wasop=0;
499da2e3ebdSchin struct lval lvalue,assignop;
500da2e3ebdSchin const char *pos;
501da2e3ebdSchin Sfdouble_t d;
502da2e3ebdSchin
503da2e3ebdSchin lvalue.value = 0;
504da2e3ebdSchin lvalue.fun = 0;
505da2e3ebdSchin again:
506da2e3ebdSchin op = gettok(vp);
507da2e3ebdSchin c = 2*MAXPREC+1;
508da2e3ebdSchin switch(op)
509da2e3ebdSchin {
510da2e3ebdSchin case A_PLUS:
511da2e3ebdSchin goto again;
512da2e3ebdSchin case A_EOF:
5137c2fbfb3SApril Chin if(precedence>2)
514da2e3ebdSchin ERROR(vp,e_moretokens);
515da2e3ebdSchin return(1);
516da2e3ebdSchin case A_MINUS:
517da2e3ebdSchin op = A_UMINUS;
518da2e3ebdSchin goto common;
519da2e3ebdSchin case A_NOT:
520da2e3ebdSchin goto common;
521da2e3ebdSchin case A_MINUSMINUS:
522da2e3ebdSchin c = A_LVALUE;
523da2e3ebdSchin op = A_DECR|T_NOFLOAT;
524da2e3ebdSchin goto common;
525da2e3ebdSchin case A_PLUSPLUS:
526da2e3ebdSchin c = A_LVALUE;
527da2e3ebdSchin op = A_INCR|T_NOFLOAT;
528da2e3ebdSchin /* FALL THRU */
529da2e3ebdSchin case A_TILDE:
530da2e3ebdSchin op |= T_NOFLOAT;
531da2e3ebdSchin common:
532da2e3ebdSchin if(!expr(vp,c))
533da2e3ebdSchin return(0);
534da2e3ebdSchin stakputc(op);
535da2e3ebdSchin break;
536da2e3ebdSchin default:
537da2e3ebdSchin vp->nextchr = vp->errchr;
538da2e3ebdSchin wasop = 1;
539da2e3ebdSchin }
540da2e3ebdSchin invalid = wasop;
541da2e3ebdSchin while(1)
542da2e3ebdSchin {
543da2e3ebdSchin assignop.value = 0;
544da2e3ebdSchin op = gettok(vp);
545da2e3ebdSchin if(op==A_DIG || op==A_REG || op==A_LIT)
546da2e3ebdSchin {
547da2e3ebdSchin if(!wasop)
548da2e3ebdSchin ERROR(vp,e_synbad);
549da2e3ebdSchin goto number;
550da2e3ebdSchin }
551da2e3ebdSchin if(wasop++ && op!=A_LPAR)
552da2e3ebdSchin ERROR(vp,e_synbad);
553da2e3ebdSchin /* check for assignment operation */
554da2e3ebdSchin if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN))
555da2e3ebdSchin {
556da2e3ebdSchin if((!lvalue.value || precedence > 3))
557da2e3ebdSchin ERROR(vp,e_notlvalue);
558da2e3ebdSchin if(precedence==3)
559da2e3ebdSchin precedence = 2;
560da2e3ebdSchin assignop = lvalue;
561da2e3ebdSchin getchr(vp);
562da2e3ebdSchin c = 3;
563da2e3ebdSchin }
564da2e3ebdSchin else
565da2e3ebdSchin {
566da2e3ebdSchin c = (strval_precedence[op]&PRECMASK);
567da2e3ebdSchin if(c==MAXPREC || op==A_POW)
568da2e3ebdSchin c++;
569da2e3ebdSchin c *= 2;
570da2e3ebdSchin }
571da2e3ebdSchin /* from here on c is the new precedence level */
572da2e3ebdSchin if(lvalue.value && (op!=A_ASSIGN))
573da2e3ebdSchin {
574da2e3ebdSchin if(vp->staksize++>=vp->stakmaxsize)
575da2e3ebdSchin vp->stakmaxsize = vp->staksize;
576da2e3ebdSchin stakputc(A_PUSHV);
577da2e3ebdSchin stakpush(vp,lvalue.value,char*);
578da2e3ebdSchin if(lvalue.flag<0)
579da2e3ebdSchin lvalue.flag = 0;
580da2e3ebdSchin stakpush(vp,lvalue.flag,short);
581da2e3ebdSchin if(vp->nextchr==0)
582da2e3ebdSchin ERROR(vp,e_badnum);
583da2e3ebdSchin if(!(strval_precedence[op]&SEQPOINT))
584da2e3ebdSchin lvalue.value = 0;
585da2e3ebdSchin invalid = 0;
586da2e3ebdSchin }
587da2e3ebdSchin else if(precedence==A_LVALUE)
588da2e3ebdSchin ERROR(vp,e_notlvalue);
589da2e3ebdSchin if(invalid && op>A_ASSIGN)
590da2e3ebdSchin ERROR(vp,e_synbad);
591da2e3ebdSchin if(precedence >= c)
592da2e3ebdSchin goto done;
593da2e3ebdSchin if(strval_precedence[op]&RASSOC)
594da2e3ebdSchin c--;
595da2e3ebdSchin if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT))
596da2e3ebdSchin {
597da2e3ebdSchin wasop = 0;
598da2e3ebdSchin if(!expr(vp,c))
599da2e3ebdSchin return(0);
600da2e3ebdSchin }
601da2e3ebdSchin switch(op)
602da2e3ebdSchin {
603da2e3ebdSchin case A_RPAR:
604da2e3ebdSchin if(!vp->paren)
605da2e3ebdSchin ERROR(vp,e_paren);
606da2e3ebdSchin if(invalid)
607da2e3ebdSchin ERROR(vp,e_synbad);
608da2e3ebdSchin goto done;
609da2e3ebdSchin
610da2e3ebdSchin case A_COMMA:
611da2e3ebdSchin wasop = 0;
612da2e3ebdSchin if(vp->infun)
613da2e3ebdSchin vp->infun++;
614da2e3ebdSchin else
615da2e3ebdSchin {
616da2e3ebdSchin stakputc(A_POP);
617da2e3ebdSchin vp->staksize--;
618da2e3ebdSchin }
619da2e3ebdSchin if(!expr(vp,c))
62034f9b3eeSRoland Mainz {
621*3e14f97fSRoger A. Faulkner stakseek(staktell()-1);
622da2e3ebdSchin return(0);
62334f9b3eeSRoland Mainz }
624da2e3ebdSchin lvalue.value = 0;
625da2e3ebdSchin break;
626da2e3ebdSchin
627da2e3ebdSchin case A_LPAR:
628da2e3ebdSchin {
629da2e3ebdSchin int infun = vp->infun;
630da2e3ebdSchin Sfdouble_t (*fun)(Sfdouble_t,...);
631da2e3ebdSchin int nargs = lvalue.nargs;
632da2e3ebdSchin fun = lvalue.fun;
633da2e3ebdSchin lvalue.fun = 0;
634da2e3ebdSchin if(fun)
635da2e3ebdSchin {
636da2e3ebdSchin if(vp->staksize++>=vp->stakmaxsize)
637da2e3ebdSchin vp->stakmaxsize = vp->staksize;
638da2e3ebdSchin vp->infun=1;
639da2e3ebdSchin stakputc(A_PUSHF);
64034f9b3eeSRoland Mainz stakpush(vp,fun,Math_f);
641da2e3ebdSchin stakputc(1);
642da2e3ebdSchin }
643da2e3ebdSchin else
644da2e3ebdSchin vp->infun = 0;
645da2e3ebdSchin if(!invalid)
646da2e3ebdSchin ERROR(vp,e_synbad);
647da2e3ebdSchin vp->paren++;
648da2e3ebdSchin if(!expr(vp,1))
649da2e3ebdSchin return(0);
650da2e3ebdSchin vp->paren--;
651da2e3ebdSchin if(fun)
652da2e3ebdSchin {
65334f9b3eeSRoland Mainz int x= (nargs>7)?2:-1;
654da2e3ebdSchin nargs &= 7;
655da2e3ebdSchin if(vp->infun != nargs)
656da2e3ebdSchin ERROR(vp,e_argcount);
657da2e3ebdSchin if(vp->staksize+=nargs>=vp->stakmaxsize)
658da2e3ebdSchin vp->stakmaxsize = vp->staksize+nargs;
65934f9b3eeSRoland Mainz stakputc(A_CALL1F+nargs+x);
660da2e3ebdSchin vp->staksize -= nargs;
661da2e3ebdSchin }
662da2e3ebdSchin vp->infun = infun;
663da2e3ebdSchin if (gettok(vp) != A_RPAR)
664da2e3ebdSchin ERROR(vp,e_paren);
665da2e3ebdSchin wasop = 0;
666da2e3ebdSchin break;
667da2e3ebdSchin }
668da2e3ebdSchin
669da2e3ebdSchin case A_PLUSPLUS:
670da2e3ebdSchin case A_MINUSMINUS:
671da2e3ebdSchin wasop=0;
672da2e3ebdSchin op |= T_NOFLOAT;
673da2e3ebdSchin case A_ASSIGN:
674da2e3ebdSchin if(!lvalue.value)
675da2e3ebdSchin ERROR(vp,e_notlvalue);
676da2e3ebdSchin if(op==A_ASSIGN)
677da2e3ebdSchin {
678da2e3ebdSchin stakputc(A_STORE);
679da2e3ebdSchin stakpush(vp,lvalue.value,char*);
680da2e3ebdSchin stakpush(vp,lvalue.flag,short);
681da2e3ebdSchin vp->staksize--;
682da2e3ebdSchin }
683da2e3ebdSchin else
684da2e3ebdSchin stakputc(op);
685da2e3ebdSchin lvalue.value = 0;
686da2e3ebdSchin break;
687da2e3ebdSchin
688da2e3ebdSchin case A_QUEST:
689da2e3ebdSchin {
690da2e3ebdSchin int offset1,offset2;
691da2e3ebdSchin stakputc(A_JMPZ);
692da2e3ebdSchin offset1 = stakpush(vp,0,short);
693da2e3ebdSchin stakputc(A_POP);
694da2e3ebdSchin if(!expr(vp,1))
695da2e3ebdSchin return(0);
696da2e3ebdSchin if(gettok(vp)!=A_COLON)
697da2e3ebdSchin ERROR(vp,e_questcolon);
698da2e3ebdSchin stakputc(A_JMP);
699da2e3ebdSchin offset2 = stakpush(vp,0,short);
700da2e3ebdSchin *((short*)stakptr(offset1)) = staktell();
701da2e3ebdSchin stakputc(A_POP);
702da2e3ebdSchin if(!expr(vp,3))
703da2e3ebdSchin return(0);
704da2e3ebdSchin *((short*)stakptr(offset2)) = staktell();
705da2e3ebdSchin lvalue.value = 0;
706da2e3ebdSchin wasop = 0;
707da2e3ebdSchin break;
708da2e3ebdSchin }
709da2e3ebdSchin
710da2e3ebdSchin case A_COLON:
711da2e3ebdSchin ERROR(vp,e_badcolon);
712da2e3ebdSchin break;
713da2e3ebdSchin
714da2e3ebdSchin case A_QCOLON:
715da2e3ebdSchin case A_ANDAND:
716da2e3ebdSchin case A_OROR:
717da2e3ebdSchin {
718da2e3ebdSchin int offset;
719da2e3ebdSchin if(op==A_ANDAND)
720da2e3ebdSchin op = A_JMPZ;
721da2e3ebdSchin else
722da2e3ebdSchin op = A_JMPNZ;
723da2e3ebdSchin stakputc(op);
724da2e3ebdSchin offset = stakpush(vp,0,short);
725da2e3ebdSchin stakputc(A_POP);
726da2e3ebdSchin if(!expr(vp,c))
727da2e3ebdSchin return(0);
728da2e3ebdSchin *((short*)stakptr(offset)) = staktell();
729da2e3ebdSchin if(op!=A_QCOLON)
730da2e3ebdSchin stakputc(A_NOTNOT);
731da2e3ebdSchin lvalue.value = 0;
732da2e3ebdSchin wasop=0;
733da2e3ebdSchin break;
734da2e3ebdSchin }
735da2e3ebdSchin case A_AND: case A_OR: case A_XOR: case A_LSHIFT:
736da2e3ebdSchin case A_RSHIFT: case A_MOD:
737da2e3ebdSchin op |= T_NOFLOAT;
738da2e3ebdSchin /* FALL THRU */
739da2e3ebdSchin case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV:
740da2e3ebdSchin case A_EQ: case A_NEQ: case A_LT: case A_LE:
741da2e3ebdSchin case A_GT: case A_GE: case A_POW:
742da2e3ebdSchin stakputc(op|T_BINARY);
743da2e3ebdSchin vp->staksize--;
744da2e3ebdSchin break;
745da2e3ebdSchin case A_NOT: case A_TILDE:
746da2e3ebdSchin default:
747da2e3ebdSchin ERROR(vp,e_synbad);
748da2e3ebdSchin number:
749da2e3ebdSchin wasop = 0;
750da2e3ebdSchin if(*vp->nextchr=='L' && vp->nextchr[1]=='\'')
751da2e3ebdSchin {
752da2e3ebdSchin vp->nextchr++;
753da2e3ebdSchin op = A_LIT;
754da2e3ebdSchin }
755da2e3ebdSchin pos = vp->nextchr;
756da2e3ebdSchin lvalue.isfloat = 0;
757da2e3ebdSchin lvalue.expr = vp->expr;
758da2e3ebdSchin lvalue.emode = vp->emode;
759da2e3ebdSchin if(op==A_LIT)
760da2e3ebdSchin {
761da2e3ebdSchin /* character constants */
762da2e3ebdSchin if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'')
763da2e3ebdSchin {
764da2e3ebdSchin d = '\\';
765da2e3ebdSchin vp->nextchr +=2;
766da2e3ebdSchin }
767da2e3ebdSchin else
768da2e3ebdSchin d = chresc(pos+1,(char**)&vp->nextchr);
769da2e3ebdSchin /* posix allows the trailing ' to be optional */
770da2e3ebdSchin if(*vp->nextchr=='\'')
771da2e3ebdSchin vp->nextchr++;
772da2e3ebdSchin }
773da2e3ebdSchin else
774da2e3ebdSchin d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
775da2e3ebdSchin if (vp->nextchr == pos)
776da2e3ebdSchin {
777da2e3ebdSchin if(vp->errmsg.value = lvalue.value)
778da2e3ebdSchin vp->errstr = pos;
779da2e3ebdSchin ERROR(vp,op==A_LIT?e_charconst:e_synbad);
780da2e3ebdSchin }
781da2e3ebdSchin if(op==A_DIG || op==A_LIT)
782da2e3ebdSchin {
783da2e3ebdSchin stakputc(A_PUSHN);
784da2e3ebdSchin if(vp->staksize++>=vp->stakmaxsize)
785da2e3ebdSchin vp->stakmaxsize = vp->staksize;
786da2e3ebdSchin stakpush(vp,d,Sfdouble_t);
787da2e3ebdSchin stakputc(lvalue.isfloat);
788da2e3ebdSchin }
789da2e3ebdSchin
790da2e3ebdSchin /* check for function call */
791da2e3ebdSchin if(lvalue.fun)
792da2e3ebdSchin continue;
793da2e3ebdSchin break;
794da2e3ebdSchin }
795da2e3ebdSchin invalid = 0;
796da2e3ebdSchin if(assignop.value)
797da2e3ebdSchin {
798da2e3ebdSchin if(vp->staksize++>=vp->stakmaxsize)
799da2e3ebdSchin vp->stakmaxsize = vp->staksize;
800da2e3ebdSchin if(assignop.flag<0)
801da2e3ebdSchin assignop.flag = 0;
802*3e14f97fSRoger A. Faulkner stakputc(c&1?A_ASSIGNOP:A_STORE);
803da2e3ebdSchin stakpush(vp,assignop.value,char*);
804da2e3ebdSchin stakpush(vp,assignop.flag,short);
805da2e3ebdSchin }
806da2e3ebdSchin }
807da2e3ebdSchin done:
808da2e3ebdSchin vp->nextchr = vp->errchr;
809da2e3ebdSchin return(1);
810da2e3ebdSchin }
811da2e3ebdSchin
arith_compile(const char * string,char ** last,Sfdouble_t (* fun)(const char **,struct lval *,int,Sfdouble_t),int emode)812da2e3ebdSchin Arith_t *arith_compile(const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode)
813da2e3ebdSchin {
814da2e3ebdSchin struct vars cur;
815da2e3ebdSchin register Arith_t *ep;
816da2e3ebdSchin int offset;
817da2e3ebdSchin memset((void*)&cur,0,sizeof(cur));
818da2e3ebdSchin cur.emode = emode;
819da2e3ebdSchin cur.expr = cur.nextchr = string;
820da2e3ebdSchin cur.convert = fun;
821da2e3ebdSchin cur.emode = emode;
822da2e3ebdSchin cur.errmsg.value = 0;
823da2e3ebdSchin cur.errmsg.emode = emode;
824da2e3ebdSchin stakseek(sizeof(Arith_t));
825da2e3ebdSchin if(!expr(&cur,0) && cur.errmsg.value)
826da2e3ebdSchin {
827da2e3ebdSchin if(cur.errstr)
828da2e3ebdSchin string = cur.errstr;
829da2e3ebdSchin (*fun)( &string , &cur.errmsg, MESSAGE, 0);
830da2e3ebdSchin cur.nextchr = cur.errchr;
831da2e3ebdSchin }
832da2e3ebdSchin stakputc(0);
833da2e3ebdSchin offset = staktell();
834da2e3ebdSchin ep = (Arith_t*)stakfreeze(0);
835da2e3ebdSchin ep->expr = string;
836da2e3ebdSchin ep->elen = strlen(string);
837da2e3ebdSchin ep->code = (unsigned char*)(ep+1);
838da2e3ebdSchin ep->fun = fun;
839da2e3ebdSchin ep->emode = emode;
840da2e3ebdSchin ep->size = offset - sizeof(Arith_t);
841da2e3ebdSchin ep->staksize = cur.stakmaxsize+1;
842da2e3ebdSchin if(last)
843da2e3ebdSchin *last = (char*)(cur.nextchr);
844da2e3ebdSchin return(ep);
845da2e3ebdSchin }
846da2e3ebdSchin
847da2e3ebdSchin /*
848da2e3ebdSchin * evaluate an integer arithmetic expression in s
849da2e3ebdSchin *
850da2e3ebdSchin * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
851da2e3ebdSchin * is a user supplied conversion routine that is called when unknown
852da2e3ebdSchin * chars are encountered.
853da2e3ebdSchin * *end points to the part to be converted and must be adjusted by convert to
854da2e3ebdSchin * point to the next non-converted character; if typ is MESSAGE then string
855da2e3ebdSchin * points to an error message string
856da2e3ebdSchin *
857da2e3ebdSchin * NOTE: (*convert)() may call strval()
858da2e3ebdSchin */
859da2e3ebdSchin
strval(const char * s,char ** end,Sfdouble_t (* conv)(const char **,struct lval *,int,Sfdouble_t),int emode)860da2e3ebdSchin Sfdouble_t strval(const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode)
861da2e3ebdSchin {
862da2e3ebdSchin Arith_t *ep;
863da2e3ebdSchin Sfdouble_t d;
864da2e3ebdSchin char *sp=0;
865da2e3ebdSchin int offset;
866da2e3ebdSchin if(offset=staktell())
867da2e3ebdSchin sp = stakfreeze(1);
868da2e3ebdSchin ep = arith_compile(s,end,conv,emode);
869da2e3ebdSchin ep->emode = emode;
870da2e3ebdSchin d = arith_exec(ep);
871da2e3ebdSchin stakset(sp?sp:(char*)ep,offset);
872da2e3ebdSchin return(d);
873da2e3ebdSchin }
874da2e3ebdSchin
875da2e3ebdSchin #if _mem_name__exception
876da2e3ebdSchin #undef _mem_name_exception
877da2e3ebdSchin #define _mem_name_exception 1
878da2e3ebdSchin #undef exception
879da2e3ebdSchin #define exception _exception
880da2e3ebdSchin #undef matherr
881da2e3ebdSchin #endif
882da2e3ebdSchin
883da2e3ebdSchin #if _mem_name_exception
884da2e3ebdSchin
885da2e3ebdSchin #undef error
886da2e3ebdSchin
887da2e3ebdSchin #if _BLD_shell && defined(__EXPORT__)
888da2e3ebdSchin #define extern __EXPORT__
889da2e3ebdSchin #endif
890da2e3ebdSchin
891da2e3ebdSchin #ifndef DOMAIN
892da2e3ebdSchin #define DOMAIN _DOMAIN
893da2e3ebdSchin #endif
894da2e3ebdSchin #ifndef OVERFLOW
895da2e3ebdSchin #define OVERFLOW _OVERFLOW
896da2e3ebdSchin #endif
897da2e3ebdSchin #ifndef SING
898da2e3ebdSchin #define SING _SING
899da2e3ebdSchin #endif
900da2e3ebdSchin
matherr(struct exception * ep)901da2e3ebdSchin extern int matherr(struct exception *ep)
902da2e3ebdSchin {
903da2e3ebdSchin const char *message;
904da2e3ebdSchin switch(ep->type)
905da2e3ebdSchin {
906da2e3ebdSchin #ifdef DOMAIN
907da2e3ebdSchin case DOMAIN:
908da2e3ebdSchin message = ERROR_dictionary(e_domain);
909da2e3ebdSchin break;
910da2e3ebdSchin #endif
911da2e3ebdSchin #ifdef OVERFLOW
912da2e3ebdSchin case OVERFLOW:
913da2e3ebdSchin message = ERROR_dictionary(e_overflow);
914da2e3ebdSchin break;
915da2e3ebdSchin #endif
916da2e3ebdSchin #ifdef SING
917da2e3ebdSchin case SING:
918da2e3ebdSchin message = ERROR_dictionary(e_singularity);
919da2e3ebdSchin break;
920da2e3ebdSchin #endif
921da2e3ebdSchin default:
922da2e3ebdSchin return(1);
923da2e3ebdSchin }
924da2e3ebdSchin level=0;
925da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),message,ep->name);
926da2e3ebdSchin return(0);
927da2e3ebdSchin }
928da2e3ebdSchin
929da2e3ebdSchin #undef extern
930da2e3ebdSchin
931da2e3ebdSchin #endif /* _mem_name_exception */
932