This is the mail archive of the cygwin@sources.redhat.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

gcc internal compiler error sig11




hi,


version info 

C:\home\maali\dist\dist-basics\mbasic>gcc -v
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/2.95.2-6/specs
gcc version 2.95.2-6 19991024 (cygwin experimental)

if i run

$ gcc -fsyntax-only basic.c


then i get 


...
...
basic.c:1177: warning: assignment from incompatible pointer type
      0 [main] cc1 412519
handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
    932 [main] cc1 412519 stackdump: Dumping stack trace to
CC1.EXE.stackdump
GCC: Internal compiler error: program cc1 got fatal signal 11

and i get this exact error every time (i don't think its 
a hardware issue).

the basic.c file is attached.


thanks for your consideration


adnan ali.
/*

 * MICRO-BASIC:

 *

 * This is a small INTEGER BASIC interpreter that I wrote a number

 * of years ago, and subsequently ported to MICRO-C. While not a great

 * example of coding style (it was a quick and dirty hack job), It is

 * quite instructive, as a simple but fairly complete interpreter.

 *

 * Variables:

 *	260 Numeric	  variables	:	A0-A9 ... Z0-Z9

 *	260 Character variables	:	A0$-A9$ ... Z0$-Z9$

 *	260 Numeric arrays		:	A0()-A9() ... Z0()-Z9()

 *

 *	For convenience the '0' variables can be referenced by letter

 *	only. IE: A is equivalent to A0 ... Z$ is equivalent to Z0$

 *

 * Statements:

 *	BEEP freq,ms			- Generate a BEEP on the PC speaker

 *	CLEAR					- Erase variables only

 *	CLOSE#n					- Close file (0-9) opened with OPEN

 *	DATA					- Enter "inline" data statements

 *	DELAY ms				- Stops for the indicated time

 *	DIM var(size)[, ... ]	- Dimension an array

 *	DOS "comand"			- Execute a DOS program

 *	END						- Terminate program with no message

 *	EXIT					- Terminate MICRO-BASIC

 *	FOR v=init TO limit [STEP increment] - Perform a counted loop

 *	GOSUB line				- Call a subroutine

 *	GOTO  line				- Jump to line

 *	IF test THEN line		- Conditional goto

 *	IF test THEN statement	- Conditional statement (next statement only)

 *	INPUT var				- Get value for variable

 *	INPUT "prompt",var		- Get value of variable with prompt

 *		prompt must be a constant string, however you can use a char variable

 *		in prompt by concatinating it to such a string: INPUT ""+a$,b$

 *	INPUT#n,var				- Get value for variable from file (0-9)

 *	LET (default)			- variable = expression

 *	LIF test THEN statements- LONG IF (all statements to end of line)

 *	LIST [start,[end]]		- List program lines

 *	LIST#n ...				- List program to file (0-9)

 *	LOAD "name"				- Load program from disk file

 *		When LOAD is used within a program, execution continues with the

 *		first line of the newly loaded program. In this case, the user

 *		variables are NOT cleared. This provides a means of chaining

 *		to a new program, and passing information to it.

 *		Also note that LOAD must be the LAST statement on a line.

 *	NEW						- Erase program and variables

 *	NEXT [v]				- End counted loop

 *	OPEN#n,"name","opts"	- Open file (0-9), opts are same as "fopen()"

 *	ORDER line				- Position data read pointer

 *	OUT port,expr			- Write to I/O port

 *	PRINT expr[,expr ...]	- Print to console

 *	PRINT#n,...				- Print to file (0-9)

 *	READ var[,var ...]		- Read data from program statements

 *		You MUST issue an "ORDER" statement targeting a line

 *		containing a valid DATA statement before using READ

 *	RETURN					- Return from subroutine

 *	REM						- Comment... reminder of line is ignored

 *	RUN [line]				- Run program

 *	SAVE ["name"]			- Save program to disk file

 *	STOP					- Terminate program & issue message

 *

 * Operators:

 *	+						- Addition, string concatination

 *	-						- Unary minus, subtraction

 *	*, /, %,				- multiplication, division, modulus

 *	&, |, ^					- AND, OR, Exclusive OR

 *	=, <>					- Assign/test equal, test NOTequal (num or string)

 *	<, <=, >, >=			- LT, LE, GT, GE (numbers only)

 *	!						- Unary NOT

 *		The "test" operators (=, <>, <, <=, >, >=) can be used in any

 *		expression, and evaluate to 1 of the test is TRUE, and 0 if it

 *		is FALSE. The IF and LIF commands accept any non-zero value to

 *		indicate a TRUE condition.

 *

 * Functions:

 *	CHR$(value)				- Returns character of passed value

 *	STR$(value)				- Returns ASCII string of value's digits

 *	ASC(char)				- Returns value of passed character

 *	NUM(string)				- Convert string to number

 *	ABS(value)				- Returns absolute value of argument

 *	RND(value)				- Returns random number from 0 to (value-1)

 *	KEY()					- Test for key from keyboard

 *	INP(port)				- Read an I/O port

 *

 * Copyright 1982-2000 Dave Dunfield

 * All rights reserved.

 *

 * Permission granted for personal (non-commercial) use only.

 *

 * Compile command: cc basic -fop

 */

