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

📄 yabasic.c

📁 一个小巧的BASIC解释器的源代码很小可它的确做到了
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  
YABASIC ---  a tiny integrated Basic Compiler/Interpreter
written by Marc-Oliver Ihm 1995-99.
e-mail: ihm@kph.uni-mainz.de

  Current Version:
*/
#define BASIC_VERSION            "2.45"
/*
Date of last change: 
*/
#define DOLC                     "February 26, 1999"

char YABLICENSE[]=

"     This program is free software; you can redistribute it and/or       \n"
"     modify it under the terms of the GNU General Public License         \n"
"     as published by the Free Software Foundation; either version        \n"
"     of the License, or (at your option) any later version.              \n"
"                                                                         \n"
"     This program is distributed in the hope that it will be useful,     \n"
"     but WITHOUT ANY WARRANTY; without even the implied warranty of      \n"
"     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       \n"
"     GNU General Public License for more details.                        \n"
"                                                                         \n"
"     You should have received a copy of the GNU General Public License   \n"
"     along with this program (the file is named COPYING);                \n"
"     if not, write to the Free Software                                  \n"
"     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.           \n"
;


/* ------------- defines ---------------- */

/*
Define one and only one of the following symbols, depending on your
System:
- UNIX: uses some UNIX-features and X11
- WINDOWS: uses WIN32-features
*/


#define DONE {current=current->next;break;}  /* reduces type-work */

#if defined(UNIX) && defined(WINDOWS)
UNIX and WINDOWS are defined at once; check your compiler settings
#endif


/* ------------- includes ---------------- */


#ifndef YABASIC_INCLUDED
#include "yabasic.h"       /* all prototypes and structures */
#endif
#ifdef UNIX
#include <curses.h>
#endif


/* ------------- external references ---------------- */

extern int yylineno;   /* current line number */
extern void switch_to_my_file(FILE *); /* switches lex input */ 
extern int yyparse();  /* call bison parser */


/* ------------- global variables ---------------- */

struct symbol *symroot; /* first element in symbol list */
struct symbol *symhead; /* last element ind symbol list */
struct stackentry *stackroot; /* lowest element in stack */
struct stackentry *stackhead; /* topmost element in stack */
struct command *current; /* currently executed command */
struct command *cmdroot; /* first command */
struct command *cmdhead; /* last command */
struct command *datapointer; /* current location for read-command */
int infolevel; /* controls issuing of error messages */
int errorlevel; /* highest level of error message seen til now */
int end_of_file=FALSE; /* TRUE, if end of file has been reached */
int diagnostic_count; /* number of diagnostic messages */
int note_count; /* number of notes */
int warning_count; /* number of warning messages */
int error_count; /* number of error messages */
int interactive; /* true, if commands come from stdin */
char *string; /* for trash-strings */
int labelcount=0; /* count self-generated labels */
int commandcount; /* total number of commands */
int program_state;  /* state of program */
int prompted; /* TRUE, if prompt is fresh */
FILE *streams[10]; /* file streams */
FILE *cinstr; /* current stream for input */
FILE *coutstr; /* current stream for output */
char linebuffer[INBUFFLEN]; /* buffer for one line of input */
int curinized=FALSE; /* true, if curses has been initialized */
char *currchar; /* current char to read */
struct buff_chain *buffroot; /* start of sys-input buffer */
struct buff_chain **buffcurr; /* current entry in buff_chain */
int buffcount; /* number of filled buffers */
char *progname; /* name of yabasic-program */
char *explanation[cLAST_COMMAND-cFIRST_COMMAND+1]; /* explanations */
char **yabargv; /* arguments for yabasic */
int yabargc; /* number of arguments in yabargv */

/* printer-related */
FILE *printerfile=NULL; /* file to print on */
char *prfilename=NULL; /* filename to print on */
int print_to_file; /* print to file ? */


/* ------------- global variables for Graphics ---------------- */

