📄 yabasic.c
字号:
b=pop();
if (a->type!=stSTRING || b->type!=stSTRING) {
error(FATAL,"Need strings to concat");
return;
}
aa=a->pointer;
bb=b->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_pushstr(char *s) /* creates command pushstr */
{
struct command *cmd;
cmd=add_command(cPUSHSTR);
cmd->pointer=my_strdup(s); /* store string */
}
void pushstr(struct command *cmd)
{
/* push string onto stack */
struct stackentry *p;
p=push();
p->pointer=my_strdup((char *)cmd->pointer);
p->type=stSTRING;
}
void create_goto(char *label) /* creates command goto */
{
struct command *cmd;
cmd=add_command(cGOTO);
/* specific info */
cmd->pointer=my_strdup(label);
}
void create_gosub(char *label) /* creates command gosub */
{
struct command *cmd;
cmd=add_command(cGOSUB);
/* specific info */
cmd->pointer=my_strdup(label);
}
void jump(struct command *cmd)
/* jump to specific Label; used as goto or gosub */
{
struct command *curr;
struct stackentry *ret;
int type;
type=cmd->type;
if (type==cQGOSUB || type==cGOSUB) {
ret=push();
ret->pointer=current;
ret->type=stRETADD;
}
if (type==cQGOSUB || type==cQGOTO) {
current=(struct command *)cmd->pointer;
return;
}
curr=cmdroot;
while(curr!=cmdhead) { /* go through all commands */
if (curr->type==cLABEL && !strcmp(curr->pointer,cmd->pointer)) {
/* found right Label ! */
current=curr; /* jump to new location */
/* use the address instead of the name next time ! */
cmd->pointer=curr;
cmd->type=(type==cGOTO) ? cQGOTO:cQGOSUB; /* quick jump from now on */
return;
}
curr=curr->next;
}
/* label not found */
sprintf(string,"Can't find label '%s'",(char *)cmd->pointer);
error(ERROR,string);
}
void myreturn() /* return from gosub */
{
struct stackentry *address;
address=pop();
if (address->type!=stRETADD) {
error(ERROR,"RETURN without GOSUB");
return;
}
current=(struct command *)address->pointer;
return;
}
void create_label(char *label) /* creates command label */
{
struct command *cmd,*curr;
/* check, if label is duplicate */
curr=cmdroot;
while(curr!=cmdhead) { /* go through all commands */
if (curr->type==cLABEL && !strcmp(curr->pointer,label)) {
/* found duplicate Label ! */
sprintf(string,"duplicate label '%s'",(char *)curr->pointer);
error(ERROR,string);
return;
}
curr=curr->next;
}
cmd=add_command(cLABEL);
/* store label */
cmd->pointer=my_strdup(label);
}
void skipper()
/* used for on_goto/gosub, skip specified number of commands */
{
int i,len;
struct command *ahead; /* command to follow */
len=(int)pop()->value;
i=1;
current=current->next; /* advance to first goto/gosub */
for(i=1;i<len;i++) {
ahead=current->next->next; /* skip interleaving findnop statement */
if (ahead->type==cNOP)
break;
else
current=ahead;
}
}
void skiponce(struct command *cmd) /* skip next command exectly once */
{
if (cmd->tag) current=current->next;
cmd->tag=0;
}
void resetskiponce(struct command *cmd) /* find and reset next skip */
{
struct command *c;
c=cmd;
while(c->type!=cSKIPONCE) c=c->next;
c->tag=1;
}
void findnop()
/* used for on_gosub, find trailing nop command */
{
while(current->type!=cNOP) {
current=current->next; /* next label */
}
}
void create_print(char type) /* create command 'print' */
{
struct command *cmd;
cmd=add_command(cPRINT);
cmd->pointer=my_malloc(sizeof(int));
/* store type of print */
cmd->tag=type;
}
void print(struct command *cmd) /* print on screen */
{
int type;
struct stackentry *p,*q;
static int last='n';
char *s;
#ifdef UNIX
int x,y;
#endif
type=cmd->tag;
switch(type) {
case 'n': /* print newline */
if (curinized && coutstr==stdout) {
#ifdef WINDOWS
printf("\n");
break;
#else
getyx(stdscr,y,x);
if (y>=LINES-1) {
scrl(1);
y=y-1;
}
move(y+1,0);
refresh();
break;
#endif
} else {
string[0]='\n';
string[1]='\0';
}
onestring(string);
break;
case 'd': /* print double value */
p=pop();
sprintf(string,"%s%g",(last=='d')?" ":"",p->value);
onestring(string);
break;
case 'u':
p=pop();
q=pop();
type='d';
s=string;
if (last=='d') {
*s=' ';
s++;
}
if (!myformat(s,q->value,p->pointer)) {
sprintf(string,"'%s' is not a valid format",(char *)p->pointer);
error(ERROR,string);
break;
}
onestring(string);
break;
case 's':
p=pop();
onestring((char *)p->pointer);
break;
}
last=type;
}
void mymove() /* move to specific position on screen */
{
int x,y;
#ifdef WINDOWS
COORD coord;
#endif
y=(int)pop()->value;
if (y<0) y=0;
if (y>LINES-1) y=LINES-1;
x=(int)pop()->value;
if (x<0) x=0;
if (x>COLS-1) x=COLS-1;
if (!curinized) {
error(ERROR,"need to call 'clear screen' first");
return;
}
#ifdef UNIX
move(y,x);
refresh();
#else
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(ConsoleOutput,coord);
#endif
}
void clearscreen() /* clear entire screen */
{
#ifdef WINDOWS
DWORD written; /* number of chars actually written */
COORD coord; /* coordinates to start writing */
#endif
if (!curinized) curinit();
#ifdef UNIX
clear();
refresh();
#else
coord.X=0;
coord.Y=0;
FillConsoleOutputCharacter(ConsoleOutput,' ',LINES*COLS,
coord,&written);
FillConsoleOutputAttribute(ConsoleOutput,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,LINES*COLS,
coord,&written);
SetConsoleCursorPosition(ConsoleOutput,coord);
#endif
}
void curinit() /* initialize curses */
{
#ifdef WINDOWS
CONSOLE_SCREEN_BUFFER_INFO coninfo; /* receives console size */
#endif
#ifdef UNIX
initscr();
setscrreg(0,LINES);
scrollok(stdscr,TRUE);
def_prog_mode();
keypad(stdscr,TRUE);
#else
GetConsoleScreenBufferInfo(ConsoleOutput,&coninfo);
COLS=coninfo.dwSize.X;
LINES=coninfo.dwSize.Y;
#endif
curinized=TRUE;
}
char *replace(char *string) /* replace \n,\a, etc. */
{
char *from,*to;
from=to=string;
while(*from) {
if (*from=='\\') {
from++;
switch(*from) {
case 'n': *to='\n';break;
case 't': *to='\t';break;
case 'v': *to='\v';break;
case 'b': *to='\b';break;
case 'r': *to='\r';break;
case 'f': *to='\f';break;
case 'a': *to='\a';break;
case '\\': *to='\\';break;
case '\?': *to='\?';break;
case '\'': *to='\'';break;
case '\"': *to='\"';break;
default:
*to='\\';
to++;
*to=*from;
}
}
else
*to=*from;
from++;
to++;
}
*to='\0';
return string;
}
void create_myopen(double stream,int num) /* create command 'myopen' */
{
struct command *cmd;
if (badstream((int)stream)) return;
cmd=add_command(cOPEN);
cmd->args=(int) stream;
cmd->tag=num;
}
void myopen(struct command *cmd) /* open specified file for given name */
{
FILE *handle;
int stream;
char *name;
char *mode;
char **pmode;
static char *valid_modes[]={"r","w","a","rb","wb","ab",""};
if (cmd->tag==3)
mode=pop()->pointer;
else
mode="a";
name=pop()->pointer;
stream=cmd->args;
if (streams[stream]!=NULL) {
error(ERROR,"Stream already in use");
return;
}
for(pmode=valid_modes;**pmode;pmode++) if (!strcmp(*pmode,mode)) break;
if (!**pmode) {
sprintf(string,"\'%s\' is not a valid filemode",mode);
error(ERROR,string);
return;
}
handle=fopen(name,mode);
if (handle==NULL) {
sprintf(string,"Could not open '%s'",name);
error(ERROR,string);
return;
}
streams[stream]=handle;
}
void create_myclose(double stream) /* create command 'myclose' */
{
struct command *cmd;
if (badstream((int)stream)) return;
cmd=add_command(cCLOSE);
cmd->args=(int) stream;
return;
}
void myclose(struct command *cmd) /* close the specified stream */
{
int s;
s=cmd->args;
if (streams[s]==NULL) {
sprintf(string,"Stream %d already closed",s);
error(WARNING,string);
return;
}
fclose(streams[s]);
streams[s]=NULL;
}
void create_myswitch(int stream) /* create command myswitch */
{
struct command *cmd;
if (stream!=0 && badstream((int)stream)) return;
cmd=add_command(cSWITCH);
cmd->args=stream;
}
void myswitch(struct command *cmd) /* switch to specified stream */
{
int stream;
stream=cmd->args;
if (stream==0) {
cinstr=stdin;
coutstr=stdout;
}
else {
cinstr=streams[stream]; /* switch to stream */
coutstr=cinstr;
if (streams[stream]==NULL) {
sprintf(string,"Stream %d not opened",stream);
error(ERROR,string);
return;
}
}
return;
}
void create_testeof(double stream) /* create command 'testeof' */
{
struct command *cmd;
if (badstream((int)stream)) return;
cmd=add_command(cTESTEOF);
cmd->args=(int) stream;
return;
}
void testeof(struct command *cmd) /* close the specified stream */
{
int s,c;
struct stackentry *result;
s=cmd->args;
result=push();
result->type=stNUMBER;
if (streams[s]==NULL) {
result->value=TRUE;
return;
}
c=getc(streams[s]);
if (c==EOF) {
result->value=TRUE;
return;
}
result->value=FALSE;
ungetc(c,streams[s]);
return;
}
int badstream(int stream) /* test for valid stream id */
{
int max;
max=(FOPEN_MAX-3<9)?FOPEN_MAX-3:9;
if (stream>max || stream<1) {
sprintf(string,"Can handle only streams from 1 to %d",max);
error(ERROR,string);
return TRUE;
}
return FALSE;
}
void create_myread(char type,int rl) /* create command 'read' */
{
struct command *cmd;
cmd=add_command(cREAD);
cmd->args=rl; /* true, if read should go til eol */
cmd->tag=type; /* can be 'd' or 's' */
}
void myread(struct command *cmd) /* read string or double */
{
double d;
char buffer[INBUFFLEN]; /* buffer with current input */
int numread; /* number of bytes read */
int tileol; /* true, if read should go til end of line */
struct stackentry *s;
int currch; /* current character */
numread=0; /* no chars read'til now */
buffer[0]='\0';
tileol=cmd->args;
/* skip leading whitespace */
if (!tileol) {
do {
currch=onechar();
} while(currch==' ' || currch=='\t');
/* put back last char */
if (currch!=EOF && currch!='\0') backchar(currch);
if (currch=='\0' || currch==EOF) goto done;
}
/* read chars */
do {
currch=onechar();
buffer[numread]=currch;
numread++;
} while(((tileol && currch!='\0') ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -