97f99293114bd95b76ac4601d62c4b5645fd1a4f
[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 #include "tabular.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_tab ((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)->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
119 /* change context */
120 answer = 0;
121 storage = (programs + n)->storage;
122 storage_size = (programs + n)->storage_size;
123 argument = NULL;
124 argument_size = 0;
125 stack = (programs + n)->stack;
126 if (nbargs > 0) {
127 argument = (double *) callocordie (nbargs, sizeof (double));
128 for (i = 0, l = 0; i < nbargs; l++) {
129 if (args[l]) {
130 argument[i++] = evaluate_element (args[l], 0);
131 }
132 }
133 argument_size = nbargs;
134 }
135
136 /* evaluate program */
137 element_t *elements = dupelement ((programs + n)->root);
138 ret = evaluate_element (elements, 0);
139 delelement (elements);
140 (programs + n)->answer = answer;
141 (programs + n)->storage = storage;
142 (programs + n)->storage_size = storage_size;
143 if (argument) {
144 free (argument);
145 }
146 (programs + n)->stack = stack;
147
148 /* restore context */
149 answer = tmp.answer;
150 storage = tmp.storage;
151 storage_size = tmp.storage_size;
152 argument = tmp.argument;
153 argument_size = tmp.argument_size;
154 stack = tmp.stack;
155
156 return ret;
157 }
158
159 void list ()
160 {
161 int i;
162 fprintf (stdout, "programs:");
163 for (i = 0; i < nb_programs; i++) {
164 fprintf (stdout, " %d", (programs + i)->id);
165 }
166 fprintf (stdout, "\n");
167 }
168
169 void edit (int id)
170 {
171 int i, n = -1;
172
173 if (programs) {
174
175 /* look for program */
176 for (i = 0; i < nb_programs; i++) {
177 if ((programs + i)->id == id) {
178 n = i;
179 break;
180 }
181 }
182 }
183 if (n == -1) {
184 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
185 return;
186 }
187
188 /* set string program */
189 fprintf (stdout, "edit: %s\n", (programs + n)->string);
190 }
191
192 void savestring (int id, char *string)
193 {
194 int i, n = -1;
195
196 if (programs) {
197
198 /* look for program */
199 for (i = 0; i < nb_programs; i++) {
200 if ((programs + i)->id == id) {
201 n = i;
202 break;
203 }
204 }
205 }
206
207 /* unnecesary code */
208 //if (n == -1) {
209 // VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
210 // return;
211 //}
212 //if ((programs + n)->string) {
213 // free ((programs + n)->string);
214 //}
215
216 if (string) {
217 (programs + n)->string = strdup (string);
218 }
219 }
220
221 void del (int id)
222 {
223 int i, j, n = -1;
224
225 if (programs) {
226
227 /* look for program */
228 for (i = 0; i < nb_programs; i++) {
229 if ((programs + i)->id == id) {
230 n = i;
231 break;
232 }
233 }
234 }
235 if (n == -1) {
236 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
237 return;
238 }
239
240 /* clean program */
241 if ((programs + n)->storage) {
242 free ((programs + n)->storage);
243 }
244 if ((programs + n)->stack) {
245 free_tab ((programs + n)->stack);
246 }
247 if ((programs + n)->root) {
248 delelement ((programs + n)->root);
249 }
250 if ((programs + n)->string) {
251 free ((programs + n)->string);
252 }
253
254 /* remove entry */
255 workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t));
256 for (i = 0, j = 0; i < nb_programs; i++) {
257 if (i != n) {
258 memcpy (tmp + j, programs + i, sizeof (workspace_t));
259 j++;
260 }
261 }
262 free (programs);
263 programs = tmp;
264 nb_programs--;
265 }
266
267 /* vim: set ts=4 sw=4 et: */