From 1030dc837b10a03a02a85d5504cbeec168ce49e2 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Mon, 03 May 2010 21:53:47 +0000 Subject: Import XaoS r489 (trunk after version 3.5) --- (limited to 'src/sffe/sffe.c') diff --git a/src/sffe/sffe.c b/src/sffe/sffe.c new file mode 100644 index 0000000..668893e --- /dev/null +++ b/src/sffe/sffe.c @@ -0,0 +1,1013 @@ +/*///////////////////////////////////////////////////////////////////////////////////// +// project : sFFe ( SegFault (or Segmentation Fault :) ) formula evalutaor ) +// author : Mateusz Malczak ( mateusz@malczak.info ) +// wpage : www.segfaultlabs.com/projects/sffe +/////////////////////////////////////////////////////////////////////////////////////// +// special build for XaoS, for more info visit +// http://www.segfaultlabs.com/projects/sfXaos +/////////////////////////////////////////////////////////////////////////////////////*/ + +#include +#ifdef SFFE_USING + +#include +#include +#ifdef linux +#include +#endif +#include + +#include "sffe.h" +#ifdef SFFE_CMPLX_ASM +#include "sffe_cmplx_asm.h" +#elif SFFE_CMPLX_GSL +#include "sffe_cmplx_gsl.h" +#endif + +#define sfset(arg,val) {\ + (arg)->value = (sfNumber*)malloc(sizeof(sfNumber));\ + if ( (arg)->value ) cmplxset( *((arg)->value), (val),0 ); } + +#define sfvar(p,parser,idx) (p)->value = (sfNumber*)((parser)->vars+idx) + +/************************* custom function */ +/* all used in this section variables are defined depanding on complex number realization */ +sffunction *sffe_function(char *fn, size_t len) +{ + unsigned char idx; + for (idx = 5; idx < sffnctscount; idx += 1) /* sffnctscount - defined in sffe_cmplx_* file */ + if (!strncmp(fn, sfcmplxfunc[idx].name, len)) + return (sffunction *) (sfcmplxfunc + idx); + return NULL; +}; + +sffunction *sffe_operator(char op) +{ + switch (op) { + case '^': + return (sffunction *) sfcmplxfunc; + break; + case '+': + return (sffunction *) sfcmplxfunc + 1; + break; + case '-': + return (sffunction *) sfcmplxfunc + 2; + break; + case '*': + return (sffunction *) sfcmplxfunc + 3; + break; + case '/': + return (sffunction *) sfcmplxfunc + 4; + break; + }; + return NULL; +}; + +void *sffe_const(char *fn, size_t len, void *ptr) +{ + unsigned char idx = 3; + for (idx = 0; idx < sfvarscount; idx += 1) + if (!strncmp(fn, sfcnames[idx], len)) { + sfcvals[idx] ((sfNumber *) ptr); + return ptr; + }; + return NULL; +}; + +/************************* custom function */ + + +sffe *sffe_alloc(void) +{ + sffe *rp = (sffe *) malloc(sizeof(sffe)); + if (!rp) + return NULL; + memset(rp, 0, sizeof(sffe)); + return rp; +}; + +static void sffe_clear(sffe ** parser) +{ + sffe *p = *parser; + unsigned int i = 0, j; + for (; i < p->argCount; i++) { + for (j = 0; j < p->varCount; j++) + if (p->args[i].value == p->varPtrs[j]) + j = p->varCount; + if (j == p->varCount) + if (p->args[i].value) + free(p->args[i].value); + }; + if (p->expression) + free(p->expression); + if (p->args) + free(p->args); + if (p->oprs) + free(p->oprs); + p->expression = NULL; + p->args = NULL; + p->oprs = NULL; +}; + +void sffe_free(sffe ** parser) +{ + sffe_clear(parser); + if ((*parser)->userf) + free((*parser)->userf); + if ((*parser)->varChars) + free((*parser)->varChars); + if ((*parser)->varPtrs) + free((*parser)->varPtrs); + free(*parser); + parser = NULL; +}; + +/* not really used, marked to remove +void sffe_eval2(sffe *const parser) +{ + register sfopr* optro; + register sfopr* optr = parser->oprs; + register sfopr* optrl = parser->oprs+parser->oprCount; + optro = optr; + for ( optr=optr; optr!=optrl; optr+=1, optro+=1 ) + { + optro->arg->parg = optro->arg-1; + optr->arg->parg = optr->f( optr->arg )->parg; + }; +};*/ + +sfNumber sffe_eval(sffe * const parser) +{ + register sfopr *optro; + register sfopr *optr = parser->oprs; + register sfopr *optrl = parser->oprs + parser->oprCount; + optro = optr; + for (optr = optr; optr != optrl; optr += 1, optro += 1) { + optro->arg->parg = optro->arg - 1; + optr->arg->parg = optr->f(optr->arg)->parg; + }; + return *(parser->result); +}; + +void *sffe_regvar(sffe ** parser, sfNumber * vptrs, char vchars) +{ + unsigned int i = (*parser)->varCount; + (*parser)->varCount += 1; + (*parser)->varPtrs = + (sfNumber **) realloc((*parser)->varPtrs, + (*parser)->varCount * sizeof(sfNumber *)); + if (!(*parser)->varPtrs) + return NULL; + (*parser)->varChars = + (char *) realloc((*parser)->varChars, (*parser)->varCount); + if (!(*parser)->varChars) + return NULL; + (*parser)->varPtrs[i] = vptrs; + (*parser)->varChars[i] = toupper(vchars); + return (void *) ((*parser)->varPtrs + i); +}; + +void *sffe_regvars(sffe ** parser, unsigned int cN, sfNumber ** vptrs, + char *vchars) +{ + unsigned int i = (*parser)->varCount; + (*parser)->varCount += cN; + (*parser)->varPtrs = + (sfNumber **) realloc((*parser)->varPtrs, + (*parser)->varCount * sizeof(sfNumber *)); + if (!(*parser)->varPtrs) + return NULL; + (*parser)->varChars = + (char *) realloc((*parser)->varChars, (*parser)->varCount); + if (!(*parser)->varChars) + return NULL; + for (cN = 0; i < (*parser)->varCount; i += 1, cN += 1) { + (*parser)->varPtrs[i] = vptrs[cN]; + (*parser)->varChars[i] = toupper(vchars[cN]); + }; + return (void *) ((*parser)->varPtrs + i); +}; + +sfNumber *sffe_varptr(sffe * const parser, char vchar) +{ + unsigned int i = 0; + while (i < parser->varCount) { + if (parser->varChars[i] == vchar) + return parser->varPtrs[i]; + i += 1; + }; + return NULL; +}; + +sfNumber *sffe_setvar(sffe ** parser, sfNumber * vptrs, char vchars) +{ + unsigned int i = 0; + while (i < (*parser)->varCount) { + if ((*parser)->varChars[i] == vchars) { + sfNumber *ret = (*parser)->varPtrs[i]; + (*parser)->varPtrs[i] = vptrs; + return ret; + }; + i += 1; + }; + return NULL; +}; + +void *sffe_regfunc(sffe ** parser, char *vname, unsigned int parcnt, + sffptr funptr) +{ + sffunction *sff; + unsigned short i; + (*parser)->userf = + (sffunction *) realloc((*parser)->userf, + ((*parser)->userfCount + + 1) * sizeof(sffunction)); + if (!(*parser)->userf) + return NULL; + sff = (*parser)->userf + (*parser)->userfCount; + /* 2.XI.2007 changed to get rid of warinings */ + strcpy(sff->name, vname); + /* sff->name = (char*)malloc( strlen(vname) ); */ + for (i = 0; i < strlen(vname); i += 1) + sff->name[i] = (char) toupper((int) vname[i]); + sff->parcnt = parcnt; + sff->fptr = funptr; + (*parser)->userfCount += 1; + return (void *) sff; +}; + +void *sffe_variable(sffe * const p, char *fname, size_t len) +{ + unsigned int idx = 0; + if (len == 1) /*FIXME vars names with length > 1 should be allowed */ + for (; idx < p->varCount; idx += 1) + /* if ( !strncmp(fname,p->varChars[idx],len) ) */ + if (p->varChars[idx] == *fname) + return (void *) p->varPtrs[idx]; + return NULL; +}; + +sffunction *userfunction(const sffe * const p, char *fname, size_t len) +{ + unsigned char idx; + for (idx = 0; idx < p->userfCount; idx += 1) + if (!strncmp(fname, p->userf[idx].name, len)) + return (sffunction *) (p->userf + idx); + return NULL; +}; + +char sffe_donum(char **str) +{ /* parse number in format [-+]ddd[.dddd[e[+-]ddd]] */ + unsigned char flag = 0; /*bit 1 - dot, bit 2 - dec, bits 3,4 - stan, bits 5..8 - error */ + if (**str == '-') { + flag = 0x80; + *str += 1; + }; + if (**str == '+') + *str += 1; + while (!((flag >> 4) & 0x07)) { + switch ((flag & 0x0f) >> 2) { + case 0: /*0..9 */ + while (isdigit(**str)) + *str += 1; + switch (**str) { /*only '.' or 'E' allowed */ + case '.': + flag = (flag & 0xf3) | 4; + break; + case 'E': + flag = (flag & 0xf3) | 8; + break; + default: + flag = 0x10; + }; + break; + case 1: /*. */ + if (flag & 0x03) + flag = 0x20; + else + *str += 1; /*no 2nd dot, no dot after E */ + flag = (flag & 0xf2) | 0x01; + break; + case 2: /*e */ + if (flag & 0x02) + flag = 0x30; + else + *str += 1; /*no 2nd E */ + if (!isdigit(**str)) { /*after E noly [+-] allowed */ + if (**str != '-' && **str != '+') + flag = 0x40; + else + *str += 1; + }; + flag = (flag & 0xf1) | 0x02; + break; + }; + }; + if (flag & 0x80) + flag ^= 0x80; + return flag >> 4; +}; + +char sffe_docmplx(char **str, sfarg ** arg) +{ /* parse complex number in format { [-+]ddd[.dddd[e[+-]ddd]] ; [-+]ddd[.dddd[e[+-]ddd]] } */ + char *chr, *chi; + chr = *str; + if (sffe_donum(str) > 1) + return 1; + if (*(*str)++ != ';') + return 2; + chi = *str; + if (sffe_donum(str) > 1) + return 1; + if (*(*str)++ != '}') + return 2; + + cmplxset(*(*arg)->value, atof(chr), atof(chi)); + return 0; +}; + +char sffe_doname(char **str) +{ + do { + *str += 1; + } while (isalnum(**str) || **str == '_'); + if (strchr("+-*/^~!@#$%&<>?\\:\"|", (int) **str)) + return 1; /*punctator */ + if (**str == '(') + return 2; /* ( - funkcja */ + if (**str == '.') + return 3; /*error :( this means something like X. COS. PI. */ + return 1; +}; + +int sffe_parse(sffe ** parser, char *expression) +{ +/**************var area */ + struct opstack__ { +#ifdef SFFE_DEVEL + char c; /* used in debug build to store operator character */ +#endif + unsigned char t; /* store priority of the operator 'f' */ + sffptr f; + }; + struct stack__ { + struct opstack__ *stck; + unsigned int size; //number of items on stack + struct stack__ *prev; + } *stmp, *stack; + sffunction **fnctbl; + sffunction **f; + sfarg *arg, *argcnt; + char *ech; + char *ch1, *ch2; + char *expcode; /*tokenized form : (f(n)+f(n))*f(n)-n (f-func, n-num,const) */ + unsigned int ui1, ui2; + unsigned char opr; + char err; + sffe *p; +/**************used defines */ +#define MEMERROR 1 +#define UNBALANCEDBRACKES 2 +#define INVALIDFUNCTION 3 +#define INAVLIDNUMBER 4 +#define UNKNOWNCONST 5 +#define OPERATOR 6 +#define STACKERROR 7 +#define PARCNTERROR 8 +#define NO_FUNCTIONS 9 +#define code(chr) \ + expcode = (char*)realloc(expcode,ui1+2);\ + expcode[ui1++] = chr;\ + ch2 = expcode+ui1-1;\ + opr = chr;\ + expcode[ui1] = '\0'; +#define errset(errno) {\ + err = errno;\ + break;} +#define insertfnc(fnc) \ + for ( argcnt=p->args+p->argCount-1; argcnt>arg; argcnt-=1 )\ + argcnt->value = (argcnt-1)->value;\ + sfset(argcnt,-1.0); +#ifdef SFFE_DEVEL +#define sfpopstack(a)\ + {\ + stack->size-=1;\ + insertfnc(NULL);\ + printf("%c",stack->stck[stack->size].c);\ + p->oprs[ui1].arg = (sfarg*)arg;\ + p->oprs[ui1].f = stack->stck[stack->size].f;\ + ui1 += 1;\ + arg += 1;\ + }; +#else +#define sfpopstack(a)\ + {\ + stack->size-=1;\ + insertfnc(NULL);\ + p->oprs[ui1].arg = (sfarg*)arg;\ + p->oprs[ui1].f = stack->stck[stack->size].f;\ + ui1 += 1;\ + arg += 1;\ + }; +#endif + +#define priority(chr)\ + (*chr=='f')?0x60:(\ + (*chr=='^')?0x40:(\ + ((*chr=='/')||(*chr=='*'))?0x20:(\ + ((*chr=='+')||(*chr=='-'))?0x00:0x80\ + )\ + )\ + ) + +#ifdef SFFE_DEVEL + printf("parse - BEGIN\n"); +#endif +/**************** CODE */ + fnctbl = NULL; + ech = expression; + expcode = (char *) malloc(1); + err = 0; + //parser + p = *parser; + /* clear all internal structures */ + if (p->expression) + sffe_clear(parser); + + p->oprCount = 0; + p->argCount = 0; + p->expression = (char *) malloc(strlen(expression) + 1); + strcpy(p->expression, expression); + ech = p->expression; + +#ifdef SFFE_DEVEL + printf + ("\n|-----------------------------------------\n+ > %s[%d] - parsing\n|-----------------------------------------\n", + __FILE__, __LINE__); + printf("| input (dl.=%d) :|%s|\n", strlen(p->expression), + p->expression); +#endif + +/*! PHASE 1 !!!!!!!!! remove spaces, count brackets, change decimal separators ',' to '.', remove multiple operators eg. ++--++1 -> 1, -+++2 -> -2 */ + ch1 = NULL; + ui1 = 0; /*brackets */ + ch2 = ech; + while (isspace(*ech)) + ech += 1; /* skip leading spaces */ + while (*ech) { + /*handle brackets and chaange ','->'.' */ + switch (*ech) { + case '[': + *ech = '('; + case '(': + ui1 += 1; + break; + case ']': + *ech = ')'; + case ')': + ui1 -= 1; + break; + case ',': + *ech = '.'; + break; + }; + *ch2 = (char) toupper((int) *ech); + /*fix multiple arithm operators */ + if (ch1 && strchr("+-/*^", (int) *ech) + && strchr("+-/*^", (int) *ch1)) { + if (*ch1 == '-' && *ech == '-') + *ch1 = '+'; + else if (*ch1 == '-' && *ech == '+') + *ch1 = '-'; + else if (*ch1 == '+' && *ech == '-') + *ch1 = '-'; + else if (*ch1 == *ech) + *ch1 = *ech; + else if (*ech == '-') + ch1 = ++ch2; + else if (*ch1 != *ech) { + err = OPERATOR; + break; + }; + } else { + ch1 = ch2; + ch2 += 1; + }; + do { + ech += 1; + } while (isspace(*ech)); /*skip spaces */ + }; + *ch2 = '\0'; + p->expression = + (char *) realloc(p->expression, strlen(p->expression) + 1); + if (ui1 && !err) + err = UNBALANCEDBRACKES; + +#ifdef SFFE_DEVEL + printf("| check (dl.=%d) :|%s|\n", strlen(p->expression), + p->expression); +#endif + +/*! PHASE 2 !!!!!!!! tokenize expression, lexical analysis (need optimizations) */ + *expcode = '\0'; + ch2 = NULL; + ui1 = 0; + ch1 = NULL; /*string starting position */ + ech = p->expression; + opr = '('; /* in case of leading '-' */ + while (*ech && !err) { + ch1 = ech; + + if (isalpha(*ech)) { + switch (sffe_doname(&ech)) { + case 1: /* const or variable */ + p->args = + (sfarg *) realloc(p->args, + (++p->argCount) * sizeof(sfarg)); + if (!p->args) + errset(MEMERROR); + arg = p->args + p->argCount - 1; + arg->value = + (sfNumber *) sffe_variable(p, ch1, + (size_t) (ech - ch1)); + if (!arg->value) { + sfset(arg, 10.0); + if (arg->value) { + if (!sffe_const + (ch1, (size_t) (ech - ch1), arg->value)) + errset(UNKNOWNCONST); + } else + errset(MEMERROR); + }; + opr = 'n'; + break; + case 2: /* function */ + fnctbl = + (sffunction **) realloc(fnctbl, + (p->oprCount + + 1) * sizeof(sffunction *)); + if (!fnctbl) + errset(MEMERROR); + f = fnctbl + (p->oprCount++); + *f = NULL; + if (p->userfCount) + /*is it user defined function */ + *f = (sffunction *) (void *) userfunction(p, ch1, + (size_t) (ech + - + ch1)); + if (!*f) + /*if not, is it build in function */ + *f = (sffunction *) (void *) sffe_function(ch1, + (size_t) + (ech - + ch1)); + /* if not -> ERROR */ + if (!*f) + errset(INVALIDFUNCTION); + opr = 'f'; + break; + case 3: /* what ? */ + errset(OPERATOR); + break; + }; + } else /* numbers (this part can be optimized) */ + /* is it a real number */ if (isdigit(*ech) + || (strchr("/*^(", (int) opr) + && strchr("+-", *ech))) { + ch1 = ech; /* st = 1; */ + if (sffe_donum(&ech) > 1) + errset(INAVLIDNUMBER); + /*epx */ + p->args = + (sfarg *) realloc(p->args, + (++p->argCount) * sizeof(sfarg)); + if (!p->args) + errset(MEMERROR); + arg = p->args + p->argCount - 1; + /* 22.I.2009 fix for '-n'/'+n', which was parsed as 0*n */ + if ((ech - ch1) == 1 && (*ch1 == '-')) + sfset(arg, -1) + else + sfset(arg, atof(ch1)); + /*epx */ + opr = 'n'; + } else + /* if not, it can be complex number */ +#ifdef SFFE_COMPLEX + if (*ech == '{') { + ech += 1; + p->args = + (sfarg *) realloc(p->args, + (++p->argCount) * sizeof(sfarg)); + if (!p->args) + errset(MEMERROR); + arg = p->args + p->argCount - 1; + sfset(arg, 0); + if (sffe_docmplx(&ech, &arg)) + errset(INAVLIDNUMBER); + opr = 'n'; + } else +#endif + /* if not, we have operator */ + { + ch1 = (char *) sffe_operator(*ech); + + if (ch1) { + fnctbl = + (sffunction **) realloc(fnctbl, + (++p->oprCount) * + sizeof(sffunction *)); + if (!fnctbl) + errset(MEMERROR); + fnctbl[p->oprCount - 1] = (sffunction *) ch1; + }; + ch1 = ech; + opr = *ech; + ech += 1; + }; + + + /* check if multiply sign skipped, nf, n(, )( */ + if (!err && ui1 > 0) + if (opr == 'f' || opr == 'n' || opr == '(') + if (*ch2 == 'n' || *ch2 == ')') { + ch1 = (char *) sffe_operator('*'); + fnctbl = + (sffunction **) realloc(fnctbl, + (++p->oprCount) * + sizeof(sffunction *)); + if (!fnctbl) + errset(MEMERROR); + if (opr == 'f') { + fnctbl[p->oprCount - 1] = fnctbl[p->oprCount - 2]; + fnctbl[p->oprCount - 2] = (sffunction *) ch1; + } else + fnctbl[p->oprCount - 1] = (sffunction *) ch1; + ch1 = (char *) (int) opr; /* ]:-> */ + code('*'); + opr = (char) (int) ch1; + ch1 = NULL; + }; + + code(opr); + }; + + ech = expcode; + +#ifdef SFFE_DEVEL + printf + ("| compiled expr. :|%s|\n| operacje: %d\n| stale,zmienne: %d\n| stack not.: ", + expcode, p->oprCount, p->argCount); +#endif + +/*! PRE PHASE 3 !!!!! no operations in expression = single numeric value */ + if (!p->oprCount && p->argCount == 1) { + p->oprs = (sfopr *) malloc(p->argCount * sizeof(sfopr)); + p->oprs[0].arg = (sfarg *) p->args; + p->oprs[0].f = NULL; + p->result = (sfNumber *) p->args->value; + } else +/*! PHASE 3 !!!!! create sffe 'stack' notation ]:-> */ +/* lots of memory operations are done here but no memory leaks should occur */ + if (!err) { + ui1 = p->argCount + p->oprCount; + p->args = (sfarg *) realloc(p->args, ui1 * sizeof(sfarg)); + memset(p->args + p->argCount, 0, p->oprCount * sizeof(sfarg)); + p->argCount = ui1; + arg = p->args; + p->oprs = (sfopr *) malloc(p->oprCount * sizeof(sfopr)); + ch1 = NULL; /* number */ + /* stacks ( stores operations and controls parameters count inside of brackts blocks ) */ + stack = (struct stack__ *) malloc(sizeof(struct stack__)); + stack->size = 0; /* 0-stack is empty, but ready to write (one slot allocated), >0-number of element on stack */ + stack->stck = + (struct opstack__ *) malloc(sizeof(struct opstack__)); + stack->prev = NULL; + memset(stack->stck, 0, sizeof(struct opstack__)); + ui1 = 0; /* used in defines */ + f = fnctbl; + + while (*ech && !err) { + switch (*ech) { + /* O */ + case '+': + case '-': + case '*': + case '/': + case '^': + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + }; + + ch1 = (char *) (int) (priority(ech)); + /* there is an operator on stack */ + if (stack->size) { + /* double casting to get rid of 'cast from pointer to integer of different size' warning + * remove all operators with higher, or equal priority + **/ + while ((unsigned char) (int) ch1 <= + stack->stck[stack->size - 1].t) { + sfpopstack(NULL); + stack->stck = (struct opstack__ *) realloc(stack->stck, sizeof(struct opstack__)); /* is this reallocation really needed ?!? */ + if (stack->size == 0) + break; + }; + stack->stck = + (struct opstack__ *) realloc(stack->stck, + (stack->size + + 1) * + sizeof(struct + opstack__)); + }; + +#ifdef SFFE_DEVEL + stack->stck[stack->size].c = *ech; +#endif + + stack->stck[stack->size].t = (unsigned char) (int) ch1; /* store operator prority */ + stack->stck[stack->size].f = ((sffunction *) (*f))->fptr; /* get function pointer */ + stack->size += 1; + f += 1; + ch1 = NULL; + break; + /* F */ + case 'f': + stack->stck = + (struct opstack__ *) realloc(stack->stck, + (stack->size + + 1) * + sizeof(struct opstack__)); +#ifdef SFFE_DEVEL + stack->stck[stack->size].c = 'f'; +#endif + + /* mark operator as a function, and store number of parameters (0 - unlimited) */ + stack->stck[stack->size].t = + 0x60 | (((sffunction *) (*f))->parcnt & 0x1F); + stack->stck[stack->size].f = ((sffunction *) (*f))->fptr; /* get function pointer */ + + stack->size += 1; + f += 1; + ch1 = NULL; + break; + /* ( */ + case '(': + /* store current stack */ + stmp = (struct stack__ *) malloc(sizeof(struct stack__)); + stmp->prev = stack; + stack = stmp; + stack->size = 0; + stack->stck = + (struct opstack__ *) malloc(sizeof(struct opstack__)); +#ifdef SFFE_DEVEL + stack->stck[0].c = '_'; +#endif + opr = 0; + break; + /* ; */ + case ';': + /* check if anything whas been read !!! */ + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + ch1 = NULL; + }; + /* if there is something on stack, flush it we need to read next parameter */ + while (stack->size) + sfpopstack(NULL); + + /* wrong number of parameters */ + ch2 = (char *) (stack->prev->stck + stack->prev->size - 1); + if ((((struct opstack__ *) ch2)->t & 0x1f) == 1) + errset(PARCNTERROR); + ((struct opstack__ *) ch2)->t = + 0x60 | ((((struct opstack__ *) ch2)->t & 0x1f) - 1); + break; + /* ) */ + case ')': + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + } + ch1 = NULL; + + /* if there is something on stack, flush it we need to read next parameter */ + while (stack->size) + sfpopstack(NULL); + + if (!stack->prev) + errset(STACKERROR); + stmp = stack; + free(stmp->stck); + stack = stmp->prev; + free(stmp); + + /* i was reading function, if so at the top of current + * stack is a function. identified by '*.t==3' + **/ + ch2 = (char *) (stack->stck + stack->size - 1); + if ((((struct opstack__ *) ch2)->t & 0xE0) == 0x60) { + /* wrong number of parameters */ + if ((((struct opstack__ *) ch2)->t & 0x1f) > 1) + errset(PARCNTERROR); + if (!err) { + sfpopstack(NULL); + if (stack->size) + stack->stck = + (struct opstack__ *) realloc(stack->stck, + (stack-> + size) * + sizeof(struct + opstack__)); + }; + }; + break; + /* n */ + case 'n': + ch1 = ech; + break; + }; + ech += 1; + }; + + if (!err) { + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + } + + while (stack) { /*clean up stack */ + while (stack->size) { + stack->size -= 1; +#ifdef SFFE_DEVEL + printf("%c", stack->stck[stack->size].c); +#endif + insertfnc(NULL); + p->oprs[ui1].arg = (sfarg *) arg; + p->oprs[ui1].f = stack->stck[stack->size].f; + ui1 += 1; + arg += 1; + }; + free(stack->stck); + stmp = stack->prev; + free(stack); + stack = stmp; + }; + + /* set up formula call stack */ + (p->args)->parg = NULL; + for (ui1 = 1; ui1 < p->argCount; ui1 += 1) + (p->args + ui1)->parg = (p->args + ui1 - 1); + +#ifdef SFFE_DEVEL + printf("\n| numbers :"); + for (ui1 = 0; ui1 < p->argCount; ui1 += 1) { + if ((p->args + ui1)->value) + printf(" %g%+gI", real((*(p->args + ui1)->value)), + imag((*(p->args + ui1)->value))); + else + printf(" [_]"); + }; + + printf("\n| functions fnctbl:"); + for (ui1 = 0; ui1 < p->oprCount; ui1 += 1) + printf(" 0x%.6X [%s]", (int) fnctbl[ui1]->fptr, + fnctbl[ui1]->name); + + printf("\n| functions used ptrs:"); + for (ui1 = 0; ui1 < p->oprCount; ui1 += 1) + printf(" 0x%.6X", (int) p->oprs[ui1].f); +#endif + } else { /* prevent memory leaks */ + + while (stack) { /* clean up stack */ + free(stack->stck); + stmp = stack->prev; + free(stack); + stack = stmp; + }; + }; + /* set up evaluation result pointer (result is stored in last operation return) */ + p->result = (sfNumber *) (p->oprs + p->oprCount - 1)->arg->value; + if (!p->result) + err = MEMERROR; + }; + + if (err) { +#ifdef SFFE_DEVEL + /* in debug mode report errors on stdout */ + printf("Parser error : "); + switch (err) { + case MEMERROR: + printf(" MEMORY ERROR!!"); + break; + case UNBALANCEDBRACKES: + printf(" UNBALANCED BRACKETS!! : %s\n", ch1); + break; + case INVALIDFUNCTION: + printf(" UNKNOWN FUNCTION!! : %s\n", ch1); + break; + case INAVLIDNUMBER: + printf(" NUMBER FORMAT!! : %s\n", ch1); + break; + case UNKNOWNCONST: + printf(" UNKOWN CONST or VAR NAME!! : %s\n", ch1); + break; + case OPERATOR: + printf(" UNKNOWN OPERATOR!! : %s\n", ch1); + break; + case STACKERROR: + printf(" INTERNAL STACK CORRUPTED!! : %s\n", ch1); + break; + case PARCNTERROR: + printf(" FUNCTION PARAMETERS ERROR!! : %s\n", ch1); + break; + case NO_FUNCTIONS: + printf("Formula error ! ARE YOU KIDDING ME ?!? : %s", ch1); + break; + }; +#endif + /* try to store error message */ + if (p->errormsg) + switch (err) { + case MEMERROR: + sprintf(p->errormsg, "Formula error ! MEMORY ERROR!!"); + break; + case UNBALANCEDBRACKES: + sprintf(p->errormsg, + "Formula error ! UNBALANCED BRACKETS!! : %s", ch1); + break; + case INVALIDFUNCTION: + sprintf(p->errormsg, + "Formula error ! UNKNOWN FUNCTION!! : %s", ch1); + break; + case INAVLIDNUMBER: + sprintf(p->errormsg, + "Formula error ! NUMBER FORMAT!! : %s", ch1); + break; + case UNKNOWNCONST: + sprintf(p->errormsg, + "Formula error ! UNKOWN CONST or VAR NAME!! : %s", + ch1); + break; + case OPERATOR: + sprintf(p->errormsg, + "Formula error ! UNKNOWN OPERATOR!! : %s", ch1); + break; + case STACKERROR: + sprintf(p->errormsg, + "Formula error ! INTERNAL STACK CORRUPTED!! : %s", + ch1); + break; + case PARCNTERROR: + sprintf(p->errormsg, + "Formula error ! FUNCTION PARAMETERS ERROR!! : %s", + ch1); + break; + case NO_FUNCTIONS: + sprintf(p->errormsg, + "Formula error ! ARE YOU KIDDING ME ?!? : %s", + ch1); + break; + }; + /* if error -> clean up */ + sffe_clear(&p); + }; + + /*undefine defines */ +#undef priority +#undef sfpopstack +#undef insertfnc +#undef code +#undef errset +#undef MEMERROR +#undef UNBALANCEDBRACKES +#undef INVALIDFUNCTION +#undef INAVLIDNUMBER +#undef UNKNOWNCONST +#undef OPERATOR +#undef STACKERROR +#undef PARCNTERROR + free(expcode); + free(fnctbl); + +#ifdef SFFE_DEVEL + printf("\nparse - END\n"); +#endif + return err; +}; + +#undef sfset +#undef sfvar + +#endif -- cgit v0.9.1