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();