📄 numexpr.c
字号:
/****************************************************************************** * FREXX PROGRAMMING LANGUAGE * ****************************************************************************** numexpr.c Supports *FULL* C language expression operator priority and much more...! *****************************************************************************//************************************************************************ * * * fpl.library - A shared library interpreting script langauge. * * Copyright (C) 1992-1994 FrexxWare * * Author: Daniel Stenberg * * * * This program is free software; you may redistribute for non * * commercial purposes only. Commercial programs must have a written * * permission from the author to use FPL. FPL is *NOT* public domain! * * Any provided source code is only for reference and for assurance * * that users should be able to compile FPL on any operating system * * he/she wants to use it in! * * * * You may not change, resource, patch files or in any way reverse * * engineer anything in the FPL package. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * Daniel Stenberg * * Ankdammsgatan 36, 4tr * * S-171 43 Solna * * Sweden * * * * FidoNet 2:201/328 email:dast@sth.frontec.se * * * ************************************************************************/#ifdef AMIGA#include <exec/types.h>#include <proto/exec.h>#elif defined(UNIX) || defined(WIN32)#include <sys/types.h>#endif#include "script.h"#include <stdio.h>#include <stddef.h>#include <limits.h>#include "debug.h"static ReturnCode INLINE GetArrayInfo(struct Data *, long *, long *, long, uchar *);static ReturnCode INLINE Convert(struct Expr *, struct Data *);static ReturnCode INLINE PrototypeInside(struct Data *, struct Expr *val, long, struct Identifier *);static ReturnCode INLINE inside(struct Data *, struct fplArgument *, struct Identifier *);#ifdef STRING_STACKstatic ReturnCode INLINE StringToStack(struct Data *, struct fplStr **);static ReturnCode INLINE StringFromStack(struct Data *, struct fplStr **);#endif/*********************************************************************** * * int Expression(struct Expr *, struct Data *, uchar, struct Local *) * * Returns a nonzero value if any error occured. * The result of the Expression is returned in the Expr structure which you * give the pointer to in the first argument. * *****************/ReturnCode REGARGSExpression(struct Expr *val, /* return value struct pointer */ struct Data *scr, /* everything */ long control, /* ESPECIALLLY DEFINED */ struct Identifier *ident) /* pointer to the pointer holding the local variable names linked list */{ struct Expr *expr, *basexpr; ReturnCode ret; struct Identifier *pident; /* general purpose struct identifier pointer */ struct Unary *un; /* general purpose struct Unary pointers */ long *dims=NULL; /* dimension pointer for variable arrays! */ long pos; /* general purpose integer */ uchar *text; /* general purpose char pointer */ uchar hit; uchar *array; long num; long *nump; /* for general purpose long pointers */ struct fplMsg *msg; struct fplStr *string;#if defined(AMIGA) && defined(SHARED) if(ret=CheckStack(scr, scr->stack_limit, scr->stack_margin)) { if(ret==1) return(FPLERR_OUT_OF_MEMORY); else return(FPLERR_OUT_OF_STACK); }#endif GETMEM(expr, sizeof(struct Expr)); memset(expr, 0, sizeof(struct Expr)); basexpr=expr; do { if(ret=Eat(scr)) { /* getaway blanks and comments */ if(control&CON_END && ret==FPLERR_UNEXPECTED_END) { /* If there can be an unexpected ending, break out of the loop with a nice return code! */ break; } } else if(expr->flags&FPL_STRING && !(control&CON_GROUNDLVL)) /* get outta string calcs if not on ground level! */ break; if(!(expr->flags&FPL_OPERAND)) { /* operand coming up */ if(control&CON_IDENT || isident(*scr->text)) { /* * It's a valid identifier character. */ uchar *point; num=0; /* Dimension counter when taking care of array variables */ if(control&CON_IDENT) { if(!ident) ret=FPLERR_IDENTIFIER_NOT_FOUND; control&=~CON_IDENT; /* switch off that bit to get away from any trouble such as double using this! */ } else { CALL(Getword(scr)); ret=GetIdentifier(scr, scr->buf, &ident); } point=scr->text; Eat(scr); /* getaway blanks */ /* * `ret' can only be FPL_OK or FPLERR_IDENTIFIER_NOT_FOUND at this * position. */ if(control&CON_DECLARE && *scr->text==CHAR_OPEN_PAREN) { CALL(PrototypeInside(scr, val, control, ident)); expr->flags|=FPL_OPERAND|FPL_ACTION; } else if(control&CON_DECLARE || (ident && ident->flags&FPL_VARIABLE)) { /* The ident check above really must be there, otherwise we might read it when it is a NULL pointer" */ /* it's a variable */ pident=ident; if(ret && /* we didn't find it... */ !(control&CON_DECLARE)) /* and we're not declaring! */ /* * We didn't find the requested identifier and we're *NOT* * declaring. This means error! */ return(ret); else if(!ret) { if(ident->flags&FPL_REFERENCE) return FPLERR_ILLEGAL_VARIABLE; /* this is a reference _only_! */ /* The symbol was found */ if(control&CON_LEVELOK) /* level _is_ OK! */ ; else if(control&CON_DECLARE && (ident->level>=scr->varlevel || scr->varlevel==1)) { /* * If the name already declared in this (or higher) level * and declaration is wanted. */ if((ident->flags&FPL_STATIC_VARIABLE && control&CON_DECLSTATIC && ident->level==scr->varlevel) || /* * If this is a `static' variable and the variable already * exists on this very level in this very function as static, * then skip this. It's perfectly OK to jump to the ending * semicolon since this has been parsed before! */ (ident->flags&FPL_EXPORT_SYMBOL && control&CON_DECLEXP)) { /* * If this is an `export' symbol and it already exists as an * `export' symbol! Then just ignore this! */ /* * The current implementation unfortunately uses the statement * below to pass this declaration. That means comma- * separated exported symbols will be passed if only the first * is alredy declared... This will although work in all those * cases it is the SAME code that is executed twice! */ if(GetEnd(scr, CHAR_SEMICOLON, (uchar)255, FALSE)) return FPLERR_MISSING_SEMICOLON; scr->text--; /* get back on the semicolon! */ break; } else { CALL(Warn(scr, FPLERR_IDENTIFIER_USED)); /* run it over! */ DelIdentifier(scr, ident->name, NULL); } } else if(!(control&CON_DECLARE) && (ident->level && /* not global */ ident->level<(scr->varlevel-scr->level))) /* * From the wrong program level and we're not declaring. */ return(FPLERR_IDENTIFIER_NOT_FOUND); else if(ident->flags&FPL_STATIC_VARIABLE && ((ident->func && (ident->func==scr->func)) || ident->level>scr->varlevel) ) /* * A static variable declared either in the wrong function or * in a higher level! */ return(FPLERR_IDENTIFIER_NOT_FOUND); } text = NULL; /* no name information yet! */ control &= ~CON_LEVELOK; /* forget about the level OK stuff!! */ if(*scr->text==CHAR_OPEN_BRACKET) { /* * It's an array. Get the result of the expression within the * square brackets. */ if(!dims) { GETMEM(dims, MAX_DIMS*sizeof(long)); } if(!(control&CON_DECLARE) && pident->data.variable.size) num=pident->data.variable.num; if(control&CON_DECLARE || num) { /* * Get the name now, cause the GetArrayInfo() call may * destroy the 'scr->buf' buffer! */ STRDUP(text, scr->buf); GETMEM(nump, sizeof(long)); *nump = num; CALL(GetArrayInfo(scr, dims, nump, control, text)); num = *nump; FREE(nump); if(!(control&CON_DECLARE)) { /* * Free the name now, cause we don't declare anything * and this isn't needed any more! */ FREE(text); text = NULL; } if(!(control&CON_DECLARE)) { if(num > pident->data.variable.num) { /* * If not declaring and overfilled quota: fail! * * * Copy the variable name to the buffer to make the * error message look good! */ strcpy(scr->buf, pident->name); return FPLERR_ILLEGAL_ARRAY; } else { for(pos=0; pos<num; pos++) if(pident->data.variable.dims[pos]<=dims[pos]) { /* * Copy the variable name to the buffer to make the * error message look good! */ strcpy(scr->buf, pident->name); return FPLERR_ILLEGAL_ARRAY; } } } point=scr->text; /* move point to current location */ Eat(scr); /* pass all traling whitespaces */ } } if(control&CON_DECLARE) { expr->flags|=FPL_ACTION; GETMEM(pident, sizeof(struct Identifier)); pident->level= (control&(CON_DECLEXP|CON_DECLGLOB))?0:scr->varlevel; pident->flags= (control&CON_DECLINT?FPL_INT_VARIABLE:FPL_STRING_VARIABLE)| (control&CON_DECLEXP?FPL_EXPORT_SYMBOL:0)| (control&CON_DECLGLOB?FPL_GLOBAL_SYMBOL: (control&CON_DECLSTATIC?FPL_STATIC_VARIABLE:0))| (control&CON_DECL8?FPL_CHAR_VARIABLE: (control&CON_DECL16?FPL_SHORT_VARIABLE:0))| (control&CON_DECLCONST?FPL_READONLY:0); pident->file=scr->prog->name; /* file */ pident->func=scr->func; /* declared in this function */ /* Get variable name */ if(text) /* * The name has already been allocated above! */ pident->name = text; else { /* * Get the name! */ STRDUP(pident->name, scr->buf); /* no real strdup */ } if(num) { /* * Array variable declaration! It is a bit different from * common variable declaration so I decided to put the code * for it right here: */ long size=dims[0]; /* array size */ for(pos=1; pos<num; pos++) size*=dims[pos]; /* Now `size' is the total number of members in the array we're about to declare */ /* Get memory for the dimension array */ GETMEM(pident->data.variable.dims, num * sizeof(long)); /* Copy the dim info to the newly allocated area */ memcpy((void *)pident->data.variable.dims, dims, num*sizeof(long)); /* Get memory for the array */ GETMEM(pident->data.variable.var.val32, size * sizeof(long)); /* Set all string lengths to NULL and integers to zero: */ memset(pident->data.variable.var.val32, 0, size * sizeof(void *)); pident->data.variable.size=size; /* total number of array members */ pident->data.variable.num=num; /* number of dimensions */ /* reset the dims array! */ memset((void *)dims, 0, sizeof(long) * num); /* reset num: */ num=1; } else {#ifdef DEBUG CheckMem(scr, pident);#endif GETMEM(pident->data.variable.var.val32, sizeof(long)); *pident->data.variable.var.val32=0; pident->data.variable.num=0; pident->data.variable.size=1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -