All pastes #983044 Raw Edit

Mine

public c v1 · immutable
·published 2008-04-12 23:58 UTC
rendered paste body
/***************** MAIN.C ***************/#include <stdio.h>#include <stdlib.h>#include "sdata.h"#include "parse.h"#include "eval.h"#include "errors.h"int main () {	char *code;	while (1) {		code = malloc (100*sizeof(char));		printf ("> ");		gets (code);		list *expr = parse (code);		while (errorcount ("parse")) {			printerror ("parse");			poperror ("parse");		}		printsdata (run(expr));		printf ("\n");		freelist (expr);		free (expr);		free (code);						}	return 0;}/***************** SDATA.C ***************/#include <stdlib.h>#include <stdio.h>#include "sdata.h"#include "bignum.h"#include "errors.h"struct sdata {	S_type tag;	void *data;};struct list {	sdata *contents;	struct list *cdr;};sdata *car (list *lst) { 	if (lst == 0) {		adderror ("car", "no car of the empty list");		printerror ("car");		exit (-1);	}	return lst->contents; }list *cdr (list *lst) { 	if (lst == 0) {		adderror ("cdr", "no cdr of the empty list");		printerror ("cdr");		exit (-1);	}	return lst->cdr; }/* instead of cons accepting a void*, a type tag and a list, the function	is overloaded for seperate types. this will provide a cleaner api */list *cons (void *newdata, S_type ntype, list *lst) {	list *newlst = malloc (sizeof(list));	newlst->contents = malloc (sizeof (sdata));	if (newlst == 0 || newlst->contents == 0) {		adderror ("cons", "malloc error, out of memory");		printerror ("cons");		exit (-1);	}	newlst->contents->tag = ntype;	newlst->contents->data = newdata;						   	newlst->cdr = lst;	return newlst;}list *reverse (list *lst) {	list *prev = 0;	list *head = lst;	list *tmp;	while (head) {		tmp = head->cdr;		head->cdr = prev;		prev = head;		head = tmp;	}	return prev;}unsigned int length (list *lst) {	unsigned int i = 0;	list *ptr = lst;	while (ptr) { 		i++; 		ptr = cdr(ptr);	}	return i;}void freesdata (sdata *d) {	free (d->data);}void freelist (list *lst) {	if (lst != 0) {		freesdata (lst->contents);		freelist (lst->cdr);	}}void printlist (list *lst) {	list *ptr = lst;	printf ("(");	while (ptr != 0) {		printsdata (car (ptr));		ptr = cdr(ptr);		if (ptr) { printf (" "); }	}	printf (")");}void printsdata (sdata *s) {	if (s == 0) return;	switch (s->tag) {		case sNUMBER:			printf ("%s", bn_numbertostring(s->data));			break;		case sSYMBOL:			printf ("%s", (char*)s->data);			break;		case sCONS:			printlist ((list*)s->data);			break;	}}/***************** BIGNUM.C ***************/#include <stdlib.h>#include <stdio.h> // for sprintf#include <math.h>#include "errors.h"#include "bignum.h"typedef enum Numtype {	INTEGER, /* base */	REAL, /* base */	RATIONAL, /* compound */	COMPLEX /* compound */} Numtype;typedef struct {	Numtype tag;	int exact;	void *num;} bignum;typedef struct {	void *data;} big_inexact; typedef struct {	bignum *data1;	bignum *data2;} big_binary;/* Assumes num is a properly formatted string */void *bn_create(char *num, int type, int exact) {	bignum *ans = malloc (sizeof (bignum));	ans->exact = exact;	ans->tag = type;		switch (type) {		case INTEGER:			ans = 0;			break;		case REAL:			ans->num = malloc (sizeof(big_inexact));			((big_inexact *)ans->num)->data = malloc (sizeof(double));			*(double *)((big_inexact *)ans->num)->data = atof (num);			break;		case RATIONAL:			if (exact) {							}			else {							}			ans = 0;			break;		case COMPLEX:			if (exact) {			}			else {							}			ans = 0;			break;	}	return ans;}void *bn_copy (void *n) {	bignum *ans = malloc (sizeof (bignum));	if (ans == 0) malloc_error ("bn_copy");		switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			break;		case RATIONAL:			break;		case COMPLEX:			break;	}	return ans;}void freebn (void *n) {	switch (((bignum *)n)->tag) {		case INTEGER:			/* ... */			//free ((big_exact *)(((bignum *)n)->num));			break;		case REAL:			free ((double *)((big_inexact *)((bignum *)n)->num)->data);			free ((big_inexact *)(((bignum *)n)->num));			break;		case RATIONAL:		case COMPLEX:			freebn ( (bignum *)((big_binary *)n)->data1);			freebn ( (bignum *)((big_binary *)n)->data2);						free ((big_binary *)((bignum *)n)->num);			break;	}	}void bn_negate (void *n) {	switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			*(double *)((big_inexact *)((bignum *)n)->num)->data *= -1;			break;		case RATIONAL:			bn_negate (((big_binary *)((bignum *)n)->num)->data1);			break;		case COMPLEX:			bn_negate (((big_binary *)((bignum *)n)->num)->data1);			bn_negate (((big_binary *)((bignum *)n)->num)->data2);			break;	}}void bn_add (void *n, void *m) {	switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			*(double *)((big_inexact *)((bignum *)n)->num)->data += *(double *)((big_inexact *)((bignum *)m)->num)->data;			break;		case RATIONAL:			break;		case COMPLEX:			break;	}}void bn_multiply (void *n, void *m) {	switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			*(double *)((big_inexact *)((bignum *)n)->num)->data *= *(double *)((big_inexact *)((bignum *)m)->num)->data;			break;		case RATIONAL:			break;		case COMPLEX:			break;	}}void bn_divide (void *n, void *m) {	switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			*(double *)((big_inexact *)((bignum *)n)->num)->data /= *(double *)((big_inexact *)((bignum *)m)->num)->data;			break;		case RATIONAL:			break;		case COMPLEX:			break;	}	}void bn_expt (void *n, void *m) {	switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			*(double *)((big_inexact *)((bignum *)n)->num)->data = 				pow (*(double *)((big_inexact *)((bignum *)n)->num)->data, *(double *)((big_inexact *)((bignum *)m)->num)->data);			break;		case RATIONAL:			break;		case COMPLEX:			break;	}	}int bn_equal (void *n, void*m) {	int ans;	if (((bignum *)n)->tag != ((bignum *)n)->tag) matchtags (n, m);	switch (((bignum *)n)->tag) {		case INTEGER:			ans = 0;			break;		case REAL:			ans = (*(double *)((big_inexact *)((bignum *)n)->num)->data == *(double *)((big_inexact *)((bignum *)m)->num)->data);			break;		case RATIONAL:			ans = 0;			break;		case COMPLEX:			ans = 0;			break;	}	return ans;}int bn_lessthan (void *n, void*m) {	return 0; /* FIX */	}int bn_lessthanequal (void *n, void*m) {	return 0; /* FIX */	}int bn_greaterthan (void *n, void*m) {	return 0; /* FIX */	}int bn_greaterthanequal (void *n, void*m) {	return 0; /* FIX */}void bn_abs (void *n) {	/* ... */	}void bn_acos (void *n) {	/* ... */}void bn_add1 (void *n) {	/* ... */}void bn_angle (void *n) {	/* ... */}void bn_asin (void *n) {	/* ... */}void bn_atan (void *n) {	/* ... */}void bn_ceiling (void *n) {	/* ... */}void bn_conjugate (void *n) {	/* ... */	}void bn_cos (void *n) {	/* ... */}void bn_denominator (void *n) {	if (bn_integer (n)) {	//	return bn_create ("1", INTEGER, 1);	}	if (((bignum *)n)->tag != RATIONAL) {		adderror ("bn_denominator", "number not rational or integer");		printerror ("bn_denominator");		exit (-1);	}	//return 0;//(bignum *)((big_rational *)(((bignum *)n)->num)->denominator);}int bn_even (void *n) {	if (!bn_integer (n)) {		adderror ("bn_even/bn_odd", "expects integer argument");		printerror ("bn_even/bn_odd");		exit (-1);	}	return 0; /*  FIX: Fill me! */   }void bn_exact_to_inexact (void *n) {	/* ... */}	void bn_exp (void *n) {	/* ... */	}void bn_floor (void *n) {	/* ... */	}void bn_gcd (void *n, void *m) {	/* ... */}void bn_imagpart (void *n) {	//if ( ((bignum *)n)->tag == COMPLEX) 	//	return 0;//(bignum *)((big_complex *)((bignum *)n->num)->im);	//else 	//	return bn_create ("0", INTEGER, 1);}void bn_inexact_to_exact (void *n) {	/* ... */	}void bn_lcm (void *n) {	/* ... */}void bn_log (void *n) {		/* ... */}void bn_magnitude (void *n) {	/* ... */}void bn_makepolar (void *n, void *m) {	/* ... */}void bn_max (void *n, void *m) {	//if (bn_greaterthan (n, m))	//	return n;	//return m;}void bn_min (void *n, void *m) {	//if (bn_lessthan (n, m))	//	return n;	//return m;}void bn_modulo (void *n, void *m) {	/* ... */}int bn_negative (void *n) {	int ans = 0;	switch (((bignum *)n)->tag) {		case INTEGER:			break;		case REAL:			ans = (0 > *(double *)(((big_inexact *)(((bignum *)n)->num))->data));			break;		case RATIONAL:			break;		case COMPLEX:			break;	}	return ans;}char *bn_numbertostring (void *n) {	char *ans;	switch (((bignum *)n)->tag) {		case INTEGER:			ans = 0;			break;		case REAL:			ans = malloc (80*sizeof(char));			snprintf (ans, 79, "%.10G", *(double *)((big_inexact *)((bignum *)n)->num)->data);			break;		case RATIONAL:			ans = 0;					  			break;		case COMPLEX:			ans = 0;			break;	}	return ans;}void bn_numerator (void *n) {	//if (bn_integer (n)) {	//	return n;	//}	//if (((bignum *)n)->tag != RATIONAL) {	//	adderror ("bn_numerator", "number not rational or integer");	//	printerror ("bn_numerator");	//	exit (-1);	//}	//return 0;//(bignum *)((big_rational *)(((bignum *)n)->num)->numerator);}int bn_odd (void *n) {	if (bn_even (n)) 		return 0;	return 1;}int bn_positive (void *n) {	if (bn_negative (n)) 		return 0;	return 1;}void bn_quotient (void *n, void *m) {	//return bn_floor (bn_divide (n, m));}void bn_realpart (void *n) {	//if ( ((bignum *)n)->tag == COMPLEX) 	//	return ((big_binary *)(((bignum *)n)->num))->data1;	//else 	//	return n;}void bn_remainder (void *n, void *m) { 	/* ... */}void bn_round (void *n) {	//bignum *ans = 0;	//switch (((bignum *)n)->tag) {	//	case INTEGER:	//		ans = bn_copy (n);	//		break; /* already rounded */	//	case REAL:				//		int *newval = malloc (sizeof (int));	//		*newval = round ((double *)((big_inexact *)(((bignum *)n)->num)));	//		char *tmp[80];	//		sprintf (tmp, 79, "%i", newval);	//		ans = bn_create (tmp, INTEGER, 1);	//		free (tmp);	//		break;	//	case RATIONAL:	//		ans = 0;	//		break;	//	case COMPLEX:	//		ans = 0;	//		break;	//}	//return 0;}void bn_sgn (void *n) {	/* ... */}void bn_sin (void *n) {	bignum *ans;	switch (((bignum *)n)->tag) {		case INTEGER:			ans = 0;			break;		case REAL:			ans = bn_copy (n);			*(float *)(((big_inexact *)ans->num)->data) = sin (*(float *)(((big_inexact *)ans->num)->data));			break;		case RATIONAL:			ans = 0;			break;	}	//return ans;}void bn_sqrt (void *n) {	/* ... */}void bn_sub1 (void *n) {	/* ... */}void bn_tan (void *n){	/* ... */}int bn_zero (void *n) {	return 0; /* FIX */}int bn_exact (void *n) {	if (((bignum *)n)->exact) 		return 1;	else if (((bignum *)n)->tag == RATIONAL) {		if (bn_exact (0) && bn_exact (0)) /* FIX */			return 1;	}	else if (((bignum *)n)->tag == COMPLEX) {		if (bn_exact (0) && bn_exact (0)) /* FIX: lazy */			return 1;	}	return 0;}int bn_inexact (void *n) {	if (bn_exact (n))		return 0;	return 1;}int bn_integer (void *n) {	if (((bignum *)n)->exact == 1) {		return 1; /* FIX: wrong, do actual test */	}	return 0;}int bn_rational (void *n) {	if (((bignum *)n)->tag == RATIONAL || bn_integer (n)) 		return 1;	return 0;}int bn_real (void *n) {	if (((bignum *)n)->tag == COMPLEX)		return 0;	return 1;}/***************** PARSE.C ***************/#include <stdlib.h>#include <string.h>#include "sdata.h"#include "errors.h"#include <stdio.h>#define LPAREN 1#define LSQRPAREN 2#define RPAREN 3#define RSQRPAREN 4/* pattern matching */int isparen (char a) { 	if (a == '(') return LPAREN; 	if (a == '[') return LSQRPAREN; 	if (a == ')') return RPAREN;	if (a == ']') return RSQRPAREN;	return 0;	}int isnum (char a) { 	if (a >= '0' && a<= '9') 		return 1; 	return 0; }int iswhite (char a) { 	if (a == ' ' || a == '\t' || a == '\n') 		return 1; 	return 0; }int isnamechar (char a) { 	if (!(iswhite(a) || isparen(a) || a == '\"' || a == ','|| a == '\'' || a == '`' || a == '|' || a == ';' || a == '#')) 		return 1; 	return 0; }/* CONTRACT: parse: string -> listof (expr) PURPOSE: Consume a string and parse it into a list of expr's, made of sdata EFFECTS: None usually. Critical errors print to stdout and halt. ERRORS: Non critical errors are added to the error stack and the function returns 0. NOTES:  */list *parse (char *code) {	enum State {			START, 		NUMBER,		IDENTIFIER 	} state;	enum Numstate {		INTEGER,		REAL, /* restricts numbers to one decimal point per number, and fractions to int/int */		RATIONAL, /* restricts fractions to only have 1 numerator and 1 denominator */		COMPLEX /* restricts complex numbers to have 1 real part and 1 imaginary part */	} numstate;		list *expr = 0;	int i = 0, k = 0; /* when we start parsing something interesting, 'i' will point to the front of the token, 'k' to the end */		int imagrational = 0;	int imagnegative = 0;	int imagreal = 0;		/* place to temporarily store data */	char *cdata;		state = START;	int done = 0;	while (!done) {		switch (state) {			case START:				if (code[k] == '\0')					done = 1;				else if (isnum(code[k]) || code[k] == '-') {					state = NUMBER;					numstate = INTEGER;					i = k;				}				else if (isnamechar(code[k])) {					state = IDENTIFIER;					i = k;				}				else if (isparen (code[k])) {					/* catch stray close parens */					if (isparen (code[k]) == RPAREN)		{ adderror ("parse", "unexpected )"); return 0; }					if (isparen (code[k]) == RSQRPAREN)		{ adderror ("parse", "unexpected ]"); return 0; }										int opens  = 1;					int m;					i = k;					k++;					while (opens > 0) {						m = isparen (code[k]);						if (code[k] == '\0') { 							if (code[i] == '(')	adderror ("parse", "unexpected end of file: expected )"); 							if (code[i] == '[')	adderror ("parse", "unexpected end of file: expected ]");							return 0;						}						else if (m == LPAREN || m == LSQRPAREN)	opens++;						else if (m == RPAREN || m == RSQRPAREN)	opens--;						k++;					}					k--;					cdata = malloc ((k - i - 1)*sizeof(char));					if (cdata == 0) malloc_error ("parse");									strncpy (cdata, &code[i+1], k - i - 1); /* exclude the outermost open/close parens */					cdata[k - i - 1] = '\0';					expr = cons (parse (cdata), sCONS, expr);					free (cdata);				}				else if (iswhite(code[k])) i = k; /* extra whitespace is ignored */				else {					adderror ("parse", "in state START, found unexpected character");					return 0;				}				break;			case NUMBER:				/* check to see if we are done parsing the number */				if (iswhite(code[k]) || code[k] == '\0' || isparen(code[k]) || code[k] == 'i') {					cdata = malloc ((k - i + 1)*sizeof(char));					if (cdata == 0) malloc_error ("parse");					strncpy (cdata, &code[i], k - i);					cdata[k - i] = '\0';					int exact = 1;					if (numstate == COMPLEX && imagreal) exact = 0;					if (numstate == REAL) exact = 0;					void *newnum = bn_create (cdata, numstate, exact);					expr = cons (newnum, sNUMBER, expr);					free (cdata);					if (code[k] == '\0') done = 1;					if (isparen (code[k])) k--; /* seeing it was an accident, someone else has to deal with it */ 										state = START;					imagreal = 0;				}				else { /* we are not done, handle the next char */					switch (numstate) {						case REAL:							if (isnum (code[k])) { /* do nothing */ }							else if (code[k] == '+' || code[k] == '-') {								numstate = COMPLEX;								imagrational = 0;								if (code[i] == '-') imagnegative = 1;								else imagnegative = 0;								imagreal = 1;							}							else if (isnamechar (code[k])) state = IDENTIFIER;							else  {								adderror ("parse", "in state REAL, found unexpected character");								return 0;							}							break;						case INTEGER:							if (code[k] == '.') numstate = REAL; 							else if (isnum (code[k])) { /* do nothing */ }							else if (code[k] == '/') numstate = RATIONAL;							else if (code[k] == '+' || code[k] == '-') {								numstate = COMPLEX;								imagrational = 0;								if (code[i] == '-') imagnegative = 1;								else imagnegative = 0;								imagreal = 0;							}							else if (isnamechar (code[k])) state = IDENTIFIER;							else {								adderror ("parse", "in state NUMBER, numstate INTEGER, found unexpected character");								return 0;							}							break;						case RATIONAL:							if (isnum (code[k])) { /* do nothing */ }							else if (code[k] == '+' || code[k] == '-') {								numstate = COMPLEX;								imagrational = 0;								if (code[i] == '-') imagnegative = 1;								else imagnegative = 0;								imagreal = 0;							}							else if (isnamechar (code[k])) state = IDENTIFIER;							else {								adderror ("parse", "in state NUMBER, numstate RATIONAL, found unexpected character");								return 0;							}											break;						case COMPLEX:							if (isnum (code[k])) { /* do nothing */ }							else if (code[k] == '.' && imagreal == 0) imagreal = 1;							else if (code[k] == '/' && imagrational == 0) imagrational = 1;							else if (isnamechar (code[k])) state = IDENTIFIER;						else {							adderror ("parse", "in state NUMBER, substate COMPLEX, found unexpected character");							return 0;						}										break;					}				}				break;			case IDENTIFIER:				if (iswhite (code[k]) || code[k] == '\0' || isparen(code[k])) {					/* parse string */					cdata = malloc ((k - i + 1)*sizeof(char));					if (cdata == 0) malloc_error ("parse");					strncpy (cdata, &code[i], k - i);					cdata[k - i] = '\0';					expr = cons (cdata, sSYMBOL, expr);					state = START;					if (code[k] == '\0') done = 1;					if (isparen (code[k])) k--; /* seeing it was an accident, someone else has to deal with it */ 				}				else if (isnum (code[k]) || isnamechar (code[k])) { /* do nothing */ }				else {					adderror ("parse", "in state SYMBOL, found unexpected character");					return 0;				}				break;		}		k++;	}	expr = reverse (expr);	return expr;}/***************** EVAL.C ***************/#include <stdlib.h>#include "sdata.h"sdata *lookup (char *key, char **env_names, sdata **defs, unsigned int nsize) {	int i;	for (i = 0; i < nsize; i++) {		if (strcmp(key, env_names[i]) == 0) {			return defs[i];		}	}	return 0;}int is_prm (char *key) {	static char *prm_list[] = { 		"+", "-", "*", "/", "=", "expt", "add1", "sub1", "cons", "empty",		"car", "cdr", "remainder", "equal?", "number?", "symbol?" 	};	int i;	for (i = 0; i < 16; i++) {		if (strcmp(prm_list[i], key)) {			return 1;		}	}	return 0;		}sdata *eval (sdata *expr, char **env_names, sdata **defs, unsigned int envsize) {	if (expr->data == 0 || expr->tag == sNUMBER) {		return expr; /* a number or the empty list */	}	if (expr->tag == sSYMBOL) {		sdata *look = lookup ((char *)expr->data, env_names, defs, envsize);		printsdata (look);		if (look == 0) {			if (is_prm ((char *)expr->data)) {				return expr; 			}			else {				adderror ("eval", "could not find symbol");				printerror ("eval");				exit (-1);			}		}		return look;	}		/* therefore, it must be a cons */	/* should check if first thing is actually a symbol! */	list *lst = (list *)expr->data;	char *ident = (char *)car(lst)->data;		if (is_prm(ident)) {		if (strcmp("+", ident) == 0) {			sdata *acc = malloc (sizeof (sdata));			acc = eval(car(cdr(lst)), env_names, defs, envsize);			list *ptr = cdr(cdr(lst));			while (ptr) {				bn_add (acc->data, eval(car(ptr), env_names, defs, envsize)->data);				ptr = cdr(ptr);			}			return acc;		}		if (strcmp("*", ident) == 0) {			sdata *acc = malloc (sizeof (sdata));			acc = eval(car(cdr(lst)), env_names, defs, envsize);			list *ptr = cdr(cdr(lst));			while (ptr) {				bn_multiply (acc->data, eval(car(ptr), env_names, defs, envsize)->data);				ptr = cdr(ptr);			}			return acc;		}				else {			adderror ("eval", "prm not found");			printerror ("eval");			exit (-1);		}	}	else {		adderror ("eval", "unrecognized syntax");		printerror ("eval");		exit (-1);			}}sdata *run (list *code) {	list *answers = 0;	char **env_names = 0;	sdata **defs = 0;	unsigned int envsize = 0;		list *ptr = code;	sdata *tmp;	while (ptr) {		if (0) { /* it's a definition */			return 0; 		}		else {			tmp = eval( car(code), env_names, defs, envsize);			answers = cons (tmp->data, tmp->tag, answers);		}		ptr = cdr (ptr);	}		if (length(answers) == 1) {		return car (answers);	}	else {		sdata *ans = malloc (sizeof (sdata));		ans->tag = sCONS;		ans->data = answers;		return ans;	}}/***************** ERRORS.C ***************/#include <stdlib.h>#include <stdio.h>#include <string.h>#include "sdata.h"#include "errors.h"list *errorstack = 0;void adderror (char *funcname, char *desc) {	char *internal_funcname = malloc ((1+strlen(funcname))*sizeof(char));	char *internal_desc = malloc ((1+strlen(desc))*sizeof(char));		if (internal_funcname == 0 || internal_desc == 0) {		printf ("In adderror: malloc failure");		exit (-1);	}	strcpy (internal_funcname, funcname);	strcpy (internal_desc, desc);		list *newerror = 0;		newerror = cons (internal_desc, sSYMBOL, newerror);	newerror = cons (internal_funcname, sSYMBOL, newerror);		errorstack = cons (newerror, sCONS, errorstack);}void poperror (char *funcname) {	list *prev = 0;	list *ptr = errorstack;	while (ptr) {		if (strcmp((char *)car((list *)car(ptr)->data)->data, funcname) == 0) {			if (prev == 0) { /* its the first thing on the "stack" */				errorstack = cdr (errorstack);				freelist (ptr);				free (ptr);				return;			}			else { 				errorstack = cons (prev, sCONS, cdr(ptr));				freesdata (car(ptr));				free ((list *)car(ptr));				return;			}		}		ptr = (list *)cdr(ptr);	}}char *get_error_desc (char *funcname) {	list *ptr = errorstack;	while (ptr) {		if (strcmp((char *)car((list *)car(ptr)->data)->data, funcname) == 0) {			return (char *)car(cdr((list *)car(ptr)->data))->data;		}		ptr = cdr(ptr);	}	printf ("Error: in get_error_desc: no errors for function %s\n", funcname);	exit (ERROR_ERROR); /* error wasn't found, error! */}unsigned int errorcount (char *funcname) {	list *ptr = errorstack;	int ans = 0;	while (ptr) {		if (strcmp((char *)car((list *)car(ptr)->data)->data, funcname) == 0) {			ans++;		}		ptr = cdr (ptr);	}	return ans;}void printerror (char *funcname) {	printf ("Error in %s: %s\n", funcname, get_error_desc (funcname));}void malloc_error (char *f) {	printf ("Error in %s: malloc error, out of memory?", f);	exit (-1);}/***************** SDATA.H ***************/#ifndef SDATA_INCLUDED#define SDATA_INCLUDED#include "bignum.h"/* Definitions */typedef enum S_type { sNUMBER, sSYMBOL, sCONS } S_type;typedef struct {	S_type tag;	void *data;} sdata;typedef struct list list;/* lists */sdata *car (list *);list *cdr (list *);list *cons (void *, S_type, list *); list *reverse (list *);unsigned int length (list *);void freelist (list *);void printlist (list *);/* sdata */void printsdata (sdata *);void freesdata (sdata *);				#endif /* SDATA_INCLUDED *//***************** BIGNUM.H ***************/#ifndef BIGNUM_INCLUDED#define BIGNUM_INCLUDED/* boring things*/void *bn_create (char *, int, int);void *bn_copy (void *);void freebn (void *);/* basic arithmetic */void bn_negate (void *);void bn_add (void *, void *);void bn_multiply (void *, void *);void bn_divide (void *, void *);void bn_expt (void *, void *);/* comparison */int bn_equal (void *, void*);int bn_lessthan (void *, void*);int bn_lessthanequal (void *, void*);int bn_greaterthan (void *, void*);int bn_greaterthanequal (void *, void*);/* other math */void bn_abs (void *);void bn_acos (void *);void bn_add1 (void *);void bn_angle (void *);void bn_asin (void *);void bn_atan (void *);void bn_ceiling (void *);void bn_conjugate (void *);void bn_cos (void *);// void bn_cosh (void *);void bn_denominator (void *);int bn_even (void *);void bn_exact_to_inexact (void *);void bn_exp (void *);void bn_floor (void *);void bn_gcd (void *, void *);void bn_imagpart (void *);void bn_inexact_to_exact (void *);void bn_lcm (void *);void bn_log (void *);void bn_magnitude (void *);void bn_makepolar (void *, void *);void bn_max (void *, void *);void bn_min (void *, void *);void bn_modulo (void *, void *);int bn_negative (void *);char *bn_numbertostring (void *);void bn_numerator (void *);int bn_odd (void *);int bn_positive (void *);void bn_quotient (void *, void *);void bn_realpart (void *);void bn_remainder (void *, void *);void bn_round (void *);void bn_sgn (void *);void bn_sin (void *);// void bn_sinh (void *);void bn_sqrt (void *);void bn_sub1 (void *);void bn_tan (void *);int bn_zero (void *);/* type predicates */int bn_exact (void *);int bn_inexact (void *);int bn_integer (void *);int bn_rational (void *);int bn_real (void *);#endif // BIGNUM_INCLUDED/***************** PARSE.H ***************/#ifndef PARSE_INCLUDED#define PARSE_INCLUDED#include "sdata.h"list *parse (char *);#endif // PARSE_INCLUDED/***************** EVAL.H ***************/#ifndef EVAL_INCLUDED#define EVAL_INCLUDED#include "sdata.h"sdata *run (list *);#endif /* EVAL_INCLUDED *//***************** ERRORS.H ***************/#ifndef ERRORS_INCLUDED#define ERRORS_INCLUDEDvoid adderror (char *, char *);unsigned int errorcount (char *);char *geterrordesc (char *);void poperror (char *);void printerror (char *);void malloc_error (char *);#define MALLOC_ERROR 0#define PARSE_ERROR 1#define EVAL_ERROR 2#define ERROR_ERROR 3#endif // ERRORS_INCLUDED