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