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