char *text_align; /* specifies alignement of text */
char *winorigin; /* direction to increase y */
#ifdef UNIX
Display *display; /* X-Display */
Window window,root; /* ID of window and root window */
GC gc; /* GC for drawing */
GC rgc; /* GC for reverse drawing */
XSizeHints sizehints; /* hints for window manager */
static unsigned long f_colour,b_colour; /* colors */
XFontStruct *myfont; /* properties of default font */
#elif WINDOWS
WNDCLASS myclass; /* window class for my program */
HWND window;   /* handle of my window */
HANDLE this_instance;
HDC devcon; /* device context for screen */
HDC bitcon; /* device context backing bitmap */
HBITMAP backbit; /* backing bitmap */
char *my_class="my_class";
HANDLE wthandle; /* handle of win thread */
DWORD wtid; /* id of win thread */
HANDLE wtevent=INVALID_HANDLE_VALUE; /* handle for win thread event */
LOGFONT logfont; /* structure for font-characteristics */
HFONT myfont; /* handle of font for screen */
HFONT printerfont; /* handle of printer-font */
HPEN printerpen; /* handle of printer-pen */
HDC printer=NULL; /* handle of printer */
float prnscale;  /* scaling factor for printer */
float prnoff;  /* offset for printer */
BOOL Commandline; /* true if launched from command line */
HANDLE ConsoleInput; /* handle for console input */
HANDLE ConsoleOutput; /* handle for console output */
int LINES=0; /* number of lines on screen */
int COLS=0; /* number of columns on screen */
HANDLE mainthread=INVALID_HANDLE_VALUE; /* handle to main thread */
#endif

int winwidth,winheight;  /* size of window */
int winx,winy; /* position of window */
int winopened=FALSE; /* flag if window is open already */
double psscale; /* from pixels to points */
int fontheight; /* height of used font in pixel */
char *foreground=NULL;
char *background=NULL;
char *geometry=NULL;
char *displayname=NULL;
char *font=NULL;

/* for plotting */
double xoff=0.; /* offset for x-mapping */
double xinc=1.; /* inclination of x-mapping */
double yoff=0.; /* offset for y-mapping */
double yinc=1.; /* inclination for y-mapping */

/* timing */
time_t compilation_start,compilation_end,execution_end;


/* ------------- main program ---------------- */

int main(int argc,char **argv)
{
#ifdef WINDOWS
  CONSOLE_SCREEN_BUFFER_INFO csbi;
#endif
	
  string=(char *)malloc(sizeof(char)*INBUFFLEN);
	
  program_state=HATCHED;
  infolevel=WARNING; /* set the initial Infolevel */
	
#ifdef WINDOWS
  /* get handle for current thread */
  DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),
		  GetCurrentProcess(),&mainthread,THREAD_ALL_ACCESS,FALSE,0);

  /* get handle of instance */
  this_instance=GetModuleHandle(NULL);
	
  /* define my window class */
  myclass.style=0;
  myclass.lpfnWndProc=(LPVOID)mywindowproc;
  myclass.cbClsExtra=0; /* no extra bytes */
  myclass.cbWndExtra=0;
  myclass.hInstance=this_instance;
  myclass.hIcon=LoadIcon(this_instance,"yabasicIcon");
  myclass.hCursor=LoadCursor(NULL,IDC_ARROW); /*  standard cursor */
  myclass.hbrBackground=(HBRUSH)COLOR_WINDOW; /* default-background */
  myclass.lpszMenuName=NULL;
  myclass.lpszClassName=my_class;
	
  RegisterClass(&myclass);
	
  /* get console handles */
  ConsoleInput=GetStdHandle(STD_INPUT_HANDLE);
  ConsoleOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	
  /* find out, if launched from commandline */
  GetConsoleScreenBufferInfo(ConsoleOutput,&csbi);
  Commandline=!((csbi.dwCursorPosition.X==0) && (csbi.dwCursorPosition.Y==0));
  if ((csbi.dwSize.X<=0) || (csbi.dwSize.Y <= 0)) Commandline=TRUE;
	
