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