summaryrefslogtreecommitdiff
path: root/dc/stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'dc/stack.c')
-rw-r--r--dc/stack.c109
1 files changed, 80 insertions, 29 deletions
diff --git a/dc/stack.c b/dc/stack.c
index 1d8a9bf..49422df 100644
--- a/dc/stack.c
+++ b/dc/stack.c
@@ -1,11 +1,12 @@
/*
* implement stack functions for dc
*
- * Copyright (C) 1994, 1997, 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1994, 1997, 1998, 2000, 2005, 2006, 2008, 2012, 2016
+ * 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)
+ * the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -14,12 +15,8 @@
* 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:
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * 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
@@ -41,7 +38,7 @@
#define Empty_Stack fprintf(stderr, "%s: stack empty\n", progname)
-/* simple linked-list implementaion suffices: */
+/* simple linked-list implementation suffices: */
struct dc_list {
dc_data value;
struct dc_array *array; /* opaque */
@@ -53,7 +50,8 @@ typedef struct dc_list dc_list;
static dc_list *dc_stack=NULL;
/* the named register stacks */
-static dc_list *dc_register[DC_REGCOUNT];
+typedef dc_list *dc_listp;
+static dc_listp dc_register[DC_REGCOUNT];
/* allocate a new dc_list item */
@@ -86,7 +84,7 @@ dc_binop DC_DECLARG((op, kscale))
dc_data b;
dc_data r;
- if (!dc_stack || !dc_stack->link){
+ if (dc_stack == NULL || dc_stack->link == NULL){
Empty_Stack;
return;
}
@@ -126,7 +124,7 @@ dc_binop2 DC_DECLARG((op, kscale))
dc_data r1;
dc_data r2;
- if (!dc_stack || !dc_stack->link){
+ if (dc_stack == NULL || dc_stack->link == NULL){
Empty_Stack;
return;
}
@@ -164,7 +162,7 @@ dc_cmpop DC_DECLVOID()
dc_data a;
dc_data b;
- if (!dc_stack || !dc_stack->link){
+ if (dc_stack == NULL || dc_stack->link == NULL){
Empty_Stack;
return 0;
}
@@ -198,7 +196,9 @@ dc_triop DC_DECLARG((op, kscale))
dc_data c;
dc_data r;
- if (!dc_stack || !dc_stack->link || !dc_stack->link->link){
+ if (dc_stack == NULL
+ || dc_stack->link == NULL
+ || dc_stack->link->link == NULL){
Empty_Stack;
return;
}
@@ -244,7 +244,7 @@ dc_clear_stack DC_DECLVOID()
dc_list *n;
dc_list *t;
- for (n=dc_stack; n; n=t){
+ for (n=dc_stack; n!=NULL; n=t){
t = n->link;
if (n->value.dc_type == DC_NUMBER)
dc_free_num(&n->value.v.number);
@@ -297,7 +297,7 @@ int
dc_top_of_stack DC_DECLARG((result))
dc_data *result DC_DECLEND
{
- if (!dc_stack){
+ if (dc_stack == NULL){
Empty_Stack;
return DC_FAIL;
}
@@ -308,9 +308,10 @@ dc_top_of_stack DC_DECLARG((result))
return DC_SUCCESS;
}
-/* set *result to a dup of the value on the top of the named register stack */
+/* set *result to a dup of the value on the top of the named register stack,
+ * or 0 (zero) if the stack is empty */
/*
- * DC_FAIL is returned if the named stack is empty (and *result unchanged),
+ * DC_FAIL is returned if an internal bug is detected
* DC_SUCCESS is returned otherwise
*/
int
@@ -322,12 +323,15 @@ dc_register_get DC_DECLARG((regid, result))
regid = regmap(regid);
r = dc_register[regid];
- if ( ! r ){
- fprintf(stderr, "%s: register ", progname);
- dc_show_id(stderr, regid, " is empty\n");
+ if (r==NULL){
+ *result = dc_int2data(0);
+ }else if (r->value.dc_type==DC_UNINITIALIZED){
+ fprintf(stderr, "%s: BUG: register ", progname);
+ dc_show_id(stderr, regid, " exists but is uninitialized?\n");
return DC_FAIL;
+ }else{
+ *result = dc_dup(r->value);
}
- *result = dc_dup(r->value);
return DC_SUCCESS;
}
@@ -344,7 +348,7 @@ dc_register_set DC_DECLARG((regid, value))
regid = regmap(regid);
r = dc_register[regid];
- if ( ! r )
+ if (r == NULL)
dc_register[regid] = dc_alloc();
else if (r->value.dc_type == DC_NUMBER)
dc_free_num(&r->value.v.number);
@@ -369,7 +373,7 @@ dc_pop DC_DECLARG((result))
dc_list *r;
r = dc_stack;
- if (!r){
+ if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){
Empty_Stack;
return DC_FAIL;
}
@@ -396,7 +400,7 @@ dc_register_pop DC_DECLARG((stackid, result))
stackid = regmap(stackid);
r = dc_register[stackid];
- if (!r){
+ if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){
fprintf(stderr, "%s: stack register ", progname);
dc_show_id(stderr, stackid, " is empty\n");
return DC_FAIL;
@@ -411,6 +415,44 @@ dc_register_pop DC_DECLARG((stackid, result))
}
+/* cyclically rotate the "n" topmost elements of the stack;
+ * negative "n" rotates forward (topomost element becomes n-th deep)
+ * positive "n" rotates backward (topmost element becomes 2nd deep)
+ *
+ * If stack depth is less than "n", whole stack is rotated
+ * (without raising an error).
+ */
+void
+dc_stack_rotate(int n)
+{
+ dc_list *p; /* becomes bottom of sub-stack */
+ dc_list *r; /* predecessor of "p" */
+ int absn = n<0 ? -n : n;
+
+ /* always do nothing for empty stack or degenerate rotation depth */
+ if (!dc_stack || absn < 2)
+ return;
+ /* find bottom of rotation sub-stack */
+ r = NULL;
+ for (p=dc_stack; p->link && --absn>0; p=p->link)
+ r = p;
+ /* if stack has only one element, treat rotation as no-op */
+ if (!r)
+ return;
+ /* do the rotation, in appropriate direction */
+ if (n > 0) {
+ r->link = p->link;
+ p->link = dc_stack;
+ dc_stack = p;
+ } else {
+ dc_list *new_tos = dc_stack->link;
+ dc_stack->link = p->link;
+ p->link = dc_stack;
+ dc_stack = new_tos;
+ }
+}
+
+
/* tell how many entries are currently on the evaluation stack */
int
dc_tell_stackdepth DC_DECLVOID()
@@ -418,7 +460,7 @@ dc_tell_stackdepth DC_DECLVOID()
dc_list *n;
int depth=0;
- for (n=dc_stack; n; n=n->link)
+ for (n=dc_stack; n!=NULL; n=n->link)
++depth;
return depth;
}
@@ -442,7 +484,7 @@ dc_tell_length DC_DECLARG((value, discard_p))
if (discard_p == DC_TOSS)
dc_free_num(&value.v.number);
} else if (value.dc_type == DC_STRING) {
- length = dc_strlen(value.v.string);
+ length = (int) dc_strlen(value.v.string);
if (discard_p == DC_TOSS)
dc_free_str(&value.v.string);
} else {
@@ -462,7 +504,7 @@ dc_printall DC_DECLARG((obase))
{
dc_list *n;
- for (n=dc_stack; n; n=n->link)
+ for (n=dc_stack; n!=NULL; n=n->link)
dc_print(n->value, obase, DC_WITHNL, DC_KEEP);
}
@@ -475,7 +517,7 @@ 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;
+ return r == NULL ? NULL : r->array;
}
/* set the current array head for the named array */
@@ -488,7 +530,16 @@ dc_set_stacked_array DC_DECLARG((array_id, new_head))
array_id = regmap(array_id);
r = dc_register[array_id];
- if ( ! r )
+ if (r == NULL)
r = dc_register[array_id] = dc_alloc();
r->array = new_head;
}
+
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 4
+ * End:
+ * vi: set ts=4 :
+ */