#endif
	
  parse_arguments(argc,argv);
	
  time(&compilation_start);
  initialize();
  program_state=INITIALIZED;
	
  error(NOTE,"Calling parser/compiler");
  if (interactive) {
    printf("Enter your program; type <RETURN> twice, when done.\n");
  }
  program_state=COMPILING;
  if (yyparse() && errorlevel>ERROR) {
    error(ERROR,"Couldn't parse program");
  }
	
  add_command(cEND);
  sprintf(string,"Read %d line(s)",yylineno);
  error(NOTE,string);
  sprintf(string,"Generated %d command(s)",commandcount);
  error(NOTE,string);
	
  time(&compilation_end);
	
  if (errorlevel>ERROR) {
    program_state=RUNNING;
    run_it();}
  else {
    program_state=FINISHED;
    error(ERROR,"Program not executed");
  }
	
  sprintf(string,"%d diagnostic(s), %d note(s), %d warning(s), %d error(s)",
	  diagnostic_count,note_count,warning_count,error_count);
  error(NOTE,string);
  time(&execution_end);
  sprintf(string,"Compilation time = %g second(s)",
	  difftime(compilation_start,compilation_end));
  error(NOTE,string);
  sprintf(string,"Execution time = %g second(s)",
	  difftime(execution_end,compilation_end));
  error(NOTE,string);    
  end_it((errorlevel<=ERROR)?1:0);
  return 0;
}



/* ------------- subroutines ---------------- */


struct symbol *get_sym(char *name,int type,int add) 
     /* gets the value of a symbol, or creates it with initial value type */
{
  struct symbol *curr,*new;
	
  curr=symroot;
  while(curr!=symhead) {   /* search 'til head of list */
    if (curr->type==type  /* do the types match ? */
	&&!strcmp(name,curr->name))  /* do the names match ? */
      return curr; /* give back address */
    curr=curr->next; /* try next entry */
  }
  /* run (ppp) through all variables. */
  if (!add) return NULL;  /* dont create, if not found */
  /* end of list, create new element */
  new=(struct symbol *)my_malloc(sizeof(struct symbol)); /* ceate new item */
  symhead=new;  /* advance head */
  curr->name=my_strdup(name);  /* store new name */
  curr->next=new;
  curr->value=0.0;
  curr->pointer=NULL;
  curr->type=type;
  curr->value=0.0;
  if (type==sySTRING) {   /* create empty string */
    curr->pointer=my_malloc(sizeof(char));
    *(char *)(curr->pointer)='\0';
  }
  return curr;
}

void create_pushdbl(double value) /* create command 'cPUSHDBL' */
{
  struct command *cmd;
	
  cmd=add_command(cPUSHDBL);
  if (cmd->pointer==NULL) cmd->pointer=my_malloc(sizeof(double));
  *(double *)(cmd->pointer)=value;
}


void pushdbl(struct command *cmd) 
{
  /* push double onto stack */
  struct stackentry *p;
	
  p=push();
  p->value= *(double *)cmd->pointer;
  p->type=stNUMBER;
}


void create_pushdblsym(char *symbol) /* create command 'pushdblsym' */
{
  struct command *cmd;
	
  cmd=add_command(cPUSHDBLSYM);
  /* get room to store specific information */
  cmd->pointer= &(get_sym(symbol,syNUMBER,TRUE)->value);
}


void pushdblsym(struct command *cmd) 
{
  /* push double symbol onto stack */
  struct stackentry *p;
	
  p=push();
  p->value=*(double *)cmd->pointer;
  p->type=stNUMBER;
}


void create_popdblsym(char *symbol) /* create command 'popdblsym' */
{
  struct command *cmd;
  struct symbol *s;
	
  cmd=add_command(cPOPDBLSYM);
  if (symbol) {
    /* store specific information: */
    s=get_sym(symbol,syNUMBER,TRUE);
    cmd->pointer= &(s->value);
  }
  else {
    cmd->pointer=NULL;
    return;
  }
}


void popdblsym(struct command *cmd)   /* pop double from stack */
{
  double d;
	
  d=pop()->value;
  if (cmd->pointer==NULL) return;
  *(double *)(cmd->pointer)=d;
}


