e4bec8136de70f8f7517773aff1a2241fc0a2cd8
[egate.git] / fml / fmlmem.c
1 /*
2  * Copyright (c) 1995, the EUROPAGATE consortium (see below).
3  *
4  * The EUROPAGATE consortium members are:
5  *
6  *    University College Dublin
7  *    Danmarks Teknologiske Videnscenter
8  *    An Chomhairle Leabharlanna
9  *    Consejo Superior de Investigaciones Cientificas
10  *
11  * Permission to use, copy, modify, distribute, and sell this software and
12  * its documentation, in whole or in part, for any purpose, is hereby granted,
13  * provided that:
14  *
15  * 1. This copyright and permission notice appear in all copies of the
16  * software and its documentation. Notices of copyright or attribution
17  * which appear at the beginning of any file must remain unchanged.
18  *
19  * 2. The names of EUROPAGATE or the project partners may not be used to
20  * endorse or promote products derived from this software without specific
21  * prior written permission.
22  *
23  * 3. Users of this software (implementors and gateway operators) agree to
24  * inform the EUROPAGATE consortium of their use of the software. This
25  * information will be used to evaluate the EUROPAGATE project and the
26  * software, and to plan further developments. The consortium may use
27  * the information in later publications.
28  * 
29  * 4. Users of this software agree to make their best efforts, when
30  * documenting their use of the software, to acknowledge the EUROPAGATE
31  * consortium, and the role played by the software in their work.
32  *
33  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
34  * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
35  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
36  * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
37  * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
38  * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
39  * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
40  * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
41  * USE OR PERFORMANCE OF THIS SOFTWARE.
42  *
43  */
44 /*
45  * FML interpreter. Europagate, 1995
46  *
47  * $Log: fmlmem.c,v $
48  * Revision 1.12  1995/05/16 09:39:34  adam
49  * LICENSE.
50  *
51  * Revision 1.11  1995/03/02  10:18:48  adam
52  * Bug fix.
53  *
54  * Revision 1.10  1995/03/02  08:06:03  adam
55  * Fml function strsub implemented. New test files marc[45].fml.
56  * New test options in fmltest.
57  *
58  * Revision 1.9  1995/02/27  09:01:20  adam
59  * Regular expression support. Argument passing by name option. New FML
60  * function strlen.
61  *
62  * Revision 1.8  1995/02/23  08:32:05  adam
63  * Changed header.
64  *
65  * Revision 1.6  1995/02/10  18:15:52  adam
66  * FML function 'strcmp' implemented. This function can be used to
67  * test for existence of MARC fields.
68  *
69  * Revision 1.5  1995/02/09  14:37:18  adam
70  * Removed .depend from cvs. Removed function fml_mk_list.
71  *
72  * Revision 1.4  1995/02/09  14:33:37  adam
73  * Split source fml.c and define relevant build-in functions in separate
74  * files. New operators mult, div, not, llen implemented.
75  *
76  * Revision 1.3  1995/02/09  13:07:15  adam
77  * Nodes are freed now. Many bugs fixed.
78  *
79  * Revision 1.2  1995/02/06  15:23:26  adam
80  * Added some more relational operators (le,ne,ge). Added increment
81  * and decrement operators. Function index changed, so that first
82  * element is 1 - not 0. Function fml_atom_val edited.
83  *
84  * Revision 1.1.1.1  1995/02/06  13:48:10  adam
85  * First version of the FML interpreter. It's slow and memory isn't
86  * freed properly. In particular, the FML nodes aren't released yet.
87  *
88  */
89 #include <stdio.h>
90 #include <stdlib.h>
91 #include <string.h>
92 #include <assert.h>
93
94 #include "fmlp.h"
95
96 #define FML_ATOM_CHUNK 1024
97 #define FML_NODE_CHUNK 1024
98
99 static int no_nodes = 0;
100 static int no_atoms = 0;
101
102 struct fml_node *fml_node_alloc (Fml fml)
103 {
104     struct fml_node *n;
105
106     if (! fml->node_free_list)
107     {
108         int i;
109
110         n = fml->node_free_list = malloc (sizeof(*n) * FML_NODE_CHUNK);
111         if (!n)
112         {
113             (*fml->err_handle)(FML_ERR_NOMEM);
114             exit (1);
115         }
116         for (i = FML_ATOM_CHUNK-1; --i >= 0; n++)
117             n->p[1] = n+1;
118         n->p[1] = NULL;
119     }
120     n = fml->node_free_list;
121     fml->node_free_list = n->p[1];
122     n->p[0] = n->p[1] = NULL;
123     n->is_atom = 0;
124     no_nodes++;
125     return n;
126 }
127
128 static struct fml_atom *atom_malloc (Fml fml)
129 {
130     struct fml_atom *fa;
131
132     if (! fml->atom_free_list)
133     {
134         int i;
135
136         fa = fml->atom_free_list = malloc (sizeof(*fa) * FML_ATOM_CHUNK);
137         if (!fa)
138         {
139             (*fml->err_handle)(FML_ERR_NOMEM);
140             exit (1);
141         }
142         for (i = FML_ATOM_CHUNK-1; --i >= 0; fa++)
143             fa->next = fa+1;
144         fa->next = NULL;
145     }
146     fa = fml->atom_free_list;
147     fml->atom_free_list = fa->next;
148     no_atoms++;
149     return fa;
150 }
151
152 static void atom_delete (Fml fml, struct fml_atom *a)
153 {
154     a->next = fml->atom_free_list;
155     fml->atom_free_list = a;
156     no_atoms--;
157 }
158
159 static struct fml_atom *atom_copy (Fml fml, struct fml_atom *a)
160 {
161     struct fml_atom *a0, *a1;
162
163     a0 = a1 = atom_malloc (fml);
164     while (a)
165     {
166         memcpy (&a1->buf, &a->buf, FML_ATOM_BUF);
167         if (!a->next)
168             break;
169         a = a->next;
170         a1 = a1->next = atom_malloc (fml);
171     }
172     a1->next = NULL;
173     return a0;
174 }
175
176 struct fml_atom *fml_atom_alloc (Fml fml, char *str)
177 {
178     int soff = 0;
179     struct fml_atom *a, *a0;
180
181     a0 = a = atom_malloc (fml);
182     strncpy (a->buf, str, FML_ATOM_BUF);
183     while (strlen (str+soff) >= FML_ATOM_BUF)
184     {
185         struct fml_atom *an;
186
187         an = atom_malloc (fml);
188         a->next = an;
189         soff += FML_ATOM_BUF;
190         strncpy (an->buf, str+soff, FML_ATOM_BUF);
191         a = an;
192     }
193     a->next = NULL;
194     return a0;
195 }
196
197 int fml_atom_cmp (Fml fml, struct fml_atom *a1, struct fml_atom *a2)
198 {
199     while (a1 && a2)
200     {
201         int n;
202         n = strncmp (a1->buf, a2->buf, FML_ATOM_BUF);
203         if (n)
204             return n;
205         a1 = a1->next;
206         a2 = a2->next;
207     }
208     if (!a1 && !a2)
209         return 0;
210     if (a1)
211         return 1;
212     return -1;
213 }
214
215 int fml_atom_str (struct fml_atom *a, char *str)
216 {
217     int i, len = 0;
218
219     assert (a);
220     while (a->next)
221     {
222         if (str)
223             memcpy (str+len, a->buf, FML_ATOM_BUF);
224         len += FML_ATOM_BUF;
225         a = a->next;
226     }
227     for (i=0; i<FML_ATOM_BUF && a->buf[i]; i++)
228         ;
229     if (str)
230     {
231         memcpy (str+len, a->buf, i);
232         str[len+i] = 0;
233     }
234     len += i;
235     return len;
236 }
237
238 void fml_atom_strx (struct fml_atom *a, char *str, int max)
239 {
240     int len = 0;
241
242     assert (a);
243     while (a->next && len < max - 2*FML_ATOM_BUF)
244     {
245         memcpy (str+len, a->buf, FML_ATOM_BUF);
246         len += FML_ATOM_BUF;
247         a = a->next;
248     }
249     strncpy (str+len, a->buf, FML_ATOM_BUF-1);
250     str[len+FML_ATOM_BUF-1] = '\0';
251 }
252
253 int fml_atom_len (struct fml_atom *a)
254 {
255     int len = 0;
256     if (a)
257     {
258         while (a->next)
259         {
260             len += FML_ATOM_BUF;
261             a = a->next;
262         }
263         len += strlen (a->buf);
264     } 
265     return len;
266 }
267
268 int fml_atom_val (struct fml_atom *a)
269 {
270     static char arg[256];
271     assert (a);
272     if (!a->next)
273         return atoi (a->buf);
274     fml_atom_strx (a, arg, 200);
275     return atoi (arg);
276 }
277
278 struct fml_node *fml_mk_node_val (Fml fml, int val)
279 {
280     static char arg[64];
281     struct fml_node *fn;
282
283     sprintf (arg, "%d", val);
284     fn = fml_node_alloc (fml);
285     fn->is_atom = 1;
286     fn->p[0] = fml_atom_alloc (fml, arg);
287     return fn;
288 }
289
290 void fml_node_delete (Fml fml, struct fml_node *fn)
291 {
292     struct fml_node *f1;
293     while (fn)
294     {
295         if (fn->is_atom)
296             atom_delete (fml, fn->p[0]);
297         else
298             fml_node_delete (fml, fn->p[0]);
299         f1 = fn->p[1];
300         
301         fn->p[1] = fml->node_free_list;
302         fml->node_free_list = fn;
303         no_nodes--;
304
305         fn = f1;
306     }
307 }
308
309 struct fml_node *fml_node_copy (Fml fml, struct fml_node *fn)
310 {
311     struct fml_node *fn0, *fn1;
312
313     if (!fn)
314         return NULL;
315     fn1 = fn0 = fml_node_alloc (fml);
316     while (1)
317     {
318         if (fn->is_atom)
319         {
320             fn1->is_atom = 1;
321             fn1->p[0] = atom_copy (fml, fn->p[0]);
322         }
323         else 
324             fn1->p[0] = fml_node_copy (fml, fn->p[0]);
325         if (!fn->p[1])
326             break;
327         fn = fn->p[1];
328         fn1 = fn1->p[1] = fml_node_alloc (fml);
329     }
330     return fn0;
331 }
332
333 void fml_node_stat (Fml fml)
334 {
335     if (fml->debug & 2)
336         printf ("<<node=%d, atom=%d>>", no_nodes, no_atoms);
337 }
338
339 struct fml_atom *fml_atom_strsub (Fml fml, struct fml_atom *a, int o, int l)
340 {
341     static char buf[512];
342     char *cp;
343     struct fml_atom *an;
344     int ol = fml_atom_len (a);
345
346     if (ol >= 510)
347     {
348         cp = malloc (ol + 1);
349         assert (cp);
350     }
351     else
352         cp = buf;
353     fml_atom_str (a, buf);
354     if (o + l < ol)
355         buf[o+l] = '\0';
356     an = fml_atom_alloc (fml, buf+o);
357     if (ol >= 510)
358         free (cp);
359     return an;
360 }