diff options
Diffstat (limited to 'contrib/bc/dc/stack.c')
| -rw-r--r-- | contrib/bc/dc/stack.c | 494 |
1 files changed, 0 insertions, 494 deletions
diff --git a/contrib/bc/dc/stack.c b/contrib/bc/dc/stack.c deleted file mode 100644 index 1d8a9bf73133..000000000000 --- a/contrib/bc/dc/stack.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * implement stack functions for dc - * - * Copyright (C) 1994, 1997, 1998 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. - * 59 Temple Place, Suite 330 - * Boston, MA 02111 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_array *array; /* opaque */ - 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->array = NULL; - 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 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, - * 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; -} - -/* 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); - } -} - - -/* 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); - dc_array_free(n->array); - 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 if (r->value.dc_type == DC_UNINITIALIZED) - ; - 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; - dc_array_free(r->array); - 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; - dc_array_free(r->array); - 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_p is DC_TOSS, 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_p)) - dc_data value DC_DECLSEP - dc_discard discard_p DC_DECLEND -{ - int length; - - if (value.dc_type == DC_NUMBER){ - length = dc_numlen(value.v.number); - if (discard_p == DC_TOSS) - dc_free_num(&value.v.number); - } else if (value.dc_type == DC_STRING) { - length = dc_strlen(value.v.string); - if (discard_p == DC_TOSS) - 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, DC_WITHNL, DC_KEEP); -} - - - - -/* get the current array head for the named array */ -struct dc_array * -dc_get_stacked_array DC_DECLARG((array_id)) - int array_id DC_DECLEND -{ - dc_list *r = dc_register[regmap(array_id)]; - return r ? r->array : NULL; -} - -/* set the current array head for the named array */ -void -dc_set_stacked_array DC_DECLARG((array_id, new_head)) - int array_id DC_DECLSEP - struct dc_array *new_head DC_DECLEND -{ - dc_list *r; - - array_id = regmap(array_id); - r = dc_register[array_id]; - if ( ! r ) - r = dc_register[array_id] = dc_alloc(); - r->array = new_head; -} |
