head	1.2;
access;
symbols
	perseant-exfatfs-base-20250801:1.2
	perseant-exfatfs-base-20240630:1.2
	cjep_sun2x:1.2.0.44
	cjep_sun2x-base:1.2
	cjep_staticlib_x-base1:1.2
	cjep_staticlib_x:1.2.0.42
	cjep_staticlib_x-base:1.2
	phil-wifi-20200421:1.2
	phil-wifi-20200411:1.2
	phil-wifi-20200406:1.2
	pgoyette-compat-merge-20190127:1.2
	pgoyette-compat-20190127:1.2
	pgoyette-compat-20190118:1.2
	pgoyette-compat-1226:1.2
	pgoyette-compat-1126:1.2
	pgoyette-compat-1020:1.2
	pgoyette-compat-0930:1.2
	pgoyette-compat-0906:1.2
	pgoyette-compat-0728:1.2
	pgoyette-compat-0625:1.2
	pgoyette-compat-0521:1.2
	pgoyette-compat-0502:1.2
	pgoyette-compat-0422:1.2
	pgoyette-compat-0415:1.2
	pgoyette-compat-0407:1.2
	pgoyette-compat-0330:1.2
	pgoyette-compat-0322:1.2
	pgoyette-compat-0315:1.2
	pgoyette-compat:1.2.0.40
	pgoyette-compat-base:1.2
	perseant-stdc-iso10646:1.2.0.38
	perseant-stdc-iso10646-base:1.2
	prg-localcount2-base3:1.2
	prg-localcount2-base2:1.2
	prg-localcount2-base1:1.2
	prg-localcount2:1.2.0.36
	prg-localcount2-base:1.2
	pgoyette-localcount-20170426:1.2
	bouyer-socketcan-base1:1.2
	pgoyette-localcount-20170320:1.2
	bouyer-socketcan:1.2.0.34
	bouyer-socketcan-base:1.2
	pgoyette-localcount-20170107:1.2
	pgoyette-localcount-20161104:1.2
	localcount-20160914:1.2
	pgoyette-localcount-20160806:1.2
	pgoyette-localcount-20160726:1.2
	pgoyette-localcount:1.2.0.32
	pgoyette-localcount-base:1.2
	netbsd-5-2-3-RELEASE:1.2
	netbsd-5-1-5-RELEASE:1.2
	yamt-pagecache-base9:1.2
	yamt-pagecache-tag8:1.2
	tls-earlyentropy:1.2.0.28
	tls-earlyentropy-base:1.2
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.2
	riastradh-drm2-base3:1.2
	netbsd-5-2-2-RELEASE:1.2
	netbsd-5-1-4-RELEASE:1.2
	netbsd-5-2-1-RELEASE:1.2
	netbsd-5-1-3-RELEASE:1.2
	agc-symver:1.2.0.30
	agc-symver-base:1.2
	tls-maxphys-base:1.2
	yamt-pagecache-base8:1.2
	netbsd-5-2:1.2.0.26
	yamt-pagecache-base7:1.2
	netbsd-5-2-RELEASE:1.2
	netbsd-5-2-RC1:1.2
	yamt-pagecache-base6:1.2
	yamt-pagecache-base5:1.2
	yamt-pagecache-base4:1.2
	netbsd-5-1-2-RELEASE:1.2
	netbsd-5-1-1-RELEASE:1.2
	yamt-pagecache-base3:1.2
	yamt-pagecache-base2:1.2
	yamt-pagecache:1.2.0.24
	yamt-pagecache-base:1.2
	bouyer-quota2-nbase:1.2
	bouyer-quota2:1.2.0.22
	bouyer-quota2-base:1.2
	matt-nb5-pq3:1.2.0.20
	matt-nb5-pq3-base:1.2
	netbsd-5-1:1.2.0.18
	netbsd-5-1-RELEASE:1.2
	netbsd-5-1-RC4:1.2
	netbsd-5-1-RC3:1.2
	netbsd-5-1-RC2:1.2
	netbsd-5-1-RC1:1.2
	netbsd-5-0-2-RELEASE:1.2
	netbsd-5-0-1-RELEASE:1.2
	jym-xensuspend-nbase:1.2
	netbsd-5-0:1.2.0.16
	netbsd-5-0-RELEASE:1.2
	netbsd-5-0-RC4:1.2
	netbsd-5-0-RC3:1.2
	netbsd-5-0-RC2:1.2
	jym-xensuspend:1.2.0.14
	jym-xensuspend-base:1.2
	netbsd-5-0-RC1:1.2
	netbsd-5:1.2.0.12
	netbsd-5-base:1.2
	mjf-devfs2:1.2.0.10
	mjf-devfs2-base:1.2
	yamt-pf42-base4:1.2
	yamt-pf42-base3:1.2
	hpcarm-cleanup-nbase:1.2
	yamt-pf42-base2:1.2
	yamt-pf42:1.2.0.8
	yamt-pf42-base:1.2
	keiichi-mipv6:1.2.0.6
	keiichi-mipv6-base:1.2
	cube-autoconf:1.2.0.4
	cube-autoconf-base:1.2
	hpcarm-cleanup:1.2.0.2
	hpcarm-cleanup-base:1.2
	netbsd-1-3-PATCH003:1.1.1.2
	netbsd-1-3-PATCH003-CANDIDATE2:1.1.1.2
	netbsd-1-3-PATCH003-CANDIDATE1:1.1.1.2
	netbsd-1-3-PATCH003-CANDIDATE0:1.1.1.2
	netbsd-1-3-PATCH002:1.1.1.2
	netbsd-1-3-PATCH001:1.1.1.2
	netbsd-1-3-RELEASE:1.1.1.2
	netbsd-1-3-BETA:1.1.1.2
	netbsd-1-3:1.1.1.2.0.2
	netbsd-1-3-base:1.1.1.2
	fsf-bc-1-04:1.1.1.2
	fsf:1.1.1
	netbsd-1-2-PATCH001:1.1.1.1
	netbsd-1-2-RELEASE:1.1.1.1
	netbsd-1-2-BETA:1.1.1.1
	netbsd-1-2-base:1.1.1.1
	netbsd-1-2:1.1.1.1.0.6
	netbsd-1-1-PATCH001:1.1.1.1
	netbsd-1-1-RELEASE:1.1.1.1
	netbsd-1-1:1.1.1.1.0.2
	netbsd-1-1-base:1.1.1.1
	dc-1-03:1.1.1.1
	GNU-dc-1-03:1.1.1;
