⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yabasic.c

📁 一个小巧的BASIC解释器的源代码很小可它的确做到了
💻 C
📖 第 1 页 / 共 5 页
字号:
  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 + -