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