locks; strict;
comment	@ * @;


1.2
date	99.01.16.05.57.51;	author simonb;	state dead;
branches;
next	1.1;

1.1
date	94.12.01.04.26.46;	author phil;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	94.12.01.04.26.47;	author phil;	state Exp;
branches;
next	1.1.1.2;

1.1.1.2
date	97.04.29.00.34.29;	author phil;	state Exp;
branches;
next	;


desc
@@


1.2
log
@Update bc to 1.05a and dc to 1.2, which source in src/gnu/dist/bc.
@
text
@/* 
 * evaluate the dc language, from a FILE* or a string
 *
 * Copyright (C) 1994 Free Software Foundation, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can either send email to this
 * program's author (see below) or write to: The Free Software Foundation,
 * Inc.; 675 Mass Ave. Cambridge, MA 02139, USA.
 */

/* This is the only module which knows about the dc input language */

#include "config.h"

#include <stdio.h>
#ifdef HAVE_STRING_H
# include <string.h>	/* memchr */
#else
# ifdef HAVE_MEMORY_H
#  include <memory.h>	/* memchr, maybe */
# else
#  ifdef HAVE_STRINGS_H
#   include <strings.h>	/* memchr, maybe */
#  endif
#endif
#endif
#include "dc.h"
#include "dc-proto.h"

typedef enum {
	DC_OKAY,		/* no further intervention needed for this command */
	DC_EATONE,		/* caller needs to eat the lookahead char */
	DC_QUIT,		/* quit out of unwind_depth levels of evaluation */

	/* with the following return values, the caller does not have to 
	 * fret about rescan_stdin's value
	 */
	DC_INT,			/* caller needs to parse a dc_num from input stream */
	DC_STR,			/* caller needs to parse a dc_str from input stream */
	DC_SYSTEM,		/* caller needs to run a system() on next input line */
	DC_COMMENT,		/* caller needs to skip to the next input line */

	DC_EOF_ERROR	/* unexpected end of input; abort current eval */
} dc_status;

static int dc_ibase=10;		/* input base, 2 <= dc_ibase <= DC_IBASE_MAX */
static int dc_obase=10;		/* output base, 2 <= dc_obase */
static int dc_scale=0;		/* scale (see user documentaton) */

/* forward reference */
static dc_status dc_evalstr DC_PROTO((dc_data));

/* for Quitting evaluations */
static int unwind_depth=0;

/* if true, active Quit will not exit program */
static dc_boolean unwind_noexit=DC_FALSE;

/* if true, stdin has been mucked with, dc_evalfile() needs to resyncronize */
static dc_boolean rescan_stdin=DC_FALSE;


/* input_fil and input_str are passed as arguments to dc_getnum */

/* used by the input_* functions: */
static FILE *input_fil_fp;
static const char *input_str_string;

/* Since we have a need for two characters of pushback, and
 * ungetc() only guarantees one, we place the second pushback here
 */
static int input_pushback;

/* passed as an argument to dc_getnum */
static int
input_fil DC_DECLVOID()
{
	if (input_pushback != EOF){
		int c = input_pushback;
		input_pushback = EOF;
		return c;
	}
	return getc(input_fil_fp);
}

/* passed as an argument to dc_getnum */
static int
input_str DC_DECLVOID()
{
	if (!*input_str_string)
		return EOF;
	return *input_str_string++;
}



/* takes a string and evals it; frees the string when done */
/* Wrapper around dc_evalstr to avoid duplicating the free call
 * at all possible return points.
 */
static dc_status
dc_eval_and_free_str DC_DECLARG((string))
	dc_data string DC_DECLEND
{
	dc_status status;

	status = dc_evalstr(string);
	if (string.dc_type == DC_STRING)
		dc_free_str(&string.v.string);
	return status;
}


/* dc_func does the grunt work of figuring out what each input
 * character means; used by both dc_evalstr and dc_evalfile
 *
 * c -> the "current" input character under consideration
 * peekc -> the lookahead input character
 */
static dc_status
dc_func DC_DECLARG((c, peekc))
	int c DC_DECLSEP
	int peekc DC_DECLEND
{
	/* we occasionally need these for temporary data */
	/* Despite the GNU coding standards, it is much easier
	 * to have these decared once here, since this function
	 * is just one big switch statement.
	 */
	dc_data datum;
	int tmpint;

	switch (c){
	case '_': case '.':
	case '0': case '1': case '2': case '3':
	case '4': case '5': case '6': case '7':
	case '8': case '9': case 'A': case 'B':
	case 'C': case 'D': case 'E': case 'F':
		return DC_INT;
	case ' ':
	case '\t':
	case '\n':
		/* standard command separators */
		break;

	case '+':	/* add top two stack elements */
		dc_binop(dc_add, dc_scale);
		break;
	case '-':	/* subtract top two stack elements */
		dc_binop(dc_sub, dc_scale);
		break;
	case '*':	/* multiply top two stack elements */
		dc_binop(dc_mul, dc_scale);
		break;
	case '/':	/* divide top two stack elements */
		dc_binop(dc_div, dc_scale);
		break;
	case '%':
		/* take the remainder from  division of the top two stack elements */
		dc_binop(dc_rem, dc_scale);
		break;
	case '^':	/* exponientiation of the top two stack elements */
		dc_binop(dc_exp, dc_scale);
		break;
	case '<':
		/* eval register named by peekc if
		 * less-than holds for top two stack elements
		 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_cmpop() <  0)
			if (dc_register_get(peekc, &datum) == DC_SUCCESS)
				if (dc_eval_and_free_str(datum) == DC_QUIT)
					return DC_QUIT;
		return DC_EATONE;
	case '=':
		/* eval register named by peekc if
		 * equal-to holds for top two stack elements
		 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_cmpop() == 0)
			if (dc_register_get(peekc, &datum) == DC_SUCCESS)
				if (dc_eval_and_free_str(datum) == DC_QUIT)
					return DC_QUIT;
		return DC_EATONE;
	case '>':
		/* eval register named by peekc if
		 * greater-than holds for top two stack elements
		 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_cmpop()  > 0)
			if (dc_register_get(peekc, &datum) == DC_SUCCESS)
				if (dc_eval_and_free_str(datum) == DC_QUIT)
					return DC_QUIT;
		return DC_EATONE;
	case '?':	/* read a lnie from standard-input and eval it */
		for (c=peekc; c=='\n'; c=getc(stdin))
			;
		ungetc(c, stdin);
		if (dc_eval_and_free_str(dc_readstring(stdin, '\n', '\n')) == DC_QUIT)
			return DC_QUIT;
		rescan_stdin = DC_TRUE;
		return DC_OKAY;
	case '[':	/* read to balancing ']' into a dc_str */
		return DC_STR;
	case '!':	/* read to newline and call system() on resulting string */
		return DC_SYSTEM;
	case '#':	/* comment; skip remainder of current line */
		return DC_COMMENT;

	case 'c':	/* clear whole stack */
		dc_clear_stack();
		break;
	case 'd':	/* duplicate the datum on the top of stack */
		if (dc_top_of_stack(&datum) == DC_SUCCESS)
			dc_push(dc_dup(datum));
		break;
	case 'f':	/* print list of all stack items */
		dc_printall(dc_obase);
		break;
	case 'i':	/* set input base to value on top of stack */
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = 0;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_num2int(datum.v.number, DC_TRUE);
			if ( ! (2 <= tmpint  &&  tmpint <= DC_IBASE_MAX) )
				fprintf(stderr,
						"%s: input base must be a number \
between 2 and %d (inclusive)\n",
						progname, DC_IBASE_MAX);
			else
				dc_ibase = tmpint;
		}
		break;
	case 'k':	/* set scale to value on top of stack */
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = -1;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_num2int(datum.v.number, DC_TRUE);
			if ( ! (tmpint >= 0) )
				fprintf(stderr,
						"%s: scale must be a nonnegative number\n",
						progname);
			else
				dc_scale = tmpint;
		}
		break;
	case 'l':	/* "load" -- push value on top of register stack named
				 * by peekc onto top of evaluation stack; does not
				 * modify the register stack
				 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_register_get(peekc, &datum) == DC_SUCCESS)
			dc_push(datum);
		return DC_EATONE;
	case 'o':	/* set output base to value on top of stack */
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = 0;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_num2int(datum.v.number, DC_TRUE);
			if ( ! (tmpint > 1) )
				fprintf(stderr,
						"%s: output base must be a number greater than 1\n",
						progname);
			else
				dc_obase = tmpint;
		}
		break;
	case 'p':	/* print the datum on the top of stack */
		if (dc_top_of_stack(&datum) == DC_SUCCESS)
			dc_print(datum, dc_obase);
		break;
	case 'q':	/* quit two levels of evaluation, posibly exiting program */
		unwind_depth = 2;
		unwind_noexit = DC_FALSE;
		return DC_QUIT;
	case 's':	/* "store" -- replace top of register stack named
				 * by peekc with the value popped from the top
				 * of the evaluation stack
				 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_pop(&datum) == DC_SUCCESS)
			dc_register_set(peekc, datum);
		return DC_EATONE;
	case 'v':	/* replace top of stack with its square root */
		if (dc_pop(&datum) == DC_SUCCESS){
			dc_num tmpnum;
			if (datum.dc_type != DC_NUMBER){
				fprintf(stderr,
						"%s: square root of nonnumeric attempted\n",
						progname);
			}else if (dc_sqrt(datum.v.number, dc_scale, &tmpnum) == DC_SUCCESS){
				dc_free_num(&datum.v.number);
				datum.v.number = tmpnum;
				dc_push(datum);
			}
		}
		break;
	case 'x':	/* eval the datum popped from top of stack */
		if (dc_pop(&datum) == DC_SUCCESS){
			if (datum.dc_type == DC_STRING){
				if (dc_eval_and_free_str(datum) == DC_QUIT)
					return DC_QUIT;
			}else if (datum.dc_type == DC_NUMBER){
				dc_push(datum);
			}else{
				dc_garbage("at top of stack", -1);
			}
		}
		break;
	case 'z':	/* push the current stack depth onto the top of stack */
		dc_push(dc_int2data(dc_tell_stackdepth()));
		break;

	case 'I':	/* push the current input base onto the stack */
		dc_push(dc_int2data(dc_ibase));
		break;
	case 'K':	/* push the current scale onto the stack */
		dc_push(dc_int2data(dc_scale));
		break;
	case 'L':	/* pop a value off of register stack named by peekc
				 * and push it onto the evaluation stack
				 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_register_pop(peekc, &datum) == DC_SUCCESS)
			dc_push(datum);
		return DC_EATONE;
	case 'O':	/* push the current output base onto the stack */
		dc_push(dc_int2data(dc_obase));
		break;
	case 'P':	/* print the value popped off of top-of-stack;
				 * do not add a trailing newline
				 */
		if (dc_pop(&datum) == DC_SUCCESS){
			if (datum.dc_type == DC_STRING)
				dc_out_str(datum.v.string, DC_FALSE, DC_TRUE);
			else if (datum.dc_type == DC_NUMBER)
				dc_out_num(datum.v.number, dc_obase, DC_FALSE, DC_TRUE);
			else
				dc_garbage("at top of stack", -1);
		}
		break;
	case 'Q':	/* quit out of top-of-stack nested evals;
				 * pops value from stack;
				 * does not exit program (stops short if necessary)
				 */
		if (dc_pop(&datum) == DC_SUCCESS){
			unwind_depth = 0;
			unwind_noexit = DC_TRUE;
			if (datum.dc_type == DC_NUMBER)
				unwind_depth = dc_num2int(datum.v.number, DC_TRUE);
			if (unwind_depth > 0)
				return DC_QUIT;
			fprintf(stderr,
					"%s: Q command requires a positive number\n",
					progname);
		}
		break;
	case 'S':	/* pop a value off of the evaluation stack
				 * and push it onto the register stack named by peekc
				 */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_pop(&datum) == DC_SUCCESS)
			dc_register_push(peekc, datum);
		return DC_EATONE;
	case 'X':	/* replace the number on top-of-stack with its scale factor */
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = 0;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_tell_scale(datum.v.number, DC_TRUE);
			dc_push(dc_int2data(tmpint));
		}
		break;
	case 'Z':	/* replace the datum on the top-of-stack with its length */
		if (dc_pop(&datum) == DC_SUCCESS)
			dc_push(dc_int2data(dc_tell_length(datum, DC_TRUE)));
		break;

	case ':':	/* store into array */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = -1;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_num2int(datum.v.number, DC_TRUE);
			if (dc_pop(&datum) == DC_SUCCESS){
				if (tmpint < 0)
					fprintf(stderr,
							"%s: array index must be a nonnegative integer\n",
							progname);
				else
					dc_array_set(peekc, tmpint, datum);
			}
		}
		return DC_EATONE;
	case ';':	/* retreive from array */
		if (peekc == EOF)
			return DC_EOF_ERROR;
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = -1;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_num2int(datum.v.number, DC_TRUE);
			if (tmpint < 0)
				fprintf(stderr,
						"%s: array index must be a nonnegative integer\n",
						progname);
			else
				dc_push(dc_array_get(peekc, tmpint));
		}
		return DC_EATONE;

	default:	/* What did that user mean? */
		fprintf(stderr, "%s: ", progname);
		dc_show_id(stdout, c, " unimplemented\n");
		break;
	}
	return DC_OKAY;
}


/* takes a string and evals it */
static dc_status
dc_evalstr DC_DECLARG((string))
	dc_data string DC_DECLEND
{
	const char *s;
	const char *end;
	const char *p;
	size_t len;
	int c;
	int peekc;
	int count;

	if (string.dc_type != DC_STRING){
		fprintf(stderr,
				"%s: eval called with non-string argument\n",
				progname);
		return DC_OKAY;
	}
	s = dc_str2charp(string.v.string);
	end = s + dc_strlen(string.v.string);
	while (s < end){
		c = *(const unsigned char *)s++;
		peekc = EOF;
		if (s < end)
			peekc = *(const unsigned char *)s;
		switch (dc_func(c, peekc)){
		case DC_OKAY:
			break;
		case DC_EATONE:
			if (peekc != EOF)
				++s;
			break;
		case DC_QUIT:
			if (unwind_depth > 0){
				--unwind_depth;
				return DC_QUIT;
			}
			return DC_OKAY;

		case DC_INT:
			input_str_string = s - 1;
			dc_push(dc_getnum(input_str, dc_ibase, &peekc));
			s = input_str_string;
			if (peekc != EOF)
				--s;
			break;
		case DC_STR:
			count = 1;
			for (p=s; p<end && count>0; ++p)
				if (*p == ']')
					--count;
				else if (*p == '[')
					++count;
			len = p - s;
			dc_push(dc_makestring(s, len-1));
			s = p;
			break;
		case DC_SYSTEM:
			s = dc_system(s);
		case DC_COMMENT:
			s = memchr(s, '\n', (size_t)(end-s));
			if (!s)
				s = end;
			++s;
			break;

		case DC_EOF_ERROR:
			fprintf(stderr, "%s: unexpected EOS\n", progname);
			return DC_OKAY;
		}
	}
	return DC_OKAY;
}


/* This is the main function of the whole DC program.
 * Reads the file described by fp, calls dc_func to do
 * the dirty work, and takes care of dc_func's shortcomings.
 */
int
dc_evalfile DC_DECLARG((fp))
	FILE *fp DC_DECLEND
{
	int c;
	int peekc;
	dc_data datum;

	for (c=getc(fp); c!=EOF; c=peekc){
		peekc = getc(fp);
		rescan_stdin = DC_FALSE;
		switch (dc_func(c, peekc)){
		case DC_OKAY:
			if (rescan_stdin == DC_TRUE  &&  fp == stdin)
				peekc = getc(fp);
			break;
		case DC_EATONE:
			peekc = getc(fp);
			break;
		case DC_QUIT:
			if (unwind_noexit != DC_TRUE)
				return DC_SUCCESS;
			fprintf(stderr,
					"%s: Q command argument exceeded string execution depth\n",
					progname);
			if (rescan_stdin == DC_TRUE  &&  fp == stdin)
				peekc = getc(fp);
			break;

		case DC_INT:
			input_fil_fp = fp;
			input_pushback = c;
			ungetc(peekc, fp);
			dc_push(dc_getnum(input_fil, dc_ibase, &peekc));
			break;
		case DC_STR:
			ungetc(peekc, fp);
			datum = dc_readstring(fp, '[', ']');
			dc_push(datum);
			peekc = getc(fp);
			break;
		case DC_SYSTEM:
			ungetc(peekc, fp);
			datum = dc_readstring(stdin, '\n', '\n');
			(void)dc_system(dc_str2charp(datum.v.string));
			dc_free_str(&datum.v.string);
			peekc = getc(fp);
			break;
		case DC_COMMENT:
			while (peekc!=EOF && peekc!='\n')
				peekc = getc(fp);
			if (peekc != EOF)
				peekc = getc(fp);
			break;

		case DC_EOF_ERROR:
			fprintf(stderr, "%s: unexpected EOF\n", progname);
			return DC_FAIL;
		}
	}
	return DC_SUCCESS;
}
@


1.1
log
@Initial revision
@
text
@@