#include <stdio.h>

#include <setjmp.h>



/* Fixed parameters */

#define BUFFER_SIZE 100		/* input buffer size */

#define NUM_VAR 	260		/* number of variables */

#define SA_SIZE 	100		/* string accumulator size */



/* Control stack constant identifiers */

#define _FOR		1000	/* indicate FOR statement */

#define _GOSUB		_FOR+1	/* indicate GOSUB statement */



/* Primary keywords */

#define	LET		1

#define	EXIT	2

#define	LIST	3

#define	NEW		4

#define	RUN		5

#define	CLEAR	6

#define	GOSUB	7

#define	GOTO	8

#define	RETURN	9

#define	PRINT	10

#define	FOR		11

#define	NEXT	12

#define	IF		13

#define	LIF		14

#define	REM		15

#define	STOP	16

#define	END		17

#define	INPUT	18

#define	OPEN	19

#define	CLOSE	20

#define	DIM		21

#define	ORDER	22

#define	READ	23

#define	DATA	24

#define	SAVE	25

#define	LOAD	26

#define	DELAY	27

#define	BEEP	28

#define	DOS		29

#define	OUT		30



/* Secondary keywords */

#define	TO		31	/* Also used as marker */

#define	STEP	32

#define	THEN	33



/* Operators and functions */

#define	ADD		34	/* Also used as marker */

#define	SUB		35

#define	MUL		36

#define	DIV		37

#define	MOD		38

#define	AND		39

#define	OR		40

#define	XOR		41

#define	EQ		42

#define	NE		43

#define	LE		44

#define	LT		45

#define	GE		46

#define	GT		47

#define	CHR		48

#define	STR		49

#define	ASC		50

#define	ABS		51

#define	NUM		52

#define	RND		53

#define	KEY		54

#define	INP		55



#define	RUN1	99



/* Make sure this token table matches the above definitions */

static char *reserved_words[] = {

	"LET", "EXIT", "LIST", "NEW", "RUN", "CLEAR", "GOSUB", "GOTO",

	"RETURN", "PRINT", "FOR", "NEXT", "IF", "LIF", "REM", "STOP",

	"END", "INPUT", "OPEN", "CLOSE", "DIM", "ORDER", "READ", "DATA",

	"SAVE", "LOAD", "DELAY", "BEEP", "DOS", "OUT",

	"TO", "STEP", "THEN",

	"+", "-", "*", "/", "%", "&", "|", "^",

	"=", "<>", "<=", "<", ">=", ">",

	"CHR$(", "STR$(", "ASC(", "ABS(", "NUM(", "RND(", "KEY(", "INP(",

	0 };



/* Table of operator priorities */

static char priority[] = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 1, 1, 1 };



/* Table of error messages */

static char *error_messages[] = {

	"Syntax",

	"Illegal program",

	"Illegal direct",

	"Line number",

	"Wrong type",

	"Divide by zero",

	"Nesting",

	"File not open",

	"File already open",

	"Input",

	"Dimension",

	"Data",

	"Out of memory"

	};



struct line_record {

	unsigned Lnumber;

	struct line_record *Llink;

	char Ltext[]; };



char sa1[SA_SIZE], sa2[SA_SIZE];		/* String accumulators */

struct line_record *pgm_start,			/* Indicates start of program */

	*runptr,							/* Line we are RUNnning */

	*readptr;							/* Line we are READing */



unsigned dim_check[NUM_VAR];			/* Check dim sizes for arrays */



FILE *filein, *fileout;					/* File I/O active pointers */



jmp_buf savjmp;							/* Save area for set/longjmp */



/* Misc. global variables */

