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