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.26;	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
@/* 
 * implement stack functions for dc
 *
 * 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 module is the only one that knows what stacks (both the
 * regular evaluation stack and the named register stacks)
 * look like.
 */

#include "config.h"

#include <stdio.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "dc.h"
#include "dc-proto.h"
#include "dc-regdef.h"

/* an oft-used error message: */
#define Empty_Stack	fprintf(stderr, "%s: stack empty\n", progname)


/* simple linked-list implementaion suffices: */
struct dc_list {
	dc_data value;
	struct dc_list *link;
};
typedef struct dc_list dc_list;

/* the anonymous evaluation stack */
static dc_list *dc_stack=NULL;

/* the named register stacks */
static dc_list *dc_register[DC_REGCOUNT];


/* allocate a new dc_list item */
static dc_list *
dc_alloc DC_DECLVOID()
{
	dc_list *result;

	result = dc_malloc(sizeof *result);
	result->value.dc_type = DC_UNINITIALIZED;
	result->link = NULL;
	return result;
}


/* check that there are two numbers on top of the stack,
 * then call op with the popped numbers.  Construct a dc_data
 * value from the dc_num returned by op and push it
 * on the stack.
 * If the op call doesn't return DC_SUCCESS, then leave the stack
 * unmodified.
 */
void
dc_binop DC_DECLARG((op, kscale))
	int (*op)DC_PROTO((dc_num, dc_num, int, dc_num *)) DC_DECLSEP
	int kscale DC_DECLEND
{
	dc_data a;
	dc_data b;
	dc_data r;

	if (!dc_stack || !dc_stack->link){
		Empty_Stack;
		return;
	}
	if (dc_stack->value.dc_type!=DC_NUMBER
			|| dc_stack->link->value.dc_type!=DC_NUMBER){
		fprintf(stderr, "%s: non-numeric value\n", progname);
		return;
	}
	(void)dc_pop(&b);
	(void)dc_pop(&a);
	if ((*op)(a.v.number, b.v.number, kscale, &r.v.number) == DC_SUCCESS){
		r.dc_type = DC_NUMBER;
		dc_push(r);
		dc_free_num(&a.v.number);
		dc_free_num(&b.v.number);
	}else{
		/* op failed; restore the stack */
		dc_push(a);
		dc_push(b);
	}
}

/* check that there are two numbers on top of the stack,
 * then call dc_compare with the popped numbers.
 * Return negative, zero, or positive based on the ordering
 * of the two numbers.
 */
int
dc_cmpop DC_DECLVOID()
{
	int result;
	dc_data a;
	dc_data b;

	if (!dc_stack || !dc_stack->link){
		Empty_Stack;
		return 0;
	}
	if (dc_stack->value.dc_type!=DC_NUMBER
			|| dc_stack->link->value.dc_type!=DC_NUMBER){
		fprintf(stderr, "%s: non-numeric value\n", progname);
		return 0;
	}
	(void)dc_pop(&b);
	(void)dc_pop(&a);
	result = dc_compare(b.v.number, a.v.number);
	dc_free_num(&a.v.number);
	dc_free_num(&b.v.number);
	return result;
}


/* initialize the register stacks to their initial values */
void
dc_register_init DC_DECLVOID()
{
	int i;

	for (i=0; i<DC_REGCOUNT; ++i)
		dc_register[i] = NULL;
}

/* clear the evaluation stack */
void
dc_clear_stack DC_DECLVOID()
{
	dc_list *n;
	dc_list *t;

	for (n=dc_stack; n; n=t){
		t = n->link;
		if (n->value.dc_type == DC_NUMBER)
			dc_free_num(&n->value.v.number);
		else if (n->value.dc_type == DC_STRING)
			dc_free_str(&n->value.v.string);
		else
			dc_garbage("in stack", -1);
		free(n);
	}
	dc_stack = NULL;
}

/* push a value onto the evaluation stack */
void
dc_push DC_DECLARG((value))
	dc_data value DC_DECLEND
{
	dc_list *n = dc_alloc();

	if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING)
		dc_garbage("in data being pushed", -1);
	n->value = value;
	n->link = dc_stack;
	dc_stack = n;
}

/* push a value onto the named register stack */
void
dc_register_push DC_DECLARG((stackid, value))
	int stackid DC_DECLSEP
	dc_data value DC_DECLEND
{
	dc_list *n = dc_alloc();

	stackid = regmap(stackid);
	n->value = value;
	n->link = dc_register[stackid];
	dc_register[stackid] = n;
}

/* set *result to the value on the top of the evaluation stack */
/* The caller is responsible for duplicating the value if it
 * is to be maintained as anything more than a transient identity.
 *
 * DC_FAIL is returned if the stack is empty (and *result unchanged),
 * DC_SUCCESS is returned otherwise
 */
int
dc_top_of_stack DC_DECLARG((result))
	dc_data *result DC_DECLEND
{
	if (!dc_stack){
		Empty_Stack;
		return DC_FAIL;
	}
	if (dc_stack->value.dc_type!=DC_NUMBER
			&& dc_stack->value.dc_type!=DC_STRING)
		dc_garbage("at top of stack", -1);
	*result = dc_stack->value;
	return DC_SUCCESS;
}

/* set *result to a dup of the value on the top of the named register stack */
/*
 * DC_FAIL is returned if the named stack is empty (and *result unchanged),
 * DC_SUCCESS is returned otherwise
 */
int
dc_register_get DC_DECLARG((regid, result))
	int regid DC_DECLSEP
	dc_data *result DC_DECLEND
{
	dc_list *r;

	regid = regmap(regid);
	r = dc_register[regid];
	if ( ! r ){
		fprintf(stderr, "%s: register ", progname);
		dc_show_id(stderr, regid, " is empty\n");
		return DC_FAIL;
	}
	*result = dc_dup(r->value);
	return DC_SUCCESS;
}

/* set the top of the named register stack to the indicated value */
/* If the named stack is empty, craft a stack entry to enter the
 * value into.
 */
void
dc_register_set DC_DECLARG((regid, value))
	int regid DC_DECLSEP
	dc_data value DC_DECLEND
{
	dc_list *r;

	regid = regmap(regid);
	r = dc_register[regid];
	if ( ! r )
		dc_register[regid] = dc_alloc();
	else if (r->value.dc_type == DC_NUMBER)
		dc_free_num(&r->value.v.number);
	else if (r->value.dc_type == DC_STRING)
		dc_free_str(&r->value.v.string);
	else
		dc_garbage("", regid);
	dc_register[regid]->value = value;
}

/* pop from the evaluation stack
 *
 * DC_FAIL is returned if the stack is empty (and *result unchanged),
 * DC_SUCCESS is returned otherwise
 */
int
dc_pop DC_DECLARG((result))
	dc_data *result DC_DECLEND
{
	dc_list *r;

	r = dc_stack;
	if (!r){
		Empty_Stack;
		return DC_FAIL;
	}
	if (r->value.dc_type!=DC_NUMBER && r->value.dc_type!=DC_STRING)
		dc_garbage("at top of stack", -1);
	*result = r->value;
	dc_stack = r->link;
	free(r);
	return DC_SUCCESS;
}

/* pop from the named register stack
 *
 * DC_FAIL is returned if the named stack is empty (and *result unchanged),
 * DC_SUCCESS is returned otherwise
 */
int
dc_register_pop DC_DECLARG((stackid, result))
	int stackid DC_DECLSEP
	dc_data *result DC_DECLEND
{
	dc_list *r;

	stackid = regmap(stackid);
	r = dc_register[stackid];
	if (!r){
		fprintf(stderr, "%s: stack register ", progname);
		dc_show_id(stderr, stackid, " is empty\n");
		return DC_FAIL;
	}
	if (r->value.dc_type!=DC_NUMBER && r->value.dc_type!=DC_STRING)
		dc_garbage(" stack", stackid);
	*result = r->value;
	dc_register[stackid] = r->link;
	free(r);
	return DC_SUCCESS;
}


/* tell how many entries are currently on the evaluation stack */
int
dc_tell_stackdepth DC_DECLVOID()
{
	dc_list *n;
	int depth=0;

	for (n=dc_stack; n; n=n->link)
		++depth;
	return depth;
}


/* return the length of the indicated data value;
 * if discard_flag is true, the deallocate the value when done
 *
 * The definition of a datum's length is deligated to the
 * appropriate module.
 */
int
dc_tell_length DC_DECLARG((value, discard_flag))
	dc_data value DC_DECLSEP
	dc_boolean discard_flag DC_DECLEND
{
	int length;

	if (value.dc_type == DC_NUMBER){
		length = dc_numlen(value.v.number);
		if (discard_flag == DC_TRUE)
			dc_free_num(&value.v.number);
	} else if (value.dc_type == DC_STRING) {
		length = dc_strlen(value.v.string);
		if (discard_flag == DC_TRUE)
			dc_free_str(&value.v.string);
	} else {
		dc_garbage("in tell_length", -1);
		/*NOTREACHED*/
		length = 0;	/*just to suppress spurious compiler warnings*/
	}
	return length;
}



/* print out all of the values on the evaluation stack */
void
dc_printall DC_DECLARG((obase))
	int obase DC_DECLEND
{
	dc_list *n;

	for (n=dc_stack; n; n=n->link)
		dc_print(n->value, obase);
}
@


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.
a107 43
 * then call op with the popped numbers.  Construct two dc_data
 * values from the dc_num's returned by op and push them
 * on the stack.
 * If the op call doesn't return DC_SUCCESS, then leave the stack
 * unmodified.
 */
void
dc_binop2 DC_DECLARG((op, kscale))
	int (*op)DC_PROTO((dc_num, dc_num, int, dc_num *, dc_num *)) DC_DECLSEP
	int kscale DC_DECLEND
{
	dc_data a;
	dc_data b;
	dc_data r1;
	dc_data r2;

	if (!dc_stack || !dc_stack->link){
		Empty_Stack;
		return;
	}
	if (dc_stack->value.dc_type!=DC_NUMBER
			|| dc_stack->link->value.dc_type!=DC_NUMBER){
		fprintf(stderr, "%s: non-numeric value\n", progname);
		return;
	}
	(void)dc_pop(&b);
	(void)dc_pop(&a);
	if ((*op)(a.v.number, b.v.number, kscale,
								&r1.v.number, &r2.v.number) == DC_SUCCESS){
		r1.dc_type = DC_NUMBER;
		dc_push(r1);
		r2.dc_type = DC_NUMBER;
		dc_push(r2);
		dc_free_num(&a.v.number);
		dc_free_num(&b.v.number);
	}else{
		/* op failed; restore the stack */
		dc_push(a);
		dc_push(b);
	}
}

/* check that there are two numbers on top of the stack,
a133 45
}

/* check that there are three numbers on top of the stack,
 * then call op with the popped numbers.  Construct a dc_data
 * value from the dc_num returned by op and push it
 * on the stack.
 * If the op call doesn't return DC_SUCCESS, then leave the stack
 * unmodified.
 */
void
dc_triop DC_DECLARG((op, kscale))
	int (*op)DC_PROTO((dc_num, dc_num, dc_num, int, dc_num *)) DC_DECLSEP
	int kscale DC_DECLEND
{
	dc_data a;
	dc_data b;
	dc_data c;
	dc_data r;

	if (!dc_stack || !dc_stack->link || !dc_stack->link->link){
		Empty_Stack;
		return;
	}
	if (dc_stack->value.dc_type!=DC_NUMBER
			|| dc_stack->link->value.dc_type!=DC_NUMBER
			|| dc_stack->link->link->value.dc_type!=DC_NUMBER){
		fprintf(stderr, "%s: non-numeric value\n", progname);
		return;
	}
	(void)dc_pop(&c);
	(void)dc_pop(&b);
	(void)dc_pop(&a);
	if ((*op)(a.v.number, b.v.number, c.v.number,
				kscale, &r.v.number) == DC_SUCCESS){
		r.dc_type = DC_NUMBER;
		dc_push(r);
		dc_free_num(&a.v.number);
		dc_free_num(&b.v.number);
		dc_free_num(&c.v.number);
	}else{
		/* op failed; restore the stack */
		dc_push(a);
		dc_push(b);
		dc_push(c);
	}
@