char *cmdptr,							/* Command line parse pointer */

	*dataptr,							/* Read data pointer */

	buffer[BUFFER_SIZE],				/* General input buffer */

	mode = 0,							/* 0=Stopped, !0=Running */

	expr_type,							/* Type of last expression */

	nest;								/* Nest level of expr. parser */

unsigned line,							/* Current line number */

	ctl_ptr = 0,						/* Control stack pointer */

	ctl_stk[50];						/* Control stack */



/*

 * The following variables must be iniitialized to zero. If your

 * compiler does not automatically zero uninitialized global

 * variables, modify these declarations to initialize them.

 */

char filename[65];						/* Name of program file */

FILE *files[10];						/* File unit numbers */

int num_vars[NUM_VAR];					/* Numeric variables */

int *dim_vars[NUM_VAR];					/* Dimensioned arrays */

char *char_vars[NUM_VAR];				/* Character variables */



/*

 * Test for end of expression

 */

int is_e_end(char c)

{

	if((c >= (-128+TO)) && (c < (-128+ADD)))

		return(1);

	return (c == '\0') || (c == ':') || (c == ')') || (c == ',');

}



/*

 * Test for end of statement

 */

int is_l_end(char c)

{

	return (c == '\0') || (c == ':');

}



/*

 * Test for terminator character

 */

int isterm(char c)

{

	return (c == ' ') || (c == '\t');

}



/*

 * Advance to next non-blank & retreive data

 */

char skip_blank()

{

	while(isterm(*cmdptr))

		++cmdptr;

	return *cmdptr;

}



/*

 * Advance to., retrieve and skip next non blank

 */

char get_next()

{

	char c;



	while(isterm(c=*cmdptr))

		++cmdptr;

	if(c)

		++cmdptr;

	return c;

}



/*

 * Test for a specific character occuring next & remove if found

 */

int test_next(int token)

{

	if(skip_blank() == token) {

		++cmdptr;

		return -1; }

	return 0;

}



/*

 * Expect a specific token - syntax error if not found

 */

expect(int token)

{

	if(get_next() != token)

		error(0);

}



/*

 * Lookup up word from command line in table

 */

unsigned lookup(char *table[])

{

	unsigned i;

	char *cptr, *optr;



	optr = cmdptr;

	for(i=0; cptr = table[i]; ++i) {

		while((*cptr) && (*cptr == toupper(*cmdptr))) {

			++cptr;

			++cmdptr; }

		if(!*cptr) {

			if(! (isalnum(*(cptr-1)) && isalnum(*cmdptr)) ) {

				skip_blank();

				return i+1; } }

		cmdptr = optr; }

	return 0;

}



/*

 * Get a number from the input buffer

 */

unsigned get_num()

{

	unsigned value;

	char c;



	value = 0;

	while(isdigit(c=*cmdptr)) {

		++cmdptr;

		value = (value * 10) + (c - '0'); }

	return value;

}



/*

 * Allocate memory and zero it

 */

char *allocate(unsigned size)

{

	char *ptr;

	if(!(ptr = malloc(size)))

		error(12);

	memset(ptr, 0, size);

	return ptr;

}



/*

 * Delete a line from the program

 */

delete_line(unsigned lino)

{

	struct line_record *cptr, *bptr;



	if(!(cptr = pgm_start))					/* no lines in pgm */

		return;

	do {

		if(lino == cptr->Lnumber) {			/* we have line to delete */

			if(cptr == pgm_start) {			/* first line in pgm */	

				pgm_start = cptr->Llink;

				return; }

			else {

				bptr->Llink = cptr->Llink;	/* skip it in linked list */

				free(cptr); } }				/* let it go */

		bptr = cptr; }

	while(cptr = cptr->Llink);

}



/*

 * Insert a line into the program

 */

insert_line(unsigned lino)

{

	unsigned i;

	struct line_record *cptr, *bptr, *optr;

	char *ptr;



	ptr = cmdptr;

	for(i=5; *ptr; ++i)

		++ptr;

	bptr = allocate(i);

	bptr->Lnumber = lino;

	for(i=0; *cmdptr; ++i)

		bptr->Ltext[i] = *cmdptr++;

	bptr->Ltext[i] = 0;

	if((!(cptr = pgm_start)) || (lino < cptr->Lnumber)) {	/* at start */

		bptr->Llink = pgm_start;

		pgm_start = bptr; }

	else {				/* inserting into main part of pgm */

		for(;;) {

			optr = cptr;

			if((!(cptr = cptr->Llink)) || (lino < cptr->Lnumber)) {

				bptr->Llink = optr->Llink;

				optr->Llink = bptr;

				break; } } }

}



