e78fc3c928f6532ef0081e3b73df2157b51d72fb
[egate.git] / fml / fmlmem.c
1 /*
2  * FML interpreter. Europagate, 1995
3  *
4  * $Log: fmlmem.c,v $
5  * Revision 1.11  1995/03/02 10:18:48  adam
6  * Bug fix.
7  *
8  * Revision 1.10  1995/03/02  08:06:03  adam
9  * Fml function strsub implemented. New test files marc[45].fml.
10  * New test options in fmltest.
11  *
12  * Revision 1.9  1995/02/27  09:01:20  adam
13  * Regular expression support. Argument passing by name option. New FML
14  * function strlen.
15  *
16  * Revision 1.8  1995/02/23  08:32:05  adam
17  * Changed header.
18  *
19  * Revision 1.6  1995/02/10  18:15:52  adam
20  * FML function 'strcmp' implemented. This function can be used to
21  * test for existence of MARC fields.
22  *
23  * Revision 1.5  1995/02/09  14:37:18  adam
24  * Removed .depend from cvs. Removed function fml_mk_list.
25  *
26  * Revision 1.4  1995/02/09  14:33:37  adam
27  * Split source fml.c and define relevant build-in functions in separate
28  * files. New operators mult, div, not, llen implemented.
29  *
30  * Revision 1.3  1995/02/09  13:07:15  adam
31  * Nodes are freed now. Many bugs fixed.
32  *
33  * Revision 1.2  1995/02/06  15:23:26  adam
34  * Added some more relational operators (le,ne,ge). Added increment
35  * and decrement operators. Function index changed, so that first
36  * element is 1 - not 0. Function fml_atom_val edited.
37  *
38  * Revision 1.1.1.1  1995/02/06  13:48:10  adam
39  * First version of the FML interpreter. It's slow and memory isn't
40  * freed properly. In particular, the FML nodes aren't released yet.
41  *
42  */
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <assert.h>
47
48 #include "fmlp.h"
49
50 #define FML_ATOM_CHUNK 1024
51 #define FML_NODE_CHUNK 1024
52
53 static int no_nodes = 0;
54 static int no_atoms = 0;
55
56 struct fml_node *fml_node_alloc (Fml fml)
57 {
58     struct fml_node *n;
59
60     if (! fml->node_free_list)
61     {
62         int i;
63
64         n = fml->node_free_list = malloc (sizeof(*n) * FML_NODE_CHUNK);
65         if (!n)
66         {
67             (*fml->err_handle)(FML_ERR_NOMEM);
68             exit (1);
69         }
70         for (i = FML_ATOM_CHUNK-1; --i >= 0; n++)
71             n->p[1] = n+1;
72         n->p[1] = NULL;
73     }
74     n = fml->node_free_list;
75     fml->node_free_list = n->p[1];
76     n->p[0] = n->p[1] = NULL;
77     n->is_atom = 0;
78     no_nodes++;
79     return n;
80 }
81
82 static struct fml_atom *atom_malloc (Fml fml)
83 {
84     struct fml_atom *fa;
85
86     if (! fml->atom_free_list)
87     {
88         int i;
89
90         fa = fml->atom_free_list = malloc (sizeof(*fa) * FML_ATOM_CHUNK);
91         if (!fa)
92         {
93             (*fml->err_handle)(FML_ERR_NOMEM);
94             exit (1);
95         }
96         for (i = FML_ATOM_CHUNK-1; --i >= 0; fa++)
97             fa->next = fa+1;
98         fa->next = NULL;
99     }
100     fa = fml->atom_free_list;
101     fml->atom_free_list = fa->next;
102     no_atoms++;
103     return fa;
104 }
105
106 static void atom_delete (Fml fml, struct fml_atom *a)
107 {
108     a->next = fml->atom_free_list;
109     fml->atom_free_list = a;
110     no_atoms--;
111 }
112
113 static struct fml_atom *atom_copy (Fml fml, struct fml_atom *a)
114 {
115     struct fml_atom *a0, *a1;
116
117     a0 = a1 = atom_malloc (fml);
118     while (a)
119     {
120         memcpy (&a1->buf, &a->buf, FML_ATOM_BUF);
121         if (!a->next)
122             break;
123         a = a->next;
124         a1 = a1->next = atom_malloc (fml);
125     }
126     a1->next = NULL;
127     return a0;
128 }
129
130 struct fml_atom *fml_atom_alloc (Fml fml, char *str)
131 {
132     int soff = 0;
133     struct fml_atom *a, *a0;
134
135     a0 = a = atom_malloc (fml);
136     strncpy (a->buf, str, FML_ATOM_BUF);
137     while (strlen (str+soff) >= FML_ATOM_BUF)
138     {
139         struct fml_atom *an;
140
141         an = atom_malloc (fml);
142         a->next = an;
143         soff += FML_ATOM_BUF;
144         strncpy (an->buf, str+soff, FML_ATOM_BUF);
145         a = an;
146     }
147     a->next = NULL;
148     return a0;
149 }
150
151 int fml_atom_cmp (Fml fml, struct fml_atom *a1, struct fml_atom *a2)
152 {
153     while (a1 && a2)
154     {
155         int n;
156         n = strncmp (a1->buf, a2->buf, FML_ATOM_BUF);
157         if (n)
158             return n;
159         a1 = a1->next;
160         a2 = a2->next;
161     }
162     if (!a1 && !a2)
163         return 0;
164     if (a1)
165         return 1;
166     return -1;
167 }
168
169 int fml_atom_str (struct fml_atom *a, char *str)
170 {
171     int i, len = 0;
172
173     assert (a);
174     while (a->next)
175     {
176         if (str)
177             memcpy (str+len, a->buf, FML_ATOM_BUF);
178         len += FML_ATOM_BUF;
179         a = a->next;
180     }
181     for (i=0; i<FML_ATOM_BUF && a->buf[i]; i++)
182         ;
183     if (str)
184     {
185         memcpy (str+len, a->buf, i);
186         str[len+i] = 0;
187     }
188     len += i;
189     return len;
190 }
191
192 void fml_atom_strx (struct fml_atom *a, char *str, int max)
193 {
194     int len = 0;
195
196     assert (a);
197     while (a->next && len < max - 2*FML_ATOM_BUF)
198     {
199         memcpy (str+len, a->buf, FML_ATOM_BUF);
200         len += FML_ATOM_BUF;
201         a = a->next;
202     }
203     strncpy (str+len, a->buf, FML_ATOM_BUF-1);
204     str[len+FML_ATOM_BUF-1] = '\0';
205 }
206
207 int fml_atom_len (struct fml_atom *a)
208 {
209     int len = 0;
210     if (a)
211     {
212         while (a->next)
213         {
214             len += FML_ATOM_BUF;
215             a = a->next;
216         }
217         len += strlen (a->buf);
218     } 
219     return len;
220 }
221
222 int fml_atom_val (struct fml_atom *a)
223 {
224     static char arg[256];
225     assert (a);
226     if (!a->next)
227         return atoi (a->buf);
228     fml_atom_strx (a, arg, 200);
229     return atoi (arg);
230 }
231
232 struct fml_node *fml_mk_node_val (Fml fml, int val)
233 {
234     static char arg[64];
235     struct fml_node *fn;
236
237     sprintf (arg, "%d", val);
238     fn = fml_node_alloc (fml);
239     fn->is_atom = 1;
240     fn->p[0] = fml_atom_alloc (fml, arg);
241     return fn;
242 }
243
244 void fml_node_delete (Fml fml, struct fml_node *fn)
245 {
246     struct fml_node *f1;
247     while (fn)
248     {
249         if (fn->is_atom)
250             atom_delete (fml, fn->p[0]);
251         else
252             fml_node_delete (fml, fn->p[0]);
253         f1 = fn->p[1];
254         
255         fn->p[1] = fml->node_free_list;
256         fml->node_free_list = fn;
257         no_nodes--;
258
259         fn = f1;
260     }
261 }
262
263 struct fml_node *fml_node_copy (Fml fml, struct fml_node *fn)
264 {
265     struct fml_node *fn0, *fn1;
266
267     if (!fn)
268         return NULL;
269     fn1 = fn0 = fml_node_alloc (fml);
270     while (1)
271     {
272         if (fn->is_atom)
273         {
274             fn1->is_atom = 1;
275             fn1->p[0] = atom_copy (fml, fn->p[0]);
276         }
277         else 
278             fn1->p[0] = fml_node_copy (fml, fn->p[0]);
279         if (!fn->p[1])
280             break;
281         fn = fn->p[1];
282         fn1 = fn1->p[1] = fml_node_alloc (fml);
283     }
284     return fn0;
285 }
286
287 void fml_node_stat (Fml fml)
288 {
289     if (fml->debug & 2)
290         printf ("<<node=%d, atom=%d>>", no_nodes, no_atoms);
291 }
292
293 struct fml_atom *fml_atom_strsub (Fml fml, struct fml_atom *a, int o, int l)
294 {
295     static char buf[512];
296     char *cp;
297     struct fml_atom *an;
298     int ol = fml_atom_len (a);
299
300     if (ol >= 510)
301     {
302         cp = malloc (ol + 1);
303         assert (cp);
304     }
305     else
306         cp = buf;
307     fml_atom_str (a, buf);
308     if (o + l < ol)
309         buf[o+l] = '\0';
310     an = fml_atom_alloc (fml, buf+o);
311     if (ol >= 510)
312         free (cp);
313     return an;
314 }