/[webpac]/openisis/0.9.9e/core/uti.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

Annotation of /openisis/0.9.9e/core/uti.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 604 - (hide annotations)
Mon Dec 27 21:49:01 2004 UTC (19 years, 4 months ago) by dpavlin
File MIME type: text/plain
File size: 21881 byte(s)
import of new openisis release, 0.9.9e

1 dpavlin 604 /*
2     The Malete project - the Z39.2/Z39.50 database framework of OpenIsis.
3     Version 0.9.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.
14     See the GNU 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: uti.c,v 1.25 2004/11/11 13:13:01 kripke Exp $
25     utilities
26     */
27    
28     #include <string.h> /* strlen */
29     #include <stdarg.h>
30    
31    
32     #include "../core/core.h"
33    
34     /* ************************************************************
35     data
36     */
37     const char b36dig[36] = {
38     '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h',
39     'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
40     };
41    
42     const char b36val[256] = {
43     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
44     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
45     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
46     0, 1, 2, 3, 4, 5, 6, 7, 8, 9,36,36,36,36,36,36,
47     36,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
48     25,26,27,28,29,30,31,32,33,34,35,36,36,36,36,36,
49     36,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
50     25,26,27,28,29,30,31,32,33,34,35,36,36,36,36,36,
51     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
52     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
53     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
54     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
55     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
56     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
57     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
58     36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36
59     };
60    
61     const unsigned char lat1up[256] = {
62     0,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
63     ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
64     ' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
65     '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
66     '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
67     'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
68     '`','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
69     'P','Q','R','S','T','U','V','W','X','Y','Z','{','|','}','~',' ',
70     ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
71     ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
72     ' ',161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
73     176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
74     'A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I',
75     'T','N','O','O','O','O','O',215,'O','U','U','U','U','Y','T','S',
76     'A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I',
77     'T','N','O','O','O','O','O',247,'O','U','U','U','U','Y','T','Y'
78     };
79    
80     const unsigned char lat1ct[256] = {
81     /* NUL STX SOT ETX EOT ENQ ACK BEL */
82     CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,
83     /* BS HT LF VT FF CR SO SI */
84     CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,
85     /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
86     CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,
87     /* CAN EM SUB ESC FS GS RS US */
88     CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,CT_W,
89     /*blank ! " # $ % & ' */
90     CT_W,CT_S,CT_S,CT_S,CT_S,CT_S,CT_S,CT_S,
91     /* ( ) * + , - . / */
92     CT_S,CT_S,CT_S,CT_S,CT_S,CT_S,CT_S,CT_S,
93     /* 0 1 2 3 4 5 6 7 */
94     CT_D,CT_D,CT_D,CT_D,CT_D,CT_D,CT_D,CT_D,
95     /* 8 9 : ; < = > ? */
96     CT_D,CT_D,CT_S,CT_S,CT_S,CT_S,CT_S,CT_S,
97     /* @ A B C D E F G */
98     CT_S,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,
99     CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A, /* H-O */
100     CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A, /* P-W */
101     /* X Y Z [ \ ] ^ _ */
102     CT_A,CT_A,CT_A,CT_S,CT_S,CT_S,CT_S,CT_I,
103     /* ` a b c d e f g */
104     CT_S,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,
105     CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,
106     CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,CT_A,
107     /* x y z { | } ~ DEL */
108     CT_A,CT_A,CT_A,CT_S,CT_S,CT_S,CT_S,CT_S,
109     /* 32 C1 controls */
110     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
111     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
112     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
113     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
114     /* 32 mostly symbols */
115     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
116     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
117     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
118     0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
119     /* 64 Latin alphas including 2 symbols */
120     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,
121     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,
122     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L, 0 ,
123     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,
124     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,
125     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,
126     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L, 0 ,
127     CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L,CT_L
128     };
129    
130     /* ************************************************************
131     general utilities
132     */
133    
134    
135     int a2il ( const char *p, int l, int *res )
136     {
137     const char *s = p;
138     const char *e;
139     char op = 0;
140     int d, ret = 0;
141     if ( 0 > l ) { /* 0 terminated */
142     while ( ' ' >= (unsigned char)*p )
143     if ( !*p++ )
144     return p - s -1;
145     e = p+11; /* max useful, we bail out on 0 byte */
146     } else
147     for ( e = p+l; p < e && ' ' >= (unsigned char)*p; ) /* skip white */
148     p++;
149     if ( p < e )
150     switch ( *p ) {
151     case '-':
152     if ( p+1 == e ) ret = 1; /* so sole '-' is -1 */
153     case '~': /* sole ~ is ~0 */
154     case '+':
155     op = *p++;
156     }
157     if ( p < e && '0' == *p && ++p < e && 'x' == *p )
158     while ( ++p < e && 16 > (d = b36val[(unsigned char)*p]) )
159     ret = (ret<<4) + d;
160     else
161     for ( ;p < e && 10 > (d = b36val[(unsigned char)*p]); p++ )
162     ret = 10*ret + d;
163     if (0 != res)
164     switch (op) {
165     case '-': *res = -ret; break;
166     case '~': *res = ~ret; break;
167     default: *res = ret;
168     }
169     return p - s;
170     } /* a2il */
171    
172     int a2i ( const char *p, int l ) {
173     int res;
174     a2il (p, l, &res);
175     return res;
176     }
177    
178     int a2id ( const char *p, int l, int dflt ) {
179     int res;
180     if (0 > l) {
181     l = (int) strlen (p);
182     }
183     if (l != a2il (p, l, &res)) {
184     return dflt;
185     }
186     return res;
187     }
188    
189    
190     int i2a ( char *p, int i )
191     {
192     if ( i ) {
193     int min, dig = 0, j;
194     if ( 0 < i )
195     min = 0;
196     else {
197     min = 1;
198     *p++ = '-';
199     i = -i;
200     }
201     for ( j=i; j; j/=10 )
202     dig++;
203     for ( *(p+=dig)=0; i; i/=10 )
204     *--p = '0' + (i % 10);
205     return min+dig;
206     }
207     *p = '0';
208     return 1;
209     } /* i2a */
210    
211    
212     int u2a ( char *p, unsigned u )
213     {
214     if ( u ) {
215     char *d = p+10;
216     for ( ; u; u/=10 )
217     *--d = '0' + (u % 10);
218     if ( p < d ) {
219     char *e = p+10, *q = p;
220     while ( d < e )
221     *q++ = *d++;
222     return q-p;
223     }
224     return 10;
225     }
226     *p = '0';
227     return 1;
228     } /* u2a */
229    
230    
231    
232    
233     /* ************************************************************
234     field functions
235     */
236    
237     int vGet ( Fld *dst, const Fld *src, const char *opt )
238     {
239     char *p, *e = src->val + src->len;
240     const char *q;
241    
242     if ( !dst->val || (p = dst->val+dst->len) < src->val || dst->val > e ) {
243     /* initial */
244     p = src->val;
245     if ( (!opt || '*' == *opt) && (!src->len || TAB == *p) ) {
246     dst->tag = 0;
247     dst->val = p; /* catch empty primary */
248     return 1 + (dst->len = 0);
249     }
250     } else if ( p >= e )
251     goto notfound;
252     if ( p == src->val && (!opt || '*' == *opt) && TAB != *p )
253     dst->tag = 0;
254     else {
255     for (;;) {
256     if ( e == p )
257     goto notfound;
258     if ( TAB != *p++ )
259     continue;
260     if ( e == p ) /* bad trailing tab */
261     goto notfound;
262     /* p is on valid subfield indicator */
263     if ( !opt ) /* take any */
264     break;
265     for (q=opt; *q; )
266     if (*p == *q++)
267     goto takeit; /* break 2 */
268     }
269     takeit:
270     dst->tag = *p++;
271     }
272     dst->val = p;
273     while ( e > p && TAB != *p )
274     p++;
275     return 1 + (dst->len = p - dst->val);
276     notfound:
277     dst->val = 0;
278     dst->len = 0;
279     return 0;
280     } /* vGet */
281    
282    
283     int vCmp ( const Fld *a, const Fld *b )
284     {
285     unsigned l = a->len;
286     int cmp;
287    
288     if ( l > b->len ) l = b->len;
289     return (l && (cmp = memcmp(a->val, b->val, l)))
290     ? cmp : (int)a->len - (int)b->len;
291     }
292    
293    
294     int vGt ( const Fld *a, const Fld *b )
295     {
296     unsigned l = a->len;
297     int cmp = 0;
298    
299     if ( l > b->len ) l = b->len;
300     return (l && 0 < (cmp = memcmp(a->val, b->val, l))) ? 1
301     : !cmp && a->len > b->len;
302     }
303    
304    
305    
306     /* ************************************************************
307     record functions
308     */
309    
310     unsigned rSiz ( const Fld *r )
311     {
312     unsigned ret = 0;
313     const Fld *e = r + RLEN(r);
314    
315     while ( r < e )
316     ret += (r++)->len;
317     return ret;
318     } /* rSiz */
319    
320    
321     const Fld *rGet ( const Fld *r, int tag, int *pos )
322     {
323     const Fld *e = r + RLEN(r);
324     const Fld *p = r + (pos ? *pos : 0);
325    
326     while ( ++p < e )
327     if ( tag == p->tag ) {
328     if ( pos )
329     *pos = p-r;
330     return p;
331     }
332     if ( pos )
333     *pos = e-r;
334     return 0;
335     } /* rGet */
336    
337    
338     const Fld *rKey ( const Fld *r, int tag, const char *key )
339     {
340     const Fld *e = r + RLEN(r);
341     const Fld *d = 0;
342     unsigned kl = strlen(key);
343    
344     while ( ++r < e )
345     if ( tag == r->tag ) {
346     if ( VKEY(r, key, kl) )
347     return r;
348     if ( !r->len || TAB == *r->val )
349     d = r;
350     }
351     return d;
352     } /* rKey */
353    
354    
355     const Fld *rDup ( const Fld *src, unsigned siz )
356     {
357     int len = RLEN(src);
358     const Fld *e = src + len;
359     Fld *dst, *f;
360     char *p;
361    
362     if ( !siz )
363     siz = rSiz( src );
364     f = dst = mAlloc( len*sizeof(Fld) + siz );
365     p = ((char*)dst) + len*sizeof(Fld);
366     for ( ;src < e; src++, f++ ) {
367     f->tag = src->tag;
368     memcpy( f->val = p, src->val, f->len = src->len );
369     p += f->len;
370     }
371     return dst;
372     } /* rDup */
373    
374    
375     int rSer ( char *buf, const Fld *f )
376     {
377     #if 0
378     static const char repl[4] = { 0, VT, TAB, ' ' };
379     const char *s, *e;
380     #endif
381     const Fld *fe = REND(f);
382     char *p = buf;
383    
384     while ( ++f < fe ) {
385     p += i2a( p, f->tag );
386     *p++ = TAB;
387     memcpy(p, f->val, f->len);
388     p += f->len;
389     #if 0
390     e = (s = f->val) + f->len;
391     for (;;) {
392     while ( s<e && LF != (*p++ = *s++) ) /* tight */
393     ;
394     if ( s==e )
395     break;
396     if ( opt )
397     p[-1] = repl[opt];
398     else
399     *p++ = TAB;
400     }
401     #endif
402     *p++ = LF;
403     }
404     *p++ = LF;
405     return p - buf;
406     } /* rSer */
407    
408    
409     #define REVBIT 0x80000000 /* highest bit on the length */
410     #define LENMSK 0x7fffffff /* will cut fields longer 2GB */
411    
412     /*
413     basic weak-heap-sort (Dutton 93)
414     for faster variants see indexed-relaxed-weak-heap-sort (Edelkamp)
415     or, for slightly better avg, quick-weak-heap-sort
416     */
417     void rSort ( Fld *r, VGt *gt )
418     {
419     Fld head, tmp;
420     int l = -r->tag -1;
421     int i;
422    
423     if ( 2 > l )
424     return;
425     /* fields to sort are r[1]..r[l]
426     we use r[0]..r[l-1], since whs puts biggest at 0 in first step
427     and sorts the others at 1..l-1
428     */
429     head = *r;
430     *r = r[l];
431     /* weak-heap-forestify
432     every node roots a weak heap AND is <= root
433     (especially the leftist independent roots are <= root)
434     */
435     for ( i=l; --i; ) {
436     int g = i; /* granma is 1st left i or root, if i is totally leftist ;) */
437     while (!(1&g)) /* we're left child */
438     g >>= 1; /* shift granma right :( */
439     g >>= 1;
440     r[i].len &= LENMSK;
441     /* merge: swap if g < i */
442     if ( !gt(r+i, r+g) )
443     continue;
444     tmp = r[i]; r[i] = r[g]; r[g] = tmp; /* swap */
445     r[i].len |= REVBIT;
446     }
447    
448     /* re-weak-heap-forestify */
449     for ( i=l; --i>1; ) {
450     int j=1, left;
451     r[i].len &= LENMSK; /* i's REVBIT no longer needed */
452     /* follow path of left childs (independent roots) */
453     while ( i > (left = (j<<1) + ((REVBIT & r[j].len)?1:0)) )
454     j = left;
455     /* put max of them and i (new root) at i */
456     do {
457     /* merge: swap if i < j */
458     /* clear all REVBITs, as gt will probably access .len */
459     int rj = REVBIT & r[j].len;
460     r[j].len &= LENMSK; /* now i,j both are clean */
461     if ( !gt(r+j, r+i) ) {
462     r[j].len |= rj;
463     continue;
464     }
465     tmp = r[i]; r[i] = r[j]; r[j] = tmp; /* swap */
466     /* toggle original REVBIT at j, which now is at i */
467     if ( ! rj )
468     r[j].len |= REVBIT;
469     } while (j >>= 1);
470     }
471     r[1].len &= LENMSK; /* 2... have been cleared */
472     /* initial root still untouched biggest (never had REVBIT) */
473     r[l] = *r;
474     *r = head;
475     } /* rSort */
476    
477    
478     void rSortTag ( Fld *r ) /* could use radixsort here ... */
479     {
480     Fld head, tmp;
481     int l = -r->tag -1;
482     int i;
483    
484     if ( 2 > l )
485     return;
486     head = *r;
487     *r = r[l];
488     for ( i=l; --i; ) {
489     int g = i;
490     while (!(1&g))
491     g >>= 1;
492     g >>= 1;
493     r[i].len &= LENMSK;
494     if ( r[g].tag >= r[i].tag )
495     continue;
496     tmp = r[i]; r[i] = r[g]; r[g] = tmp; /* swap */
497     r[i].len |= REVBIT;
498     }
499    
500     for ( i=l; --i>1; ) {
501     int j=1, left;
502     while ( i > (left = (j<<1) + ((REVBIT & r[j].len)?1:0)) )
503     j = left;
504     do {
505     if ( r[i].tag >= r[j].tag )
506     continue;
507     tmp = r[i]; r[i] = r[j]; r[j] = tmp; /* swap */
508     if ( REVBIT & r[i].len )
509     r[j].len &= LENMSK;
510     else
511     r[j].len |= REVBIT;
512     } while (j >>= 1);
513     }
514     r[l] = *r;
515     *r = head;
516     while ( l-- ) /* clearing them later is significantly faster */
517     (++r)->len &= LENMSK;
518     } /* rSortTag */
519    
520    
521     void rSortVal (Fld *r)
522     {
523     Fld head, tmp;
524     int l = -r->tag -1;
525     unsigned cl; /* compare length */
526     int i, cmp;
527    
528     if ( 2 > l )
529     return;
530     head = *r;
531     *r = r[l];
532     for ( i=l; --i; ) {
533     int g = i;
534     while (!(1&g))
535     g >>= 1;
536     g >>= 1;
537     if ( (cl = r[g].len) > r[i].len )
538     cl = r[i].len;
539     if ( !cl ? !r[i].len
540     : (0 < (cmp = memcmp(r[g].val,r[i].val,cl))
541     || (!cmp && r[i].len == cl))
542     ) /* i <= g: ok */
543     continue;
544     tmp = r[i]; r[i] = r[g]; r[g] = tmp;
545     r[i].len |= REVBIT;
546     }
547    
548     for ( i=l; --i>1; ) {
549     int j=1, left;
550     r[i].len &= LENMSK;
551     while ( i > (left = (j<<1) + ((REVBIT & r[j].len)?1:0)) )
552     j = left;
553     do {
554     unsigned clj = LENMSK & r[j].len;
555     if ( (cl = r[i].len) > clj )
556     cl = clj;
557     if ( !cl ? !r[j].len
558     : (0 < (cmp = memcmp(r[i].val,r[j].val,cl))
559     || (!cmp && clj == cl))
560     ) /* j <= i: ok */
561     continue;
562     tmp = r[i]; r[i] = r[j]; r[j] = tmp;
563     if ( REVBIT & r[i].len ) { /* toggle j's REVBIT */
564     r[i].len &= LENMSK;
565     r[j].len &= LENMSK;
566     } else
567     r[j].len |= REVBIT;
568     } while (j >>= 1);
569     }
570     r[1].len &= LENMSK;
571     r[l] = *r;
572     *r = head;
573     } /* rSortVal */
574    
575    
576    
577     /* ************************************************************
578     list functions
579     */
580    
581     List *lInit ( List *l, const char *fmt, ... )
582     {
583     memset( l, 0, sizeof(*l) );
584     l->blk = &l->bl0;
585     l->fld = l->fl0;
586     l->fav = DEFFIELDS;
587     l->bok = l->buf = l->bl0.byt;
588     l->end = l->buf + DEFBLKLEN;
589     l->siz = 0;
590     if ( fmt ) { /* print header */
591     va_list ap;
592     va_start( ap, fmt );
593     lOut( l, -1, 0, fmt, ap );
594     va_end( ap );
595     }
596     return l;
597     } /* lInit */
598    
599    
600     #define LBLK_FREE( l ) \
601     while ( (l)->blk != &(l)->bl0 ) { \
602     LBlk *__nxt = (l)->blk->nxt; \
603     mBlkFree( (l)->blk ); \
604     (l)->blk = __nxt; \
605     }
606    
607    
608     List *lClr ( List *l )
609     {
610     l->fav -= l->fld->tag;
611     l->fld->tag = 0;
612     l->fld->val = l->bl0.byt;
613     l->fld->len = 0;
614     l->bok = l->buf = l->bl0.byt;
615     l->end = l->buf + DEFBLKLEN;
616     l->siz = 0;
617     LBLK_FREE(l);
618     return l;
619     } /* lClr */
620    
621    
622     List *lReset ( List *l )
623     {
624     if ( l->fld->val != l->bl0.byt ) { /* header has moved */
625     if ( l->fld->len > DEFBLKLEN )
626     l->fld->len = DEFBLKLEN; /* truncate header !!! */
627     memmove( l->bl0.byt, l->fld->val, l->fld->len );
628     l->fld->val = l->bl0.byt;
629     }
630     l->fav += -1 - l->fld->tag;
631     l->fld->tag = -1;
632     l->bok = l->buf = l->bl0.byt + l->fld->len;
633     l->end = l->buf + DEFBLKLEN;
634     l->siz = l->fld->len;
635     LBLK_FREE(l);
636     return l;
637     } /* lReset */
638    
639    
640     void OPT_STDCALL lFini ( List *l )
641     {
642     LBLK_FREE(l);
643     if ( l->fld != l->fl0 )
644     mFldFree( l->fld );
645     } /* lFini */
646    
647    
648     int OPT_REGPARM lExtend ( List *l, unsigned need, int fields )
649     {
650     LBlk *nju;
651     Fld *contig;
652    
653     if ( 0 <= fields )
654     contig = 0;
655     else {
656     contig = LLAST(l);
657     fields = -fields -1;
658     need += contig->len;
659     }
660     LOG_DBG(LOG_VERBOSE, "lExtend need %u avl %d fields %u fav %d ctg %d",
661     need, LAVL(l), fields, l->fav, contig);
662    
663     if ( l->fav < (unsigned)fields ) {
664     int had = - l->fld->tag;
665     Fld *f;
666    
667     if ( fields < had>>2 ) /* grow 25% */
668     fields = had>>2;
669     else if ( fields < DEFFIELDS )
670     fields = DEFFIELDS;
671     f = mFldAlloc(fields + had);
672     memcpy( f, l->fld, had*sizeof(Fld) );
673     if ( l->fld != l->fl0 )
674     mFldFree( l->fld );
675     l->fld = f;
676     l->fav = (unsigned)fields;
677     }
678    
679     if ( LAVL(l) >= need )
680     return 1;
681    
682     l->siz += l->buf - l->blk->byt; /* add to secondary size */
683     nju = mBlkAlloc(need + DEFBLKLEN/2);
684     nju->nxt = l->blk;
685     l->blk = nju;
686     l->buf = nju->byt;
687     l->end = l->buf + nju->siz; /* >= requested */
688     if ( contig ) {
689     memcpy( l->buf, contig->val, contig->len );
690     contig->val = l->buf;
691     l->buf += contig->len;
692     }
693     return 1;
694     } /* lExtend */
695    
696     static const char at[] = { TAB, '@' };
697    
698     int lArgv ( List *l, int tag, int argc, const char **argv )
699     {
700     LNEWF( l, tag, 4000 );
701     if ( !argc )
702     return 0;
703     if ( '-' != **argv ) {
704     const char *a = *argv++;
705     argc--;
706     LAPPS( l, a );
707     }
708     while ( argc-- ) {
709     const char *a = *argv++;
710     unsigned len = 1;
711     if ( '-' == *a )
712     a++;
713     else
714     len = 2;
715     LAPP( l, at, len );
716     LAPPS( l, a );
717     }
718     return LLAST(l)->len;
719     } /* lArgv */
720    
721    
722     List *lVar ( List *l, int argc, const char **argv )
723     {
724     static const char tab = TAB;
725     LNEWF( l, -1, 4000 );
726     if ( !argc )
727     return l;
728     if ( '-' != **argv ) {
729     const char *a = *argv++;
730     argc--;
731     LAPPS( l, a );
732     }
733     while ( argc-- ) {
734     const char *a = *argv++;
735     if ( '-' == *a ) {
736     a++;
737     LAPP( l, &tab, 1 );
738     } else {
739     LNEWF( l, 1, 100 );
740     }
741     LAPPS( l, a );
742     }
743     return l;
744     } /* lVar */
745    
746    
747     int lCpy ( List *l, const Fld *src, unsigned need )
748     {
749     int len = RLEN(src);
750     const Fld *e = src + len;
751    
752     if ( !need )
753     need = rSiz( src );
754     if ( !lExtend(l, need, len) )
755     return 0;
756     for ( ;src < e; src++ )
757     LADDF( l, src );
758     return len;
759     } /* lCpy */
760    
761    
762     int lParse (List *l, const char *p, int s)
763     {
764     int state = LPS_VAL&s, bits = (LPS_NEG|LPS_CR)&s;
765     const char *e = p + (LPS_LEN&s), *lf;
766     unsigned len;
767     Fld *f = LLAST(l);
768    
769     for (;;) switch (state) {
770     case LPS_SOR:
771     case LPS_SOL:
772     switch (*p) {
773     case CR:
774     if (e == p+1) goto done; /* ignore */
775     if (LF != p[1]) break; /* weird crap */
776     p++;
777     case LF: /* got blank line */
778     return e - p - 1;
779     }
780     LNEWF(l, 0, 80);
781     if ( (LPS_SOR==state) && (CT_IS(D,*p) || '-' == *p) ) {
782     eRr(LOG_WARN, "no message name");
783     LNEWF(l, 0, 80);
784     }
785     f = LLAST(l);
786     state = LPS_TAG;
787     if ( '-' != *p )
788     bits &= ~LPS_NEG;
789     else {
790     bits |= LPS_NEG;
791     if ( e == ++p ) goto done;
792     }
793     case LPS_TAG:
794     while ( CT_IS(D,*p) ) {
795     f->tag = f->tag*10 + b36val[(unsigned char)*p];
796     if ( e == ++p ) goto done;
797     }
798     if ( LPS_NEG & bits )
799     f->tag = -f->tag;
800     LOG_DBG(LOG_DEBUG, "got tag %d", f->tag);
801     state = LPS_VAL;
802     if ( TAB == *p && e == ++p ) goto done;
803     case LPS_VAL:
804     lf = memchr(p, LF, e-p);
805     if ( !lf )
806     len = e-p;
807     else if ( (len = lf-p) && CR == lf[-1] ) {
808     if ( LPS_CR & bits )
809     len--;
810     else if ( f == l->fld ) {
811     len--;
812     bits |= LPS_CR;
813     LOG_DBG(LOG_DEBUG, "detected crlf");
814     }
815     }
816     LAPP(l, p, len);
817     if ( lf ) {
818     state = LPS_SOL;
819     /* if ( f == l->fld ) STRIP W\t ? */
820     if ( e > (p = lf+1) )
821     continue;
822     }
823     goto done;
824     } // for switch
825     done:
826     return state|bits;
827     } /* lParse */
828    
829    
830     int lOut ( List *l, int tag, const char *fmt, ... )
831     {
832     va_list ap;
833     int indir = !fmt;
834     int bav;
835     int len=0, i;
836     unsigned u;
837     char *p, *q=0, c=0;
838     const char *tok = 0;
839    
840     va_start( ap, fmt );
841     if ( indir ) {
842     va_list ap2;
843     fmt = va_arg(ap, const char*);
844     ap2 = va_arg(ap, va_list);
845     va_end( ap );
846     ap = ap2;
847     }
848     LNEWF( l, tag, 4000 );
849     bav = LAVL(l);
850     p = l->buf;
851     for (;;) {
852     if ( !*fmt )
853     goto extend;
854     if ('%' != *fmt) {
855     tok = fmt+1;
856     while (*tok && '%'!=*tok)
857     tok++;
858     if ( bav < (len = tok-fmt) )
859     goto extend;
860     memcpy(p, fmt, len);
861     p += len;
862     bav -= len;
863     if ( !*(fmt = tok) )
864     goto extend;
865     }
866     /* now '%' == *fmt */
867     switch (c = *++fmt) {
868     case 0: /* bah -- trailing % */
869     goto extend;
870     case '0': /* only in %0nx */
871     if ( fmt[1] < '1' || '8' < fmt[1] || 'x' != fmt[2] )
872     continue;
873     c = fmt[1];
874     tok = fmt + 2;
875     case '2': /* meaning %02x */
876     case '4':
877     case '8':
878     if ( 'x' == fmt[1] ) tok = fmt + 1; /* optional */
879     if (0) {
880     case 'x':
881     c = '4';
882     case 'd':
883     case 'u':
884     tok = fmt;
885     }
886     if ( bav < (len = 12) )
887     goto extend;
888     u = va_arg(ap, unsigned);
889     switch (c) {
890     case 'd': len = i2a(p, (int)u); break;
891     case 'u': len = u2a(p, u); break;
892     default:
893     i = len = c - '0';
894     while (i--) {
895     p[i] = b36dig[u & 0xf];
896     u >>= 4;
897     }
898     }
899     fmt = tok;
900     break; /* the numbers */
901     case 'c':
902     if ( bav < (len = 1) )
903     goto extend;
904     *p = (char)va_arg(ap, int);
905     break;
906     default:
907     case '%':
908     if ( bav < (len = 1) )
909     goto extend;
910     *p = c;
911     break;
912     case 'b': /* bytes -- eats 2 args len, q */
913     len = 2*va_arg(ap, int);
914     q = va_arg(ap, char*);
915     if ( bav < len )
916     goto extend;
917     the_bytes_thing:
918     for (i=0; i<len; ) {
919     u = (unsigned char)*q++;
920     p[i++] = b36dig[u>>4];
921     p[i++] = b36dig[u & 0xf];
922     }
923     break;
924     case '.': /* only used as .*s */
925     if ( '*' != *++fmt || 's' != *++fmt )
926     continue; /* prolly bad ... */
927     case '*': /* shorthand */
928     len = va_arg(ap, int);
929     case 's':
930     q = va_arg(ap, char*);
931     if ( 's' == c )
932     len = strlen(q);
933     if ( 0 ) {
934     Fld *v;
935     case 'v':
936     v = va_arg(ap, Fld*);
937     len = v->len;
938     q = v->val;
939     }
940     if ( bav < len )
941     goto extend;
942     the_string_thing: /* for eivind aarset */
943     /* since we need to shift args to check len and cannot unshift */
944     memcpy(p, q, len);
945     }
946     p += len;
947     bav -= len;
948     fmt++;
949     continue;
950     extend:
951     LLAST( l )->len += p - l->buf;
952     l->buf = p;
953     if ( !*fmt )
954     break;
955     /* need len */
956     lExtend(l, len, -1);
957     bav = LAVL(l);
958     p = l->buf;
959     switch (c) {
960     case '.':
961     case '*':
962     case 's':
963     goto the_string_thing;
964     case 'b':
965     goto the_bytes_thing;
966     }
967     fmt--; /* simply start over */
968     }
969     if ( !indir ) /* else it's not ours and caller should va_end */
970     va_end( ap );
971     return len;
972     } /* lOut */

  ViewVC Help
Powered by ViewVC 1.1.26