/*

 * Tokenize input line and Add/Replace a source line if suitable

 */

edit_program()

{

	unsigned value;

	char *ptr, c;



	cmdptr = ptr = buffer;

	/* Translate special tokens into codes */

	while(c = *cmdptr) {

		if(value = lookup(reserved_words))

			*ptr++ = value | 0x80;

		else {

			*ptr++ = c;

			++cmdptr;

			if(c == '"') {		/* double quote */

				while((c = *cmdptr) && (c != '"')) {

					++cmdptr;

					*ptr++ = c; }

				*ptr++ = *cmdptr++; } } }

	*ptr = 0;

	cmdptr = buffer;



	if(isdigit(skip_blank())) {	/* Valid source line */

		value = get_num();		/* Get line number */

		delete_line(value);		/* Delete the old */

		if(skip_blank())

			insert_line(value);

		return -1; }			/* Insert the new */

	return 0;

}



/*

 * Locate given line in source

 */

struct line_record *find_line(unsigned line)

{

	struct line_record *cptr;



	for(cptr = pgm_start; cptr; cptr = cptr->Llink)

		if(cptr->Lnumber == line)

			return cptr;

	error(3);

}



/*

 * Compute variable address for assignment

 */

unsigned *address()

{

	unsigned i, j, *dptr;

	i = get_var();

	if(expr_type)

		return &char_vars[i];

	else {

		if(test_next('(')) {	/* Array */

			if(expr_type) error(0);

			if(!(dptr = dim_vars[i]))

				error(10);

			nest = 0;

			if((j = eval_sub()) >= dim_check[i])

				error(10);

			return &dptr[j]; } }

	return &num_vars[i];

}



/*

 * Execute a BASIC commands

 */

struct line_record *execute(char cmd)

{

	unsigned i, j, k, *dptr;

	int ii, jj;

	struct line_record *cptr;

	char c;