1.1.1.1
log
@Import of GNU dc (from bc-1.03).
@
text
@@


1.1.1.2
log
@Complete import of bc-1.04 by updating dc.
@
text
@d4 1
a4 1
 * Copyright (C) 1994, 1997 Free Software Foundation, Inc.
d42 1
a42 1
	DC_OKAY = DC_SUCCESS, /* no further intervention needed for this command */
d47 1
a47 1
	 * fret about stdin_lookahead's value
d61 3
d70 2
a71 5
/*
 * Used to synchronize lookahead on stdin for '?' command.
 * If set to EOF then lookahead is used up.
 */
static int stdin_lookahead=EOF;
d112 1
a112 1
static int
d138 1
a138 1
	 * to have these declared once here, since this function
d170 1
a170 1
		/* take the remainder from division of the top two stack elements */
a172 19
	case '~':
		/* Do division on the top two stack elements.  Return the
		 * quotient as next-to-top of stack and the remainder as
		 * top-of-stack.
		 */
		dc_binop2(dc_divrem, dc_scale);
		break;
	case '|':
		/* Consider the top three elements of the stack as (base, exp, mod),
		 * where mod is top-of-stack, exp is next-to-top, and base is
		 * second-from-top.  Mod must be non-zero and exp must be a
		 * non-negative integer.   Push the result of raising base to the exp
		 * power, reduced modulo mod.  If we had base in register b, exp in
		 * register e, and mod in register m then this is conceptually
		 * equivalent to "lble^lm%", but it is implemented in a more efficient
		 * manner, and can handle arbritrarily large values for exp.
		 */
		dc_triop(dc_modexp, dc_scale);
		break;
d209 4
a212 5
	case '?':	/* read a line from standard-input and eval it */
		if (stdin_lookahead != EOF){
			ungetc(stdin_lookahead, stdin);
			stdin_lookahead = EOF;
		}
d215 1
a223 15
	case 'a':	/* Convert top of stack to an ascii character. */
		if (dc_pop(&datum) == DC_SUCCESS){
			char tmps;
			if (datum.dc_type == DC_NUMBER){
				tmps = (char) dc_num2int(datum.v.number, DC_TRUE);
				dc_free_num(&datum.v.number);
			}else if (datum.dc_type == DC_STRING){
				tmps = *dc_str2charp(datum.v.string);
				dc_free_str(&datum.v.string);
			}else{
				dc_garbage("at top of stack", -1);
			}
			dc_push(dc_makestring(&tmps, 1));
		}
		break;
a290 11
	case 'r':	/* rotate (swap) the top two elements on the stack
				 */
		if (dc_pop(&datum) == DC_SUCCESS) {
			dc_data datum2;
			int two_status;
			two_status = dc_pop(&datum2);
			dc_push(datum);
			if (two_status == DC_SUCCESS)
				dc_push(datum2);
		}
		break;
d371 1
a371 1
					"%s: Q command requires a number >= 1\n",
a374 15
#if 0
	case 'R':	/* pop a value off of the evaluation stack,;
				 * rotate the top
				 remaining stack elements that many
				 * places forward (negative numbers mean rotate
				 * backward).
				 */
		if (dc_pop(&datum) == DC_SUCCESS){
			tmpint = 0;
			if (datum.dc_type == DC_NUMBER)
				tmpint = dc_num2int(datum.v.number, DC_TRUE);
			dc_stack_rotate(tmpint);
		}
		break;
#endif
d439 1
a439 1
int
d502 1
a502 2
			else
				++s;
a525 1
	stdin_lookahead = EOF;
d528 1
a528 6
		/*
		 * The following if() is the only place where ``stdin_lookahead''
		 * might be set to other than EOF:
		 */
		if (fp == stdin)
			stdin_lookahead = peekc;
d531 1
a531 1
			if (stdin_lookahead != peekc  &&  fp == stdin)
d539 1
a539 1
				return DC_FAIL;
d543 1
a543 1
			if (stdin_lookahead != peekc  &&  fp == stdin)
@
