/[webpac]/trunk/openisis/lfdt.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/openisis/lfdt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (hide annotations)
Mon Mar 8 17:49:13 2004 UTC (20 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 25042 byte(s)
including openisis 0.9.0 into webpac tree

1 dpavlin 237 /*
2     openisis - an open implementation of the CDS/ISIS database
3     Version 0.8.x (patchlevel see file Version)
4     Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5    
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10    
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     Lesser General Public License for more details.
15    
16     You should have received a copy of the GNU Lesser General Public
17     License along with this library; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19    
20     see README for more information
21     EOH */
22    
23     /*
24     $Id: lfdt.c,v 1.25 2003/06/15 15:57:43 mawag Exp $
25     implementation of FDT calls and static FDTs.
26     */
27    
28     #include <limits.h> /* CHAR_MAX,PATH_MAX */
29     #include <stdio.h>
30     #include <string.h>
31    
32     #include "openisis.h"
33     #include "loi.h"
34     #include "lfdt.h"
35     #include "luti.h"
36    
37     #define FDF_EXT ".fdt"
38     #define FDF_NAMLEN 30
39     #define FDF_PATLEN 20 /* format of *.fdt */
40     #define FDF_TOOLEN 6
41    
42     #if FDF_NAMLEN >= FD_NAMELEN
43     fix me
44     #endif
45    
46     /* ************************************************************
47     private types
48     */
49    
50     /* ************************************************************
51     private data
52     */
53    
54     #define _FD_DFLTDB \
55     { OPENISIS_SC_DFLTDB, 0, FTX, 0, 0, DBNLEN, "defaultdb", \
56     "Name of default db", 0, 0, 0, 0 }
57    
58     #define _FD_DPATH \
59     { OPENISIS_DPATH, 0, FTX, 0, 0, PATH_MAX, "dbpath", \
60     "Database Path", 0, 0, 0, 0 }
61    
62     #define _FD_DENC \
63     { OPENISIS_DENC, 0, FTX, 0, 0, 32, "encoding", \
64     "Encoding", 0, 0, 0, 0 }
65    
66     static Fd _fdsys[] = {
67     /* 700 ... OpenIsis system parameters */
68     { OPENISIS_SPATH, 0, FTX, 0, 0, PATH_MAX, "syspath",
69     "Global Database Path", 0, 0, 0, 0 },
70     { OPENISIS_SLOGF, 0, FTX, 0, 0, PATH_MAX, "logfile",
71     "Logfile Name", 0, 0, 0, 0 },
72     { OPENISIS_SLOGV, 0, FTE, 0, 0, 16, "v",
73     "Verbosity of Logging", 0, 0, 0, 0 },
74     { OPENISIS_SLOGV, 0, FTV, 0, 0, 0, "off",
75     "don't log anything", 0, 0, 0, 0 },
76     { OPENISIS_SLOGV, 0, FTV, 0, 0, 1, "fatal", "", 0, 0, 0, 0 },
77     { OPENISIS_SLOGV, 0, FTV, 0, 0, 3, "syserr", "", 0, 0, 0, 0 },
78     { OPENISIS_SLOGV, 0, FTV, 0, 0, 4, "error", "", 0, 0, 0, 0 },
79     { OPENISIS_SLOGV, 0, FTV, 0, 0, 5, "warn", "", 0, 0, 0, 0 },
80     { OPENISIS_SLOGV, 0, FTV, 0, 0, 6, "info", "", 0, 0, 0, 0 },
81     { OPENISIS_SLOGV, 0, FTV, 0, 0, 7, "verbose", "", 0, 0, 0, 0 },
82     { OPENISIS_SLOGV, 0, FTV, 0, 0, 8, "trace", "", 0, 0, 0, 0 },
83     { OPENISIS_SLOGV, 0, FTV, 0, 0, 9, "debug", "", 0, 0, 0, 0 },
84     { OPENISIS_SLOGV, 0, FTV, 0, 0, 10, "all", "", 0, 0, 0, 0 },
85     _FD_DFLTDB,
86     _FD_DPATH,
87     _FD_DENC
88     };
89     static Fdt _fdtsys = {
90     sizeof (_fdsys) / sizeof (_fdsys[0]),
91     _fdsys,
92     0
93     };
94    
95     static Fd _fdsch[] = {
96     { OPENISIS_SC_NAME, 0, FTX, 0, 0, SCNLEN, "name",
97     "Identification of remote scheme", 0, 0, 0, 0 },
98     { OPENISIS_SC_HOST, 0, FTX, 0, 0, 64, "host",
99     "Hostname of remote scheme", 0, 0, 0, 0 },
100     { OPENISIS_SC_PORT, 0, FTN, 0, 0, 5, "port",
101     "Port of remote scheme", 0, 0, 0, 0 },
102     _FD_DFLTDB,
103     _FD_DPATH,
104     _FD_DENC
105     };
106     static Fdt _fdtsch = {
107     sizeof (_fdsch) / sizeof (_fdsch[0]),
108     _fdsch,
109     0
110     };
111    
112     static Fd _fddb[] = {
113     { OPENISIS_DNAME, 0, FTX, 0, 0, DBNLEN, "db",
114     "Identification of database", 0, 0, 0, 0 },
115     { OPENISIS_DTYPE, 0, FTE, 0, 0, 256, "format",
116     "Database Format", 0, 0, 0, 0 },
117     { OPENISIS_DTYPE, 0, FTV, 0, 0, 0, "autoformat",
118     "Database Format", 0, 0, 0, 0 },
119     { OPENISIS_DTYPE, 0, FTV, 0, 0, 1, "naligned",
120     "Database Format", 0, 0, 0, 0 },
121     { OPENISIS_DTYPE, 0, FTV, 0, 0, 2, "aligned",
122     "Database Format", 0, 0, 0, 0 },
123     { OPENISIS_DRO , 0, FTB, 0, 0, 1, "ro",
124     "Readonly Flag", 0, 0, 0, 0 },
125     _FD_DPATH,
126     { OPENISIS_DDUMP, 0, FTB, 0, 0, 1, "internaldump",
127     "Internal Dump Flag", 0, 0, 0, 0 },
128     _FD_DENC,
129     { OPENISIS_DFDT, 0, FTX, 0, 0, 256, "fdt",
130     "Path to fdt", 0, 0, 0, 0 }
131     };
132     static Fdt _fdtdb = {
133     sizeof (_fddb) / sizeof (_fddb[0]),
134     _fddb,
135     0
136     };
137    
138     static Fd _fdfd[] = {
139     { OPENISIS_FDID, 0, FTN, 0, 0, 10, "tag",
140     "Tag number of field", 0, 0, 0, 0 },
141     { OPENISIS_FDSUB, 0, FTX, 0, 0, 1, "subfield",
142     "Subfield", 0, 0, 0, 0 },
143     { OPENISIS_FDTYPE, 0, FTE, 0, 0, 2, "type",
144     "Field type", 0, 0, 0, 0 },
145     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTX, "alphanum",
146     "Field type", 0, 0, 0, 0 },
147     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTA, "alpha",
148     "Field type", 0, 0, 0, 0 },
149     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTN, "numeric",
150     "Field type", 0, 0, 0, 0 },
151     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTP, "pattern",
152     "Field type", 0, 0, 0, 0 },
153     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTI, "iso",
154     "Field type", 0, 0, 0, 0 },
155     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTE, "enum",
156     "Field type", 0, 0, 0, 0 },
157     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTB, "boolean",
158     "Field type", 0, 0, 0, 0 },
159     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTT, "table",
160     "Field type", 0, 0, 0, 0 },
161     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTS, "structure",
162     "Field type", 0, 0, 0, 0 },
163     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTX, "subalphanum",
164     "Subfield type", 0, 0, 0, 0 },
165     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTA, "subalpha",
166     "Subfield type", 0, 0, 0, 0 },
167     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTN, "subnumeric",
168     "Subfield type", 0, 0, 0, 0 },
169     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTP, "subpattern",
170     "Subfield type", 0, 0, 0, 0 },
171     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTI, "subiso",
172     "Subfield type", 0, 0, 0, 0 },
173     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTE, "subenum",
174     "Subfield type", 0, 0, 0, 0 },
175     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTF | FTB, "subbool",
176     "Subfield type", 0, 0, 0, 0 },
177     { OPENISIS_FDTYPE, 0, FTV, 0, 0, FTV, "enum value",
178     "Enumeration value", 0, 0, 0, 0 },
179     { OPENISIS_FDREP, 0, FTB, 0, 0, 1, "repeatable",
180     "Repeatable flag", 0, 0, 0, 0 },
181     { OPENISIS_FDNUMC, 0, FTN, 0, 0, 2, "numchilds",
182     "Number of subfield childs", 0, 0, 0, 0 },
183     { OPENISIS_FDLEN, 0, FTN, 0, 0, 10, "length",
184     "Field length or enum value", 0, 0, 0, 0 },
185     { OPENISIS_FDNAME, 0, FTX, 0, 0, 30, "name",
186     "Field name", 0, 0, 0, 0 },
187     { OPENISIS_FDDESC, 0, FTX, 0, 0, 31, "description",
188     "Description", 0, 0, 0, 0 },
189     { OPENISIS_FDPAT, 0, FTX, 0, 0, 128, "pattern",
190     "Pattern", 0, 0, 0, 0 },
191     { OPENISIS_FDDFLT, 0, FTX, 0, 0, 1024, "default",
192     "Default value", 0, 0, 0, 0 },
193     { OPENISIS_FDINFO, 0, FTS, 0, 0, 1, "info",
194     "Embedded info record", 0, 0, 0, 0 },
195     { OPENISIS_FDCHLD, 0, FTX, 1, 0, 1, "children",
196     "Subfield childs", 0, 0, 0, 0 }
197     };
198     static Fdt _fdtfd = {
199     sizeof (_fdfd) / sizeof (_fdfd[0]),
200     _fdfd,
201     0
202     };
203    
204     #define _FD_FDT \
205     { OPENISIS_FDT_LEN, 0, FTN, 0, 0, 3, "flen", \
206     "Length of fdt", 0, 0, 0, 0 }, \
207     { OPENISIS_FDT_FD, 0, FTS, 1, 0, 1, "fd", \
208     "Field description", 0, 0, 0, 0 }, \
209     { OPENISIS_FDT_REC, 0, FTS, 0, 0, 1, "frec", \
210     "Embedded info record", 0, 0, 0, 0 }
211    
212     static Fd _fdfdt[] = {
213     _FD_FDT
214     };
215     static Fdt _fdtfdt = {
216     sizeof (_fdfdt) / sizeof (_fdfdt[0]),
217     _fdfdt,
218     0
219     };
220    
221     #define _FD_COM \
222     { OPENISIS_COM_SID, 0, FTN, 0, 0, 2, "sid", \
223     "Client Session Id", 0, 0, 0, 0 }, \
224     { OPENISIS_COM_SER, 0, FTN, 0, 0, 5, "ser", \
225     "Request Serial No.", 0, 0, 0, 0 }, \
226     { OPENISIS_COM_DBN, 0, FTX, 0, 0, DBNLEN, "db", \
227     "DB Identification", 0, 0, 0, 0 }, \
228     { OPENISIS_COM_TMS, 0, FTN, 0, 0, 10, "tms", \
229     "Server Db Timestamp", 0, 0, 0, 0 }, \
230     { OPENISIS_COM_ROW, 0, FTN, 0, 0, 10, "rowid", \
231     "RowId", 0, 0, 0, 0 }, \
232     _FD_FDT, \
233     { OPENISIS_COM_CFG, 0, FTS, 0, 0, 0, "config", \
234     "Config", 0, 0, 0, 0 }, \
235     { OPENISIS_COM_REC, 0, FTS, 1, 0, 0, "rec", \
236     "Data", 0, 0, 0, 0 }
237    
238     static Fd _fdrqs[] = {
239     _FD_COM,
240     { OPENISIS_RQS_TYPE, 0, FTE, 0, 0, 32, "type",
241     "Request type", 0, 0, 0, 0 },
242     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_OPEN, "open",
243     "open db", 0, 0, 0, 0 },
244     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_CLOS, "close",
245     "close db", 0, 0, 0, 0 },
246     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_MNT, "mount",
247     "mount db", 0, 0, 0, 0 },
248     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_LSDB, "ls",
249     "list dbs", 0, 0, 0, 0 },
250     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_MROW, "maxrow",
251     "get maxrowid", 0, 0, 0, 0 },
252     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_QRY, "query",
253     "exec query", 0, 0, 0, 0 },
254     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_READ, "read",
255     "fetch row", 0, 0, 0, 0 },
256     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_INS, "insert",
257     "insert rec", 0, 0, 0, 0 },
258     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_UPD, "update",
259     "update rec", 0, 0, 0, 0 },
260     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_DEL, "delete",
261     "delete row", 0, 0, 0, 0 },
262     { OPENISIS_RQS_TYPE, 0, FTV, 0, 0, OPENISIS_RQST_EVAL, "eval",
263     "evaluate command", 0, 0, 0, 0 },
264     { OPENISIS_RQS_FLG, 0, FTN, 0, 0, 4, "flags",
265     "Request flags", 0, 0, 0, 0 },
266     { OPENISIS_RQS_QMOD, 0, FTN, 0, 0, 5, "mode",
267     "Query Mode", 0, 0, 0, 0 },
268     { OPENISIS_RQS_SKIP, 0, FTN, 0, 0, 5, "skip",
269     "Query Skip", 0, 0, 0, 0 },
270     { OPENISIS_RQS_SIZE, 0, FTN, 0, 0, 5, "size",
271     "Result Length", 0, 0, 0, 0 },
272     { OPENISIS_RQS_KEY, 0, FTX, 0, 0, OPENISIS_QRY_KEYLEN, "key",
273     "Query Key", 0, 0, 0, 0 },
274     { OPENISIS_RQS_IDX, 0, FTS, 0, 0, 0, "idx",
275     "Index to Update", 0, 0, 0, 0 }
276     };
277     static Fdt _fdtrqs = {
278     sizeof (_fdrqs) / sizeof (_fdrqs[0]),
279     _fdrqs,
280     0
281     };
282    
283     static Fd _fdrsp[] = {
284     _FD_COM,
285     { OPENISIS_RSP_DBID, 0, FTN, 0, 0, 2, "dbid",
286     "Id of local db", 0, 0, 0, 0 },
287     { OPENISIS_RSP_ERR, 0, FTN, 0, 0, 5, "error",
288     "Error Code", 0, 0, 0, 0 },
289     { OPENISIS_RSP_MSG, 0, FTX, 0, 0, OPENISIS_ERRMSGLEN, "msg",
290     "Error Message", 0, 0, 0, 0 },
291     { OPENISIS_RSP_NUMT, 0, FTN, 0, 0, 5, "total",
292     "Total No. of Records", 0, 0, 0, 0 },
293     { OPENISIS_RSP_NUMR, 0, FTN, 0, 0, 5, "size",
294     "Number of Records", 0, 0, 0, 0 },
295     { OPENISIS_RSP_CERR, 0, FTN, 0, 0, 5, "error2",
296     "Client Side Error", 0, 0, 0, 0 }
297     };
298     static Fdt _fdtrsp = {
299     sizeof (_fdrsp) / sizeof (_fdrsp[0]),
300     _fdrsp,
301     0
302     };
303    
304     /* ************************************************************
305     public data
306     */
307    
308     const Fdt *openIsisFdtSyspar = &_fdtsys;
309     const Fdt *openIsisFdtScheme = &_fdtsch;
310     const Fdt *openIsisFdtDbpar = &_fdtdb;
311     const Fdt *openIsisFdtFd = &_fdtfd;
312     const Fdt *openIsisFdtFdt = &_fdtfdt;
313     const Fdt *openIsisFdtRqs = &_fdtrqs;
314     const Fdt *openIsisFdtRsp = &_fdtrsp;
315    
316    
317     /* ************************************************************
318     private functions
319     */
320    
321     static char *fFileGets (FILE *fp) {
322     static char buf[4096];
323     char *res;
324     int len;
325     while (1) {
326     nxtl:
327     if (0 == (res = fgets (buf, sizeof(buf) - 1, fp))) {
328     break;
329     }
330     buf[sizeof(buf) - 1] = 0;
331     if (!(len = strlen (res))) {
332     continue;
333     }
334     --len;
335     while (0 <= len) {
336     if ('\n' != res[len] && '\r' != res[len]) {
337     break;
338     }
339     res[len] = 0;
340     if (0 > --len) {
341     goto nxtl;
342     }
343     }
344     break;
345     }
346     return res;
347     }
348    
349     static void strrtrim (char *str) {
350     char *p = str + strlen (str) - 1;
351     while (p >= str && (' ' == *p || '\t' == *p)) {
352     *p-- = 0;
353     }
354     }
355    
356     static void fDesc2Name (char *d, char *n) {
357     while (1) {
358     if (!(*n = *d)) {
359     return;
360     }
361     if ('A' <= *n && 'Z' >= *n) {
362     *n += 'a' - 'A';
363     ++n;
364     ++d;
365     continue;
366     }
367     if ('_' == *n ||
368     ('a' <= *n && 'z' >= *n) ||
369     ('0' <= *n && '9' >= *n)) {
370     ++n;
371     ++d;
372     continue;
373     }
374     while (1) {
375     ++d;
376     if (!*d) {
377     *n = 0;
378     return;
379     }
380     if (('A' <= *d && 'Z' >= *d) ||
381     ('a' <= *d && 'z' >= *d) ||
382     ('0' <= *d && '9' >= *d)) {
383     break;
384     }
385     }
386     *n++ = '_';
387     }
388     }
389    
390     static int fLine2Fd (char *line, Fd **fd, int *num) {
391     char name[FD_NAMELEN];
392     char pat[1 + FDF_PATLEN];
393     Fd buff, bufs;
394     char *P;
395     char *L = line;
396     int tag, len, typ, rep, idx;
397     if (FDF_NAMLEN + FDF_PATLEN >= strlen (L)) {
398     return sMsg (ERR_INVAL, "fFileFd: illegal line <%s>", line);
399     }
400     strncpy (name, L, FDF_NAMLEN) [FDF_NAMLEN] = 0;
401     strrtrim (name);
402     if (! *name) {
403     return sMsg (ERR_INVAL, "fFileFd: no descr in line <%s>", line);
404     }
405     L += FDF_NAMLEN;
406     strncpy (pat, L, FDF_PATLEN) [FDF_PATLEN] = 0;
407     strrtrim (pat);
408     L += FDF_PATLEN;
409     if (4 != sscanf (L, "%d %d %d %d", &tag, &len, &typ, &rep)) {
410     return sMsg (ERR_INVAL, "fFileFd: no type in line <%s>", line);
411     }
412     switch (typ) {
413     case 0: typ = FTX; break;
414     case 1: typ = FTA; break;
415     case 2: typ = FTN; break;
416     case 3: typ = FTP; break;
417     default: return sMsg (ERR_INVAL,
418     "fFileFd: unrecognized type %d in line <%s>", typ, line);
419     }
420     memset (&buff, 0, sizeof (Fd));
421     buff.id = tag;
422     buff.type = typ;
423     buff.rep = 0 != rep;
424     buff.len = len;
425     strcpy (buff.desc, name);
426     fDesc2Name (name, buff.name);
427     if (! *buff.name) {
428     return sMsg (ERR_INVAL, "fFileFd: illegal name in line <%s>", line);
429     }
430     if (FTP == typ) {
431     if (! *pat) {
432     return sMsg (ERR_INVAL, "fFileFd: illegal pat in line <%s>", line);
433     }
434     buff.pat = mDup (pat, -1);
435     if (! buff.pat) {
436     return sMsg (ERR_NOMEM, "fFileFd: cannot allocate pat");
437     }
438     }
439     idx = luti_ptrincr (fd, num, 1, sizeof(Fd), -1);
440     if (0 > idx) {
441     return sMsg (ERR_NOMEM,
442     "fFileFd: cannot extend fd array %d", *num);
443     }
444     memcpy (*fd + idx, &buff, sizeof(Fd));
445     if (FTP != typ) {
446     for (P = pat; *P; ++P) {
447     memcpy (&bufs, &buff, sizeof(Fd));
448     bufs.subf = *P;
449     bufs.type = FTX;
450     idx = luti_ptrincr (fd, num, 1, sizeof(Fd), -1);
451     if (0 > idx) {
452     return sMsg (ERR_NOMEM,
453     "fFileFd: cannot extend fd array %d", *num);
454     }
455     memcpy (*fd + idx, &bufs, sizeof(Fd));
456     }
457     }
458     return 0;
459     }
460    
461     static int fLine2Tool (char *line, Rec **rec) {
462     char tool[1 + FDF_TOOLEN];
463     char *L = line;
464     int len, typ;
465     switch (*L) {
466     case 'w':
467     case 'W':
468     typ = OPENISIS_DFMT;
469     break;
470     case 'f':
471     case 'F':
472     typ = OPENISIS_DPFT;
473     break;
474     case 's':
475     case 'S':
476     typ = OPENISIS_DFST;
477     break;
478     default:
479     return sMsg (ERR_INVAL, "fLine2Tool: illegal line <%s>", line);
480     }
481     L += 2;
482     len = strlen (L);
483     while (0 < len) {
484     strncpy (tool, L, FDF_TOOLEN) [FDF_TOOLEN] = 0;
485     strrtrim (tool);
486     RADDS (*rec, typ, tool, !0);
487     if (! *rec) {
488     return sMsg (ERR_NOMEM, "fLine2Tool: cannot extend rec");
489     }
490     L += FDF_TOOLEN;
491     len -= FDF_TOOLEN;
492     }
493     return 0;
494     }
495    
496     static int fResolveChilds (Fd *fd, int len) {
497     char msg[256] = { 0 };
498     Fd *buf[CHAR_MAX];
499     Fd **C;
500     Fd *F, *G;
501     int numc;
502     int err = 0;
503     for (F = fd + len; --F >= fd; ) {
504     if (! F->subf) {
505     numc = 0;
506     C = buf;
507     for (G = fd + len; --G >= fd; ) {
508     if (G->subf && (! G->id || G->id == F->id)) {
509     if (CHAR_MAX == numc) {
510     err = ERR_INVAL;
511     sprintf (msg,
512     "fResolveChilds: too many childs for %s",
513     F->name);
514     break;
515     }
516     *C++ = G;
517     ++numc;
518     }
519     }
520     if (numc) {
521     C = mAlloc (numc * sizeof(Fd));
522     if (! C) {
523     return sMsg (ERR_NOMEM, "fResolveChilds");
524     }
525     F->subs = (Fd**) memcpy (C, buf, numc * sizeof(Fd));
526     F->slen = numc;
527     }
528     }
529     }
530     if (err) {
531     return sMsg (err, msg);
532     }
533     return 0;
534     }
535    
536     static void fFreeFd (Fd *fd) {
537     if (fd) {
538     if (fd->pat) {
539     mFree (fd->pat);
540     }
541     if (fd->dflt) {
542     mFree (fd->dflt);
543     }
544     if (fd->info) {
545     mFree (fd->info);
546     }
547     if (fd->subs) {
548     mFree (fd->subs);
549     }
550     }
551     }
552    
553     static Fdt* fCleanupArr (Fdt *fdt, Fd *arr, int len) {
554     Fd *F;
555     for (F = arr + len; --F >= arr; ) {
556     fFreeFd (F);
557     }
558     mFree (arr);
559     mFree (fdt);
560     return 0;
561     }
562    
563     /* ************************************************************
564     package functions
565     */
566    
567     /* ************************************************************
568     public functions
569     */
570    
571     Fd* fById ( const Fdt *fdt, int id, int subf )
572     {
573     Fd *f, *e;
574     if (! fdt) {
575     return 0;
576     }
577     for (e = (f = fdt->fd) + fdt->len; --e >= f; ) {
578     if (id == e->id && subf == e->subf && ! (0xf0 & e->type)) {
579     return e;
580     }
581     }
582     return 0;
583     }
584    
585     Fd* fByName ( const Fdt *fdt, const char *name )
586     {
587     Fd *f, *e, *g;
588     const char *p;
589     int l, cnt;
590     if (! fdt || ! name) {
591     return 0;
592     }
593     f = fdt->fd;
594     e = f + fdt->len;
595     if ( '-' == *name ) /* ignore leading dash */
596     name++;
597     if (! *name) {
598     return 0;
599     }
600     if ( '0' <= *name && *name <= '9' )
601     return fById( fdt, a2i( name, -1 ), 0 );
602     p = name;
603     while ( 'a' <= *p ? *p <= 'z' : '9' >= *p ? *p >= '0' : '_' == *p )
604     p++;
605     l = p - name;
606     if ( ! l || l > FD_NAMELEN - 1 )
607     return 0;
608     for ( cnt = 0, g = 0; f < e; f++ ) {
609     if ( *name == *f->name
610     && !(0xf0 & f->type) /* is field */
611     && !memcmp( name, f->name, l ) ) {
612     if (!f->name[l]) {
613     return f;
614     }
615     g = f;
616     ++cnt;
617     }
618     }
619     return 1 == cnt ? g : 0;
620     }
621    
622     /**
623     lookup enum:
624     if name is numeric, the value is returned, if legal
625     considered are value entries with given id or id 0
626     - if there is an exact match with same id, this is used
627     - if there is an exact match with id 0, this is used
628     - if name is a unique prefix on given id, this is used
629     - if name is no prefix on given id, but a unique prefix on 0, this is used
630     */
631     int fEnum ( Fdt *fdt, int id, const char *name )
632     {
633     Fd *f = fdt->fd, *e = f + fdt->len,
634     *x0 = 0, *pi = 0, *p0 = 0;
635     int ui = 1, u0 = 1; /* unique */
636     int l = strlen( name );
637     if ( ! l || l > FD_NAMELEN - 1 )
638     return NOENUM;
639     if ( ('0' <= *name && *name <= '9')
640     || ('-' == *name && '0' <= name[1] && name[1] <= '9')
641     ) {
642     int v = a2i( name, l );
643     for ( ; f < e; f++ ) {
644     if ( FTV == f->type && v == f->len && (f->id == id || !f->id) )
645     return v;
646     }
647     return NOENUM;
648     }
649     for ( ; f < e; f++ ) {
650     if ( FTV != f->type
651     || *name != *f->name
652     || memcmp( name, f->name, l )
653     || (f->id && f->id != id)
654     )
655     continue;
656     if ( !f->name[l] ) { /* exact match */
657     if ( f->id == id )
658     return f->len;
659     x0 = f; /* f->id is 0 */
660     continue;
661     }
662     /* prefix match */
663     if ( f->id == id ) {
664     if ( pi )
665     ui = 0;
666     else
667     pi = f;
668     } else
669     if ( p0 )
670     u0 = 0;
671     else
672     p0 = f;
673     }
674     return x0 ? x0->len
675     : pi ? (ui ? pi->len : NOENUM)
676     : p0 && u0 ? p0->len : NOENUM;
677     }
678    
679     Fdt* fFree ( Fdt *fdt ) {
680     Fd *F, *E;
681     if (fdt) {
682     if (fdt->fd) {
683     for (E = (F = fdt->fd) + fdt->len; --E >= F; ) {
684     fFreeFd (E);
685     }
686     mFree (fdt->fd);
687     }
688     if (fdt->rec) {
689     mFree (fdt->rec);
690     }
691     mFree (fdt);
692     }
693     return 0;
694     }
695    
696     Fdt* fFromFile (char *path) {
697     FILE *fp;
698     char *line;
699     Fdt *res;
700     Fd *fd;
701     Rec *rec;
702     int len, err;
703    
704     /* ldb::setext */
705     len = strlen (path) - 4;
706     memcpy (path + len, FDF_EXT, 4);
707     if ( 'A'<=path[len-1] && path[len-1]<= 'Z' ) {
708     char *p = path + len;
709     for ( ;*p; p++ ) /* use uppercase extensions */
710     if ( 'a' <= *p && *p <= 'z' )
711     *p -= 'a'-'A';
712     }
713    
714     fp = fopen (path, "r");
715     if (! fp) {
716     sMsg (LOG_INFO | ERR_BADF, "no such fdt: %s", path);
717     return 0;
718     }
719     res = mAlloc (sizeof(Fdt));
720     if (! res) {
721     fclose (fp);
722     sMsg (ERR_NOMEM, "fFromFile");
723     return 0;
724     }
725     sMsg (LOG_VERBOSE, "> reading fdt: %s", path);
726    
727     fd = 0;
728     rec = 0;
729     err = len = 0;
730     while ((line = fFileGets (fp))) {
731     if ('*' == *line) {
732     continue;
733     }
734     if (':' == line[1]) {
735     if (-ERR_NOMEM == (err = fLine2Tool (line, &rec))) {
736     break;
737     }
738     continue;
739     }
740     if (-ERR_NOMEM == (err = fLine2Fd (line, &fd, &len))) {
741     break;
742     }
743     }
744    
745     fclose (fp);
746     res->fd = fd;
747     res->rec = rec;
748     res->len = len;
749    
750     if (-ERR_NOMEM == err) {
751     return fFree (res);
752     }
753    
754     sMsg (LOG_VERBOSE, "< %d entries in fdt", len);
755     return res;
756     }
757    
758     #define ADDFDS(tag,val) \
759     RADDS (rec, tag, val, !0); \
760     if (! rec) { return 0; }
761    
762     Rec* fFd2Rec (const Fd *fd, Rec *rec, int embchld) {
763     char buf[16];
764     Fd **E, **F;
765     Rec *child;
766     if (! fd) {
767     return rec;
768     }
769     i2a (buf, fd->id);
770     ADDFDS (OPENISIS_FDID, buf);
771     if ((*buf = fd->subf)) {
772     buf[1] = 0;
773     ADDFDS (OPENISIS_FDSUB, buf);
774     }
775     i2a (buf, fd->type);
776     ADDFDS (OPENISIS_FDTYPE, buf);
777     i2a (buf, fd->rep);
778     ADDFDS (OPENISIS_FDREP, buf);
779     i2a (buf, fd->len);
780     ADDFDS (OPENISIS_FDLEN, buf);
781     ADDFDS (OPENISIS_FDNAME, fd->name);
782     ADDFDS (OPENISIS_FDDESC, fd->desc);
783     if (fd->pat) {
784     ADDFDS (OPENISIS_FDPAT, fd->pat);
785     }
786     if (fd->dflt) {
787     ADDFDS (OPENISIS_FDDFLT, fd->dflt);
788     }
789     if (fd->info) {
790     rec = luti_wrap (rec, fd->info, OPENISIS_FDINFO);
791     if (! rec) {
792     return 0;
793     }
794     }
795     if (embchld && fd->slen) {
796     for (E = (F = fd->subs) + fd->slen; rec && F < E; ++F) {
797     child = fFd2Rec (*F, 0, 0);
798     if (! child) {
799     return rec;
800     }
801     rec = luti_wrap (rec, child, OPENISIS_FDCHLD);
802     }
803     if (rec) {
804     rec = rAddI (rec, OPENISIS_FDNUMC, fd->slen, !0);
805     }
806     }
807     return rec;
808     }
809    
810     Rec* fFdt2Rec (const Fdt *fdt, Rec *rec, int embchld) {
811     Fd *E, *F;
812     Rec *R;
813     int len;
814     if (! fdt) {
815     return rec;
816     }
817     if (fdt->rec) {
818     rec = luti_wrap (rec, fdt->rec, OPENISIS_FDT_REC);
819     if (! rec) { return 0; }
820     }
821     for (E = (F = fdt->fd) + fdt->len, len = 0; F < E; ++F) {
822     if (! F->subf || ! embchld) {
823     R = fFd2Rec (F, 0, embchld);
824     if (! R) {
825     return rec;
826     }
827     rec = luti_wrap (rec, R, OPENISIS_FDT_FD);
828     mFree (R);
829     if (! rec) {
830     return 0;
831     }
832     ++len;
833     }
834     }
835     rec = rAddI (rec, OPENISIS_FDT_LEN, len, !0);
836     return rec;
837     }
838    
839     Fd *fRec2Fd (Rec *rec, Fd *buf) {
840     char name[FD_NAMELEN];
841     Field *F, *E;
842     Fd *fd;
843     int got = 0;
844     if (! rec) {
845     return 0;
846     }
847     if (! (fd = buf)) {
848     fd = mAlloc (sizeof(Fd));
849     if (! fd) {
850     return 0;
851     }
852     }
853     *name = 0;
854     for (E = (F = rec->field) + rec->len; F < E; ++F) {
855     switch (F->tag) {
856     case OPENISIS_FDID:
857     got |= 0x01;
858     fd->id = a2id (F->val, F->len, 0);
859     break;
860     case OPENISIS_FDSUB:
861     if (! (1 == F->len || (2 == F->len && ! F->val[1]))) {
862     sMsg (ERR_INVAL,
863     "fRec2Fd: ignoring illegal subfield id (%s)", name);
864     }
865     else {
866     fd->subf = F->val[0];
867     }
868     break;
869     case OPENISIS_FDTYPE:
870     got |= 0x02;
871     fd->type = (char) a2id (F->val, F->len, 0);
872     break;
873     case OPENISIS_FDREP:
874     if (! (1 == F->len || (2 == F->len && ! F->val[1]))) {
875     sMsg (ERR_INVAL,
876     "fRec2Fd: ignoring illegal repeatable flag (%s)", name);
877     }
878     else {
879     fd->rep = F->val[0] && '0' != F->val[0];
880     }
881     break;
882     case OPENISIS_FDLEN:
883     fd->len = (short) a2id (F->val, F->len, 0);
884     break;
885     case OPENISIS_FDNAME:
886     got |= 0x04;
887     if (FD_NAMELEN <= F->len) {
888     memcpy (name, F->val, FD_NAMELEN - 1);
889     name[FD_NAMELEN - 1] = 0;
890     sMsg (ERR_INVAL,
891     "fRec2Fd: name too long (%d) - truncated to %s",
892     F->len, name);
893     }
894     else {
895     memcpy (name, F->val, F->len);
896     name[F->len] = 0;
897     }
898     if (! *fd->desc) {
899     strcpy (fd->desc, name);
900     }
901     fDesc2Name (name, fd->name);
902     if (!*(fd->name)) {
903     sMsg (ERR_INVAL,
904     "fRec2Fd: illegal name (%s)", name);
905     got &= ~0x04;
906     }
907     break;
908     case OPENISIS_FDDESC:
909     if (FD_NAMELEN <= F->len) {
910     memcpy (fd->desc, F->val, FD_NAMELEN - 1);
911     fd->desc[FD_NAMELEN - 1] = 0;
912     sMsg (ERR_INVAL,
913     "fRec2Fd: descr too long (%d) - truncated to %s (%s)",
914     F->len, fd->desc, name);
915     }
916     else {
917     memcpy (fd->desc, F->val, F->len);
918     fd->desc[F->len] = 0;
919     }
920     break;
921     case OPENISIS_FDPAT:
922     if (fd->pat) {
923     sMsg (ERR_INVAL,
924     "fRec2Fd: ignoring multiple occurences of pattern (%s)",
925     name);
926     }
927     else {
928     fd->pat = (char*) mAlloc (1 + F->len);
929     if (! fd->pat) {
930     goto err;
931     }
932     memcpy (fd->pat, F->val, F->len);
933     fd->pat[F->len] = 0;
934     }
935     break;
936     case OPENISIS_FDDFLT:
937     if (fd->dflt) {
938     sMsg (ERR_INVAL,
939     "fRec2Fd: ignoring multiple occurences of dflt (%s)",
940     name);
941     }
942     else {
943     fd->dflt = (char*) mAlloc (1 + F->len);
944     if (! fd->dflt) {
945     goto err;
946     }
947     memcpy (fd->dflt, F->val, F->len);
948     fd->dflt[F->len] = 0;
949     }
950     break;
951     case OPENISIS_FDINFO:
952     if (fd->info) {
953     sMsg (ERR_INVAL,
954     "fRec2Fd: ignoring multiple occurences of info (%s)",
955     name);
956     }
957     else {
958     int pos = F - rec->field;
959     fd->info = luti_unwrap (rec, &pos, OPENISIS_FDINFO, -1);
960     if (! fd->info) {
961     goto err;
962     }
963     F = rec->field + pos - 1;
964     }
965     break;
966     default:
967     sMsg (ERR_INVAL,
968     "fRec2Fd: ignoring unexpected tag %d (%s)",
969     F->tag, name);
970     }
971     }
972     if (0x07 != got) {
973     sMsg (ERR_TRASH,
974     "fRec2Fd: incomplete field description [%x] (%s)", got, name);
975     err:
976     if (fd->pat) { mFree (fd->pat); }
977     if (fd->dflt) { mFree (fd->dflt); }
978     if (fd->info) { mFree (fd->info); }
979     if (fd != buf) { mFree (fd); }
980     return 0;
981     }
982     return fd;
983     }
984    
985     Fdt *fRec2Fdt (Rec *rec) {
986     Rec *R, *cfg;
987     Fdt *fdt;
988     Fd fdbuf;
989     Fd *F, *arr;
990     int err, num, len, pos;
991     if (!rec) {
992     return 0;
993     }
994     num = rInt (rec, OPENISIS_FDT_LEN, 0, 0);
995     if (0 >= num) {
996     return 0;
997     }
998     arr = (Fd*) mAlloc (num * sizeof (Fd));
999     if (!arr) {
1000     return 0;
1001     }
1002     fdt = (Fdt*) mAlloc (sizeof(Fdt));
1003     if (! fdt) {
1004     mFree (arr);
1005     return 0;
1006     }
1007     for (F = arr, len = pos = 0; num; --num) {
1008     R = luti_unwrap (rec, &pos, OPENISIS_FDT_FD, -1);
1009     if (!R) {
1010     return fCleanupArr (fdt, arr, len);
1011     }
1012     memset (&fdbuf, 0, sizeof(Fd));
1013     if (fRec2Fd (R, &fdbuf)) {
1014     memcpy (F, &fdbuf, sizeof(Fd));
1015     ++len;
1016     ++F;
1017     }
1018     mFree (R);
1019     }
1020     if (len != num) {
1021     num = len * sizeof(Fd);
1022     F = (Fd*) mAlloc (num);
1023     if (! F) {
1024     return fCleanupArr (fdt, arr, len);
1025     }
1026     memcpy (F, arr, num);
1027     mFree (arr);
1028     arr = F;
1029     }
1030     cfg = luti_unwrap (rec, 0, OPENISIS_FDT_REC, -1);
1031     fdt->len = len;
1032     fdt->fd = arr;
1033     fdt->rec = cfg;
1034     err = fResolveChilds (arr, len);
1035     if (-ERR_NOMEM == err) {
1036     return fFree (fdt);
1037     }
1038     return fdt;
1039     }
1040    

  ViewVC Help
Powered by ViewVC 1.1.26