	switch(cmd & 0x7F) {

		case LET :

			dptr = address();

			j = expr_type;



			expect(-128+EQ);



			k = eval();



			if(j != expr_type)

				error(0);

			if(!expr_type)		/* numeric assignment */

				*dptr = k;

			else {				/* character assignment */

				if(*dptr)

					free(*dptr);

				if(*sa1)

					strcpy(*dptr = allocate(strlen(sa1)+1), sa1);

				else

					*dptr = 0; }

			break;

		case EXIT :

			exit(0);

		case LIST :

			chk_file(1);

			if(!isdigit(skip_blank())) {

				i=0; j=-1; }

			else {

				i = get_num();

				if(get_next() == ',') {

					if(isdigit(skip_blank()))

						j=get_num();

					else

						j = -1; }

				else

					j=i; }

			disp_pgm(fileout,i,j);

			break;

		case NEW :

			clear_vars();

			clear_pgm();

			longjmp(savjmp, 1);

		case RUN :

			direct_only();

			clear_vars();

		case RUN1 :		/* No clearing */

			if(is_e_end(skip_blank()))

				runptr = pgm_start;

			else

				runptr = find_line(eval_num());

			--mode;			/* indicate running */

newline:

			while(runptr) {

				cmdptr = runptr->Ltext;

				line = runptr->Lnumber;

				do {

					if((cmd = skip_blank()) < 0) {

						++cmdptr;

						if(dptr=execute(cmd)) {

							runptr = dptr;

							goto newline; } }

					else

						execute(1); }

				while((c = get_next()) == ':');

				if(c)

					error(0);

				runptr = runptr->Llink; }

			mode = 0;

			break;

		case CLEAR :

			clear_vars();

			break;

		case GOSUB :

			ctl_stk[ctl_ptr++] = runptr;

			ctl_stk[ctl_ptr++] = cmdptr;

			ctl_stk[ctl_ptr++] = _GOSUB;

		case GOTO :

			pgm_only();

			return find_line(eval_num());

		case RETURN :

			pgm_only();

			if(ctl_stk[--ctl_ptr] != _GOSUB)

				error(6);

			cmdptr = ctl_stk[--ctl_ptr];

			runptr = ctl_stk[--ctl_ptr];

			line = runptr->Lnumber;

			skip_stmt();

			break;

		case PRINT :

			chk_file(1);

			j = 0;

			do {

				if(is_l_end(skip_blank()))

					--j;

				else {

					i = eval();

					if(!expr_type) {

						num_string(i, sa1);

						putc(' ',fileout); }

					fputs(sa1, fileout); } }

			while(test_next(','));

			if(!j)

				putc('\n', fileout);

			break;

		case FOR :

			pgm_only();

			ii = 1;			/* default step value */

			i = get_var();

			if(expr_type) error(0);

			expect(-128+EQ);

			num_vars[i] = eval();

			if(expr_type) error(0);

			expect(-128+TO);

			jj = eval();

			if(test_next(-128+STEP))

				ii = eval();

			skip_stmt();

			ctl_stk[ctl_ptr++] = runptr;	/* line */

			ctl_stk[ctl_ptr++] = cmdptr;	/* command pointer */

			ctl_stk[ctl_ptr++] = ii;		/* step value */

			ctl_stk[ctl_ptr++] = jj;		/* limit value */

			ctl_stk[ctl_ptr++] = i;			/* variable number */

			ctl_stk[ctl_ptr++] = _FOR;

			break;

		case NEXT :

			pgm_only();

			if(ctl_stk[ctl_ptr-1] != _FOR)

				error(6);

			i = ctl_stk[ctl_ptr-2];

			if(!is_l_end(skip_blank()))

				if(get_var() != i) error(6);

			jj = ctl_stk[ctl_ptr-3];	/* get limit */

			ii = ctl_stk[ctl_ptr-4];	/* get step */

			num_vars[i] += ii;

			if((ii < 0) ? num_vars[i] >= jj : num_vars[i] <= jj) {

				cmdptr = ctl_stk[ctl_ptr-5];

				runptr = ctl_stk[ctl_ptr-6];

				line = runptr->Lnumber; }

			else

				ctl_ptr -= 6;

			break;

		case IF :

			i = eval_num();

			expect(-128+THEN);

			if(i) {

				if(isdigit(cmd = skip_blank()))

					return find_line(eval_num());

				else if(cmd < 0) {

					++cmdptr;

					return execute(cmd); }

				else

					execute(1); }

			else

				skip_stmt();

			break;

		case LIF :

			i = eval_num();

			expect(-128+THEN);

			if(i) {

				if((cmd = skip_blank()) < 0) {

					++cmdptr;

					return execute(cmd); }

				else

					execute(1);

				break; }

		case DATA :

			pgm_only();

		case REM :

			if(mode) {

				if(cptr = runptr->Llink)

					return cptr;

				longjmp(savjmp, 1); }

			break;

		case STOP :

			pgm_only();

			printf("STOP in line %u\n",line);

		case END :

			pgm_only();

			longjmp(savjmp, 1);

		case INPUT :

			ii = chk_file(1);

			if(skip_blank() == '"') {		/* special prompt */

				eval();

				expect(','); }

			else

				strcpy(sa1, "? ");

			dptr = address();

			cptr = cmdptr;

input:		if(ii == -1)

				fputs(sa1, stdout);

			cmdptr = fgets(buffer, sizeof(buffer)-1 ,filein);

			if(expr_type) {

				if(*dptr) free(*dptr);

				strcpy(*dptr = allocate(strlen(buffer)+1), buffer); }

			else {

				k = 0;

				if(test_next('-'))

					--k;

				if(!isdigit(*cmdptr)) {

					if(ii != -1) error(9);

					fputs("Input error\n",stdout);

					goto input; }

				j = get_num();

				*dptr = (k) ? 0-j: j; }

			cmdptr = cptr;

			break;

		case OPEN :

			if(skip_blank() != '#') error(0);

			if(files[i = chk_file(0)]) error(8);

			eval_char();

			strcpy(buffer, sa1);

			expect(',');

			eval_char();

			files[i] = fopen(buffer,sa1);

			break;

		case CLOSE :

			if((i = chk_file(1)) == -1) error(0);

			if(!filein) error(8);

			fclose(files[i]);

			files[i] = 0;

			break;

		case DIM :

			do {

				if(dptr = dim_vars[i = get_var()])

					free(dptr);

				dim_vars[i] = allocate((dim_check[i] = eval_num()+1) * 2); }

			while(test_next(','));

			break;

		case ORDER :

			readptr = find_line(eval_num());

			dptr = cmdptr;

			cmdptr = readptr->Ltext;

			if(get_next() != -128+DATA)

				error(11);

			dataptr = cmdptr;

			cmdptr = dptr;

			break;

		case READ :

			do {

				dptr = address();

				j = expr_type;

				cptr = cmdptr;

				cmdptr = dataptr;

				ii = line;

				if(!skip_blank()) {		/* End of line */

					readptr = readptr->Llink;

					cmdptr = readptr->Ltext;

					if(get_next() != -128+DATA)

						error(11); }

				line = readptr->Lnumber;

				k = eval();

				test_next(',');

				dataptr = cmdptr;

				cmdptr = cptr;

				line = ii;

				if(j != expr_type)

					error(11);

				if(!expr_type)		/* numeric assignment */

					*dptr = k;

				else {				/* character assignment */

					if(*dptr)

						free(*dptr);

					if(*sa1)

						strcpy(*dptr = allocate(strlen(sa1)+1), sa1);

					else

						*dptr = 0; } }

			while(test_next(','));

			break;

		case DELAY :

			delay(eval_num());

			break;

		case BEEP :

			i = eval_num();

			expect(',');

			beep(i, eval_num());

			break;

		case DOS :

			eval_char();

			system(sa1);

			break;

		case OUT :

			i = eval_num();

			expect(',');

			out(i, eval_num());

			break;

		case SAVE :

			direct_only();

			if(skip_blank()) {

				eval_char();

				concat(filename, sa1, ".BAS"); }

			if(fileout = fopen(filename, "wv")) {

				disp_pgm(fileout, 0, -1);

				fclose(fileout); }

			break;

		case LOAD :

			eval_char();

			concat(filename, sa1, ".BAS");

			if(filein = fopen(filename, "rv")) {

				if(!mode) clear_vars();

				clear_pgm();

				while(fgets(buffer, sizeof(buffer)-1, filein))

					edit_program();

				fclose(filein);

				return pgm_start; }

			longjmp(savjmp, 1);

		default :			/* unknown */

			error(0); }

