📄 numexpr.c
字号:
switch(*scr->text) { case CHAR_CLOSE_BRACE: num--; /* back one dimension */ if(num>=0 && num<pident->data.variable.num) dims[num]=0; else { CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY)); num=0; } scr->text++; break; case CHAR_COMMA: /* * Increase the last dimension member for next loop: */ if(num>0 && num<=pident->data.variable.num) dims[num-1]++; else { CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY)); num=pident->data.variable.num; } scr->text++; break; case CHAR_OPEN_BRACE: num++; /* next dimension */ scr->text++; break; default: hit=FALSE; break; } if(hit && !ret) { CALL(Eat(scr)); } else break; } if(!num) break; pos=ArrayNum(num, pident->data.variable.num, dims, pident->data.variable.dims); if(pos<0) { CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY)); pos=0; } /* assign! */ CALL(Expression(val, scr, CON_NORMAL|CON_NUM, NULL)); CALL(CmpAssign(scr, val->val.val, &pident->data.variable.var.val32[pos], pident->flags, was)); expr->val.val=pident->data.variable.var.val32[pos]; /* while */ } while(1); } expr->flags|=FPL_NOFREE; /* the memory pointed to by the expr->val.val is strings of proper variables. Do not free them now! */ } else { /* * No assignment, primary operator or none at all! */ long *value; if(control&CON_DECLARE) expr->val.val=0; else { if(pident->data.variable.num) { pos=ArrayNum(num, pident->data.variable.num, dims, pident->data.variable.dims); if(pos<0) { CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY)); pos=0; } } else pos=0; value=&pident->data.variable.var.val32[pos]; if(*point==CHAR_PLUS && point[1]==CHAR_PLUS) { /*post increment*/ if(pident->flags&FPL_READONLY) return FPLERR_READONLY_VIOLATE; expr->flags|=FPL_ACTION; expr->val.val=(*value)++; scr->text+=2; } else if(*point==CHAR_MINUS && point[1]==CHAR_MINUS) { /* post decrement */ if(pident->flags&FPL_READONLY) return FPLERR_READONLY_VIOLATE; expr->flags|=FPL_ACTION; expr->val.val=(*value)--; scr->text+=2; } else { /* plain variable or pre operation */ if(un=expr->unary) { if(un->unary!=OP_PREINC && un->unary!=OP_PREDEC) { expr->val.val=*value; } else { if(pident->flags&FPL_READONLY) return FPLERR_READONLY_VIOLATE; if(un->unary==OP_PREINC) expr->val.val=++(*value); else expr->val.val=--(*value); expr->unary=un->next; FREE(un); } } else expr->val.val=*value; } if(pident->flags&FPL_VARIABLE_LESS32) { if(pident->flags&FPL_CHAR_VARIABLE) { expr->val.val=(long)((signed char)expr->val.val); *value=(long)((signed char)*value); } else { /* sixteen bits */ expr->val.val=(long)((signed short)expr->val.val); *value=(long)((signed short)*value); } } } CALL(NewMember(scr, &expr)); } } /* end of integer handling */ } else if(ret && (*scr->text!=CHAR_OPEN_PAREN)) return(ret); /* FPLERR_IDENTIFIER_NOT_FOUND */ else { /* some sort of function */ /* * FUNCTION HANDLER PART: */ struct fplArgument *pass; /* struct pointer to send as argument to the function handler */ long allocspace; if(ret) { if(!(scr->flags&FPLDATA_ALLFUNCTIONS) || *scr->text!=CHAR_OPEN_PAREN) /* If the ability to parse all functions isn't turned on, or if the following character is not an open parenthesis, fail! */ return(ret); } num=0; /* number of arguments */ expr->flags|=FPL_OPERAND|FPL_ACTION; /* This sure is action...! */ GETMEM(pass, sizeof(struct fplArgument)); if(!ident) { /* The function does not exist as a declared function! */ STRDUP(pass->name, scr->buf); pass->ID=FPL_UNKNOWN_FUNCTION; text="o>"; /* optional parameter list as argument! */ } else { pass->name=ident->name; pass->ID=ident->data.external.ID; text=ident->data.inside.format; } pass->argc=0; pass->key=(void *)scr; if(!ident || FPL_OPTEXPRARG == ident->data.inside.ret) { /* * The function we invoked was not found regularly! * Set return type! */ /* * We try to determine whether it should return an int or a string. * We interpret the return value as we should do to make it pass * as a valid expression. That is, if the flag tells us this * should be a string expression to be valid, we take it as a * string, but if it tells us its an integer expression, we read * it as an integer!!! */ if(control&CON_STRING) hit = FPL_STRARG; else { if(control&CON_NUM) hit = FPL_INTARG; else /* * We don't know which kind of return code the function * should give us! */ hit = FPL_OPTEXPRARG; } } else { hit = UPPER(ident->data.inside.ret); if(control&CON_STRING && (hit!=FPL_STRARG)) return FPLERR_UNEXPECTED_INT_STATEMENT; if(control&CON_NUM && (hit!=FPL_INTARG)) return FPLERR_UNEXPECTED_STRING_STATEMENT; } pass->ret = hit; if(*scr->text!=CHAR_OPEN_PAREN) { CALL(Warn(scr, FPLERR_MISSING_PARENTHESES)); /* >warning< */ } else scr->text++; CALL(Eat(scr)); if(text && *text) { uchar b='a'; uchar a; /* if the function takes arguments */ /* * Allocate arrays to use for data storage while parsing * the arguments. Maximum number of arguments is * MAX_ARGUMENTS. */ num=strlen(text); /* number of arguments to this function */ if(text[num-1]!=FPL_ARGLIST) allocspace=num+1; else allocspace=MAX_ARGUMENTS; /* * By adjusting the number of allocated bytes to the smallest * necessary, my recursive example program used only a fifth * as much memory as when always allocating memory for * MAX_ARGUMENTS. */ /* allocate an array */ GETMEM(pass->argv, sizeof(uchar *)*allocspace); /* allocate new format string */ GETMEM(pass->format, sizeof(uchar)*allocspace); /* allocate allocate-flag string */ GETMEM(array, sizeof(uchar)*allocspace); while(!ret && *scr->text!=CHAR_CLOSE_PAREN && text && *text) { b=(*text==FPL_ARGLIST)?b:UPPER(*text); if(FPL_OPTARG == b && CHAR_AND == scr->text[0]) a = FPL_OPTVARARG; else a = b; if(pass->argc==allocspace) { uchar *temp; GETMEM(temp, sizeof(uchar *)*(allocspace+MAX_ARGUMENTS)); memcpy(temp, pass->argv, sizeof(uchar *)*allocspace); FREE(pass->argv); pass->argv=(void **)temp; GETMEM(temp, sizeof(uchar)*(allocspace+MAX_ARGUMENTS)); memcpy(temp, pass->format, sizeof(uchar)*allocspace); FREE(pass->format); pass->format=temp; GETMEM(temp, sizeof(uchar)*(allocspace+MAX_ARGUMENTS)); memcpy(temp, array, sizeof(uchar)*allocspace); FREE(array); array=temp; allocspace += MAX_ARGUMENTS; } switch(a) { case FPL_OPTEXPRARG: case FPL_OPTARG: case FPL_STRARG: CALL(Expression(val, scr, (a==FPL_STRARG?CON_STRING:0), NULL)); if(a==FPL_STRARG || val->flags&FPL_STRING) { CALL(StringExpr(val, scr)); /* get more strings? */ /* Enter string symbol in the created format string! */ pass->format[pass->argc]=FPL_STRARG; if(val->val.str) { /* Set this to TRUE if deallocation is wanted on this string after the function call! */ array[pass->argc]=!(val->flags&FPL_NOFREE); /* * Point to the string (that is zero terminated)! */ pass->argv[pass->argc]=val->val.str->string; } else { GETMEM(string, sizeof(struct fplStr)); memset(string, 0, sizeof(struct fplStr)); pass->argv[pass->argc]=string->string; array[pass->argc]=1; /* allocation has been done! */ } } else { pass->format[pass->argc]=FPL_INTARG; pass->argv[pass->argc]=(void *)val->val.val; } pass->argc++; break; case FPL_INTARG: CALL(Expression(val, scr, CON_NUM, NULL)); pass->format[pass->argc]=FPL_INTARG; pass->argv[pass->argc++]=(void *)val->val.val; break; case FPL_OPTVARARG: case FPL_STRVARARG: case FPL_INTVARARG: case FPL_INTARRAYVARARG: case FPL_STRARRAYVARARG: { register ReturnCode ok; if(*scr->text != CHAR_AND) { ok = FPLERR_ILLEGAL_REFERENCE; } else { scr->text++; ok = FPL_OK; } CALL(Getword(scr)); /* Use the `pident' pointer here, cause the `ident' pointer is already being used by the function we're about to invoke! */ CALL(GetIdentifier(scr, scr->buf, &pident)); if(ok) { /* missing &-character! */ if(pident->flags&FPL_REFERENCE) /* get the referenced variable instead! */ pident = pident->data.variable.ref; else return FPLERR_ILLEGAL_REFERENCE; /* no reference! */ } } if(FPL_INTARRAYVARARG == a || FPL_STRARRAYVARARG == a) { if(!pident->data.variable.num) return FPLERR_ILLEGAL_REFERENCE; } else if(FPL_OPTVARARG != a && pident->data.variable.num) /* only straight variables! */ return FPLERR_ILLEGAL_PARAMETER; if( (pident->flags&FPL_INT_VARIABLE && (a==FPL_STRVARARG || a == FPL_STRARRAYVARARG)) || (pident->flags&FPL_STRING_VARIABLE && (a==FPL_INTVARARG || a == FPL_INTARRAYVARARG))) { CALL(Warn(scr, FPLERR_ILLEGAL_VARIABLE)); /* can't copy wrong variable! */ pass->argv[pass->argc]=NULL; } else pass->argv[pass->argc]=(void *)pident; pass->format[pass->argc++]= (pident->flags&FPL_STRING? (pident->data.variable.num?FPL_STRARRAYVARARG:FPL_STRVARARG): (pident->data.variable.num?FPL_INTARRAYVARARG: FPL_INTVARARG)); Eat(scr); break; default: CALL(Warn(scr, FPLERR_ILLEGAL_PARAMETER)); break; /* just ignore it and be happy! */ } if(*text!=FPL_ARGLIST) text++; if(*scr->text==CHAR_COMMA) { scr->text++; CALL(Eat(scr)); /* eat white space! */ } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -