2 * implement stack functions for dc
4 * Copyright (C) 1994, 1997, 1998 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you can either send email to this
18 * program's author (see below) or write to:
20 * The Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330
22 * Boston, MA 02111 USA
25 /* This module is the only one that knows what stacks (both the
26 * regular evaluation stack and the named register stacks)
38 #include "dc-regdef.h"
40 /* an oft-used error message: */
41 #define Empty_Stack fprintf(stderr, "%s: stack empty\n", progname)
44 /* simple linked-list implementaion suffices: */
47 struct dc_array
*array
; /* opaque */
50 typedef struct dc_list dc_list
;
52 /* the anonymous evaluation stack */
53 static dc_list
*dc_stack
=NULL
;
55 /* the named register stacks */
56 static dc_list
*dc_register
[DC_REGCOUNT
];
59 /* allocate a new dc_list item */
61 dc_alloc
DC_DECLVOID()
65 result
= dc_malloc(sizeof *result
);
66 result
->value
.dc_type
= DC_UNINITIALIZED
;
73 /* check that there are two numbers on top of the stack,
74 * then call op with the popped numbers. Construct a dc_data
75 * value from the dc_num returned by op and push it
77 * If the op call doesn't return DC_SUCCESS, then leave the stack
81 dc_binop
DC_DECLARG((op
, kscale
))
82 int (*op
)DC_PROTO((dc_num
, dc_num
, int, dc_num
*)) DC_DECLSEP
89 if (!dc_stack
|| !dc_stack
->link
){
93 if (dc_stack
->value
.dc_type
!=DC_NUMBER
94 || dc_stack
->link
->value
.dc_type
!=DC_NUMBER
){
95 fprintf(stderr
, "%s: non-numeric value\n", progname
);
100 if ((*op
)(a
.v
.number
, b
.v
.number
, kscale
, &r
.v
.number
) == DC_SUCCESS
){
101 r
.dc_type
= DC_NUMBER
;
103 dc_free_num(&a
.v
.number
);
104 dc_free_num(&b
.v
.number
);
106 /* op failed; restore the stack */
112 /* check that there are two numbers on top of the stack,
113 * then call op with the popped numbers. Construct two dc_data
114 * values from the dc_num's returned by op and push them
116 * If the op call doesn't return DC_SUCCESS, then leave the stack
120 dc_binop2
DC_DECLARG((op
, kscale
))
121 int (*op
)DC_PROTO((dc_num
, dc_num
, int, dc_num
*, dc_num
*)) DC_DECLSEP
122 int kscale DC_DECLEND
129 if (!dc_stack
|| !dc_stack
->link
){
133 if (dc_stack
->value
.dc_type
!=DC_NUMBER
134 || dc_stack
->link
->value
.dc_type
!=DC_NUMBER
){
135 fprintf(stderr
, "%s: non-numeric value\n", progname
);
140 if ((*op
)(a
.v
.number
, b
.v
.number
, kscale
,
141 &r1
.v
.number
, &r2
.v
.number
) == DC_SUCCESS
){
142 r1
.dc_type
= DC_NUMBER
;
144 r2
.dc_type
= DC_NUMBER
;
146 dc_free_num(&a
.v
.number
);
147 dc_free_num(&b
.v
.number
);
149 /* op failed; restore the stack */
155 /* check that there are two numbers on top of the stack,
156 * then call dc_compare with the popped numbers.
157 * Return negative, zero, or positive based on the ordering
158 * of the two numbers.
161 dc_cmpop
DC_DECLVOID()
167 if (!dc_stack
|| !dc_stack
->link
){
171 if (dc_stack
->value
.dc_type
!=DC_NUMBER
172 || dc_stack
->link
->value
.dc_type
!=DC_NUMBER
){
173 fprintf(stderr
, "%s: non-numeric value\n", progname
);
178 result
= dc_compare(b
.v
.number
, a
.v
.number
);
179 dc_free_num(&a
.v
.number
);
180 dc_free_num(&b
.v
.number
);
184 /* check that there are three numbers on top of the stack,
185 * then call op with the popped numbers. Construct a dc_data
186 * value from the dc_num returned by op and push it
188 * If the op call doesn't return DC_SUCCESS, then leave the stack
192 dc_triop
DC_DECLARG((op
, kscale
))
193 int (*op
)DC_PROTO((dc_num
, dc_num
, dc_num
, int, dc_num
*)) DC_DECLSEP
194 int kscale DC_DECLEND
201 if (!dc_stack
|| !dc_stack
->link
|| !dc_stack
->link
->link
){
205 if (dc_stack
->value
.dc_type
!=DC_NUMBER
206 || dc_stack
->link
->value
.dc_type
!=DC_NUMBER
207 || dc_stack
->link
->link
->value
.dc_type
!=DC_NUMBER
){
208 fprintf(stderr
, "%s: non-numeric value\n", progname
);
214 if ((*op
)(a
.v
.number
, b
.v
.number
, c
.v
.number
,
215 kscale
, &r
.v
.number
) == DC_SUCCESS
){
216 r
.dc_type
= DC_NUMBER
;
218 dc_free_num(&a
.v
.number
);
219 dc_free_num(&b
.v
.number
);
220 dc_free_num(&c
.v
.number
);
222 /* op failed; restore the stack */
230 /* initialize the register stacks to their initial values */
232 dc_register_init
DC_DECLVOID()
236 for (i
=0; i
<DC_REGCOUNT
; ++i
)
237 dc_register
[i
] = NULL
;
240 /* clear the evaluation stack */
242 dc_clear_stack
DC_DECLVOID()
247 for (n
=dc_stack
; n
; n
=t
){
249 if (n
->value
.dc_type
== DC_NUMBER
)
250 dc_free_num(&n
->value
.v
.number
);
251 else if (n
->value
.dc_type
== DC_STRING
)
252 dc_free_str(&n
->value
.v
.string
);
254 dc_garbage("in stack", -1);
255 dc_array_free(n
->array
);
261 /* push a value onto the evaluation stack */
263 dc_push
DC_DECLARG((value
))
264 dc_data value DC_DECLEND
266 dc_list
*n
= dc_alloc();
268 if (value
.dc_type
!=DC_NUMBER
&& value
.dc_type
!=DC_STRING
)
269 dc_garbage("in data being pushed", -1);
275 /* push a value onto the named register stack */
277 dc_register_push
DC_DECLARG((stackid
, value
))
278 int stackid DC_DECLSEP
279 dc_data value DC_DECLEND
281 dc_list
*n
= dc_alloc();
283 stackid
= regmap(stackid
);
285 n
->link
= dc_register
[stackid
];
286 dc_register
[stackid
] = n
;
289 /* set *result to the value on the top of the evaluation stack */
290 /* The caller is responsible for duplicating the value if it
291 * is to be maintained as anything more than a transient identity.
293 * DC_FAIL is returned if the stack is empty (and *result unchanged),
294 * DC_SUCCESS is returned otherwise
297 dc_top_of_stack
DC_DECLARG((result
))
298 dc_data
*result DC_DECLEND
304 if (dc_stack
->value
.dc_type
!=DC_NUMBER
305 && dc_stack
->value
.dc_type
!=DC_STRING
)
306 dc_garbage("at top of stack", -1);
307 *result
= dc_stack
->value
;
311 /* set *result to a dup of the value on the top of the named register stack */
313 * DC_FAIL is returned if the named stack is empty (and *result unchanged),
314 * DC_SUCCESS is returned otherwise
317 dc_register_get
DC_DECLARG((regid
, result
))
319 dc_data
*result DC_DECLEND
323 regid
= regmap(regid
);
324 r
= dc_register
[regid
];
326 fprintf(stderr
, "%s: register ", progname
);
327 dc_show_id(stderr
, regid
, " is empty\n");
330 *result
= dc_dup(r
->value
);
334 /* set the top of the named register stack to the indicated value */
335 /* If the named stack is empty, craft a stack entry to enter the
339 dc_register_set
DC_DECLARG((regid
, value
))
341 dc_data value DC_DECLEND
345 regid
= regmap(regid
);
346 r
= dc_register
[regid
];
348 dc_register
[regid
] = dc_alloc();
349 else if (r
->value
.dc_type
== DC_NUMBER
)
350 dc_free_num(&r
->value
.v
.number
);
351 else if (r
->value
.dc_type
== DC_STRING
)
352 dc_free_str(&r
->value
.v
.string
);
353 else if (r
->value
.dc_type
== DC_UNINITIALIZED
)
356 dc_garbage("", regid
);
357 dc_register
[regid
]->value
= value
;
360 /* pop from the evaluation stack
362 * DC_FAIL is returned if the stack is empty (and *result unchanged),
363 * DC_SUCCESS is returned otherwise
366 dc_pop
DC_DECLARG((result
))
367 dc_data
*result DC_DECLEND
376 if (r
->value
.dc_type
!=DC_NUMBER
&& r
->value
.dc_type
!=DC_STRING
)
377 dc_garbage("at top of stack", -1);
380 dc_array_free(r
->array
);
385 /* pop from the named register stack
387 * DC_FAIL is returned if the named stack is empty (and *result unchanged),
388 * DC_SUCCESS is returned otherwise
391 dc_register_pop
DC_DECLARG((stackid
, result
))
392 int stackid DC_DECLSEP
393 dc_data
*result DC_DECLEND
397 stackid
= regmap(stackid
);
398 r
= dc_register
[stackid
];
400 fprintf(stderr
, "%s: stack register ", progname
);
401 dc_show_id(stderr
, stackid
, " is empty\n");
404 if (r
->value
.dc_type
!=DC_NUMBER
&& r
->value
.dc_type
!=DC_STRING
)
405 dc_garbage(" stack", stackid
);
407 dc_register
[stackid
] = r
->link
;
408 dc_array_free(r
->array
);
414 /* tell how many entries are currently on the evaluation stack */
416 dc_tell_stackdepth
DC_DECLVOID()
421 for (n
=dc_stack
; n
; n
=n
->link
)
427 /* return the length of the indicated data value;
428 * if discard_p is DC_TOSS, the deallocate the value when done
430 * The definition of a datum's length is deligated to the
431 * appropriate module.
434 dc_tell_length
DC_DECLARG((value
, discard_p
))
435 dc_data value DC_DECLSEP
436 dc_discard discard_p DC_DECLEND
440 if (value
.dc_type
== DC_NUMBER
){
441 length
= dc_numlen(value
.v
.number
);
442 if (discard_p
== DC_TOSS
)
443 dc_free_num(&value
.v
.number
);
444 } else if (value
.dc_type
== DC_STRING
) {
445 length
= dc_strlen(value
.v
.string
);
446 if (discard_p
== DC_TOSS
)
447 dc_free_str(&value
.v
.string
);
449 dc_garbage("in tell_length", -1);
451 length
= 0; /*just to suppress spurious compiler warnings*/
458 /* print out all of the values on the evaluation stack */
460 dc_printall
DC_DECLARG((obase
))
465 for (n
=dc_stack
; n
; n
=n
->link
)
466 dc_print(n
->value
, obase
, DC_WITHNL
, DC_KEEP
);
472 /* get the current array head for the named array */
474 dc_get_stacked_array
DC_DECLARG((array_id
))
475 int array_id DC_DECLEND
477 dc_list
*r
= dc_register
[regmap(array_id
)];
478 return r
? r
->array
: NULL
;
481 /* set the current array head for the named array */
483 dc_set_stacked_array
DC_DECLARG((array_id
, new_head
))
484 int array_id DC_DECLSEP
485 struct dc_array
*new_head DC_DECLEND
489 array_id
= regmap(array_id
);
490 r
= dc_register
[array_id
];
492 r
= dc_register
[array_id
] = dc_alloc();