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