2057 lines
48 KiB
C
2057 lines
48 KiB
C
/*
|
|
|
|
YABASIC --- a simple Basic Interpreter
|
|
written by Marc-Oliver Ihm 1995-2004
|
|
homepage: www.yabasic.de
|
|
|
|
function.c --- code for functions
|
|
|
|
This file is part of yabasic and may be copied only
|
|
under the terms of either the Artistic License or
|
|
the GNU General Public License (GPL), both of which
|
|
can be found at www.yabasic.de
|
|
|
|
*/
|
|
|
|
|
|
/* ------------- includes ---------------- */
|
|
#include "YabInterface.h"
|
|
#ifndef YABASIC_INCLUDED
|
|
#include "yabasic.h" /* all prototypes and structures */
|
|
#endif
|
|
|
|
|
|
/* ------------- external references ---------------- */
|
|
|
|
extern int mylineno; /* current line number */
|
|
extern int yyparse(); /* call bison parser */
|
|
|
|
|
|
/* ------------- local functions ---------------- */
|
|
|
|
static char *fromto(char *,int,int); /* get portion of string (mid$ et al) */
|
|
static void clear_buff(); /* clear system-input buffers */
|
|
static void store_buff(char *,int); /* store system-input buffer */
|
|
static int do_glob(char *,char *); /* actually do the globbing */
|
|
static double other2dec(char *,int); /* convert hex to decimal */
|
|
static char *dec2other(double,int); /* convert decimal to hex */
|
|
static double peek(char *, YabInterface *); /* peek into internals */
|
|
static char *peek2(char *,struct command *); /* peek into internals */
|
|
static char *peek3(char *,char *); /* peek into internals */
|
|
static int peekfile(int); /* read a byte from stream */
|
|
static char *do_system(char *); /* executes command via command.com */
|
|
static int do_system2(char *); /* execute command as system */
|
|
|
|
|
|
/* ------------- global variables ---------------- */
|
|
|
|
struct command *lastdata=NULL; /* used to associate all data-commands with each others */
|
|
static struct buff_chain *buffroot; /* start of sys-input buffer */
|
|
static struct buff_chain **buffcurr; /* current entry in buff_chain */
|
|
static int buffcount; /* number of filled buffers */
|
|
|
|
|
|
/* ------------- subroutines ---------------- */
|
|
|
|
|
|
void token(struct command *cmd) /* extract token from variable */
|
|
{
|
|
int split;
|
|
struct stackentry *s;
|
|
struct symbol *sym;
|
|
struct array *ar;
|
|
int num=0,i;
|
|
char *p,*q;
|
|
char **pp;
|
|
char *del,*line;
|
|
int wasdel,isdel;
|
|
|
|
|
|
if (cmd->type==cSPLIT2 || cmd->type==cTOKEN2)
|
|
del=pop(stSTRING)->pointer;
|
|
else
|
|
del=" \t";
|
|
split=(cmd->type==cSPLIT || cmd->type==cSPLIT2);
|
|
s=pop(stSTRINGARRAYREF);
|
|
line=pop(stSTRING)->pointer;
|
|
sym=get_sym(s->pointer,syARRAY,amSEARCH);
|
|
if (!sym || !sym->pointer) {
|
|
sprintf(string,"array '%s()' is not defined",strip(s->pointer));
|
|
error(ERROR,string);
|
|
goto token_done;
|
|
}
|
|
ar=sym->pointer;
|
|
if (ar->dimension>1) {
|
|
error(ERROR,"only one dimensional arrays allowed");
|
|
goto token_done;
|
|
}
|
|
|
|
/* count number of tokens */
|
|
isdel=TRUE;
|
|
if (split && *line) num=1;
|
|
else num=0;
|
|
for(p=line;*p;++p) {
|
|
wasdel=isdel;
|
|
isdel=(strchr(del,*p)!=NULL);
|
|
if (split) {
|
|
if (isdel) num++;
|
|
} else {
|
|
if (isdel && isdel!=wasdel) num++;
|
|
}
|
|
}
|
|
if (!split && !isdel) num++;
|
|
|
|
/* free previous array content */
|
|
for(i=0;i<ar->bounds[0];i++) free(((char **)ar->pointer)[i]);
|
|
free(ar->pointer);
|
|
ar->pointer=my_malloc((num+1)*sizeof(char *));
|
|
pp=ar->pointer;
|
|
pp[0]=my_strdup("");
|
|
|
|
/* extract tokens */
|
|
i=1;
|
|
isdel=TRUE;
|
|
if (*line) {
|
|
for(p=q=line;;p++) {
|
|
wasdel=isdel;
|
|
isdel=(strchr(del,*p)!=NULL) || !*p;
|
|
if ((split && isdel) || (!split && (isdel && isdel!=wasdel))) {
|
|
while(strchr(del,*q) && q<p) q++;
|
|
pp[i]=my_strndup(q,p-q+1);
|
|
pp[i][p-q]='\0';
|
|
q=p+1;
|
|
i++;
|
|
}
|
|
if (!*p) break;
|
|
}
|
|
}
|
|
|
|
ar->bounds[0]=num+1;
|
|
token_done:
|
|
s=push();
|
|
s->type=stNUMBER;
|
|
s->value=num;
|
|
}
|
|
|
|
|
|
void tokenalt(struct command *cmd) /* extract token from variable with alternate semantics */
|
|
{
|
|
char *del; /* delimiter for strings */
|
|
struct stackentry *t;
|
|
char *old,*new,*tok;
|
|
int split;
|
|
|
|
if (cmd->type==cSPLITALT2 || cmd->type==cTOKENALT2)
|
|
del=pop(stSTRING)->pointer;
|
|
else
|
|
del=" \t";
|
|
split=(cmd->type==cSPLITALT || cmd->type==cSPLITALT2);
|
|
|
|
t=pop(stSTRING);
|
|
old=t->pointer;
|
|
t->pointer=NULL; /* prevent push from freeing the memory */
|
|
t=push();
|
|
t->type=stSTRING;
|
|
new=old;
|
|
tok=NULL;
|
|
while(*new) {
|
|
if (!tok && (!strchr(del,*new) || split)) tok=new; /* found start of token */
|
|
if (tok && strchr(del,*new)) break; /* found end of token */
|
|
new++;
|
|
}
|
|
if (*new) {
|
|
*new='\0'; /* terminate token */
|
|
new++;
|
|
if (!split) {
|
|
while(*new) {
|
|
if (!strchr(del,*new)) break; /* found start of next token */
|
|
new++;
|
|
}
|
|
}
|
|
}
|
|
t->pointer=my_strdup(tok?tok:""); /* copy token */
|
|
/* move rest of string */
|
|
while(*new) {
|
|
*old=*new;
|
|
old++;
|
|
new++;
|
|
};
|
|
*old='\0';
|
|
}
|
|
|
|
|
|
void glob(void) /* check, if pattern globs string */
|
|
{
|
|
char *str,*pat;
|
|
struct stackentry *stack;
|
|
int res;
|
|
|
|
pat=(char *)pop(stSTRING)->pointer;
|
|
str=(char *)pop(stSTRING)->pointer;
|
|
|
|
res=do_glob(str,pat);
|
|
stack=push();
|
|
stack->value=res;
|
|
stack->type=stNUMBER;
|
|
}
|
|
|
|
|
|
static int do_glob(char *str,char *pat) /* actually do the globbing */
|
|
{
|
|
int res;
|
|
|
|
if (infolevel>=DEBUG) {
|
|
sprintf(string,"globbing '%s' on '%s'",str,pat);
|
|
error(DEBUG,string);
|
|
}
|
|
if (*pat=='\0' && *str=='\0') return TRUE;
|
|
else if (*pat=='\0') return FALSE;
|
|
else if (*pat=='?' && *str=='\0') return FALSE;
|
|
else if (*pat=='?') {
|
|
if (*str=='\0') return FALSE;
|
|
pat++;
|
|
str++;
|
|
}
|
|
else if (*pat=='*') {
|
|
pat++;
|
|
res=FALSE;
|
|
while(*str && !(res=do_glob(str,pat))) str++;
|
|
if (res) return TRUE;
|
|
}
|
|
else if (*str=='\0') return FALSE;
|
|
else {
|
|
while(*pat && *pat!='?' && *pat!='*') {
|
|
if (*pat!=*str) return FALSE;
|
|
str++;
|
|
pat++;
|
|
}
|
|
}
|
|
return do_glob(str,pat);
|
|
}
|
|
|
|
|
|
void concat() /* concatenates two strings from stack */
|
|
{
|
|
struct stackentry *c;
|
|
char *aa,*bb,*cc;
|
|
|
|
aa=pop(stSTRING)->pointer;
|
|
bb=pop(stSTRING)->pointer;
|
|
cc=(char *) my_malloc(sizeof(char)*(strlen(aa)+strlen(bb)+1));
|
|
strcpy(cc,bb);
|
|
strcat(cc,aa);
|
|
c=push();
|
|
c->type=stSTRING;
|
|
c->pointer=cc;
|
|
}
|
|
|
|
|
|
void create_changestring(int type) /* create command 'changestring' */
|
|
{
|
|
struct command *cmd;
|
|
|
|
cmd=add_command(cCHANGESTRING,FALSE);
|
|
cmd->args=type;
|
|
}
|
|
|
|
|
|
void changestring(struct command *current) /* changes a string */
|
|
{
|
|
int type,a2,a3;
|
|
char *newpart;
|
|
char *oldstring;
|
|
int i,len;
|
|
struct stackentry *a1;
|
|
|
|
type=current->args;
|
|
newpart=pop(stSTRING)->pointer;
|
|
if (type>fTWOARGS) a3=(int)pop(stNUMBER)->value;
|
|
if (type>fONEARGS) a2=(int)pop(stNUMBER)->value;
|
|
a1=pop(stSTRING);
|
|
oldstring=a1->pointer;
|
|
a1->pointer=NULL; /* this prevents push from freeing the memory */
|
|
|
|
if (!oldstring || !*oldstring) return;
|
|
switch(type) {
|
|
case fMID:
|
|
for(i=1;i<a2+a3;i++) {
|
|
if (!oldstring[i-1]) break;
|
|
if (i>=a2) {
|
|
if (!newpart[i-a2]) break;
|
|
oldstring[i-1]=newpart[i-a2];
|
|
}
|
|
}
|
|
break;
|
|
case fMID2:
|
|
len=strlen(oldstring);
|
|
for(i=1;i<=len;i++) {
|
|
if (!oldstring[i-1]) break;
|
|
if (i>=a2) {
|
|
if (!newpart[i-a2]) break;
|
|
oldstring[i-1]=newpart[i-a2];
|
|
}
|
|
}
|
|
break;
|
|
case fLEFT:
|
|
for(i=1;i<=a2;i++) {
|
|
if (!oldstring[i-1] || !newpart[i-1]) break;
|
|
oldstring[i-1]=newpart[i-1];
|
|
}
|
|
break;
|
|
case fRIGHT:
|
|
len=strlen(oldstring);
|
|
for(i=1;i<=len;i++) {
|
|
if (i>len-a2) {
|
|
if (!newpart[i-1-len+a2]) break;
|
|
oldstring[i-1]=newpart[i-1-len+a2];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void create_function(int type) /* create command 'function' */
|
|
/* type can be sin,cos,mid$ ... */
|
|
{
|
|
struct command *cmd;
|
|
|
|
cmd=add_command(cFUNCTION,FALSE);
|
|
cmd->args=type;
|
|
}
|
|
|
|
|
|
void function(struct command *current,YabInterface* yab) /* performs a function */
|
|
{
|
|
struct stackentry *stack,*a1,*a2,*a3,*a4,*a5,*a6;
|
|
char *pointer;
|
|
double value;
|
|
time_t datetime;
|
|
int type,result,len,start,i,max, linenum;
|
|
char *str,*str2, *str3, *str4, *str5;
|
|
|
|
a3=NULL;
|
|
a4=NULL;
|
|
a5=NULL;
|
|
a6=NULL;
|
|
type=current->args;
|
|
if (type>fFIVEARGS) a6=pop(stSTRING_OR_NUMBER);
|
|
if (type>fFOURARGS) a5=pop(stSTRING_OR_NUMBER);
|
|
if (type>fTHREEARGS) a4=pop(stSTRING_OR_NUMBER);
|
|
if (type>fTWOARGS) a3=pop(stSTRING_OR_NUMBER);
|
|
if (type>fONEARGS) a2=pop(stSTRING_OR_NUMBER);
|
|
if (type>fZEROARGS) a1=pop(stSTRING_OR_NUMBER);
|
|
linenum = current->line;
|
|
|
|
switch (type) {
|
|
case fSIN:
|
|
value=sin(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fASIN:
|
|
value=asin(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fCOS:
|
|
value=cos(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fACOS:
|
|
value=acos(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fTAN:
|
|
value=tan(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fATAN:
|
|
value=atan(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fEXP:
|
|
value=exp(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fLOG:
|
|
value=log(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fLOG2:
|
|
value=log(a1->value)/log(a2->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fLEN:
|
|
value=(double) strlen(a1->pointer);
|
|
result=stNUMBER;
|
|
break;
|
|
case fSTR:
|
|
sprintf(string,"%g",a1->value);
|
|
pointer=my_strdup(string);
|
|
result=stSTRING;
|
|
break;
|
|
case fSTR2:
|
|
case fSTR3:
|
|
result=stSTRING;
|
|
if (!myformat(string,a1->value,a2->pointer,a3?a3->pointer:NULL)) {
|
|
pointer=my_strdup("");
|
|
sprintf(string,"'%s' is not a valid format",(char *)a2->pointer);
|
|
error(ERROR,string);
|
|
break;
|
|
}
|
|
pointer=my_strdup(string);
|
|
break;
|
|
case fSQRT:
|
|
value=sqrt(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fSQR:
|
|
value=a1->value*a1->value;
|
|
result=stNUMBER;
|
|
break;
|
|
case fINT:
|
|
if (a1->value<0)
|
|
value=-floor(-a1->value);
|
|
else
|
|
value=floor(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fFRAC:
|
|
if (a1->value<0)
|
|
value=a1->value+floor(-a1->value);
|
|
else
|
|
value=a1->value-floor(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fABS:
|
|
value=fabs(a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fSIG:
|
|
if (a1->value<0) value=-1.;
|
|
else if (a1->value>0) value=1.;
|
|
else value=0.;
|
|
result=stNUMBER;
|
|
break;
|
|
case fMOD:
|
|
value=a1->value-a2->value*(int)(a1->value/a2->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fRAN:
|
|
value=a1->value*((double)rand()/RAND_MAX);
|
|
result=stNUMBER;
|
|
break;
|
|
case fRAN2:
|
|
value=(double)rand()/RAND_MAX;
|
|
result=stNUMBER;
|
|
break;
|
|
case fMIN:
|
|
if (a1->value>a2->value)
|
|
value=a2->value;
|
|
else
|
|
value=a1->value;
|
|
result=stNUMBER;
|
|
break;
|
|
case fMAX:
|
|
if (a1->value>a2->value)
|
|
value=a1->value;
|
|
else
|
|
value=a2->value;
|
|
result=stNUMBER;
|
|
break;
|
|
case fVAL:
|
|
i=sscanf((char *) a1->pointer,"%lf",&value);
|
|
if (i!=1) value=0;
|
|
result=stNUMBER;
|
|
break;
|
|
case fATAN2:
|
|
value=atan2(a1->value,a2->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fLEFT:
|
|
str=a1->pointer;
|
|
len=(int)a2->value;
|
|
pointer=fromto(str,0,len-1);
|
|
result=stSTRING;
|
|
break;
|
|
case fRIGHT:
|
|
str=a1->pointer;
|
|
max=strlen(str);
|
|
len=(int)a2->value;
|
|
pointer=fromto(str,max-len,max-1);
|
|
result=stSTRING;
|
|
break;
|
|
case fMID:
|
|
str=a1->pointer;
|
|
start=(int)a2->value;
|
|
len=(int)a3->value;
|
|
pointer=fromto(str,start-1,start+len-2);
|
|
result=stSTRING;
|
|
break;
|
|
case fMID2:
|
|
str=a1->pointer;
|
|
start=(int)a2->value;
|
|
pointer=fromto(str,start-1,strlen(str));
|
|
result=stSTRING;
|
|
break;
|
|
case fINKEY:
|
|
pointer=inkey(a1->value);
|
|
result=stSTRING;
|
|
break;
|
|
case fAND:
|
|
value=(int)a1->value & (int)a2->value;
|
|
result=stNUMBER;
|
|
break;
|
|
case fOR:
|
|
value=(int)a1->value | (int)a2->value;
|
|
result=stNUMBER;
|
|
break;
|
|
case fEOR:
|
|
value=(int)a1->value ^ (int)a2->value;
|
|
result=stNUMBER;
|
|
break;
|
|
/*
|
|
case fMOUSEX:
|
|
getmousexybm(a1->pointer,&i,NULL,NULL,NULL);
|
|
value=i;
|
|
result=stNUMBER;
|
|
break;
|
|
case fMOUSEY:
|
|
getmousexybm(a1->pointer,NULL,&i,NULL,NULL);
|
|
value=i;
|
|
result=stNUMBER;
|
|
break;
|
|
case fMOUSEB:
|
|
getmousexybm(a1->pointer,NULL,NULL,&i,NULL);
|
|
value=i;
|
|
result=stNUMBER;
|
|
break;
|
|
case fMOUSEMOD:
|
|
getmousexybm(a1->pointer,NULL,NULL,NULL,&i);
|
|
value=i;
|
|
result=stNUMBER;
|
|
break;*/
|
|
case fCHR:
|
|
pointer=my_malloc(2);
|
|
i=(int)floor(a1->value);
|
|
if (i>255 || i<0) {
|
|
sprintf(string,"can't convert %g to character",a1->value);
|
|
error(ERROR,string);
|
|
return;
|
|
}
|
|
pointer[1]='\0';
|
|
pointer[0]=(unsigned char)i;
|
|
result=stSTRING;
|
|
break;
|
|
case fASC:
|
|
value=((unsigned char *)a1->pointer)[0];
|
|
result=stNUMBER;
|
|
break;
|
|
case fBIN:
|
|
pointer=dec2other(a1->value,2);
|
|
result=stSTRING;
|
|
break;
|
|
case fHEX:
|
|
pointer=dec2other(a1->value,16);
|
|
result=stSTRING;
|
|
break;
|
|
case fDEC:
|
|
value=other2dec(a1->pointer,16);
|
|
result=stNUMBER;
|
|
break;
|
|
case fDEC2:
|
|
value=other2dec(a1->pointer,(int)(a2->value));
|
|
result=stNUMBER;
|
|
break;
|
|
case fUPPER:
|
|
str=a1->pointer;
|
|
pointer=my_malloc(strlen(str)+1);
|
|
i=-1;
|
|
do {
|
|
i++;
|
|
pointer[i]=toupper((int)str[i]);
|
|
} while(pointer[i]);
|
|
result=stSTRING;
|
|
break;
|
|
case fLOWER:
|
|
str=a1->pointer;
|
|
pointer=my_malloc(strlen(str)+1);
|
|
i=-1;
|
|
do {
|
|
i++;
|
|
pointer[i]=tolower((int)str[i]);
|
|
} while(pointer[i]);
|
|
result=stSTRING;
|
|
break;
|
|
case fLTRIM:
|
|
str=a1->pointer;
|
|
while(isspace(*str)) str++;
|
|
pointer=my_strdup(str);
|
|
result=stSTRING;
|
|
break;
|
|
case fRTRIM:
|
|
str=a1->pointer;
|
|
i=strlen(str)-1;
|
|
while(isspace(str[i]) && i>=0) i--;
|
|
str[i+1]='\0';
|
|
pointer=my_strdup(str);
|
|
result=stSTRING;
|
|
break;
|
|
case fTRIM:
|
|
str=a1->pointer;
|
|
i=strlen(str)-1;
|
|
while(isspace(str[i]) && i>=0) i--;
|
|
str[i+1]='\0';
|
|
while(isspace(*str)) str++;
|
|
pointer=my_strdup(str);
|
|
result=stSTRING;
|
|
break;
|
|
case fINSTR:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
if (*str2)
|
|
pointer=strstr(str,str2);
|
|
else
|
|
pointer=NULL;
|
|
if (pointer==NULL)
|
|
value=0;
|
|
else
|
|
value=pointer-str+1;
|
|
result=stNUMBER;
|
|
break;
|
|
case fINSTR2:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
start=(int)a3->value;
|
|
if (start>strlen(str)) {
|
|
value=0;
|
|
} else {
|
|
if (start<1) start=1;
|
|
pointer=strstr(str+start-1,str2);
|
|
if (pointer==NULL)
|
|
value=0;
|
|
else
|
|
value=pointer-str+1;
|
|
}
|
|
result=stNUMBER;
|
|
break;
|
|
case fRINSTR:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
len=strlen(str2);
|
|
for(i=strlen(str)-1;i>=0;i--) if (!strncmp(str+i,str2,len)) break;
|
|
value=i+1;
|
|
result=stNUMBER;
|
|
break;
|
|
case fRINSTR2:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
len=strlen(str2);
|
|
start=(int)a3->value;
|
|
if (start<1) {
|
|
value=0;
|
|
} else {
|
|
if (start>strlen(str)) start=strlen(str);
|
|
for(i=start-1;i;i--) if (!strncmp(str+i,str2,len)) break;
|
|
value=i+1;
|
|
}
|
|
result=stNUMBER;
|
|
break;
|
|
case fDATE:
|
|
pointer=my_malloc(100);
|
|
time(&datetime);
|
|
strftime(pointer,100,"%w-%m-%d-%Y-%a-%b",localtime(&datetime));
|
|
result=stSTRING;
|
|
break;
|
|
case fTIME:
|
|
pointer=my_malloc(100);
|
|
time(&datetime);
|
|
strftime(pointer,100,"%H-%M-%S",localtime(&datetime));
|
|
sprintf(pointer+strlen(pointer),"-%d",
|
|
(int)(time(NULL)-compilation_start));
|
|
result=stSTRING;
|
|
break;
|
|
case fSYSTEM:
|
|
str=a1->pointer;
|
|
pointer=do_system(str);
|
|
result=stSTRING;
|
|
break;
|
|
case fSYSTEM2:
|
|
str=a1->pointer;
|
|
value=do_system2(str);
|
|
result=stNUMBER;
|
|
break;
|
|
case fPEEK:
|
|
str=a1->pointer;
|
|
value=peek(str, yab);
|
|
result=stNUMBER;
|
|
break;
|
|
case fPEEK2:
|
|
str=a1->pointer;
|
|
pointer=peek2(str,current);
|
|
result=stSTRING;
|
|
break;
|
|
case fPEEK3:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
pointer=peek3(str,str2);
|
|
result=stSTRING;
|
|
break;
|
|
case fPEEK4:
|
|
value=peekfile((int)a1->value);
|
|
result=stNUMBER;
|
|
break;
|
|
case fGETCHAR:
|
|
pointer=getchars((int)a1->value,(int)a2->value,(int)a3->value,(int)a4->value);
|
|
result=stSTRING;
|
|
break;
|
|
case fTELL:
|
|
i=(int)(a1->value);
|
|
if (badstream(i,0)) return;
|
|
if (!(stream_modes[i] & (smREAD | smWRITE| smREADWRITE))) {
|
|
sprintf(string,"stream %d not opened",i);
|
|
error(ERROR,string);
|
|
value=0;
|
|
} else {
|
|
value=ftell(streams[i]);
|
|
}
|
|
result=stNUMBER;
|
|
break;
|
|
case fMESSAGE:
|
|
pointer = getmessages(yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fMOUSE:
|
|
str = a1->pointer;
|
|
pointer = getmousemessages(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTRANSLATE:
|
|
str = a1->pointer;
|
|
pointer = gettranslation(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fMENUTRANSLATE:
|
|
str = a1->pointer;
|
|
pointer = getmenutranslation(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTEXTGET:
|
|
str = a1->pointer;
|
|
pointer = textget(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTEXTGET3:
|
|
str = a1->pointer;
|
|
pointer = textget3(str,a2->value,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTEXTGET6:
|
|
str = a1->pointer;
|
|
str2 = a2->pointer;
|
|
pointer = textget6(str,str2,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTEXTCONTROLGET:
|
|
str = a1->pointer;
|
|
pointer = textcontrolget(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fNUMWINDOWS:
|
|
value = numwindows();
|
|
result = stNUMBER;
|
|
break;
|
|
case fISMOUSEIN:
|
|
str = a1->pointer;
|
|
value = ismousein(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fMOUSEMOVE: //vasper
|
|
pointer = getmousein(yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fDRAWIMAGE:
|
|
str=a3->pointer;
|
|
str2=a4->pointer;
|
|
value = createimage(a1->value,a2->value,str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDRAWIMAGE2:
|
|
str=a5->pointer;
|
|
str2=a6->pointer;
|
|
value = createimage2(a1->value,a2->value,a3->value,a4->value,str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDRAWSVG:
|
|
str=a5->pointer;
|
|
str2=a6->pointer;
|
|
value = createsvg(a1->value,a2->value,a3->value,a4->value,str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fLOAD:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
pointer = getloadfilepanel(str,str2,str3,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fSAVE:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
str4=a4->pointer;
|
|
pointer = getsavefilepanel(str,str2,str3,str4,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fKEYBOARD:
|
|
str=a1->pointer;
|
|
pointer = keyboardmessages(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fCLIPBOARDPASTE:
|
|
pointer = clipboardpaste(yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fCOLUMNBOXGET:
|
|
str=a1->pointer;
|
|
pointer = columnboxget(str,a2->value,a3->value,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fLISTBOXGET:
|
|
str=a1->pointer;
|
|
pointer = listboxget(str,a2->value,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTREEBOXGET:
|
|
str=a1->pointer;
|
|
pointer = treeboxget(str,a2->value,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fTEXTGET2:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = textget2(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTEXTGET4:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = textget4(str,str2,a3->value,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTEXTGET5:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
value = textget5(str,str2,str3,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fPOPUPMENU:
|
|
str=a3->pointer;
|
|
str2=a4->pointer;
|
|
pointer = popupmenu(a1->value, a2->value, str, str2,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fSCROLLBARGET:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = scrollbarget(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fSPLITVIEWGET:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = splitviewget(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fSTACKVIEWGET:
|
|
str=a1->pointer;
|
|
value = stackviewget(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTABVIEWGET:
|
|
str=a1->pointer;
|
|
value = tabviewget(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fSPINCONTROLGET:
|
|
str=a1->pointer;
|
|
value = spincontrolget(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fLISTBOXCOUNT:
|
|
str=a1->pointer;
|
|
value = listboxcount(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTREEBOXCOUNT:
|
|
str=a1->pointer;
|
|
value = treeboxcount(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDROPBOXCOUNT:
|
|
str=a1->pointer;
|
|
value = dropboxcount(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDROPBOXGET:
|
|
str=a1->pointer;
|
|
pointer = dropboxget(str,a2->value,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fDRAWGET3:
|
|
str=a1->pointer;
|
|
pointer = drawget3(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fSLIDERGET:
|
|
str=a1->pointer;
|
|
value = sliderget(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fCOLORCONTROLGET:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = colorcontrolget(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fCALENDAR:
|
|
str=a1->pointer;
|
|
pointer = calendar2(str,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fCOLUMNBOXCOUNT:
|
|
str=a1->pointer;
|
|
value = columnboxcount(str,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fWINDOWGET:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = windowgetnum(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fVIEWGET: //vasper
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = viewgetnum(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDRAWGET1:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
value = drawget1(str,str2,str3,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDRAWGET2:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = drawget2(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDRAWGET4:
|
|
str=a3->pointer;
|
|
str2=a4->pointer;
|
|
value = drawget4(a1->value, a2->value, str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fLISTBOXGETNUM:
|
|
str=a1->pointer;
|
|
value = listboxgetnum(str, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fDROPBOXGETNUM:
|
|
str=a1->pointer;
|
|
value = dropboxgetnum(str, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTREEBOXGETNUM:
|
|
str=a1->pointer;
|
|
value = treeboxgetnum(str, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fCOLUMNBOXGETNUM:
|
|
str=a1->pointer;
|
|
value = columnboxgetnum(str, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fBITMAPLOAD:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = bitmapload(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fBITMAPGET:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = bitmapgetnum(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fBITMAPCOLOR:
|
|
str = a3->pointer;
|
|
str2 = a4->pointer;
|
|
value = bitmapcolor(a1->value, a2->value, str, str2, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fBITMAPSAVE:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
value = bitmapsave(str,str2,str3,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fSOUND:
|
|
str=a1->pointer;
|
|
value = sound(str, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTREEBOXGETOPT:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = treeboxgetopt(str, str2, a3->value, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTHREADKILL:
|
|
str=a1->pointer;
|
|
value = threadkill(str, a2->value, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fTHREADGET:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = threadget(str, str2, yab, linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fALERT:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
str4=a4->pointer;
|
|
str5=a5->pointer;
|
|
value = newalert(str,str2,str3,str4,str5,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fPRINTER:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
str3=a3->pointer;
|
|
value = printer(str,str2,str3,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fISCOMPUTERON:
|
|
value = iscomputeron(yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fMESSAGESEND:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = messagesend(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
case fATTRIBUTEGET1:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
pointer = attributeget1(str,str2,yab,linenum, current->lib->s);
|
|
result = stSTRING;
|
|
break;
|
|
case fATTRIBUTEGET2:
|
|
str=a1->pointer;
|
|
str2=a2->pointer;
|
|
value = attributeget2(str,str2,yab,linenum, current->lib->s);
|
|
result = stNUMBER;
|
|
break;
|
|
default:
|
|
error(ERROR,"function called but not implemented");
|
|
return;
|
|
}
|
|
|
|
stack=push();
|
|
/* copy result */
|
|
stack->type=result;
|
|
if (result==stSTRING)
|
|
stack->pointer=pointer;
|
|
else
|
|
stack->value=value;
|
|
}
|
|
|
|
|
|
static int do_system2(char *cmd) /* execute command as system */
|
|
{
|
|
#ifdef UNIX
|
|
int ret;
|
|
#ifdef BUILD_NCURSES
|
|
if (curinized) reset_shell_mode();
|
|
#endif
|
|
ret=system(cmd);
|
|
#ifdef BUILD_NCURSES
|
|
if (curinized) reset_prog_mode();
|
|
#endif
|
|
return ret;
|
|
#else
|
|
STARTUPINFO start;
|
|
PROCESS_INFORMATION proc;
|
|
DWORD ec; /* exit code */
|
|
SECURITY_ATTRIBUTES prosec;
|
|
SECURITY_ATTRIBUTES thrsec;
|
|
char *comspec;
|
|
|
|
ZeroMemory(&prosec,sizeof(prosec));
|
|
prosec.nLength=sizeof(prosec);
|
|
prosec.bInheritHandle=TRUE;
|
|
ZeroMemory(&thrsec,sizeof(thrsec));
|
|
thrsec.nLength=sizeof(thrsec);
|
|
thrsec.bInheritHandle=TRUE;
|
|
ZeroMemory(&start,sizeof(start));
|
|
start.cb=sizeof(STARTUPINFO);
|
|
start.dwFlags=STARTF_USESTDHANDLES;
|
|
start.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
|
|
start.hStdError=GetStdHandle(STD_ERROR_HANDLE);
|
|
start.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
|
|
comspec=getenv("COMSPEC");
|
|
if (!comspec) comspec="command.com";
|
|
sprintf(string,"%s /C %s",comspec,cmd);
|
|
if (!CreateProcess(NULL,string,&prosec,&thrsec,TRUE,0,
|
|
NULL,NULL,&start,&proc)) {
|
|
sprintf(string,"couldn't execute '%s'",cmd);
|
|
error(ERROR,string);
|
|
return -1;
|
|
}
|
|
WaitForSingleObject(proc.hProcess,INFINITE);
|
|
if (!GetExitCodeProcess(proc.hProcess,&ec)) ec=-1;
|
|
CloseHandle(proc.hProcess);
|
|
CloseHandle(proc.hThread);
|
|
return ec;
|
|
#endif
|
|
}
|
|
|
|
|
|
static void clear_buff() /* clear system-input buffers */
|
|
{
|
|
buffcurr=&buffroot;
|
|
buffcount=0;
|
|
}
|
|
|
|
|
|
static void store_buff(char *buff,int len) /* store system-input buffer */
|
|
{
|
|
*buffcurr=my_malloc(sizeof(struct buff_chain));
|
|
memcpy((*buffcurr)->buff,buff,SYSBUFFLEN+1);
|
|
(*buffcurr)->len=len;
|
|
buffcurr=&((*buffcurr)->next);
|
|
buffcount++;
|
|
}
|
|
|
|
|
|
char *recall_buff() /* recall store buffer */
|
|
{
|
|
struct buff_chain *curr,*old;
|
|
char *result;
|
|
int done,len;
|
|
|
|
result=(char *)my_malloc(buffcount*(SYSBUFFLEN+1));
|
|
curr=buffroot;
|
|
len=0;
|
|
for(done=0;done<buffcount;done++) {
|
|
memcpy(result+len,curr->buff,SYSBUFFLEN);
|
|
len+=curr->len;
|
|
old=curr;
|
|
curr=curr->next;
|
|
my_free(old);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
static char *do_system(char *cmd) /* executes command via command.com */
|
|
{
|
|
static char buff[SYSBUFFLEN+1]; /* buffer to store command */
|
|
int len; /* number of bytes read */
|
|
#ifdef UNIX
|
|
FILE *p; /* points to pipe */
|
|
int c; /* char read from pipe */
|
|
#else
|
|
int ret;
|
|
STARTUPINFO start;
|
|
PROCESS_INFORMATION proc;
|
|
HANDLE piperead,pipewrite; /* both ends of pipes */
|
|
SECURITY_ATTRIBUTES prosec;
|
|
SECURITY_ATTRIBUTES thrsec;
|
|
char *comspec;
|
|
#endif
|
|
|
|
clear_buff();
|
|
|
|
#ifdef UNIX
|
|
p=popen(cmd,"r");
|
|
if (p==NULL) {
|
|
sprintf(string,"couldn't execute '%s'",cmd);
|
|
error(ERROR,string);
|
|
return my_strdup("");
|
|
}
|
|
do {
|
|
len=0;
|
|
while(len<SYSBUFFLEN) {
|
|
c=fgetc(p);
|
|
if (c==EOF) {
|
|
buff[len]='\0';
|
|
break;
|
|
}
|
|
buff[len]=c;
|
|
len++;
|
|
}
|
|
store_buff(buff,len);
|
|
} while(c!=EOF);
|
|
pclose(p);
|
|
|
|
#else
|
|
ZeroMemory(&prosec,sizeof(prosec));
|
|
prosec.nLength=sizeof(prosec);
|
|
prosec.bInheritHandle=TRUE;
|
|
ZeroMemory(&thrsec,sizeof(thrsec));
|
|
thrsec.nLength=sizeof(thrsec);
|
|
thrsec.bInheritHandle=TRUE;
|
|
|
|
/* create pipe for writing */
|
|
CreatePipe(&piperead,&pipewrite,&prosec,0);
|
|
|
|
ZeroMemory(&start,sizeof(start));
|
|
start.cb=sizeof(STARTUPINFO);
|
|
start.dwFlags=STARTF_USESTDHANDLES;
|
|
start.hStdOutput=pipewrite;
|
|
start.hStdError=pipewrite;
|
|
start.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
|
|
|
|
comspec=getenv("COMSPEC");
|
|
if (!comspec) comspec="command.com";
|
|
sprintf(string,"%s /C %s",comspec,cmd);
|
|
if (!CreateProcess(NULL,string,&prosec,&thrsec,TRUE,0,
|
|
NULL,NULL,&start,&proc)) {
|
|
sprintf(string,"couldn't execute '%s'",cmd);
|
|
error(ERROR,string);
|
|
return my_strdup("");
|
|
}
|
|
CloseHandle(pipewrite);
|
|
|
|
do {
|
|
/* wait for output to arrive */
|
|
if (!ReadFile(piperead,buff,SYSBUFFLEN,(LPDWORD)&len,NULL))
|
|
ret=GetLastError();
|
|
else
|
|
ret=0;
|
|
buff[len]='\0';
|
|
if (len>0) store_buff(buff,len);
|
|
} while(ret!=ERROR_BROKEN_PIPE && ret!=ERROR_HANDLE_EOF);
|
|
CloseHandle(piperead);
|
|
CloseHandle(proc.hProcess);
|
|
CloseHandle(proc.hThread);
|
|
#endif
|
|
return recall_buff();
|
|
}
|
|
|
|
|
|
void getmousexybm(char *s,int *px,int *py,int *pb,int *pm) /* get mouse coordinates */
|
|
{
|
|
int x=0,y=0,b=0,m=0;
|
|
char c;
|
|
|
|
if (*s) {
|
|
sscanf(s,"MB%d%c+%d:%04d,%04d",&b,&c,&m,&x,&y);
|
|
if (px) *px=x;
|
|
if (py) *py=y;
|
|
if (pb) {
|
|
if (c=='d')
|
|
*pb=b;
|
|
else
|
|
*pb=-b;
|
|
}
|
|
if (pm) *pm=m;
|
|
return;
|
|
}
|
|
/*
|
|
if (px) *px=mousex;
|
|
if (py) *py=mousey;
|
|
if (pb) *pb=mouseb;
|
|
if (pm) *pm=mousemod;*/
|
|
}
|
|
|
|
|
|
static char *dec2other(double d,int base) /* convert double to hex or binary number */
|
|
{
|
|
int len;
|
|
double dec,dec2;
|
|
char *other;
|
|
int negative=FALSE;
|
|
|
|
if (d<0) {
|
|
dec2=floor(-d);
|
|
negative=TRUE;
|
|
} else {
|
|
dec2=floor(d);
|
|
}
|
|
len=negative?2:1;
|
|
for(dec=dec2;dec>=base;dec/=base) len++;
|
|
other=my_malloc(len+1);
|
|
other[len]='\0';
|
|
dec=dec2;
|
|
for(len--;len>=0;len--) {
|
|
other[len]="0123456789abcdef"[(int)(floor(dec-base*floor(dec/base)+0.5))];
|
|
dec=floor(dec/base);
|
|
}
|
|
if (negative) other[0]='-';
|
|
return other;
|
|
}
|
|
|
|
|
|
static double other2dec(char *hex,int base) /* convert hex or binary to double number */
|
|
{
|
|
double dec;
|
|
static char *digits="0123456789abcdef";
|
|
char *found;
|
|
int i,len;
|
|
|
|
if (base!=2 && base !=16) {
|
|
sprintf(string,"Cannot convert base-%d numbers",base);
|
|
error(ERROR,string);
|
|
return 0.;
|
|
}
|
|
dec=0;
|
|
len=strlen(hex);
|
|
for(i=0;i<len;i++) {
|
|
dec*=base;
|
|
found=strchr(digits,tolower(hex[i]));
|
|
if (!found || found-digits>=base) {
|
|
sprintf(string,"Not a base-%d number: '%s'",base,hex);
|
|
error(ERROR,string);
|
|
return 0.;
|
|
}
|
|
dec+=found-digits;
|
|
}
|
|
return dec;
|
|
}
|
|
|
|
|
|
int myformat(char *dest,double num,char *format,char *sep) /* format number according to string */
|
|
{
|
|
int i1,i2; /* dummy */
|
|
char c1; /* dummy */
|
|
static char ctrl[6];
|
|
char *found,*form;
|
|
int pre,post,dot,len,i,j,digit,colons,dots;
|
|
int neg=FALSE;
|
|
double ip,fp,round;
|
|
static char *digits="0123456789";
|
|
|
|
form=format;
|
|
if (*form=='%') { /* c-style format */
|
|
strcpy(ctrl,"+- #0"); /* allowed control chars for c-format */
|
|
form++;
|
|
while((found=strchr(ctrl,*form))!=NULL) {
|
|
*found='?';
|
|
form++;
|
|
}
|
|
if (sscanf(form,"%u.%u%c%n",&i1,&i2,&c1,&i)!=3 &&
|
|
sscanf(form,"%u.%c%n",&i2,&c1,&i)!=2 &&
|
|
sscanf(form,".%u%c%n",&i2,&c1,&i)!=2 &&
|
|
sscanf(form,"%u%c%n",&i2,&c1,&i)!=2) return FALSE;
|
|
if (!strchr("feEgG",c1) || form[i]) return FALSE;
|
|
/* seems okay, let's print */
|
|
sprintf(dest,format,num);
|
|
} else { /* basic-style format */
|
|
if (num<0) {
|
|
neg=TRUE;
|
|
num=-num;
|
|
}
|
|
colons=0;
|
|
dots=0;
|
|
pre=0;
|
|
post=0;
|
|
for(form=format;*form;form++) {
|
|
if (*form==',') {
|
|
if (dots) return FALSE;
|
|
colons++;
|
|
} else if (*form=='.') {
|
|
dots++;
|
|
} else if (*form=='#') {
|
|
if (dots)
|
|
post++;
|
|
else
|
|
pre++;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (dots>1) return FALSE;
|
|
len=strlen(format);
|
|
dest[len]='\0';
|
|
round=0.5;
|
|
for(i=0;i<post;i++) round/=10.;
|
|
if (fabs(num)<round) neg=FALSE;
|
|
num+=round;
|
|
ip=floor(num);
|
|
fp=num-ip;
|
|
if (fp>1 || fp<0) fp=0;
|
|
dest[pre+colons]=format[pre+colons];
|
|
if ((int)ip) {
|
|
for(i=pre+colons-1;i>=0;i--) {
|
|
if (neg && !(int)ip) {
|
|
neg=0;
|
|
dest[i]='-';
|
|
} else {
|
|
if (format[i]=='#') {
|
|
digit=((int)ip)%10;
|
|
ip/=10;
|
|
if (((int)ip) || digit>0)
|
|
dest[i]=digits[digit];
|
|
else
|
|
dest[i]=' ';
|
|
} else {
|
|
if ((int)ip)
|
|
dest[i]=format[i];
|
|
else
|
|
dest[i]=' ';
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
i=pre+colons-1;
|
|
dest[i--]='0';
|
|
}
|
|
if ((neg && i<0) || ((int)ip)) {
|
|
strcpy(dest,format);
|
|
return TRUE;
|
|
}
|
|
if (neg) dest[i--]='-';
|
|
for(;i>=0;i--) dest[i]=' ';
|
|
for(i=pre+colons+1;i<len;i++) {
|
|
fp*=10;
|
|
digit=(int)fp;
|
|
fp-=digit;
|
|
dest[i]=digits[digit];
|
|
}
|
|
if (sep && sep[0] && sep[1]) {
|
|
for(i=0;i<len;i++) {
|
|
if (dest[i]==',') dest[i++]=sep[0];
|
|
if (dest[i]=='.') dest[i++]=sep[1];
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static char *fromto(char *str,int from,int to) /* gives back portion of string */
|
|
/* from and to can be in the range 1...strlen(str) */
|
|
{
|
|
int len,i;
|
|
char *part;
|
|
|
|
len=strlen(str);
|
|
if (from>to || to<0 || from>len-1) {
|
|
/* give back empty string */
|
|
part=my_malloc(1);
|
|
part[0]='\0';
|
|
}
|
|
else {
|
|
if (from<=0) from=0;
|
|
if (to>=len) to=len-1;
|
|
part=my_malloc(sizeof(char)*(to-from+2)); /* characters and '/0' */
|
|
for(i=from;i<=to;i++) part[i-from]=str[i]; /* copy */
|
|
part[i-from]='\0';
|
|
}
|
|
return part;
|
|
}
|
|
|
|
|
|
|
|
void mywait() /* wait given number of seconds */
|
|
{
|
|
double delay;
|
|
|
|
#ifdef UNIX
|
|
struct timeval tv;
|
|
#else
|
|
MSG msg;
|
|
int timerid;
|
|
#endif
|
|
|
|
delay=pop(stNUMBER)->value;
|
|
if (delay<0) delay=0.;
|
|
#ifdef UNIX
|
|
tv.tv_sec=(int)delay;
|
|
tv.tv_usec=(delay-(int)delay)*1000000;
|
|
select(0,NULL,NULL,NULL,&tv);
|
|
#else /* WINDOWS */
|
|
timerid=SetTimer(NULL,0,(int)(delay*1000),(TIMERPROC) NULL);
|
|
GetMessage((LPMSG)&msg,NULL,WM_TIMER,WM_TIMER);
|
|
KillTimer(NULL,timerid);
|
|
#endif
|
|
}
|
|
|
|
|
|
void mybell() /* ring ascii bell */
|
|
{
|
|
#ifdef UNIX
|
|
#ifdef BEOS
|
|
yi_beep();
|
|
#else
|
|
printf("\007");
|
|
fflush(stdout);
|
|
#endif
|
|
#else /* WINDOWS */
|
|
Beep(1000,100);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void create_poke(char flag) /* create Command 'cPOKE' */
|
|
{
|
|
struct command *cmd;
|
|
|
|
if (flag=='S' || flag=='D')
|
|
cmd=add_command(cPOKEFILE,FALSE);
|
|
else
|
|
cmd=add_command(cPOKE,FALSE);
|
|
cmd->tag=flag;
|
|
}
|
|
|
|
|
|
void poke(struct command *cmd) /* poke into internals */
|
|
{
|
|
char *dest,*s,c;
|
|
char *sarg=NULL;
|
|
double darg;
|
|
|
|
if (cmd->tag=='s')
|
|
sarg=pop(stSTRING)->pointer;
|
|
else
|
|
darg=pop(stNUMBER)->value;
|
|
|
|
dest=pop(stSTRING)->pointer;
|
|
for(s=dest;*s;s++) *s=tolower((int)*s);
|
|
/*
|
|
if (!strcmp(dest,"fontheight") && !sarg) {
|
|
fontheight=(int)darg;
|
|
#ifdef UNIX
|
|
calc_psscale();
|
|
#endif
|
|
}
|
|
else if (!strcmp(dest,"font") && sarg) {
|
|
font=my_strdup(sarg);
|
|
} */
|
|
if (!strcmp(dest,"dump") && sarg && !strcmp(sarg,"symbols")) {
|
|
dump_sym();
|
|
}
|
|
else if (!strcmp(dest,"dump") && sarg &&
|
|
(!strcmp(sarg,"sub") || !strcmp(sarg,"subs") || !strcmp(sarg,"subroutine") || !strcmp(sarg,"subroutines"))) {
|
|
dump_sub(0);
|
|
}
|
|
/*
|
|
else if (!strcmp(dest,"winwidth") && !sarg) {
|
|
winwidth=(int)darg;
|
|
if (winwidth<1) {
|
|
error(ERROR,"winwidth less than 1 pixel");
|
|
return;
|
|
}
|
|
#ifdef UNIX
|
|
calc_psscale();
|
|
#endif
|
|
}
|
|
else if (!strcmp(dest,"winheight") && !sarg) {
|
|
winheight=(int)darg;
|
|
if (winheight<1) {
|
|
error(ERROR,"winheight less than 1 pixel");
|
|
return;
|
|
}
|
|
#ifdef UNIX
|
|
calc_psscale();
|
|
#endif
|
|
}
|
|
else if (!strcmp(dest,"textalign") && sarg) {
|
|
if (!check_alignement(sarg)) return;
|
|
strncpy(text_align,sarg,2);
|
|
}
|
|
else if (!strcmp(dest,"windoworigin") && sarg) {
|
|
moveorigin(sarg);
|
|
}*/
|
|
else if (!strcmp(dest,"infolevel") && sarg) {
|
|
c=tolower((int)*sarg);
|
|
switch(c) {
|
|
case 'd': infolevel=DEBUG;break;
|
|
case 'n': infolevel=NOTE;break;
|
|
case 'w': infolevel=WARNING;break;
|
|
case 'e': infolevel=ERROR;break;
|
|
case 'f': infolevel=FATAL;break;
|
|
default:
|
|
error(ERROR,"invalid infolevel");
|
|
return;
|
|
}
|
|
if (infolevel>=DEBUG) {
|
|
sprintf(string,"switching infolevel to '%c'",c);
|
|
error(DEBUG,string);
|
|
}
|
|
}
|
|
else if (!strcmp(dest,"stdout") && sarg) {
|
|
fputs(sarg,stdout);
|
|
}
|
|
else if (!strcmp(dest,"read_controls") && !sarg) {
|
|
read_controls= darg ? 1:0;
|
|
}
|
|
else if (dest[0]=='#') {
|
|
error(ERROR,"don't use quotes when poking into file");
|
|
}
|
|
else {
|
|
error(ERROR,"invalid poke");
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void pokefile(struct command *cmd) /* poke into file */
|
|
{
|
|
char *sarg=NULL;
|
|
double darg;
|
|
int stream;
|
|
|
|
if (cmd->tag=='S')
|
|
sarg=pop(stSTRING)->pointer;
|
|
else
|
|
darg=pop(stNUMBER)->value;
|
|
stream=(int)(pop(stNUMBER)->value);
|
|
|
|
if (badstream(stream,0)) return;
|
|
|
|
if (!(stream_modes[stream] & smWRITE)) {
|
|
sprintf(string,"Stream %d not open for writing",stream);
|
|
error(ERROR,string);
|
|
return;
|
|
}
|
|
if (sarg) {
|
|
fputs(sarg,streams[stream]);
|
|
} else {
|
|
if (darg<0 || darg>255) {
|
|
error(ERROR,"stream poke out of byte range (0..255)");
|
|
return;
|
|
}
|
|
fputc((int)darg,streams[stream]);
|
|
}
|
|
}
|
|
|
|
|
|
static double peek(char *dest, YabInterface *yab) /* peek into internals */
|
|
{
|
|
char *s;
|
|
|
|
for(s=dest;*s;s++) *s=tolower((int)*s);
|
|
/*if (!strcmp(dest,"winwidth")) return winwidth;
|
|
else if (!strcmp(dest,"winheight")) return winheight;
|
|
else if (!strcmp(dest,"fontheight")) return fontheight;
|
|
else*/
|
|
if (!strcmp(dest,"screenheight")) return LINES;
|
|
else if (!strcmp(dest,"screenwidth")) return COLS;
|
|
else if (!strcmp(dest, "deskbarposition")) return yi_DeskbarPosition(yab); //deskbarposition;
|
|
else if (!strcmp(dest, "deskbarexpanded")) return yi_DeskbarExpanded(yab); //deskbarexpanded;
|
|
else if (!strcmp(dest, "deskbarwidth")) return yi_DeskbarWidth(yab); //deskbarwidth;
|
|
else if (!strcmp(dest, "deskbarheight")) return yi_DeskbarHeight(yab); //deskbarheight;
|
|
else if (!strcmp(dest, "deskbar-x")) return yi_DeskbarX(yab); //deskbar-x;
|
|
else if (!strcmp(dest, "deskbar-y")) return yi_DeskbarY(yab); //deskbar-y;
|
|
else if (!strcmp(dest, "desktopwidth")) return yi_DesktopWidth(yab); //desktopwidth;
|
|
else if (!strcmp(dest, "desktopheight")) return yi_DesktopHeight(yab); //desktopheight;
|
|
else if (!strcmp(dest, "scrollbarwidth")) return yi_ScrollbarWidth(yab); // scrollbarwidth
|
|
else if (!strcmp(dest, "menuheight")) return yi_MenuHeight(yab); // menuheight
|
|
else if (!strcmp(dest, "tabheight")) return yi_TabHeight(yab); // tabheight
|
|
else if (!strcmp(dest,"argument") || !strcmp(dest,"arguments") ) return yabargc; // number of arguments
|
|
else if (!strcmp(dest,"version")) return strtod(VERSION,NULL);
|
|
else if (!strcmp(dest,"error")) return errorcode;
|
|
else if (!strcmp(dest,"read_controls")) return read_controls;
|
|
else if (!strcmp(dest,"isbound")) return is_bound;
|
|
|
|
|
|
else if (dest[0]=='#') {
|
|
error(ERROR,"don't use quotes when peeking into a file");
|
|
return 0;
|
|
}
|
|
|
|
sprintf(stderr, "PEEK is set to %s\n", dest);
|
|
error(ERROR,"invalid peek");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int peekfile(int stream) /* read a byte from stream */
|
|
{
|
|
if (stream && badstream(stream,0)) return 0;
|
|
if (stream && !(stream_modes[stream] & smREAD | smREADWRITE)) {
|
|
sprintf(string,"stream %d not open for reading",stream);
|
|
error(ERROR,string);
|
|
return 0;
|
|
}
|
|
return fgetc(stream?streams[stream]:stdin);
|
|
}
|
|
|
|
|
|
static char *peek2(char *dest,struct command *curr) /* peek into internals */
|
|
{
|
|
char *s;
|
|
|
|
|
|
for(s=dest;*s;s++) *s=tolower((int)*s);
|
|
if (!strcmp(dest,"infolevel")) {
|
|
if (infolevel==DEBUG) return my_strdup("debug");
|
|
else if (infolevel==NOTE) return my_strdup("note");
|
|
else if (infolevel==WARNING) return my_strdup("warning");
|
|
else if (infolevel==ERROR) return my_strdup("error");
|
|
else if (infolevel==FATAL) return my_strdup("fatal");
|
|
else return my_strdup("unkown");
|
|
}
|
|
/*
|
|
else if (!strcmp(dest,"textalign")) return my_strdup(text_align);
|
|
else if (!strcmp(dest,"windoworigin")) return my_strdup(winorigin);*/
|
|
else if (!strcmp(dest,"error")) return my_strdup(errorstring);
|
|
else if (!strcmp(dest,"library")) return my_strdup(curr->lib->s);
|
|
else if (!strcmp(dest,"os")) {
|
|
#ifdef HAIKU
|
|
return my_strdup("Haiku");
|
|
#else
|
|
return my_strdup("BeOS");
|
|
#endif
|
|
}
|
|
else if (!strcmp(dest,"directory")) return my_strdup(appdirectory);
|
|
else if (!strcmp(dest,"refsreceived")) return my_strdup(refsRec);
|
|
/* else if (!strcmp(dest,"font")) return my_strdup(font); */
|
|
else if (!strcmp(dest,"argument") || !strcmp(dest,"arguments")) {
|
|
if (yabargc>0) {
|
|
s=yabargv[0];
|
|
yabargc--;
|
|
yabargv++;
|
|
}
|
|
else {
|
|
s="";
|
|
}
|
|
return my_strdup(s);
|
|
}
|
|
else {
|
|
error(ERROR,"invalid peek");
|
|
}
|
|
return my_strdup("");
|
|
}
|
|
|
|
|
|
static char *peek3(char *dest,char *cont) /* peek into internals */
|
|
{
|
|
char *s;
|
|
|
|
for(s=dest;*s;s++) *s=tolower((int)*s);
|
|
if (!strcmp(dest,"env") || !strcmp(dest,"environment")) {
|
|
return my_strdup(getenv(cont));
|
|
} else {
|
|
error(ERROR,"invalid peek");
|
|
}
|
|
return my_strdup("");
|
|
}
|
|
|
|
|
|
void create_exception(int flag) /* create command 'exception' */
|
|
{
|
|
struct command *cmd;
|
|
|
|
cmd=add_command(cEXCEPTION,FALSE);
|
|
cmd->args=flag;
|
|
}
|
|
|
|
|
|
void exception(struct command *cmd) /* change handling of exceptions */
|
|
{
|
|
if (cmd->args) {
|
|
signal(SIGINT,signal_handler); /* enable keyboard interrupt */
|
|
#ifdef SIGHUP
|
|
signal(SIGHUP,signal_handler);
|
|
#endif
|
|
#ifdef SIGQUIT
|
|
signal(SIGQUIT,signal_handler);
|
|
#endif
|
|
#ifdef SIGABRT
|
|
signal(SIGABRT,signal_handler);
|
|
#endif
|
|
#ifdef SIGTERM
|
|
signal(SIGTERM,signal_handler);
|
|
#endif
|
|
}
|
|
else {
|
|
signal(SIGINT,SIG_IGN); /* ignore keyboard interrupt */
|
|
#ifdef SIGHUP
|
|
signal(SIGHUP,SIG_IGN);
|
|
#endif
|
|
#ifdef SIGQUIT
|
|
signal(SIGQUIT,SIG_IGN);
|
|
#endif
|
|
#ifdef SIGABRT
|
|
signal(SIGABRT,SIG_IGN);
|
|
#endif
|
|
#ifdef SIGTERM
|
|
signal(SIGTERM,SIG_IGN);
|
|
#endif
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void create_restore(char *label) /* create command 'restore' */
|
|
{
|
|
struct command *c;
|
|
|
|
c=add_command(cRESTORE,FALSE);
|
|
c->pointer=my_strdup(label);
|
|
}
|
|
|
|
|
|
void restore(struct command *cmd) /* reset data pointer to given label */
|
|
{
|
|
struct command *label;
|
|
struct command **datapointer;
|
|
|
|
datapointer=&(cmd->lib->datapointer);
|
|
if (cmd->type==cRESTORE) { /* first time; got to search the label */
|
|
if (*((char *)cmd->pointer)=='\0') {
|
|
/* no label, restore to first command */
|
|
label=cmd->lib->firstdata;
|
|
} else {
|
|
label=search_label(cmd->pointer,smLABEL|smGLOBAL);
|
|
if (!label) {
|
|
/* did not find label */
|
|
sprintf(string,"can't find label '%s'",(char *)cmd->pointer);
|
|
error(ERROR,string);
|
|
return;
|
|
}
|
|
}
|
|
*datapointer=label;
|
|
if (lastdata) {
|
|
while((*datapointer)->type!=cDATA && (*datapointer)!=cmdhead) {
|
|
*datapointer=(*datapointer)->next;
|
|
}
|
|
}
|
|
cmd->pointer=*datapointer;
|
|
cmd->type=cQRESTORE;
|
|
} else {
|
|
*datapointer=cmd->pointer;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void create_dbldata(double value) /* create command dbldata */
|
|
{
|
|
struct command *c;
|
|
|
|
c=add_command(cDATA,FALSE);
|
|
c->pointer=my_malloc(sizeof(double));
|
|
if (lastdata) lastdata->nextassoc=c;
|
|
lastdata=c;
|
|
*((double *)c->pointer)=value;
|
|
c->tag='d'; /* double value */
|
|
}
|
|
|
|
|
|
void create_strdata(char *value) /* create command strdata */
|
|
{
|
|
struct command *c;
|
|
|
|
c=add_command(cDATA,FALSE);
|
|
if (lastdata) lastdata->nextassoc=c;
|
|
lastdata=c;
|
|
c->pointer=my_strdup(value);
|
|
c->tag='s'; /* string value */
|
|
}
|
|
|
|
|
|
void create_readdata(char type) /* create command readdata */
|
|
{
|
|
struct command *cmd;
|
|
|
|
cmd=add_command(cREADDATA,FALSE);
|
|
cmd->tag=type;
|
|
}
|
|
|
|
|
|
void readdata(struct command *cmd) /* read data items */
|
|
{
|
|
struct stackentry *read;
|
|
char type;
|
|
struct command **datapointer;
|
|
|
|
datapointer=&(cmd->lib->datapointer);
|
|
type=cmd->tag;
|
|
while(*datapointer && ((*datapointer)->type!=cDATA || cmd->lib!=(*datapointer)->lib)) {
|
|
*datapointer=(*datapointer)->nextassoc;
|
|
}
|
|
if (!*datapointer) {
|
|
error(ERROR,"run out of data items");
|
|
return;
|
|
}
|
|
if (type!=(*datapointer)->tag) {
|
|
error(ERROR,"type of READ and DATA don't match");
|
|
return;
|
|
}
|
|
read=push();
|
|
if (type=='d') { /* read a double value */
|
|
read->type=stNUMBER;
|
|
read->value= *((double *)(*datapointer)->pointer);}
|
|
else {
|
|
read->type=stSTRING;
|
|
read->pointer=my_strdup((*datapointer)->pointer);
|
|
}
|
|
*datapointer=(*datapointer)->nextassoc; /* next item */
|
|
}
|
|
|
|
|
|
void create_dblrelop(char c) /* create command dblrelop */
|
|
{
|
|
int type;
|
|
|
|
switch(c) {
|
|
case '=': type=cEQ;break;
|
|
case '!': type=cNE;break;
|
|
case '<': type=cLT;break;
|
|
case '{': type=cLE;break;
|
|
case '>': type=cGT;break;
|
|
case '}': type=cGE;break;
|
|
}
|
|
add_command(type,FALSE);
|
|
}
|
|
|
|
|
|
void dblrelop(struct command *type) /* compare topmost double-values */
|
|
{
|
|
double a,b,c;
|
|
struct stackentry *result;
|
|
|
|
b=pop(stNUMBER)->value;
|
|
a=pop(stNUMBER)->value;
|
|
switch(current->type) {
|
|
case cEQ:c=(a==b);break;
|
|
case cNE:c=(a!=b);break;
|
|
case cLE:c=(a<=b);break;
|
|
case cLT:c=(a<b);break;
|
|
case cGE:c=(a>=b);break;
|
|
case cGT:c=(a>b);break;
|
|
}
|
|
result=push();
|
|
result->value=c;
|
|
result->type=stNUMBER;
|
|
}
|
|
|
|
|
|
void create_strrelop(char c) /* create command strrelop */
|
|
{
|
|
int type;
|
|
|
|
switch(c) {
|
|
case '=': type=cSTREQ;break;
|
|
case '!': type=cSTRNE;break;
|
|
case '<': type=cSTRLT;break;
|
|
case '{': type=cSTRLE;break;
|
|
case '>': type=cSTRGT;break;
|
|
case '}': type=cSTRGE;break;
|
|
}
|
|
add_command(type,FALSE);
|
|
}
|
|
|
|
|
|
void strrelop(struct command *type) /* compare topmost string-values */
|
|
{
|
|
char *a,*b;
|
|
double c;
|
|
struct stackentry *result;
|
|
|
|
b=pop(stSTRING)->pointer;
|
|
a=pop(stSTRING)->pointer;
|
|
switch(current->type) {
|
|
case cSTREQ:c=(strcmp(a,b)==0);break;
|
|
case cSTRNE:c=(strcmp(a,b)!=0);break;
|
|
case cSTRLT:c=(strcmp(a,b)<0);break;
|
|
case cSTRLE:c=(strcmp(a,b)<=0);break;
|
|
case cSTRGT:c=(strcmp(a,b)>0);break;
|
|
case cSTRGE:c=(strcmp(a,b)>=0);break;
|
|
}
|
|
result=push();
|
|
result->value=c;
|
|
result->type=stNUMBER;
|
|
}
|
|
|
|
void switch_compare(void) /* compare topmost values for switch statement */
|
|
{
|
|
struct stackentry *result,*first,*second;
|
|
double r=0.;
|
|
|
|
first=pop(stANY);
|
|
second=stackhead->prev;
|
|
if ((second->type==stSWITCH_STRING || second->type==stSTRING) && first->type==stSTRING) {
|
|
if (second->type==stSWITCH_STRING)
|
|
r=1.;
|
|
else
|
|
r=(strcmp(first->pointer,second->pointer)==0)?1.:0.;
|
|
} else if ((second->type==stSWITCH_NUMBER || second->type==stNUMBER) && first->type==stNUMBER) {
|
|
if (second->type==stSWITCH_NUMBER)
|
|
r=1.;
|
|
else
|
|
r=(first->value==second->value);
|
|
} else {
|
|
error(ERROR,"Cannot mix strings and numbers in a single switch statement");
|
|
}
|
|
result=push();
|
|
result->type=stNUMBER;
|
|
result->value=r;
|
|
}
|
|
|
|
|
|
void logical_shortcut(struct command *type) /* shortcut and/or if possible */
|
|
{
|
|
struct stackentry *result;
|
|
double is;
|
|
|
|
is=stackhead->prev->value;
|
|
if ((type->type==cORSHORT && is!=0) || (type->type==cANDSHORT && is==0)) {
|
|
result=push();
|
|
error(DEBUG,"logical shortcut taken");
|
|
result->type=stNUMBER;
|
|
result->value=is;
|
|
} else {
|
|
current=current->next;
|
|
}
|
|
}
|
|
|
|
|
|
void create_boole(char c) /* create command boole */
|
|
{
|
|
int type;
|
|
|
|
switch(c) {
|
|
case '|': type=cOR;break;
|
|
case '&': type=cAND;break;
|
|
case '!': type=cNOT;break;
|
|
}
|
|
add_command(type,FALSE);
|
|
}
|
|
|
|
|
|
void boole(struct command *type) /* perform and/or/not */
|
|
{
|
|
int a,b,c;
|
|
struct stackentry *result;
|
|
|
|
a=(int)pop(stNUMBER)->value;
|
|
if (current->type==cNOT)
|
|
c=!a;
|
|
else {
|
|
b=(int)pop(stNUMBER)->value;
|
|
if (current->type==cAND)
|
|
c=a&&b;
|
|
else
|
|
c=a||b;
|
|
}
|
|
result=push();
|
|
result->value=c;
|
|
result->type=stNUMBER;
|
|
}
|
|
|