		return 0;

}



/*

 * Test for file operator, and set up pointers

 */

int chk_file(char flag)

{

	unsigned i;



	i = -1;

	if(test_next('#')) {

		if(9 < (i = eval_num())) error(7);

		test_next(',');

		filein = fileout = files[i];

		if(flag && (!filein))

			error(7); }

	else {

		filein = stdin;

		fileout = stdout; }

	return i;

}



/*

 * Display program listing

 */

disp_pgm(FILE *fp, unsigned i, unsigned j)

{

	unsigned k;

	struct line_record *cptr;

	char c;



	for(cptr = pgm_start; cptr; cptr = cptr->Llink) {

		k = cptr->Lnumber;

		if((k >= i) && (k <= j)) {

			fprintf(fp,"%u ",k);

			for(k=0; c = cptr->Ltext[k]; ++k)

				if(c < 0) {

					c = c & 127;

					fputs(reserved_words[c - 1], fp);

					if(c < ADD)

						putc(' ',fp); }

				else

					putc(c,fp);

			putc('\n', fp); } }

}



/*

 * Test for program only, and error if interactive

 */

pgm_only()

{

	if(!mode) error(2);

}



/*

 * Test for direct only, and error if running

 */

direct_only()

{

	if(mode) error(1);

}



/*

 * Skip rest of statement

 */

skip_stmt()

{

	char c;



	while((c=*cmdptr) && (c != ':')) {

		++cmdptr;

		if(c == '"') {

			while((c=*cmdptr) && (c != '"'))

				++cmdptr;

			if(c) ++cmdptr; } }

}



/*

 * Dislay error message

 */

error(unsigned en)

{

	printf("%s error", error_messages[en]);

	if(mode)

		printf(" in line %u", line);

	putc('\n',stdout);

	longjmp(savjmp, 1);

}



/*

 * Evaluate number only (no character)

 */

int eval_num()

{

	unsigned value;



	value = eval();

	if(expr_type)

		error(4);

	return value;

}



/*

 * Evaluate character only (no numeric)

 */

eval_char()

{

	eval();

	if(!expr_type)

		error(4);

}



/*

 * Evaluate an expression (numeric or character)

 */

int eval()

{

	unsigned value;



	nest = 0;

	value = eval_sub();

	if(nest != 1) error(0);

	return value;

}



/*

 * Evaluate a sub expression

 */

int eval_sub()	

