|
|
1.1 root 1: #include <stdio.h>
2: #include <assert.h>
3: #include "bc.h"
4:
5:
6: /*
7: * Newscalar takes the rvalue pointed to by lval and initializes
8: * it to have a value of zero.
9: */
10:
11: newscalar(lval)
12: register rvalue *lval;
13: {
14: minit(&lval->mantissa);
15: mcopy(mzero, &lval->mantissa);
16: lval->scale = 0;
17: }
18:
19: /*
20: * Newarray takes the array pointed to by alval and initializes it
21: * to have one element, which will have the value of zero.
22: */
23:
24: newarray(alval)
25: register array *alval;
26: {
27: alval->size = 1;
28: alval->avalue = (rvalue *)mpalc(sizeof (rvalue));
29: newscalar(alval->avalue);
30: }
31:
32: /*
33: * Arfree frees all space associated with the array pointed to by
34: * `alv'.
35: */
36:
37: arfree(alv)
38: register array *alv;
39: {
40: register rvalue *rp;
41: register int left;
42:
43: for (rp = alv->avalue, left = alv->size; --left >= 0; ++rp)
44: mvfree(&rp->mantissa);
45: mpfree(alv->avalue);
46: }
47:
48: /*
49: * Pow10 returns a pointer to a mint which is 10 ^ `power'.
50: * Note that this pointer is to a static region, and hence
51: * should not be saved, but should be used immediately.
52: * Since pow10 is frequently used for scaleing, it first
53: * checks to see if the value being requested is the same
54: * as last time, and if so, simply returns it.
55: */
56:
57: mint *
58: pow10(power)
59: register int power;
60: {
61: static int oldpow = -1;
62: static mint oldres;
63:
64: if (power != oldpow) {
65: if (power == 0)
66: return (mone);
67: spow(&ten, power, &oldres);
68: oldpow = power;
69: }
70: return (&oldres);
71: }
72:
73: /*
74: * Select returns the lvalue of the `indx'th item in the array
75: * `arry'.
76: */
77:
78: rvalue *
79: select(arry, indx)
80: register array *arry;
81: int indx;
82: {
83: register rvalue *ptr;
84: register int nsize;
85:
86: if (indx < 0)
87: bcmerr("Negative subscript");
88: if (indx >= arry->size) {
89: nsize = indx + ABUMP - indx % ABUMP;
90: /*
91: * Should be:
92: * ptr = (rvalue *)realloc(arry->avalue,
93: * nsize * (sizeof (rvalue)));
94: * if (ptr == NULL)
95: * die("Out of space");
96: * But is:
97: */
98: ptr = (rvalue *)mpalc(nsize * (sizeof (rvalue)));
99: copy((char *)arry->avalue, (char *)ptr,
100: arry->size * sizeof (rvalue));
101: mpfree(arry->avalue);
102: /*
103: * End of kludge.
104: */
105: arry->avalue = ptr;
106: ptr += arry->size;
107: do {
108: newscalar(ptr++);
109: } while (++arry->size < nsize);
110: }
111: return (&arry->avalue[indx]);
112: }
113:
114: /*
115: * Shift sets the mint `b' to the mint `a' times 10 ^ `scnt'.
116: * If `scnt' is negative, then a divide (with truncation) is
117: * done. If `scnt' is zero and `a' and `b' are the same, then
118: * no action is taken.
119: */
120:
121:
122: shift(a, scnt, b)
123: register int scnt;
124: mint *a, *b;
125: {
126: mint temp;
127:
128: if (scnt > 0)
129: mult(a, pow10(scnt), b);
130: else if (scnt < 0) {
131: minit(&temp);
132: mdiv(a, pow10(-scnt), b, &temp);
133: mvfree(&temp);
134: } else if (a != b)
135: mcopy(a, b);
136: }
137:
138: /*
139: * Rescale adjusts the scale of the rvalue pointed to by `a'
140: * to `newsc'.
141: */
142:
143: rescale(a, newsc)
144: register rvalue *a;
145: register int newsc;
146: {
147: shift(a, newsc - a->scale, a);
148: a->scale = newsc;
149: }
150:
151: /*
152: * Rtoint returns an int equal to the rvalue `a'. Any
153: * fractional part is truncated. If `a' is too large,
154: * then rtoint exits via bcerr.
155: */
156:
157: int
158: rtoint(a)
159: rvalue *a;
160: {
161: register int res;
162: mint temp;
163:
164: minit(&temp);
165: shift(&a->mantissa, - a->scale, &temp);
166: if (mcmp(mminint, &temp) > 0 || mcmp(&temp, mmaxint) > 0)
167: bcmerr("Too big for int");
168: res = mtoi(&temp);
169: mvfree(&temp);
170: return (res);
171: }
172:
173: /*
174: * Chkcall checks to make sure that a function is defined and has
175: * the right number of arguments. `fnc' is a pointer to the
176: * dictionary entry for the function and `npars' is the number
177: * of parameters with which it is called.
178: */
179:
180: chkcall(fnc, npars)
181: register dicent *fnc;
182: register int npars;
183: {
184: if (fnc->globalt != FUNCTION)
185: bcmerr("'%s' not function", fnc->word);
186: if (fnc->globalv.fvalue.body == NULL)
187: bcmerr("Function '%s' not defined", fnc->word);
188: if (fnc->globalv.fvalue.nparams != npars)
189: bcmerr("Function '%s' needs %d arguments, got %d",
190: fnc->word, fnc->globalv.fvalue.nparams, npars);
191: }
192:
193: /*
194: * Pauto intializes the automatic variables needed by a bc function
195: * as part of the CALL instruction. It also checks to make sure that
196: * there is room for them on the stack. Pauto returns the value
197: * for tos after the CALL is completed (which is a pointer to the
198: * return state). `fnc' is the function being called, tos is the
199: * old tos and limit is the last available stack entry.
200: */
201:
202: stkent *
203: pauto(fnc, tos, limit)
204: register func *fnc;
205: register stkent *tos;
206: stkent *limit;
207: {
208: register type *tp;
209: int left;
210:
211: left = fnc->nautos;
212: if (tos + left >= limit)
213: bcmerr("Out of runtime stack");
214: ++tos;
215: for (tp = &fnc->types[fnc->nparams]; --left >= 0; ++tp, ++tos)
216: switch (*tp) {
217: case SCALAR:
218: newscalar(&tos->rvalue);
219: break;
220: case ARRAY:
221: tos->alvalue = (array *)mpalc(sizeof (array));
222: newarray(tos->alvalue);
223: break;
224: default:
225: assert(FALSE);
226: }
227: return (tos);
228: }
229:
230: /*
231: * Newframe returns the new value for the frame pointer after
232: * calling the function `fcn'. `tos' is the top of the stack
233: * after the CALL (note, this points to the saved state).
234: */
235:
236: stkent *
237: newframe(fcn, tos)
238: register func *fcn;
239: stkent *tos;
240: {
241: return (tos - (fcn->nparams + fcn->nautos));
242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.