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: luti.c,v 1.48 2003/06/23 14:47:35 kripke Exp $ |
25 |
|
|
utilities |
26 |
|
|
*/ |
27 |
|
|
|
28 |
|
|
#include <string.h> /* strlen */ |
29 |
|
|
|
30 |
|
|
#include "openisis.h" |
31 |
|
|
#include "luti.h" |
32 |
|
|
|
33 |
|
|
|
34 |
|
|
/* ************************************************************ |
35 |
|
|
private types |
36 |
|
|
*/ |
37 |
|
|
|
38 |
|
|
typedef struct { |
39 |
|
|
char *name; |
40 |
|
|
int id; |
41 |
|
|
} LutiLTEnt; |
42 |
|
|
|
43 |
|
|
typedef struct OpenIsisLT { |
44 |
|
|
LutiLTEnt *arr; |
45 |
|
|
int siz; /* malloc'ed */ |
46 |
|
|
int num; /* used */ |
47 |
|
|
} LutiLTNod; |
48 |
|
|
|
49 |
|
|
#define LT_NUM 27 |
50 |
|
|
#define LT_SIZE (LT_NUM * sizeof (LutiLTNod)) |
51 |
|
|
|
52 |
|
|
#define LTIDX(name) ( \ |
53 |
|
|
('a' <= *(name) && 'z' >= *(name)) ? *(name) - 'a' : ( \ |
54 |
|
|
('A' <= *(name) && 'Z' >= *(name)) ? *(name) - 'A' : 26 \ |
55 |
|
|
)) |
56 |
|
|
|
57 |
|
|
#define LT_INCR 2 |
58 |
|
|
|
59 |
|
|
/* ************************************************************ |
60 |
|
|
private data |
61 |
|
|
*/ |
62 |
|
|
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
/* ************************************************************ |
66 |
|
|
private functions |
67 |
|
|
*/ |
68 |
|
|
|
69 |
|
|
|
70 |
|
|
/* ************************************************************ |
71 |
|
|
package data |
72 |
|
|
*/ |
73 |
|
|
const char luti_hex[16] = { |
74 |
|
|
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' |
75 |
|
|
}; |
76 |
|
|
|
77 |
|
|
/* ************************************************************ |
78 |
|
|
package functions |
79 |
|
|
*/ |
80 |
|
|
|
81 |
|
|
void log_rec ( |
82 |
|
|
int level, Rec *rec, const char *msg, const char *delim |
83 |
|
|
) { |
84 |
|
|
Field *F; |
85 |
|
|
int ch = 2; |
86 |
|
|
if (0 > level) { |
87 |
|
|
level = -level; |
88 |
|
|
ch = 1; |
89 |
|
|
} |
90 |
|
|
if ((unsigned)level > log_lev) { |
91 |
|
|
return; |
92 |
|
|
} |
93 |
|
|
if (msg && *msg) { |
94 |
|
|
sMsg (ch, msg); |
95 |
|
|
} |
96 |
|
|
sMsg (ch, "%p", rec); |
97 |
|
|
if (rec) { |
98 |
|
|
if (! delim) { |
99 |
|
|
delim = "; "; |
100 |
|
|
} |
101 |
|
|
sMsg (ch, " #f=%d", (int)rec->len); |
102 |
|
|
for (F = rec->field; rec->len > F - rec->field; ++F) { |
103 |
|
|
sMsg (ch, delim); |
104 |
|
|
sMsg (ch, "%d", (int)F->tag); |
105 |
|
|
sMsg (ch, " %.*s", (int)F->len, F->val); |
106 |
|
|
} |
107 |
|
|
} |
108 |
|
|
sMsg (ch, "\n"); |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
|
112 |
|
|
int lprint ( void *buf, int i ) |
113 |
|
|
{ |
114 |
|
|
char *c = buf; |
115 |
|
|
if ( 0 > i ) { |
116 |
|
|
*c++ = '-'; |
117 |
|
|
i = -i; |
118 |
|
|
} |
119 |
|
|
if ( ! i ) |
120 |
|
|
*c++ = '0'; |
121 |
|
|
else { |
122 |
|
|
int dig = 0, j=i; |
123 |
|
|
char *p; |
124 |
|
|
for ( ; j; j /= 10 ) |
125 |
|
|
dig++; |
126 |
|
|
p = c += dig; |
127 |
|
|
for ( ; i; i /= 10 ) |
128 |
|
|
*--p = '0' + i % 10; |
129 |
|
|
} |
130 |
|
|
*c = 0; |
131 |
|
|
return c - (char*)buf; |
132 |
|
|
} /* lprint */ |
133 |
|
|
|
134 |
|
|
|
135 |
|
|
int a2il ( const char *p, int l, int *res ) |
136 |
|
|
{ |
137 |
|
|
const char *s = p; |
138 |
|
|
const char *e = p + (0<=l ? l : (int)strlen(p)); |
139 |
|
|
char op = 0; |
140 |
|
|
int ret = 0; |
141 |
|
|
while ( p < e && ' ' >= (unsigned char)*p ) /* skip white */ |
142 |
|
|
p++; |
143 |
|
|
if ( p < e ) |
144 |
|
|
switch ( *p ) { |
145 |
|
|
case '-': |
146 |
|
|
if ( p+1 == e ) ret = 1; /* so sole '-' is -1 */ |
147 |
|
|
case '~': /* sole ~ is ~0 */ |
148 |
|
|
case '+': |
149 |
|
|
op = *p++; |
150 |
|
|
} |
151 |
|
|
if ( p < e && '0' == *p && ++p < e && 'x' == *p ) { |
152 |
|
|
while ( ++p < e ) { |
153 |
|
|
int v = *p; |
154 |
|
|
if ( '0' <= v && v <= '9' ) |
155 |
|
|
v -= '0'; |
156 |
|
|
else if ( 'a' <= v && v <= 'f' ) |
157 |
|
|
v -= 'a'-10; |
158 |
|
|
else if ( 'A' <= v && v <= 'F' ) |
159 |
|
|
v -= 'A'-10; |
160 |
|
|
else |
161 |
|
|
break; |
162 |
|
|
ret = (ret<<4) + v; |
163 |
|
|
} |
164 |
|
|
} else { |
165 |
|
|
while ( p < e && '0' <= *p && *p <= '9' ) |
166 |
|
|
ret = 10*ret + *p++ - '0'; |
167 |
|
|
} |
168 |
|
|
if (0 != res) |
169 |
|
|
switch (op) { |
170 |
|
|
case '-': *res = -ret; break; |
171 |
|
|
case '~': *res = ~ret; break; |
172 |
|
|
default: *res = ret; |
173 |
|
|
} |
174 |
|
|
return p - s; |
175 |
|
|
} /* a2il */ |
176 |
|
|
|
177 |
|
|
int a2i ( const char *p, int l ) { |
178 |
|
|
int res; |
179 |
|
|
a2il (p, l, &res); |
180 |
|
|
return res; |
181 |
|
|
} |
182 |
|
|
|
183 |
|
|
int a2id ( const char *p, int l, int dflt ) { |
184 |
|
|
int res; |
185 |
|
|
if (0 > l) { |
186 |
|
|
l = (int) strlen (p); |
187 |
|
|
} |
188 |
|
|
if (l != a2il (p, l, &res)) { |
189 |
|
|
return dflt; |
190 |
|
|
} |
191 |
|
|
return res; |
192 |
|
|
} |
193 |
|
|
|
194 |
|
|
|
195 |
|
|
int i2a ( char *p, int i ) |
196 |
|
|
{ |
197 |
|
|
if ( i ) { |
198 |
|
|
int min, dig = 0, j; |
199 |
|
|
if ( 0 < i ) |
200 |
|
|
min = 0; |
201 |
|
|
else { |
202 |
|
|
min = 1; |
203 |
|
|
*p++ = '-'; |
204 |
|
|
i = -i; |
205 |
|
|
} |
206 |
|
|
for ( j=i; j; j/=10 ) |
207 |
|
|
dig++; |
208 |
|
|
for ( *(p+=dig)=0; i; i/=10 ) |
209 |
|
|
*--p = '0' + (i % 10); |
210 |
|
|
return min+dig; |
211 |
|
|
} |
212 |
|
|
*p++ = '0'; |
213 |
|
|
*p = 0; |
214 |
|
|
return 1; |
215 |
|
|
} /* i2a */ |
216 |
|
|
|
217 |
|
|
|
218 |
|
|
int u2a ( char *p, unsigned u ) |
219 |
|
|
{ |
220 |
|
|
if ( u ) { |
221 |
|
|
int dig = 0, j; |
222 |
|
|
for ( j=u; j; j/=10 ) |
223 |
|
|
dig++; |
224 |
|
|
for ( *(p+=dig)=0; u; u/=10 ) |
225 |
|
|
*--p = '0' + (u % 10); |
226 |
|
|
return dig; |
227 |
|
|
} |
228 |
|
|
*p++ = '0'; |
229 |
|
|
*p = 0; |
230 |
|
|
return 1; |
231 |
|
|
} /* u2a */ |
232 |
|
|
|
233 |
|
|
|
234 |
|
|
LutiLT luti_ltnew () { |
235 |
|
|
LutiLT res = (LutiLT) mAlloc (LT_SIZE); |
236 |
|
|
return res; |
237 |
|
|
} |
238 |
|
|
|
239 |
|
|
void luti_ltdel (LutiLT lt) { |
240 |
|
|
LutiLTNod *N; |
241 |
|
|
LutiLTEnt *E; |
242 |
|
|
if (lt) { |
243 |
|
|
for (N = lt + LT_NUM; --N >= lt; ) { |
244 |
|
|
if (N->arr) { |
245 |
|
|
for (E = N->arr + N->num; --E >= N->arr; ) { |
246 |
|
|
if (E->name) { |
247 |
|
|
mFree (E->name); |
248 |
|
|
} |
249 |
|
|
} |
250 |
|
|
mFree (N->arr); |
251 |
|
|
} |
252 |
|
|
} |
253 |
|
|
mFree (lt); |
254 |
|
|
} |
255 |
|
|
} |
256 |
|
|
|
257 |
|
|
void luti_ltadd (LutiLT lt, const char *name, int id) { |
258 |
|
|
if (0 != lt) { |
259 |
|
|
LutiLTNod *N; |
260 |
|
|
LutiLTEnt *E; |
261 |
|
|
int idx; |
262 |
|
|
if (!name) { |
263 |
|
|
name = ""; |
264 |
|
|
} |
265 |
|
|
idx = LTIDX (name); |
266 |
|
|
N = lt + idx; |
267 |
|
|
if (N->siz == N->num) { |
268 |
|
|
E = mAlloc ( (LT_INCR + N->siz) * sizeof (LutiLTEnt)); |
269 |
|
|
if (N->siz) { |
270 |
|
|
memcpy (E, N->arr, N->siz * sizeof (LutiLTEnt)); |
271 |
|
|
mFree (N->arr); |
272 |
|
|
} |
273 |
|
|
N->arr = E; |
274 |
|
|
N->siz += LT_INCR; |
275 |
|
|
} |
276 |
|
|
N->arr[N->num].name = mDup (name, -1); |
277 |
|
|
N->arr[N->num].id = id; |
278 |
|
|
++N->num; |
279 |
|
|
} |
280 |
|
|
} |
281 |
|
|
|
282 |
|
|
int luti_ltget (LutiLT lt, const char *name) { |
283 |
|
|
if (0 != lt) { |
284 |
|
|
LutiLTNod *N; |
285 |
|
|
LutiLTEnt *E; |
286 |
|
|
int idx; |
287 |
|
|
if (!name) { |
288 |
|
|
name = ""; |
289 |
|
|
} |
290 |
|
|
idx = LTIDX (name); |
291 |
|
|
N = lt + idx; |
292 |
|
|
if (N->num) { |
293 |
|
|
for (E = N->arr + N->num; --E >= N->arr; ) { |
294 |
|
|
if (! strcmp (E->name, name)) { |
295 |
|
|
return E->id; |
296 |
|
|
} |
297 |
|
|
} |
298 |
|
|
} |
299 |
|
|
} |
300 |
|
|
return -1; |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
void luti_ltrmv (LutiLT lt, const char *name) { |
304 |
|
|
if (0 != lt) { |
305 |
|
|
LutiLTNod *N; |
306 |
|
|
LutiLTEnt *E; |
307 |
|
|
int idx; |
308 |
|
|
if (!name) { |
309 |
|
|
name = ""; |
310 |
|
|
} |
311 |
|
|
idx = LTIDX (name); |
312 |
|
|
N = lt + idx; |
313 |
|
|
if (N->num) { |
314 |
|
|
for (E = N->arr + N->num; --E >= N->arr; ) { |
315 |
|
|
if (! strcmp (E->name, name)) { |
316 |
|
|
int len = N->num - (E - N->arr) - 1; |
317 |
|
|
mFree (E->name); |
318 |
|
|
if (len) { |
319 |
|
|
memmove (E, E + 1, len * sizeof (LutiLTEnt)); |
320 |
|
|
} |
321 |
|
|
--N->num; |
322 |
|
|
return; |
323 |
|
|
} |
324 |
|
|
} |
325 |
|
|
} |
326 |
|
|
log_msg (LOG_WARN, "luti_ltrmv: no such entry <%s>", name); |
327 |
|
|
} |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
static Rec *_unwrap ( Rec *env, int *pos, int tag, int dbid, int rdonly ) |
331 |
|
|
{ |
332 |
|
|
Field *F; |
333 |
|
|
Rec *rec = 0; |
334 |
|
|
int rlen, np; |
335 |
|
|
if (! env ) { |
336 |
|
|
return 0; |
337 |
|
|
} |
338 |
|
|
if (! pos) { |
339 |
|
|
np = 0; |
340 |
|
|
pos = &np; |
341 |
|
|
} |
342 |
|
|
F = rGet (env, tag, pos); |
343 |
|
|
if (!F) { |
344 |
|
|
return 0; |
345 |
|
|
} |
346 |
|
|
rlen = a2id (F->val, (int)F->len, -1); |
347 |
|
|
if (0 > rlen) { |
348 |
|
|
sMsg (LOG_ERROR, |
349 |
|
|
"luti_unwrap: illegal reclen %d, pos %d, tag %d", |
350 |
|
|
rlen, *pos, F->tag); |
351 |
|
|
return 0; |
352 |
|
|
} |
353 |
|
|
++F; |
354 |
|
|
if (env->len < *pos + rlen) { |
355 |
|
|
sMsg (LOG_ERROR, |
356 |
|
|
"luti_unwrap: illegal reclen %d, pos %d, tag %d, env %d", |
357 |
|
|
rlen, *pos, F->tag, env->len); |
358 |
|
|
return 0; |
359 |
|
|
} |
360 |
|
|
if (! rlen && ! rdonly) { |
361 |
|
|
OPENISIS_RSPACE (rec, 0, 0); |
362 |
|
|
if (0 == rec) { |
363 |
|
|
return 0; |
364 |
|
|
} |
365 |
|
|
} |
366 |
|
|
while (0 <= --rlen) { |
367 |
|
|
if (! rdonly) { |
368 |
|
|
RADD (rec, F->tag, F->val, F->len, !0); |
369 |
|
|
if (0 == rec) { |
370 |
|
|
return 0; |
371 |
|
|
} |
372 |
|
|
} |
373 |
|
|
++F; |
374 |
|
|
++(*pos); |
375 |
|
|
} |
376 |
|
|
if (rdonly) { |
377 |
|
|
return (Rec*)1; |
378 |
|
|
} |
379 |
|
|
rec->dbid = dbid; |
380 |
|
|
return rec; |
381 |
|
|
} |
382 |
|
|
|
383 |
|
|
Rec *luti_unwrap ( Rec *env, int *pos, int tag, int dbid) |
384 |
|
|
{ |
385 |
|
|
return _unwrap (env, pos, tag, dbid, 0); |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
Rec* luti_append (Rec *tgt, Rec *src) { |
389 |
|
|
Field *F, *E; |
390 |
|
|
if (!src) { |
391 |
|
|
return tgt; |
392 |
|
|
} |
393 |
|
|
E = src->field + src->len; |
394 |
|
|
for (F = src->field; tgt && E > F; ++F) { |
395 |
|
|
RADD (tgt, F->tag, F->val, F->len, !0); |
396 |
|
|
} |
397 |
|
|
return tgt; |
398 |
|
|
} |
399 |
|
|
|
400 |
|
|
Rec *luti_wrap (Rec *env, Rec *rec, int tag) { |
401 |
|
|
if (!rec) { |
402 |
|
|
return env; |
403 |
|
|
} |
404 |
|
|
env = rAddI (env, tag, rec->len, !0); |
405 |
|
|
return luti_append (env, rec); |
406 |
|
|
} |
407 |
|
|
|
408 |
|
|
int luti_ptrincr ( |
409 |
|
|
void *start, int *num, int incr, int siz, int maxn |
410 |
|
|
) { |
411 |
|
|
char **base = (char**)start; |
412 |
|
|
char *arr; |
413 |
|
|
int oldn = *num; |
414 |
|
|
if (0 < maxn && oldn >= maxn) { |
415 |
|
|
return -1; |
416 |
|
|
} |
417 |
|
|
arr = mAlloc ((oldn + incr) * siz); |
418 |
|
|
if (!arr) { |
419 |
|
|
return -1; |
420 |
|
|
} |
421 |
|
|
if (oldn) { |
422 |
|
|
memcpy (arr, *base, oldn * siz); |
423 |
|
|
mFree (*base); |
424 |
|
|
} |
425 |
|
|
memset (arr + oldn * siz, 0, incr * siz); |
426 |
|
|
*num += incr; |
427 |
|
|
*base = arr; |
428 |
|
|
return oldn; |
429 |
|
|
} |
430 |
|
|
|
431 |
|
|
void luti_free (void **arr, int num) { |
432 |
|
|
if (arr) { |
433 |
|
|
while (0 <= --num) { |
434 |
|
|
if (arr[num]) { |
435 |
|
|
mFree (arr[num]); |
436 |
|
|
} |
437 |
|
|
} |
438 |
|
|
mFree (arr); |
439 |
|
|
} |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
int luti_true (const char *str, int len) { |
443 |
|
|
if (! str || ! *str) { |
444 |
|
|
return -1; |
445 |
|
|
} |
446 |
|
|
if (0 > len) { |
447 |
|
|
len = strlen (str); |
448 |
|
|
} |
449 |
|
|
if (1 == len) { |
450 |
|
|
if ('0' == *str || |
451 |
|
|
'f' == *str || |
452 |
|
|
'F' == *str || |
453 |
|
|
'n' == *str || |
454 |
|
|
'N' == *str |
455 |
|
|
) { |
456 |
|
|
return 0; |
457 |
|
|
} |
458 |
|
|
if ('1' == *str || |
459 |
|
|
'y' == *str || |
460 |
|
|
'Y' == *str || |
461 |
|
|
't' == *str || |
462 |
|
|
'T' == *str |
463 |
|
|
) { |
464 |
|
|
return 1; |
465 |
|
|
} |
466 |
|
|
return -1; |
467 |
|
|
} |
468 |
|
|
if (! strncmp ("false", str, len) || |
469 |
|
|
! strncmp ("no", str, len)) { |
470 |
|
|
return 0; |
471 |
|
|
} |
472 |
|
|
if (! strncmp ("true", str, len) || |
473 |
|
|
! strncmp ("yes", str, len)) { |
474 |
|
|
return 1; |
475 |
|
|
} |
476 |
|
|
return -1; |
477 |
|
|
} |
478 |
|
|
|
479 |
|
|
/* ------------------------------------------------------------------------ |
480 |
|
|
* unwrap by path |
481 |
|
|
*/ |
482 |
|
|
|
483 |
|
|
Fdt* luti_fdt_from_rec (Rec *rec) { |
484 |
|
|
Db *dbh; |
485 |
|
|
if (rec && |
486 |
|
|
0 <= rec->dbid && |
487 |
|
|
(dbh = nDbById (rec->dbid)) |
488 |
|
|
) { |
489 |
|
|
return dbh->fdt; |
490 |
|
|
} |
491 |
|
|
return 0; |
492 |
|
|
} |
493 |
|
|
|
494 |
|
|
const char* luti_parse_path ( |
495 |
|
|
const char *path, const Fdt *fdt, Fd **fd, int *tag, int *occ |
496 |
|
|
) { |
497 |
|
|
Fd *_f = 0; |
498 |
|
|
int _t = -1; |
499 |
|
|
int _o = -1; |
500 |
|
|
int num, qsub; |
501 |
|
|
|
502 |
|
|
if (fd) { |
503 |
|
|
*fd = 0; |
504 |
|
|
} |
505 |
|
|
if (tag) { |
506 |
|
|
*tag = -1; |
507 |
|
|
} |
508 |
|
|
if (occ) { |
509 |
|
|
*occ = -1; |
510 |
|
|
} |
511 |
|
|
if (! path) { |
512 |
|
|
return 0; |
513 |
|
|
} |
514 |
|
|
|
515 |
|
|
if ('.' == *path |
516 |
|
|
|| ('-' == *path && (path[1]<'0' || '9'<path[1])) |
517 |
|
|
) { /* path or option style */ |
518 |
|
|
++path; |
519 |
|
|
} |
520 |
|
|
|
521 |
|
|
num = a2il (path, -1, &_t); |
522 |
|
|
if (num) { |
523 |
|
|
if (fdt) { |
524 |
|
|
_f = fById (fdt, _t, 0); |
525 |
|
|
} |
526 |
|
|
} |
527 |
|
|
else { |
528 |
|
|
char name[OPENISIS_FD_NAMELEN]; |
529 |
|
|
if (! fdt) { |
530 |
|
|
return 0; |
531 |
|
|
} |
532 |
|
|
for (num = 0; |
533 |
|
|
path[num] && '[' != path[num] && '(' != path[num]; |
534 |
|
|
++num) |
535 |
|
|
; |
536 |
|
|
if (num > OPENISIS_FD_NAMELEN - 1) { |
537 |
|
|
return 0; |
538 |
|
|
} |
539 |
|
|
strncpy (name, path, num) [num] = 0; |
540 |
|
|
_f = fByName ( fdt, name ); |
541 |
|
|
if (! _f) { |
542 |
|
|
return 0; |
543 |
|
|
} |
544 |
|
|
_t = _f->id; |
545 |
|
|
} |
546 |
|
|
path += num; |
547 |
|
|
|
548 |
|
|
if (tag) { |
549 |
|
|
*tag = _t; |
550 |
|
|
} |
551 |
|
|
if (fd) { |
552 |
|
|
*fd = _f; |
553 |
|
|
} |
554 |
|
|
|
555 |
|
|
if ('[' != *path && '(' != *path) { |
556 |
|
|
return path; |
557 |
|
|
} |
558 |
|
|
qsub = *path; |
559 |
|
|
|
560 |
|
|
++path; |
561 |
|
|
num = a2il (path, -1, &_o); |
562 |
|
|
if (! num || 0 > _o) { |
563 |
|
|
return 0; |
564 |
|
|
} |
565 |
|
|
path += num; |
566 |
|
|
if ((']' != *path && '[' == qsub) || (')' != *path && '(' == qsub)) { |
567 |
|
|
return 0; |
568 |
|
|
} |
569 |
|
|
|
570 |
|
|
if (occ) { |
571 |
|
|
*occ = _o; |
572 |
|
|
} |
573 |
|
|
return path + 1; |
574 |
|
|
} |
575 |
|
|
|
576 |
|
|
Rec* luti_getembed ( Rec *env, const char *path, const Fdt *fdt) |
577 |
|
|
{ |
578 |
|
|
Rec *res; |
579 |
|
|
int tag, occ, idx, pos; |
580 |
|
|
if ( ! env || ! path || ! *path) { |
581 |
|
|
return 0; |
582 |
|
|
} |
583 |
|
|
if (! fdt) { |
584 |
|
|
fdt = luti_fdt_from_rec (env); |
585 |
|
|
} |
586 |
|
|
path = luti_parse_path (path, fdt, 0, &tag, &occ); |
587 |
|
|
if (! path) { |
588 |
|
|
return 0; |
589 |
|
|
} |
590 |
|
|
res = 0; |
591 |
|
|
idx = pos = 0; |
592 |
|
|
while (1) { |
593 |
|
|
res = _unwrap (env, &pos, tag, -1, idx < occ); |
594 |
|
|
if (! res) { |
595 |
|
|
return 0; |
596 |
|
|
} |
597 |
|
|
if (idx >= occ) { |
598 |
|
|
break; |
599 |
|
|
} |
600 |
|
|
++idx; |
601 |
|
|
} |
602 |
|
|
if (*path) { |
603 |
|
|
Rec *r2 = luti_getembed (res, path, 0); |
604 |
|
|
mFree (res); |
605 |
|
|
return r2; |
606 |
|
|
} |
607 |
|
|
return res; |
608 |
|
|
} |
609 |
|
|
|
610 |
|
|
|
611 |
|
|
int lhash ( const char *str, int len ) |
612 |
|
|
{ |
613 |
|
|
int h = 0; |
614 |
|
|
while ( len-- ) |
615 |
|
|
h = 31*h + *str++; |
616 |
|
|
return 0<=h ? h : -h; |
617 |
|
|
} |
618 |
|
|
|
619 |
|
|
|
620 |
|
|
/* ************************************************************ |
621 |
|
|
public functions |
622 |
|
|
*/ |
623 |
|
|
|
624 |
|
|
char *toHtml ( const char *str, int len ) |
625 |
|
|
{ |
626 |
|
|
int l; |
627 |
|
|
char *p, *e, *ret; |
628 |
|
|
if ( ! str ) |
629 |
|
|
return 0; |
630 |
|
|
if ( 0 > len ) |
631 |
|
|
len = strlen(str); |
632 |
|
|
l = len + 1; |
633 |
|
|
for ( e = (p=(char*)str) + len; p<e; p++ ) |
634 |
|
|
switch ( *p ) { |
635 |
|
|
case '<': case '>': l += 3; break; |
636 |
|
|
case '&': l += 4; break; |
637 |
|
|
case '"': l += 5; break; |
638 |
|
|
/* do not replace ' w/ ' -- many clients don't grok it */ |
639 |
|
|
} |
640 |
|
|
ret = mAlloc( l ); |
641 |
|
|
if ( ! ret ) |
642 |
|
|
return 0; |
643 |
|
|
for ( p=ret; str<e; str++ ) |
644 |
|
|
switch ( *str ) { |
645 |
|
|
case '<': *p='&'; p[1]='l'; p[2]='t'; p[3]=';'; p+=4; break; |
646 |
|
|
case '>': *p='&'; p[1]='g'; p[2]='t'; p[3]=';'; p+=4; break; |
647 |
|
|
case '&': *p='&'; p[1]='a'; p[2]='m'; p[3]='p'; p[4]=';'; p+=5; break; |
648 |
|
|
case '"': *p='&';p[1]='q';p[2]='u';p[3]='o';p[4]='t';p[5]=';';p+=6;break; |
649 |
|
|
default: *p++ = *str; |
650 |
|
|
} |
651 |
|
|
*p = 0; |
652 |
|
|
return ret; |
653 |
|
|
} /* toHtml */ |
654 |
|
|
|
655 |
|
|
|
656 |
|
|
int utf8Chk ( void *mem, int len, int *tof ) |
657 |
|
|
{ |
658 |
|
|
unsigned char *c = (unsigned char *)mem; |
659 |
|
|
int f = 0; /* expected followers */ |
660 |
|
|
int l = len; |
661 |
|
|
if ( tof ) |
662 |
|
|
f = *tof; |
663 |
|
|
for ( ; l--; c++ ) { |
664 |
|
|
unsigned char u = *c; |
665 |
|
|
int tofollow = u < 128 ? 0 : u < 192 ? -1 : u < 224 ? 1 : 2; |
666 |
|
|
if ( f ) { |
667 |
|
|
if ( 0 > tofollow ) { f--; continue; } |
668 |
|
|
break; |
669 |
|
|
} |
670 |
|
|
if ( 0 <= tofollow ) { f = tofollow; continue; } |
671 |
|
|
goto croak; |
672 |
|
|
} |
673 |
|
|
if ( tof ) |
674 |
|
|
*tof = f; |
675 |
|
|
if ( ! f ) |
676 |
|
|
return 0; |
677 |
|
|
if ( 0 > l && tof ) /* exhausted buf, want follower */ |
678 |
|
|
return 0; |
679 |
|
|
sMsg( LOG_ERROR, "expected follower at %d got %x", len-l-1, (int)*c ); |
680 |
|
|
return len-l; |
681 |
|
|
croak: |
682 |
|
|
sMsg( LOG_ERROR, "expected no follower at %d got %x", len-l-1, (int)*c ); |
683 |
|
|
return len-l; |
684 |
|
|
} /* utf8Chk */ |