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