{

	unsigned value, nstack[10], nptr, optr;

	char c, ostack[10];



	++nest;								/* indicate we went down */



/* establish first entry on number and operator stacks */

	ostack[optr = nptr = 0] = 0;		/* add zero to init */



	nstack[++nptr] = get_value();		/* get next value */

/* string operations */

	if(expr_type) {						/* string operations */

		while(!is_e_end(c = skip_blank())) {

			++cmdptr;

			c &= 0x7F;

			get_char_value(sa2);

			if(c == ADD)				/* String concatination */

				strcat(sa1, sa2);

			else {

				if(c == EQ)				/* String EQUALS */

					value = !strcmp(sa1, sa2);

				else if(c == NE)		/* String NOT EQUALS */

					value = strcmp(sa1, sa2) != 0;

				else

					error(0);

				nstack[nptr] = value;

				expr_type = 0; } } }



/* numeric operations */

	else {

		while(!is_e_end(c = skip_blank())) {

			++cmdptr;

			c = (c & 0x7F) - (ADD-1);	/* 0 based priority table */

			if(priority[c] <= priority[ostack[optr]]) {	/* execute operand */

				value = nstack[nptr--];

				nstack[nptr] = do_arith(ostack[optr--], nstack[nptr], value); }

			nstack[++nptr] = get_value();		/* stack next operand */

			if(expr_type) error(0);

			ostack[++optr] = c; }

		while(optr) {				/* clean up all pending operations */

			value = nstack[nptr--];

			nstack[nptr] = do_arith(ostack[optr--], nstack[nptr], value); } }

	if(c == ')') {

		--nest;

		++cmdptr; }

	return nstack[nptr];

}



/*

 * Get a value element for an expression

 */

int get_value()

{

	unsigned value, v, *dptr;

	char c, *ptr;



	expr_type = 0;

	if(isdigit(c = skip_blank()))

		value = get_num();

	else {

		++cmdptr;

		switch(c) {

			case '(' :			/* nesting */

				value = eval_sub();

				break;

			case '!' :			/* not */

				value = ~get_value();

				break;

			case -128+SUB :	/* negate */

				value = -get_value();

				break;

			case -128+ASC :	/* Convert character to number */

				eval_sub();

				if(!expr_type) error(4);

				value = *sa1 & 255;

				expr_type = 0;

				break;

			case -128+NUM :	/* Convert string to number */

				eval_sub();

				if(!expr_type) error(4);

				value = atoi(sa1);

				expr_type = 0;

				break;

			case -128+ABS :	/* Absolute value */

				if((value = eval_sub()) > 32767)

					value = -value;

				goto number_only;

			case -128+RND :	/* Random number */

				value = random(eval_sub());

				goto number_only;

			case -128+KEY :		/* Keyboard test */

				/* eval_sub(); */

				expect(')');

				value = kbtst();

				break;

			case -128+INP :	/* Read from port */

				value = in(eval_sub());

			number_only:

				if(expr_type) error(4);

				break;

			default:			/* test for character expression */

				--cmdptr;

				if(isalpha(c)) {		/* variable */

					value = get_var();

					if(expr_type) {		/* char */

						if(ptr = char_vars[value])

							strcpy(sa1, ptr);

						else

							strcpy(sa1, ""); }

					else {

						if(test_next('(')) {	/* Array */

							if(!(dptr = dim_vars[value]))

								error(10);

							if((v = eval_sub()) >= dim_check[value])

								error(10);

							value = dptr[v]; }

						else						/* Std variable */

							value = num_vars[value]; } }

				else

					get_char_value(sa1); } }

	return value;

}



/*

 * Get character value

 */

get_char_value(char *ptr)

{

	unsigned i;

	char c, *st;



	if((c = get_next()) == '"') {	/* character value */

		while((c = *cmdptr++) != '"') {

			if(!c) error(0);

			*ptr++ = c; }

		*ptr = 0; }

	else if(isalpha(c)) {			/* variable */

		--cmdptr;

		i = get_var();

		if(!expr_type)

			error(0);

		if(st = char_vars[i])

			strcpy(ptr,st);

		else

			strcpy(ptr,""); }

	else if(c == -128+CHR) {		/* Convert number to character */

		*ptr++ = eval_sub();

		if(expr_type)

			error(4);

		*ptr = 0; }

	else if(c == -128+STR) {		/* Convert number to string */

		num_string(eval_sub(), ptr);

		if(expr_type)

			error(4); }

	else

		error(0);

	expr_type = 1;

}



/*

 * Perform an arithmetic operation

 */

int do_arith(char opr, unsigned op1, unsigned op2)

