Merge branch 'refactoring' of https://secure.softndesign.org/git/calc into refactoring
[calc.git] / program.c
CommitLineData
a24bd519 1#include <malloc.h>
7059478f 2#include <stdio.h>
a24bd519
LM
3#include <string.h>
4
5#include "alloc.h"
6#include "debug.h"
7#include "parser.h"
8#include "stack.h"
9#include "storage.h"
3559b26c 10#include "tabular.h"
a24bd519
LM
11
12#include "program.h"
13
14/* global variables */
15
16int argument_size = 0;
17double *argument = NULL;
18
19workspace_t *programs = NULL;
20int nb_programs = 0;
21
22/* program function */
23
24void prog (int id, element_t *root)
25{
26 int i, n = -1;
27
28 if (programs == NULL) {
29
30 /* initial memory allocation */
31 programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
32 nb_programs = 1;
33 n = 0;
34
35 } else {
36
37 /* look for existing program */
38 for (i = 0; i < nb_programs; i++) {
39 if ((programs + i)->id == id) {
40 n = i;
41 break;
42 }
43 }
44 if (n == -1) {
45
46 /* new program */
47 n = nb_programs++;
48 workspace_t *tmp = (workspace_t *) callocordie (nb_programs, sizeof (workspace_t));
49 memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t));
50 free (programs);
51 programs = tmp;
52 } else {
53
54 /* clean old program */
55 if ((programs + n)->storage) {
56 free ((programs + n)->storage);
57 }
58 if ((programs + n)->stack) {
3559b26c 59 free_tab ((programs + n)->stack);
a24bd519
LM
60 }
61 if ((programs + n)->root) {
62 delelement ((programs + n)->root);
63 }
64 if ((programs + n)->string) {
65 free ((programs + n)->string);
66 (programs + n)->string = NULL;
67 }
68 }
69 }
70
71 /* set program */
72 (programs + n)->id = id;
73 (programs + n)->answer = 0;
74 (programs + n)->storage = NULL;
75 (programs + n)->storage_size = 0;
76 (programs + n)->stack = NULL;
a24bd519
LM
77 (programs + n)->root = dupelement (root);
78}
79
80double arg (int id)
81{
82 double ret = 0;
83 if ((id <= 0) || (id > argument_size)) {
84 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size));
85 } else {
86 ret = argument[id - 1];
87 }
88 return ret;
89}
90
91double call (int id, int nbargs, element_t **args)
92{
93 workspace_t tmp = {0};
94 int i, l, n = -1;
95 double ret = 0;
96
97 if (programs) {
98
99 /* look for program */
100 for (i = 0; i < nb_programs; i++) {
101 if ((programs + i)->id == id) {
102 n = i;
103 break;
104 }
105 }
106 }
107 if (n == -1) {
108 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
109 return 0;
110 }
111
112 /* store context */
113 tmp.answer = answer;
114 tmp.argument = argument;
115 tmp.argument_size = argument_size;
116 tmp.storage = storage;
117 tmp.storage_size = storage_size;
118 tmp.stack = stack;
a24bd519
LM
119
120 /* change context */
121 answer = 0;
122 storage = (programs + n)->storage;
123 storage_size = (programs + n)->storage_size;
124 argument = NULL;
125 argument_size = 0;
126 stack = (programs + n)->stack;
a24bd519
LM
127 if (nbargs > 0) {
128 argument = (double *) callocordie (nbargs, sizeof (double));
129 for (i = 0, l = 0; i < nbargs; l++) {
130 if (args[l]) {
131 argument[i++] = evaluate_element (args[l], 0);
132 }
133 }
134 argument_size = nbargs;
135 }
136
137 /* evaluate program */
138 element_t *elements = dupelement ((programs + n)->root);
139 ret = evaluate_element (elements, 0);
140 delelement (elements);
141 (programs + n)->answer = answer;
142 (programs + n)->storage = storage;
143 (programs + n)->storage_size = storage_size;
144 if (argument) {
145 free (argument);
146 }
147 (programs + n)->stack = stack;
a24bd519
LM
148
149 /* restore context */
150 answer = tmp.answer;
151 storage = tmp.storage;
152 storage_size = tmp.storage_size;
153 argument = tmp.argument;
154 argument_size = tmp.argument_size;
155 stack = tmp.stack;
a24bd519
LM
156
157 return ret;
158}
159
160void list ()
161{
162 int i;
163 fprintf (stdout, "programs:");
164 for (i = 0; i < nb_programs; i++) {
165 fprintf (stdout, " %d", (programs + i)->id);
166 }
167 fprintf (stdout, "\n");
168}
169
170void edit (int id)
171{
172 int i, n = -1;
173
174 if (programs) {
175
176 /* look for program */
177 for (i = 0; i < nb_programs; i++) {
178 if ((programs + i)->id == id) {
179 n = i;
180 break;
181 }
182 }
183 }
184 if (n == -1) {
185 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
186 return;
187 }
188
189 /* set string program */
190 fprintf (stdout, "edit: %s\n", (programs + n)->string);
191}
192
193void savestring (int id, char *string)
194{
195 int i, n = -1;
196
197 if (programs) {
198
199 /* look for program */
200 for (i = 0; i < nb_programs; i++) {
201 if ((programs + i)->id == id) {
202 n = i;
203 break;
204 }
205 }
206 }
207
208 /* unnecesary code */
209 //if (n == -1) {
210 // VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
211 // return;
212 //}
213 //if ((programs + n)->string) {
214 // free ((programs + n)->string);
215 //}
216
217 if (string) {
218 (programs + n)->string = strdup (string);
219 }
220}
221
222void del (int id)
223{
224 int i, j, n = -1;
225
226 if (programs) {
227
228 /* look for program */
229 for (i = 0; i < nb_programs; i++) {
230 if ((programs + i)->id == id) {
231 n = i;
232 break;
233 }
234 }
235 }
236 if (n == -1) {
237 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
238 return;
239 }
240
241 /* clean program */
242 if ((programs + n)->storage) {
243 free ((programs + n)->storage);
244 }
245 if ((programs + n)->stack) {
3559b26c 246 free_tab ((programs + n)->stack);
a24bd519
LM
247 }
248 if ((programs + n)->root) {
249 delelement ((programs + n)->root);
250 }
251 if ((programs + n)->string) {
252 free ((programs + n)->string);
253 }
254
255 /* remove entry */
256 workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t));
257 for (i = 0, j = 0; i < nb_programs; i++) {
258 if (i != n) {
259 memcpy (tmp + j, programs + i, sizeof (workspace_t));
260 j++;
261 }
262 }
263 free (programs);
264 programs = tmp;
265 nb_programs--;
266}
267
268/* vim: set ts=4 sw=4 et: */