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