{

	unsigned value;



	switch(opr) {

		case ADD-(ADD-1) :		/* addition */

			value = op1 + op2;

			break;

		case SUB-(ADD-1) :		/* subtraction */

			value = op1 - op2;

			break;

		case MUL-(ADD-1) :		/* multiplication */

			value = op1 * op2;

			break;

		case DIV-(ADD-1) :		/* division */

			value = op1 / op2;

			break;

		case MOD-(ADD-1) :		/* modulus */

			value = op1 % op2;

			break;

		case AND-(ADD-1) :		/* logical and */

			value = op1 & op2;

			break;

		case OR-(ADD-1) :		/* logical or */

			value = op1 | op2;

			break;

		case XOR-(ADD-1) :		/* exclusive or */

			value = op1 ^ op2;

			break;

		case EQ-(ADD-1) :		/* equals */

			value = op1 == op2;

			break;

		case NE-(ADD-1) :		/* not-equals */

			value = op1 != op2;

			break;

		case LE-(ADD-1) :		/* less than or equal to */

			value = op1 <= op2;

			break;

		case LT-(ADD-1) :		/* less than */

			value = op1 < op2;

			break;

		case GE-(ADD-1) :		/* greater than or equal to */

			value = op1 >= op2;

			break;

		case GT-(ADD-1) :		/* greater than */

			value = op1 > op2;

			break;

		default:

			error(0); }

	return value;

}



/*

 * Convert a number to a string, and place in memory

 */

num_string(unsigned value, char *ptr)

{

	char cstack[5], cptr;



	cptr = 0;



	if(value > 32767) {

		*ptr++ = '-';

		value = -value; }

	do

		cstack[cptr++] = (value % 10) + '0';

	while(value /= 10);

	while(cptr)

		*ptr++ = cstack[--cptr];

	*ptr = 0;

}



/*

 * Clear program completely

 */

clear_pgm()

{

	for(runptr = pgm_start; runptr; runptr = runptr->Llink)

		free(runptr);

	pgm_start = 0;

}



/*

 * Clear all variables to zero

 */

clear_vars()

{

	unsigned i;

	char *ptr;



	for(i=0; i < NUM_VAR; ++i) {

		num_vars[i] = 0;

		if(ptr = char_vars[i]) {	/* Character variables */

			free(ptr);

			char_vars[i] = 0; }

		if(ptr = dim_vars[i]) {		/* Dimensioned arrays */

			free(ptr);

			dim_vars[i] = 0; } }

}



/*

 * Get index for variable from its name

 */

int get_var()

{

	unsigned index;

	char c;



	if(!isalpha(c = get_next()))

		error(0);

	index = ((c - 'A') & 0x1F) * 10;

	if(isdigit(c = *cmdptr)) {

		index += (c - '0');

		c = *++cmdptr; }

	if(c == '$') {

		++cmdptr;

		expr_type = 1; }

	else

		expr_type = 0;



	return index;

}



/*

 * Main program

 */

main(int argc, char *argv[])

{

	int i, j;



/*

 * If arguments are given, copy them into the A0$, A1$, A2$ ... variables

 */

	pgm_start = j = 0;

	for(i=1; i < argc; ++i)

		char_vars[j++] = argv[i];



/*

 * If a name is given on the command line, load it as a program and

 * run immediately. If the program does not explicitly EXIT, we will

 * then proceed to an interactive session

 */

	if(j) {

		concat(filename, char_vars[0], ".BAS");

		if(filein = fopen(filename, "rv")) {

			while(fgets(buffer, sizeof(buffer)-1, filein))

				edit_program();

			fclose(filein);

			if(!setjmp(savjmp))

				execute(RUN1); } }



/*

 * Display header AFTER running command line, so that programs run as

 * "batch" commands terminating with EXIT do not get "noise" output.

 */

	printf("MICRO-BASIC 2.1 - Copyright 1982-2000 Dave Dunfield.\n");



	setjmp(savjmp);

	for(;;) {						/* Main interactive loop */

		fputs("Ready\n", stdout);

	noprompt: mode = ctl_ptr = 0;

		fgets(buffer, sizeof(buffer)-1, stdin);

		if(edit_program())			/* Tokenize & edit if OK */

			goto noprompt;

		if((i = *cmdptr) < 0) {		/* Keyword, execute command */

			++cmdptr;

			execute(i); }

		else if(i)					/* Unknown, assume LET */

			execute(LET); }

}

--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]