/[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

Contents of /trunk/openisis/lfdt.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
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