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
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.
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.
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
20 see README for more information
24 $Id: lfdt.c,v 1.25 2003/06/15 15:57:43 mawag Exp $
25 implementation of FDT calls and static FDTs.
28 #include <limits.h> /* CHAR_MAX,PATH_MAX */
37 #define FDF_EXT ".fdt"
39 #define FDF_PATLEN 20 /* format of *.fdt */
42 #if FDF_NAMLEN >= FD_NAMELEN
46 /* ************************************************************
50 /* ************************************************************
55 { OPENISIS_SC_DFLTDB, 0, FTX, 0, 0, DBNLEN, "defaultdb", \
56 "Name of default db", 0, 0, 0, 0 }
59 { OPENISIS_DPATH, 0, FTX, 0, 0, PATH_MAX, "dbpath", \
60 "Database Path", 0, 0, 0, 0 }
63 { OPENISIS_DENC, 0, FTX, 0, 0, 32, "encoding", \
64 "Encoding", 0, 0, 0, 0 }
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 },
89 static Fdt _fdtsys = {
90 sizeof (_fdsys) / sizeof (_fdsys[0]),
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 },
106 static Fdt _fdtsch = {
107 sizeof (_fdsch) / sizeof (_fdsch[0]),
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 },
126 { OPENISIS_DDUMP, 0, FTB, 0, 0, 1, "internaldump",
127 "Internal Dump Flag", 0, 0, 0, 0 },
129 { OPENISIS_DFDT, 0, FTX, 0, 0, 256, "fdt",
130 "Path to fdt", 0, 0, 0, 0 }
132 static Fdt _fdtdb = {
133 sizeof (_fddb) / sizeof (_fddb[0]),
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 }
198 static Fdt _fdtfd = {
199 sizeof (_fdfd) / sizeof (_fdfd[0]),
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 }
212 static Fd _fdfdt[] = {
215 static Fdt _fdtfdt = {
216 sizeof (_fdfdt) / sizeof (_fdfdt[0]),
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 }, \
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", \
238 static Fd _fdrqs[] = {
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 }
277 static Fdt _fdtrqs = {
278 sizeof (_fdrqs) / sizeof (_fdrqs[0]),
283 static Fd _fdrsp[] = {
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 }
298 static Fdt _fdtrsp = {
299 sizeof (_fdrsp) / sizeof (_fdrsp[0]),
304 /* ************************************************************
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;
317 /* ************************************************************
321 static char *fFileGets (FILE *fp) {
322 static char buf[4096];
327 if (0 == (res = fgets (buf, sizeof(buf) - 1, fp))) {
330 buf[sizeof(buf) - 1] = 0;
331 if (!(len = strlen (res))) {
336 if ('\n' != res[len] && '\r' != res[len]) {
349 static void strrtrim (char *str) {
350 char *p = str + strlen (str) - 1;
351 while (p >= str && (' ' == *p || '\t' == *p)) {
356 static void fDesc2Name (char *d, char *n) {
361 if ('A' <= *n && 'Z' >= *n) {
368 ('a' <= *n && 'z' >= *n) ||
369 ('0' <= *n && '9' >= *n)) {
380 if (('A' <= *d && 'Z' >= *d) ||
381 ('a' <= *d && 'z' >= *d) ||
382 ('0' <= *d && '9' >= *d)) {
390 static int fLine2Fd (char *line, Fd **fd, int *num) {
391 char name[FD_NAMELEN];
392 char pat[1 + FDF_PATLEN];
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);
400 strncpy (name, L, FDF_NAMLEN) [FDF_NAMLEN] = 0;
403 return sMsg (ERR_INVAL, "fFileFd: no descr in line <%s>", line);
406 strncpy (pat, L, FDF_PATLEN) [FDF_PATLEN] = 0;
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);
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);
420 memset (&buff, 0, sizeof (Fd));
425 strcpy (buff.desc, name);
426 fDesc2Name (name, buff.name);
428 return sMsg (ERR_INVAL, "fFileFd: illegal name in line <%s>", line);
432 return sMsg (ERR_INVAL, "fFileFd: illegal pat in line <%s>", line);
434 buff.pat = mDup (pat, -1);
436 return sMsg (ERR_NOMEM, "fFileFd: cannot allocate pat");
439 idx = luti_ptrincr (fd, num, 1, sizeof(Fd), -1);
441 return sMsg (ERR_NOMEM,
442 "fFileFd: cannot extend fd array %d", *num);
444 memcpy (*fd + idx, &buff, sizeof(Fd));
446 for (P = pat; *P; ++P) {
447 memcpy (&bufs, &buff, sizeof(Fd));
450 idx = luti_ptrincr (fd, num, 1, sizeof(Fd), -1);
452 return sMsg (ERR_NOMEM,
453 "fFileFd: cannot extend fd array %d", *num);
455 memcpy (*fd + idx, &bufs, sizeof(Fd));
461 static int fLine2Tool (char *line, Rec **rec) {
462 char tool[1 + FDF_TOOLEN];
479 return sMsg (ERR_INVAL, "fLine2Tool: illegal line <%s>", line);
484 strncpy (tool, L, FDF_TOOLEN) [FDF_TOOLEN] = 0;
486 RADDS (*rec, typ, tool, !0);
488 return sMsg (ERR_NOMEM, "fLine2Tool: cannot extend rec");
496 static int fResolveChilds (Fd *fd, int len) {
497 char msg[256] = { 0 };
503 for (F = fd + len; --F >= fd; ) {
507 for (G = fd + len; --G >= fd; ) {
508 if (G->subf && (! G->id || G->id == F->id)) {
509 if (CHAR_MAX == numc) {
512 "fResolveChilds: too many childs for %s",
521 C = mAlloc (numc * sizeof(Fd));
523 return sMsg (ERR_NOMEM, "fResolveChilds");
525 F->subs = (Fd**) memcpy (C, buf, numc * sizeof(Fd));
531 return sMsg (err, msg);
536 static void fFreeFd (Fd *fd) {
553 static Fdt* fCleanupArr (Fdt *fdt, Fd *arr, int len) {
555 for (F = arr + len; --F >= arr; ) {
563 /* ************************************************************
567 /* ************************************************************
571 Fd* fById ( const Fdt *fdt, int id, int subf )
577 for (e = (f = fdt->fd) + fdt->len; --e >= f; ) {
578 if (id == e->id && subf == e->subf && ! (0xf0 & e->type)) {
585 Fd* fByName ( const Fdt *fdt, const char *name )
590 if (! fdt || ! name) {
595 if ( '-' == *name ) /* ignore leading dash */
600 if ( '0' <= *name && *name <= '9' )
601 return fById( fdt, a2i( name, -1 ), 0 );
603 while ( 'a' <= *p ? *p <= 'z' : '9' >= *p ? *p >= '0' : '_' == *p )
606 if ( ! l || l > FD_NAMELEN - 1 )
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 ) ) {
619 return 1 == cnt ? g : 0;
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
631 int fEnum ( Fdt *fdt, int id, const char *name )
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 )
639 if ( ('0' <= *name && *name <= '9')
640 || ('-' == *name && '0' <= name[1] && name[1] <= '9')
642 int v = a2i( name, l );
643 for ( ; f < e; f++ ) {
644 if ( FTV == f->type && v == f->len && (f->id == id || !f->id) )
649 for ( ; f < e; f++ ) {
652 || memcmp( name, f->name, l )
653 || (f->id && f->id != id)
656 if ( !f->name[l] ) { /* exact match */
659 x0 = f; /* f->id is 0 */
675 : pi ? (ui ? pi->len : NOENUM)
676 : p0 && u0 ? p0->len : NOENUM;
679 Fdt* fFree ( Fdt *fdt ) {
683 for (E = (F = fdt->fd) + fdt->len; --E >= F; ) {
696 Fdt* fFromFile (char *path) {
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' )
714 fp = fopen (path, "r");
716 sMsg (LOG_INFO | ERR_BADF, "no such fdt: %s", path);
719 res = mAlloc (sizeof(Fdt));
722 sMsg (ERR_NOMEM, "fFromFile");
725 sMsg (LOG_VERBOSE, "> reading fdt: %s", path);
730 while ((line = fFileGets (fp))) {
734 if (':' == line[1]) {
735 if (-ERR_NOMEM == (err = fLine2Tool (line, &rec))) {
740 if (-ERR_NOMEM == (err = fLine2Fd (line, &fd, &len))) {
750 if (-ERR_NOMEM == err) {
754 sMsg (LOG_VERBOSE, "< %d entries in fdt", len);
758 #define ADDFDS(tag,val) \
759 RADDS (rec, tag, val, !0); \
760 if (! rec) { return 0; }
762 Rec* fFd2Rec (const Fd *fd, Rec *rec, int embchld) {
770 ADDFDS (OPENISIS_FDID, buf);
771 if ((*buf = fd->subf)) {
773 ADDFDS (OPENISIS_FDSUB, buf);
776 ADDFDS (OPENISIS_FDTYPE, buf);
778 ADDFDS (OPENISIS_FDREP, buf);
780 ADDFDS (OPENISIS_FDLEN, buf);
781 ADDFDS (OPENISIS_FDNAME, fd->name);
782 ADDFDS (OPENISIS_FDDESC, fd->desc);
784 ADDFDS (OPENISIS_FDPAT, fd->pat);
787 ADDFDS (OPENISIS_FDDFLT, fd->dflt);
790 rec = luti_wrap (rec, fd->info, OPENISIS_FDINFO);
795 if (embchld && fd->slen) {
796 for (E = (F = fd->subs) + fd->slen; rec && F < E; ++F) {
797 child = fFd2Rec (*F, 0, 0);
801 rec = luti_wrap (rec, child, OPENISIS_FDCHLD);
804 rec = rAddI (rec, OPENISIS_FDNUMC, fd->slen, !0);
810 Rec* fFdt2Rec (const Fdt *fdt, Rec *rec, int embchld) {
818 rec = luti_wrap (rec, fdt->rec, OPENISIS_FDT_REC);
819 if (! rec) { return 0; }
821 for (E = (F = fdt->fd) + fdt->len, len = 0; F < E; ++F) {
822 if (! F->subf || ! embchld) {
823 R = fFd2Rec (F, 0, embchld);
827 rec = luti_wrap (rec, R, OPENISIS_FDT_FD);
835 rec = rAddI (rec, OPENISIS_FDT_LEN, len, !0);
839 Fd *fRec2Fd (Rec *rec, Fd *buf) {
840 char name[FD_NAMELEN];
848 fd = mAlloc (sizeof(Fd));
854 for (E = (F = rec->field) + rec->len; F < E; ++F) {
858 fd->id = a2id (F->val, F->len, 0);
861 if (! (1 == F->len || (2 == F->len && ! F->val[1]))) {
863 "fRec2Fd: ignoring illegal subfield id (%s)", name);
866 fd->subf = F->val[0];
869 case OPENISIS_FDTYPE:
871 fd->type = (char) a2id (F->val, F->len, 0);
874 if (! (1 == F->len || (2 == F->len && ! F->val[1]))) {
876 "fRec2Fd: ignoring illegal repeatable flag (%s)", name);
879 fd->rep = F->val[0] && '0' != F->val[0];
883 fd->len = (short) a2id (F->val, F->len, 0);
885 case OPENISIS_FDNAME:
887 if (FD_NAMELEN <= F->len) {
888 memcpy (name, F->val, FD_NAMELEN - 1);
889 name[FD_NAMELEN - 1] = 0;
891 "fRec2Fd: name too long (%d) - truncated to %s",
895 memcpy (name, F->val, F->len);
899 strcpy (fd->desc, name);
901 fDesc2Name (name, fd->name);
904 "fRec2Fd: illegal name (%s)", name);
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;
913 "fRec2Fd: descr too long (%d) - truncated to %s (%s)",
914 F->len, fd->desc, name);
917 memcpy (fd->desc, F->val, F->len);
918 fd->desc[F->len] = 0;
924 "fRec2Fd: ignoring multiple occurences of pattern (%s)",
928 fd->pat = (char*) mAlloc (1 + F->len);
932 memcpy (fd->pat, F->val, F->len);
936 case OPENISIS_FDDFLT:
939 "fRec2Fd: ignoring multiple occurences of dflt (%s)",
943 fd->dflt = (char*) mAlloc (1 + F->len);
947 memcpy (fd->dflt, F->val, F->len);
948 fd->dflt[F->len] = 0;
951 case OPENISIS_FDINFO:
954 "fRec2Fd: ignoring multiple occurences of info (%s)",
958 int pos = F - rec->field;
959 fd->info = luti_unwrap (rec, &pos, OPENISIS_FDINFO, -1);
963 F = rec->field + pos - 1;
968 "fRec2Fd: ignoring unexpected tag %d (%s)",
974 "fRec2Fd: incomplete field description [%x] (%s)", got, name);
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); }
985 Fdt *fRec2Fdt (Rec *rec) {
990 int err, num, len, pos;
994 num = rInt (rec, OPENISIS_FDT_LEN, 0, 0);
998 arr = (Fd*) mAlloc (num * sizeof (Fd));
1002 fdt = (Fdt*) mAlloc (sizeof(Fdt));
1007 for (F = arr, len = pos = 0; num; --num) {
1008 R = luti_unwrap (rec, &pos, OPENISIS_FDT_FD, -1);
1010 return fCleanupArr (fdt, arr, len);
1012 memset (&fdbuf, 0, sizeof(Fd));
1013 if (fRec2Fd (R, &fdbuf)) {
1014 memcpy (F, &fdbuf, sizeof(Fd));
1021 num = len * sizeof(Fd);
1022 F = (Fd*) mAlloc (num);
1024 return fCleanupArr (fdt, arr, len);
1026 memcpy (F, arr, num);
1030 cfg = luti_unwrap (rec, 0, OPENISIS_FDT_REC, -1);
1034 err = fResolveChilds (arr, len);
1035 if (-ERR_NOMEM == err) {