void create_dblbin(char c) /* create command for binary double operation */
{
  switch(c) {
  case '+':add_command(cDBLADD);break;
  case '-':add_command(cDBLMIN);break;
  case '*':add_command(cDBLMUL);break;
  case '/':add_command(cDBLDIV);break;
  case '^':add_command(cDBLPOW);break;
  }
  /* no specific information needed */
}


void dblbin(struct command *cmd) /* compute with two numbers from stack */
{
  struct stackentry *d;
  double a,b,c;
	
  b=pop()->value;
  a=pop()->value;
  d=push();
  switch(cmd->type) {
  case(cDBLADD):c=a+b; break;
  case(cDBLMIN):c=a-b; break;
  case(cDBLMUL):c=a*b; break;
  case(cDBLDIV): 
    if (fabs(b)<DBL_MIN) {
      sprintf(string,"Division by zero, set to %g",DBL_MAX);
      error(NOTE,string);
      c=DBL_MAX;}
    else
      c=a/b;
    break;
  case(cDBLPOW):
    if (b==2) 
      c=a*a;
    else if (a<0) {
      error(ERROR,"Power of negative value. Don't now what to do");
      return;}
    else
      c=exp(b*log(a));
    break;
  }
  d->value=c;
  d->type=stNUMBER;
}


void negate() /* negates top of stack */
{
  struct stackentry *a,*b;
  double d;
	
  a=pop();
  d=a->value;
  b=push();
  b->type=stNUMBER;
  b->value= -d;
}


void create_pushstrptr(char *symbol) /* push string-pointer onto stack */
{
  struct command *cmd;
	
  cmd=add_command(cPUSHSTRPTR);
  cmd->pointer=&get_sym(symbol,sySTRING,TRUE)->pointer;
}


void pushstrptr(struct command *cmd)  /* push string-pointer onto stack */
{
  struct stackentry *p;
	
  p=push();
  p->pointer=*(char **)cmd->pointer;
  p->type=stSTRING;
}


void create_pushstrsym(char *symbol) /* push string-symbol onto stack */
{
  struct command *cmd;
	
  cmd=add_command(cPUSHSTRSYM);
  /* get room to store specific information */
  cmd->pointer=&get_sym(symbol,sySTRING,TRUE)->pointer;
}


void pushstrsym(struct command *cmd)  /* push string-symbol onto stack */
{
  struct stackentry *p;
	
  p=push();
  p->pointer=my_strdup(*(char **)cmd->pointer);
  p->type=stSTRING;
}


void create_popstrsym(char *symbol) /* create command 'popstrsym' */
{
  struct command *cmd;
  struct symbol *s;
	
  cmd=add_command(cPOPSTRSYM);
  if (symbol) {
    /* storing specific information: */
    s=get_sym(symbol,sySTRING,TRUE);
    cmd->pointer=(char **)&(s->pointer);
  }
  else {
    cmd->pointer=NULL;
  }
}


void popstrsym(struct command *cmd) /* pop string from stack */
{
  struct stackentry *p;
	
  p=pop();
  if (cmd->pointer==NULL) return;
  if (*(char **)cmd->pointer!=NULL) free(*(char **)cmd->pointer);
  *(char **)cmd->pointer=my_strdup(p->pointer);
}


void create_token(int delimiter) /* create command 'token' */
{
  struct command *cmd;
	
  cmd=add_command(cTOKEN);
  cmd->args=delimiter;
}


void token(struct command *cmd) /* extract token from variable */
{
  char *del; /* delimiter for strings */
  struct stackentry *t;
  char *old,*new,*tok;
  
  if (cmd->args) del=pop()->pointer;
  else del=" \t";
  
  t=pop();
  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)) tok=new; /* found start of token */
    if (tok && strchr(del,*new)) break; /* found end of token */
    new++;
  }
  if (*new) {
    *new='\0'; /* terminate token */
    new++;
    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 */
  do {
    *old=*new;
    old++;
    new++;
  } while(*new);
  *old='\0';
}


void concat() /* concetenates two strings from stack */
{
  struct stackentry *a,*b,*c;
  char *aa,*bb,*cc;
	
  a=pop();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -