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