[net.sources] Apple Aztec C source - dc.c

dcn@ihuxl.UUCP (Dave Newkirk) (11/17/83)

/* dc - desk calculator
 *
 * Adapted from C Reference Manual
 * (must be linked to flt.lib)
 *
 * Supports +,-,* and / on integer and
 * floating point. Commands include:
 *	d - duplicate top of stack (TOS)
 *	p - print TOS
 *	f - print all stack entries
 *	c - clear stack
 *	q - quit
 */

#include "stdio.h"	/* contains extra defines for EOF, etc */

#define MAXOP  20
#define NUMBER '0'
#define TOOBIG '9'

main()
{
	int type ;
	char s[MAXOP] ;
	double op2, atof(), pop(), push() ;

	while( (type = getop(s,MAXOP)) != EOF )
		switch( type ) {
			case NUMBER:
				push( atof(s) ) ;
				break ;
			case '+':
				push( pop() + pop() ) ;
				break ;
			case '*':
				push( pop() * pop() ) ;
				break ;
			case '-':
				op2 = pop() ;
				push( pop() - op2 ) ;
				break ;
			case '/':
				op2 = pop() ;
				if( op2 != 0.0 )
					push( pop() / op2 ) ;
				else
					fprintf(stderr, "dc: divide by zero\n");
				break ;
			case 'd':
				push( push( pop() ) ) ;
				break ;
			case 'p':
				top() ;
				break ;
			case 'f':
				print() ;
				break ;
			case 'c':
				empty() ;
				break ;
			case 'q':
				printf("\n") ;
				exit(0) ;
			case TOOBIG:
				fprintf(stderr, "dc: %.20s is too long\n", s ) ;
				break ;
			default:
				fprintf(stderr, "dc: unknown commnd %c\n", type ) ;
				break ;
		}

} /* end main */

/* stack declarations */

#define STACKSIZE 100

int sp = 0 ;
double stack[STACKSIZE] ;

/* push - push new value on stack */

double push(f)
double f ;
{
	if( sp < STACKSIZE )
		return stack[sp++] = f ;
	else {
		printf("dc: stack is full\n");
		empty() ;
		return 0 ;
	}

} /* end push */

/* pop - return top of stack */

double pop()
{
	if( sp > 0 )
		return stack[--sp] ;
	else {
		printf("dc: stack empty\n") ;
		empty() ;
		return 0 ;
	}

} /* end pop */

/* empty - empty the stack */

empty()
{
	sp = 0 ;
}

/* top - print top stack entry */

top()
{
	int i ;
	double d ;

	if( sp <= 0 )
		return ;
	d = stack[ sp-1 ] ;
	i = d ;
	if( ((double) i) == d )
		printf("%c%d\n", TAB, i ) ;
	else
		printf("%c%f\n", TAB, d ) ;
}

/* print - show all stack entries */

print()
{
	int i, s ;
	double d ;

	for( s=sp-1 ; s >= 0 ; s-- ) {
		d = stack[ s ] ;
		i = d ;
		if( ((double) i) == d )
			printf("%c%d\n", TAB, i ) ;
		else
			printf("%c%f\n", TAB, d ) ;
	}
}

/* getop - get next operator, operand */

getop( s, limit )
char s[] ;
int limit ;
{
	int i, c, oldc ;

	i = 0 ;
	do
		c = agetc(stdin) ;
		while( c == BLANK || c == TAB || c == NL ) ;

	i = 0 ;
	if( c != '.' && c != '-' && c != '+' && (c < '0' || c > '9') )
		return c ;

	if( c == '+' || c == '-' ) {
		oldc = c ;
		c = agetc(stdin) ;
		if( c != '.' && (c < '0' || c > '9') ) {
			ungetc( c, stdin ) ;
			return oldc ;
		}
		else
			s[i++] = oldc ;
	}
	s[i++] = c ;
	for( ; (c = agetc(stdin)) >= '0' && c <= '9' ; i++ )
		if( i < limit )
			s[i] = c ;
	if( c == '.' ) {
		if( i < limit )
			s[i] = c ;
		for( i++ ; (c = agetc(stdin)) >= '0' && c <= '9' ; i++ )
			if( i < limit )
				s[i] = c ;
	}
	if( i < limit ) {
		ungetc( c, stdin ) ;
		s[i] = EOS ;
		return NUMBER ;
	}
	else {
		while( c != NL && c != EOF )
			c = agetc(stdin) ;
		s[limit-1] = EOS ;
		return TOOBIG ;
	}

} /* end getop */