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: luti.c,v 1.48 2003/06/23 14:47:35 kripke Exp $
28 #include <string.h> /* strlen */
34 /* ************************************************************
43 typedef struct OpenIsisLT {
45 int siz; /* malloc'ed */
50 #define LT_SIZE (LT_NUM * sizeof (LutiLTNod))
52 #define LTIDX(name) ( \
53 ('a' <= *(name) && 'z' >= *(name)) ? *(name) - 'a' : ( \
54 ('A' <= *(name) && 'Z' >= *(name)) ? *(name) - 'A' : 26 \
59 /* ************************************************************
65 /* ************************************************************
70 /* ************************************************************
73 const char luti_hex[16] = {
74 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
77 /* ************************************************************
82 int level, Rec *rec, const char *msg, const char *delim
90 if ((unsigned)level > log_lev) {
101 sMsg (ch, " #f=%d", (int)rec->len);
102 for (F = rec->field; rec->len > F - rec->field; ++F) {
104 sMsg (ch, "%d", (int)F->tag);
105 sMsg (ch, " %.*s", (int)F->len, F->val);
112 int lprint ( void *buf, int i )
131 return c - (char*)buf;
135 int a2il ( const char *p, int l, int *res )
138 const char *e = p + (0<=l ? l : (int)strlen(p));
141 while ( p < e && ' ' >= (unsigned char)*p ) /* skip white */
146 if ( p+1 == e ) ret = 1; /* so sole '-' is -1 */
147 case '~': /* sole ~ is ~0 */
151 if ( p < e && '0' == *p && ++p < e && 'x' == *p ) {
154 if ( '0' <= v && v <= '9' )
156 else if ( 'a' <= v && v <= 'f' )
158 else if ( 'A' <= v && v <= 'F' )
165 while ( p < e && '0' <= *p && *p <= '9' )
166 ret = 10*ret + *p++ - '0';
170 case '-': *res = -ret; break;
171 case '~': *res = ~ret; break;
177 int a2i ( const char *p, int l ) {
183 int a2id ( const char *p, int l, int dflt ) {
186 l = (int) strlen (p);
188 if (l != a2il (p, l, &res)) {
195 int i2a ( char *p, int i )
206 for ( j=i; j; j/=10 )
208 for ( *(p+=dig)=0; i; i/=10 )
209 *--p = '0' + (i % 10);
218 int u2a ( char *p, unsigned u )
222 for ( j=u; j; j/=10 )
224 for ( *(p+=dig)=0; u; u/=10 )
225 *--p = '0' + (u % 10);
234 LutiLT luti_ltnew () {
235 LutiLT res = (LutiLT) mAlloc (LT_SIZE);
239 void luti_ltdel (LutiLT lt) {
243 for (N = lt + LT_NUM; --N >= lt; ) {
245 for (E = N->arr + N->num; --E >= N->arr; ) {
257 void luti_ltadd (LutiLT lt, const char *name, int id) {
267 if (N->siz == N->num) {
268 E = mAlloc ( (LT_INCR + N->siz) * sizeof (LutiLTEnt));
270 memcpy (E, N->arr, N->siz * sizeof (LutiLTEnt));
276 N->arr[N->num].name = mDup (name, -1);
277 N->arr[N->num].id = id;
282 int luti_ltget (LutiLT lt, const char *name) {
293 for (E = N->arr + N->num; --E >= N->arr; ) {
294 if (! strcmp (E->name, name)) {
303 void luti_ltrmv (LutiLT lt, const char *name) {
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;
319 memmove (E, E + 1, len * sizeof (LutiLTEnt));
326 log_msg (LOG_WARN, "luti_ltrmv: no such entry <%s>", name);
330 static Rec *_unwrap ( Rec *env, int *pos, int tag, int dbid, int rdonly )
342 F = rGet (env, tag, pos);
346 rlen = a2id (F->val, (int)F->len, -1);
349 "luti_unwrap: illegal reclen %d, pos %d, tag %d",
354 if (env->len < *pos + rlen) {
356 "luti_unwrap: illegal reclen %d, pos %d, tag %d, env %d",
357 rlen, *pos, F->tag, env->len);
360 if (! rlen && ! rdonly) {
361 OPENISIS_RSPACE (rec, 0, 0);
366 while (0 <= --rlen) {
368 RADD (rec, F->tag, F->val, F->len, !0);
383 Rec *luti_unwrap ( Rec *env, int *pos, int tag, int dbid)
385 return _unwrap (env, pos, tag, dbid, 0);
388 Rec* luti_append (Rec *tgt, Rec *src) {
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);
400 Rec *luti_wrap (Rec *env, Rec *rec, int tag) {
404 env = rAddI (env, tag, rec->len, !0);
405 return luti_append (env, rec);
409 void *start, int *num, int incr, int siz, int maxn
411 char **base = (char**)start;
414 if (0 < maxn && oldn >= maxn) {
417 arr = mAlloc ((oldn + incr) * siz);
422 memcpy (arr, *base, oldn * siz);
425 memset (arr + oldn * siz, 0, incr * siz);
431 void luti_free (void **arr, int num) {
442 int luti_true (const char *str, int len) {
443 if (! str || ! *str) {
468 if (! strncmp ("false", str, len) ||
469 ! strncmp ("no", str, len)) {
472 if (! strncmp ("true", str, len) ||
473 ! strncmp ("yes", str, len)) {
479 /* ------------------------------------------------------------------------
483 Fdt* luti_fdt_from_rec (Rec *rec) {
487 (dbh = nDbById (rec->dbid))
494 const char* luti_parse_path (
495 const char *path, const Fdt *fdt, Fd **fd, int *tag, int *occ
516 || ('-' == *path && (path[1]<'0' || '9'<path[1]))
517 ) { /* path or option style */
521 num = a2il (path, -1, &_t);
524 _f = fById (fdt, _t, 0);
528 char name[OPENISIS_FD_NAMELEN];
533 path[num] && '[' != path[num] && '(' != path[num];
536 if (num > OPENISIS_FD_NAMELEN - 1) {
539 strncpy (name, path, num) [num] = 0;
540 _f = fByName ( fdt, name );
555 if ('[' != *path && '(' != *path) {
561 num = a2il (path, -1, &_o);
562 if (! num || 0 > _o) {
566 if ((']' != *path && '[' == qsub) || (')' != *path && '(' == qsub)) {
576 Rec* luti_getembed ( Rec *env, const char *path, const Fdt *fdt)
579 int tag, occ, idx, pos;
580 if ( ! env || ! path || ! *path) {
584 fdt = luti_fdt_from_rec (env);
586 path = luti_parse_path (path, fdt, 0, &tag, &occ);
593 res = _unwrap (env, &pos, tag, -1, idx < occ);
603 Rec *r2 = luti_getembed (res, path, 0);
611 int lhash ( const char *str, int len )
616 return 0<=h ? h : -h;
620 /* ************************************************************
624 char *toHtml ( const char *str, int len )
633 for ( e = (p=(char*)str) + len; p<e; 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 */
643 for ( p=ret; str<e; 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;
656 int utf8Chk ( void *mem, int len, int *tof )
658 unsigned char *c = (unsigned char *)mem;
659 int f = 0; /* expected followers */
664 unsigned char u = *c;
665 int tofollow = u < 128 ? 0 : u < 192 ? -1 : u < 224 ? 1 : 2;
667 if ( 0 > tofollow ) { f--; continue; }
670 if ( 0 <= tofollow ) { f = tofollow; continue; }
677 if ( 0 > l && tof ) /* exhausted buf, want follower */
679 sMsg( LOG_ERROR, "expected follower at %d got %x", len-l-1, (int)*c );
682 sMsg( LOG_ERROR, "expected no follower at %d got %x", len-l-1, (int)*c );