harglists.c
上传用户:tjescc
上传日期:2021-02-23
资源大小:419k
文件大小:26k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /*
  2.  *  Copyright (c) Nessus Consulting S.A.R.L., 2000 - 2001
  3.  *  Email: office@nessus.com
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License 
  16.  *  along with this library; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  $Id: harglists.c,v 1.37.2.1 2005/03/22 01:31:46 renaud Exp $
  20.  *
  21.  * Author: Jordan Hrycaj <jordan@mjh.teddy-net.com>
  22.  *
  23.  * Jordan re-wrote Renauds idea of an arglists management on top
  24.  * of the hash list manager
  25.  */
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #include "hlst.h"
  30. #define EXPORTING
  31. #include <includes.h>
  32. #include <errno.h>
  33. #define __HARG_INTERNAL__
  34. #include "harglists.h"
  35. #ifdef HAVE__ALLOCA
  36. #define alloca _alloca
  37. #define HAVE_ALLOCA
  38. #endif
  39. /* set this flag if you want to dump create/destroy messages */
  40. #undef HARG_CREATE_DEBUG
  41. /* activates the lost-losts tracker functions harg_tracker_dunp()
  42.    and harg_tracket_flush() */
  43. #undef HARG_LIST_TRACKER
  44. #define HARG_DEBUG 6 /* log level ranging [0..9] (9 is more output) */
  45. /* ------------------------------------------------------------------------- *
  46.  *                   private definitions: debugging stuff                    *
  47.  * ------------------------------------------------------------------------- */
  48. #ifdef HARG_DEBUG
  49. # define IFDEBUG(cmd) cmd
  50. # define XTAG(s) __FILE__ "(%u): " s ".n", __LINE__
  51. #else
  52. # define IFDEBUG(cmd)
  53. #endif
  54. /* same as *HLOG, below but for debugging, call it  XPRINT (("problem", ..)) */
  55. #define XPRINT(l,msg) IFDEBUG ({if ((l)<=dbglevel && xlog!=0)(*xlog) msg;})
  56. /* log level dependent convenience macros */
  57. #define XPRINT0(msg) XPRINT (0,msg)
  58. #define XPRINT1(msg) XPRINT (1,msg)
  59. #define XPRINT2(msg) XPRINT (2,msg)
  60. #define XPRINT3(msg) XPRINT (3,msg)
  61. #define XPRINT4(msg) XPRINT (4,msg)
  62. #define XPRINT5(msg) XPRINT (5,msg)
  63. #define XPRINT6(msg) XPRINT (6,msg)
  64. #define XPRINT7(msg) XPRINT (7,msg)
  65. #define XPRINT8(msg) XPRINT (8,msg)
  66. #define XPRINT9(msg) XPRINT (9,msg)
  67. /* ------------------------------------------------------------------------- *
  68.  *                      private definitions                                  *
  69.  * ------------------------------------------------------------------------- */
  70. /* XMALLOC returns memory initialized to zero */
  71. #define XMALLOC(x)  emalloc(x)
  72. #define XFREE(x)    efree(&(x))
  73. #define NEED_XREALLOC /* locally installed, no mem zero needed */
  74. #define XREALLOC(x,n) xrealloc(x,n)
  75. #ifdef DMALLOC
  76. #undef NEED_XREALLOC
  77. #undef XREALLOC
  78. #define XREALLOC(x,n) realloc(x,n)
  79. #endif
  80. /* local on-the-stack memory allocation */
  81. #ifdef HAVE_ALLOCA
  82. # define XALLOCA(x)  alloca(x)
  83. # define XDEALLOC(x) /* nothing */
  84. #else
  85. # define XALLOCA(x)  XMALLOC(x)
  86. # define XDEALLOC(x) XFREE(x)
  87. #endif
  88. typedef /* data part for the data type, following */
  89. struct _harg_aligned {
  90.   union {
  91.     char data [1]; 
  92.     void  *ptr[1]; /* force alignment */
  93.   } d;
  94. } harg_aligned ;
  95. typedef /* general data type record/slot */
  96. struct _harg {
  97.   hargtype_t type;
  98.   unsigned   size;
  99.   /* type ARG_STRING, ARG_STUCT data are stored as a data block
  100.      of given size - all other data types are stored as (void*) */
  101.   harg_aligned d;
  102.   /* varable length, struct aligned  */
  103. } harg;
  104. typedef /* recursive list copying */
  105. struct _copy_cb {
  106.   harglst *trg;
  107.   int    depth;  /* recursion depth */
  108. } copy_cb ;
  109. typedef /* call back function's state buffer */
  110. struct _do_for_all_cb_state {
  111.   void *state ;
  112.   int (*cb_fn)(void*,void*,hargtype_t,unsigned,hargkey_t*) ;
  113. } do_for_all_cb_state ;
  114. typedef /* custum sort call back function descriptor */
  115. struct _csts_desc {
  116.   harglst *a;
  117.   void *cmp_desc ;
  118.   int (*cmp)(void*, harglst*,
  119.      hargkey_t  *left_key, hargtype_t  left_type,
  120.      hargkey_t *right_key, hargtype_t right_type);
  121. } csts_desc ;
  122. static void debug (const char *, long, long);
  123. /* ------------------------------------------------------------------------- *
  124.  *                       private variable                                    *
  125.  * ------------------------------------------------------------------------- */
  126. #ifdef HARG_LIST_TRACKER
  127. static hlst *harg_tracker;
  128. #endif
  129. /* default logger */
  130. static void (*xlog) (const char *, ...) = 0;
  131. IFDEBUG (static int dbglevel = HARG_DEBUG);
  132. /* ------------------------------------------------------------------------- *
  133.  *                   private functions: helpers                              *
  134.  * ------------------------------------------------------------------------- */
  135. /* the memory size of the record containing the data block */
  136. #define HARG_SIZE(   len) (sizeof (harg) - sizeof (harg_aligned) + (len))
  137. #define HARG_RECSIZE(rec) HARG_SIZE((rec)->size)
  138. /* get the byte offset of a field */
  139. #define STRUCT_OFFSET(type, field) 
  140. ((char*)(&((type*)0)->field)-(char*)0)
  141. /* given a pointer to field "field" from a structure of type "type",
  142.    get the structure pointer */
  143. #define REVERT_FIELD_PTR(p, type, field)  
  144. ((type*)(((char*)p) - STRUCT_OFFSET (type,field)))
  145. /* key length depending on the data type */
  146. #define klen_by_type(t)  (is_ptrkey_type(t) ? sizeof (void*) : 0)
  147. /* if enabled, compare ignoring remote bits */
  148. #define falsify_given_type(s,t) 
  149.         (is_specific_type (s) && get_local_type ((s)^(t)) != 0)
  150. /* compare ignoring remote and ptr key bits */
  151. #define verify_simple_type(s,t) (get_simple_type ((s)^(t)) == 0)
  152. /* compare ignoring ptr key bits */
  153. #define verify_yekrtp_type(s,t)  (get_yekrtp_type ((s)^(t)) == 0)
  154. #ifdef NEED_XREALLOC
  155. static void *
  156. xrealloc
  157.   (void       *p,
  158.    unsigned size)
  159. {
  160.   void *q = realloc (p, size) ;
  161.   if (q == 0) {
  162.     /* on out of memory, let XMALLOC do the aborting job */
  163.     q = XMALLOC (size) ;
  164.     memcpy (q, p, size) ;
  165.     XFREE (p) ;
  166.     return q;
  167.   }
  168.   return q;
  169. }
  170. #endif /* NEED_XREALLOC */
  171. #ifdef HARG_LIST_TRACKER
  172. static void
  173. harg_tracker_add
  174.   (harglst *a)
  175. {
  176.   void **R;
  177.   if (harg_tracker == 0 && (harg_tracker = create_hlst (100,0,0)) == 0)
  178.     return ;
  179.   if ((R = find_hlst (harg_tracker, (char*)&a, sizeof (void*))) == 0 &&
  180.       (R = make_hlst (harg_tracker, (char*)&a, sizeof (void*))) == 0)
  181.     return;
  182.   *R = a;
  183. }
  184. static void
  185. harg_tracker_delete
  186.   (harglst *a)
  187. {
  188.   delete_hlst (harg_tracker, (char*)&a, sizeof (void*));
  189. }
  190. #else
  191. #define harg_tracker_add(x)
  192. #define harg_tracker_delete(x)
  193. #endif
  194. #ifdef  HARG_CREATE_DEBUG
  195. #define HARG_DEBUG
  196. static void
  197. say_creating
  198.   (void    *list,
  199.    unsigned size)
  200. {
  201.   debug ("Creating harg -> 0x%lx{%u}", (long)list, size);
  202. }
  203. static void
  204. say_closing
  205.   (void    *list,
  206.    unsigned flag)
  207. {
  208.   char f [200] = "Closing harg -> 0x%lx" ;
  209.   int n = 0 ;
  210.   if (flag & H_sREMOTE) 
  211.     strcat (f, n ++ ? "|H_sREMOTE"  : ", flags=H_sREMOTE");
  212.   if (flag & H_sWRTHRU) 
  213.     strcat (f, n ++ ? "|H_sWRTHRU"  : ", flags=H_sWRTHRU");
  214.   if (flag & H_sRECURSE)
  215.     strcat (f, n ++ ? "|H_sRECURSE" : ", flags=H_sRECURSE");
  216.   debug (f, (long)list, 0);
  217. }
  218. #else
  219. #define say_creating(x,y)
  220. #define say_closing(x,y)
  221. #endif /* HARG_CREATE_DEBUG */
  222. #ifdef HARG_DEBUG
  223. static void
  224. message
  225.   (const char *s,
  226.    const char *f,
  227.    long        u,
  228.    long        v,
  229.    const char *t)
  230. {
  231.   fputs (s, stderr);
  232.   fprintf (stderr, f, u, v);
  233.   fputs (t, stderr);
  234. # ifdef _WIN32
  235.   fputc ('r', stderr);
  236. # endif 
  237.   fputc ('n', stderr);
  238. }
  239. static void
  240. debug
  241.   (const char *s,
  242.    long        u,
  243.    long        v)
  244. {
  245.   message ("DEBUG: ", s, u, v, ".");
  246. }
  247. #endif /* HARG_DEBUG */
  248. static harg*
  249. create_harg
  250.   (hargtype_t type,
  251.    void      *data,
  252.    unsigned   size)
  253. {
  254.   harg *h ; 
  255.   if (!is_blob_type (type) && size == 0)
  256.     size = sizeof (void*);
  257.   
  258.   h = XMALLOC (HARG_SIZE (size));
  259.   h->type = type ;
  260.   h->size = size ;
  261.   if (!is_blob_type (type)) {
  262.     h->d.d.ptr [0] = data ;
  263.     return h;
  264.   }
  265.   if (verify_simple_type (type, HARG_STRING) && size != 0)
  266.     /* last character is '' */
  267.     h->d.d.data [ -- size] = '' ;
  268.   if (size != 0 && data != 0)
  269.     memcpy (h->d.d.data, data, size);
  270.   return h;
  271. }
  272. /* ------------------------------------------------------------------------- *
  273.  *                   private functions: local call backs                     *
  274.  * ------------------------------------------------------------------------- */
  275. static void
  276. clean_up
  277.   (harglst     *a,
  278.    harg     *data,
  279.    hargkey_t *key,
  280.    unsigned   len)
  281. {
  282.   /* last step, delete descriptor */
  283.   if (data == 0) {
  284.     if (a == 0) 
  285.       return ;
  286.     if (a->sorter != 0)
  287.       XFREE (a->sorter) ;
  288.     XFREE (a) ;
  289.     return ;
  290.   }
  291.   /* recursively delete sublist */
  292.   if (is_harglst_type (data->type) && 
  293.       a != 0 && (a->destroy_mode & H_sRECURSE))
  294.     harg_close_any (data->d.d.ptr [0], a->destroy_mode);
  295.   
  296. # ifdef ARG_ARGLIST
  297.   else
  298.     switch (data->type) {
  299.     case HARG_ARGLIST:
  300.     case HARG_PARGLIST:
  301.       /* recursively delete sublist */
  302.       if (a != 0 && (a->destroy_mode & H_sRECURSE))
  303. arg_free_all (data->d.d.ptr [0]);
  304.     default:
  305.      break;
  306.     }
  307. # endif
  308.   XFREE (data);
  309. }
  310. static int 
  311. do_for_all_cb
  312.   (do_for_all_cb_state *s, 
  313.    harg                *h,
  314.    hargkey_t         *key, 
  315.    unsigned           len)
  316. {
  317.   return (s->cb_fn) 
  318.     (s->state, 
  319.      is_blob_type (h->type) ?h->d.d.data :h->d.d.ptr [0],
  320.      h->type, h->size, key);
  321. }
  322. static harg*
  323. a_copy
  324.   (copy_cb  *desc,
  325.    harg     *data, /* from the source list */
  326.    hargkey_t *key,
  327.    unsigned   len)
  328. {
  329.   unsigned size ;
  330.   harglst *a, *b, *c ;
  331.   if (data == 0) { /* may happen, bootstrap also */
  332.     errno = 0 ;
  333.     return 0;
  334.   }
  335.   /* stupidly copying sensless data ?? */
  336.   if (is_harglst_type (data->type) && (a = data->d.d.ptr [0]) != 0) {
  337.     c = desc->trg ; /* == 0  on bootstrap level */
  338.       if (++ desc->depth >= HLST_MAX_RDEPTH) {
  339. errno = ELOOP ;  /* recursion overflow ? */
  340. return 0;
  341.       }
  342.       /* recursively populate the sublist */    
  343.       desc->trg =       /* mark it non-bootstrap level */
  344. b = XMALLOC (sizeof (harglst)) ;
  345.       if ((b->x = copy_hlst 
  346.    (a->x, query_hlst_size (a->x),
  347.     (void*(*)(void*,void*,char*,unsigned))a_copy, desc,
  348.     (void (*)(void*,void*,char*,unsigned))clean_up, 0)) == 0) {
  349. int e = errno ;
  350. XFREE    (b);
  351. errno = e ;
  352. return 0;
  353.       }
  354.     -- desc->depth ;                     /* end recursion */
  355.     if ((desc->trg = c) == 0)                  /* restore */
  356.       return (harg*)b;      /* return value for bootstrap */
  357.     
  358.     /* local type applies, only */
  359.     return create_harg (get_local_type (data->type), b, 0);
  360.   }
  361.   
  362.   /* return a copy of the data block */
  363.   size = HARG_RECSIZE (data);
  364.   return memcpy (XMALLOC (size), data, size);
  365. }
  366. static int
  367. __csts_cb /* custum sort call back function descriptor */
  368.   (void *desc,
  369.    const char  *left_key, unsigned  left_klen,
  370.    const char *right_key, unsigned right_klen)
  371. {
  372.   harglst   *a = desc ;
  373.   csts_desc *s = a->sorter ;
  374.   harg  **left_R = (harg**)find_hlst (a->x,  left_key,  left_klen);
  375.   harg **right_R = (harg**)find_hlst (a->x, right_key, right_klen);
  376.   
  377.   return (*s->cmp) 
  378.     (s->cmp_desc, a,
  379.      left_key,  get_local_type  ((*left_R)->type),
  380.      right_key, get_local_type ((*right_R)->type));
  381. }
  382. /* ------------------------------------------------------------------------- *
  383.  *               private functions: data tree dumper                         *
  384.  * ------------------------------------------------------------------------- */
  385. static void
  386. do_newlevel
  387.   (void)
  388. {
  389.   fputs ("n", stderr);
  390. }
  391. static void
  392. do_indent
  393.   (int level)
  394. {
  395.   while (level -- > 0)
  396.     fputs ("   ", stderr);
  397.   fputs (" ", stderr);
  398. }
  399. static void
  400. do_printf
  401.   (const char *f,
  402.    harg      **R,
  403.    void       *a,
  404.    int     flags,
  405.    int     ptype,
  406.    unsigned  arg)
  407. {
  408.   if (R != 0) {
  409.     char *s = query_key_hlst ((void**)R) ;
  410.     if (ptype)
  411.       fprintf (stderr, "<0x%04X/%d> = ", (void*)s,(int)(s));
  412.     else
  413.       fprintf (stderr, "<%s> = ", s);
  414.   } else {
  415.     fprintf (stderr, "list");
  416.   }
  417.   fprintf (stderr, f, a, arg);
  418.   fputs ("n", stderr);
  419. }
  420. static void **
  421. harg_walk_next_ptr
  422.   (hargwalk *w)
  423. {
  424.   return next_hlst_search ((hsrch*)w) ;
  425. }
  426. static void
  427. do_harg_dump
  428.   (harglst *a,
  429.    int  level)
  430. {
  431.   hargwalk *w ;
  432.   harg **R, *r ;
  433.   if(a == 0 || (w = harg_walk_init (a)) == 0) {
  434.     do_printf ("-error; no such list!n",0,0,0,0,0);
  435.     return;
  436.   } 
  437.   while ((R = (harg**)harg_walk_next_ptr (w)) != 0) {
  438.     int ptrky, flags = 0;
  439.     do_indent (level);
  440.     if ((r = *R) == 0) {
  441.       do_printf ("Warning: NULL entry in listn",0,0,0,0,0);
  442.       continue ;
  443.     }
  444.     ptrky = (is_ptrkey_type (r->type) != 0);
  445.     switch (get_simple_type (r->type)) {
  446.     case HARG_STRING:
  447.       do_printf (""%s"",  R, (void*)r->d.d.data, flags, ptrky, 0);
  448.       continue ;
  449.     case HARG_BLOB:
  450.       do_printf ("%#x[%u]", R, (void*)r->d.d.data, flags, ptrky, r->size);
  451.       continue ;
  452. #ifdef ARG_ARGLIST
  453.     case HARG_ARGLIST:
  454.       do_newlevel ();
  455.       do_printf ("(old mode>) sublist ...", R, 0, flags, ptrky, 0);
  456.       arg_dump (r->d.d.ptr [0], level+1);
  457.       continue ;
  458. #endif
  459.     case HARG_HARG:
  460.       /* do_newlevel (); */
  461.       if (is_remote_type (r->type))
  462. do_printf ("remote sublist{%s} ...", R, r->d.d.ptr+1, flags, ptrky, 0);
  463.       else
  464. do_printf ("sublist{%#x} ...", R, r->d.d.ptr [0], flags, ptrky, 0);
  465.       do_harg_dump (r->d.d.ptr [0], level+1);
  466.       continue ;
  467.     case HARG_INT:
  468.       do_printf ("%d",  R, r->d.d.ptr [0], flags, ptrky, 0);
  469.       continue;
  470.     default:
  471.       do_printf ("*%#x", R, r->d.d.ptr [0], flags, ptrky, 0);
  472.     }
  473.   }
  474.   harg_walk_stop (w);
  475. }
  476. /* ------------------------------------------------------------------------- *
  477.  *                      private functions                                    *
  478.  * ------------------------------------------------------------------------- */
  479. static harg *
  480. get_harg_entry
  481.   (harglst      *a,
  482.    const char *key,
  483.    unsigned    len)
  484. {
  485.   harg **R, *r ;
  486.   if (a == 0) { 
  487.     errno = EINVAL; 
  488.     return 0; 
  489.   }
  490.     if ((R = (harg**)find_hlst (a->x, key, len)) == 0)
  491.       return 0;
  492.   
  493.   if ((r = *R) != 0)
  494.     return r;
  495.   /* zombie, should not happen, anyway */
  496.   delete_hlst (a->x, key, len);
  497.   errno = ENOENT ;
  498.   return 0;
  499. }
  500. /* ------------------------------------------------------------------------- *
  501.  *                 public functions: open/close management                   *
  502.  * ------------------------------------------------------------------------- */
  503. harglst*
  504. harg_create 
  505.   (unsigned size)
  506. {
  507.   harglst* h = XMALLOC (sizeof (harglst)) ;
  508.   h->x = create_hlst 
  509.     /* never returns NULL */
  510.     (size, (void(*)(void*,void*,char*,unsigned))clean_up, h);
  511.   say_creating (h, size);
  512.   harg_tracker_add (h);
  513.   return h ;
  514. }
  515. void
  516. harg_close_any
  517.   (harglst *a,
  518.    int   flag)
  519. {
  520.   if (a == 0)
  521.     return ;
  522.   a->destroy_mode = flag ;
  523.   say_closing (a,flag);
  524.   harg_tracker_delete (a);
  525.   destroy_hlst (a->x); /* implicitely frees a == call back descriptor */
  526. }
  527. harglst*
  528. harg_dup
  529.   (harglst*    a,
  530.    unsigned size)
  531. {
  532.   copy_cb desc ;
  533.   harg data ;
  534.   /* sanity check */
  535.   if (a == 0) {
  536.     errno = EINVAL;
  537.     return 0; 
  538.   }
  539.   desc.trg         = 0 ;
  540.   desc.depth       = 0 ;
  541.   data.type        = HARG_HARG ;
  542.   data.d.d.ptr [0] = a ;
  543.   return (harglst*)a_copy (&desc, &data, 0, 0);
  544. }
  545. /* ------------------------------------------------------------------------- *
  546.  *               public functions: varable access - modify                   *
  547.  * ------------------------------------------------------------------------- */
  548. hargkey_t*
  549. harg_addt
  550.   (harglst      *a,
  551.    hargkey_t  *key,
  552.    hargtype_t type,
  553.    int   overwrite,
  554.    unsigned   size,
  555.    void     *value)
  556. {
  557.   harg **R, *r ;
  558.   /* depending on the key type get its length */
  559.   int klen = klen_by_type (type);;
  560.   /* sanity check */
  561.   if (a == 0 || key == 0 ||
  562.       size == 0 && ((value == 0) && is_blob_type (type) ||
  563.     verify_simple_type (type, HARG_BLOB))) {
  564.     errno = EINVAL; 
  565.     return 0;
  566.   }
  567.   if (verify_simple_type (type, HARG_STRING)) {
  568.     if (size == 0) /* need a terminating '' */
  569.       size = strlen (value) + 1 ;
  570.     else
  571.       size ++ ;
  572.   }
  573.     R = (harg**)find_hlst (a->x, key, klen);
  574.   
  575.   if (R != 0) {
  576.     r = *R ;
  577.     /* record exists, do we need to overwrite ? */
  578.     if (!overwrite && type == r->type)
  579.       return query_key_hlst ((void**)R);
  580.     /* reuse the data block if the sizes did not change */
  581.     if (r->size == size) {
  582.       r->type = type ;
  583.       if (type == HARG_STRING || type == HARG_BLOB) {
  584. if (size)
  585.   memcpy (r->d.d.data, value, size);
  586.       } else {
  587. r->d.d.ptr [0] = value;
  588.       }
  589.       return query_key_hlst ((void**)R);
  590.     }
  591.     /* sizes have changed - reallocate but keep ID */
  592.     *R = create_harg (type, value, size);
  593.     XFREE (r);
  594.     return query_key_hlst ((void**)R);
  595.   }
  596.   /* no such value - create anew */
  597.   if ((R = (harg**)make_hlst (a->x, key, klen)) != 0) {
  598.     *R = create_harg (type, value, size);
  599.     return query_key_hlst ((void**)R);
  600.   }
  601.   /* cannot happen */
  602.  
  603.   return 0; 
  604. }
  605. int
  606. harg_set_valuet
  607.   (harglst      *a,
  608.    hargkey_t  *key,
  609.    hargtype_t type,
  610.    unsigned   size,
  611.    void     *value)
  612. {
  613.   harg **R, *r ;
  614.   int klen = klen_by_type (type);
  615.   /* sanity check */
  616.   if (a == 0 || key == 0 ||
  617.       size == 0 && (value == 0 && is_blob_type (type) ||
  618.     verify_simple_type (type, HARG_BLOB))) {
  619.     errno = EINVAL; 
  620.     return -1;
  621.   }
  622.   
  623.     R = (harg**)find_hlst (a->x, key, klen);
  624.   if ((r = *R) == 0) { /* zombie, should not happen, anyway */
  625.     delete_hlst (a->x, key, klen);
  626.     errno = ENOENT ;
  627.     return -1;
  628.   }
  629.   if (falsify_given_type (type, (*R)->type)) {
  630.     errno = EPERM;  /* not permitted */
  631.     return -1;
  632.   }
  633.   if (is_blob_type (r->type) == 0) {
  634.     r->d.d.ptr [0] = value ; /* the quick way */
  635.     return 0;
  636.   }
  637.   if (verify_simple_type (r->type, HARG_STRING)) {
  638.     if (size == 0) /* need a terminating '' */
  639.       size = strlen (value) + 1 ;
  640.     else
  641.       size ++ ;
  642.   }
  643.   /* remains to any blob type */
  644.   if (r->size != size) { /* reallocate that entry */
  645.     *R = create_harg (r->type, value, size);
  646.     XFREE (r);
  647.     return 0;
  648.   } 
  649.   if (value != 0) {
  650.     if (verify_simple_type (r->type, HARG_STRING))
  651.       /* the string terminator may be on protected memory */
  652.       r->d.d.data [-- size] = '' ;
  653.     memcpy (r->d.d.data, value, size);
  654.   }
  655.   return 0;
  656. }
  657. int
  658. harg_renamet
  659.   (harglst       *a,
  660.    hargkey_t   *key,
  661.    hargtype_t  type,
  662.    hargkey_t  *nkey,
  663.    hargtype_t ntype)
  664. {
  665.   harg **S, **R, *r ;
  666.   int same_keys, klen = klen_by_type (type);
  667.   /* sanity check */
  668.   if (a == 0) {
  669.     errno = EINVAL; 
  670.     return -1; 
  671.   }
  672.     R = (harg**)find_hlst (a->x, key, klen);
  673.   if ((r = *R) == 0) { /* zombie, should not happen, anyway */
  674.     delete_hlst (a->x, key, klen);
  675.     errno = ENOENT ;
  676.     return -1;
  677.   }
  678.   /* check for a specific source type */
  679.   if (falsify_given_type (type, r->type)) {
  680.     errno = EPERM ;
  681.     return -1;
  682.   }
  683.   same_keys = 
  684.     nkey == 0 || 
  685.     (is_ptrkey_type  (type) && 
  686.      is_ptrkey_type (ntype) &&
  687.      memcmp (key, nkey, sizeof (void*)) == 0) ||
  688.     (is_ptrkey_type  (type) == 0 && 
  689.      is_ptrkey_type (ntype) == 0 &&
  690.      strcmp (key, nkey) == 0)
  691.     ? 1 
  692.     : 0 
  693.     ;
  694.   if (r->type == ntype && same_keys)
  695.     return 0 ; /* nothing to do */
  696.   /* check target type groups */
  697.   if (is_blob_type   (ntype) &&   is_blob_type (r->type) ||
  698.       is_scalar_type (ntype) && is_scalar_type (r->type) ||
  699.       is_specific_type (ntype) == 0) {
  700.     if (same_keys == 0) {
  701.       /* make new index */
  702.       if ((S = (harg**)make_hlst (a->x, nkey, klen_by_type (ntype))) == 0)
  703. return -1;
  704.       *S = *R;
  705.       *R = 0;
  706.       delete_hlst (a->x, key, klen);
  707.     }
  708.     if (is_specific_type (ntype))
  709.       r->type = ntype ;
  710.     return 0;
  711.   }
  712.   errno = EPERM;  /* not permitted */
  713.   return -1 ;
  714. }
  715. int
  716. harg_removet
  717.   (harglst      *a,
  718.    hargkey_t  *key,
  719.    hargtype_t type)
  720. {
  721.   int klen = klen_by_type (type) ;
  722.   harg **R = 0;
  723.   /* sanity check */
  724.   if (a == 0 || key == 0) { 
  725.     errno = EINVAL; 
  726.     return -1; 
  727.   }
  728.     if (is_specific_type (type) && 
  729. (R = (harg**)find_hlst (a->x, key, klen)) == 0) {
  730.       errno = ENOENT ;  /* no such record */
  731.       return -1 ;
  732.     }
  733.   if (R != 0 && *R != 0 && falsify_given_type (type, (*R)->type)) {
  734.     errno = EPERM ;
  735.     return -1;
  736.   }
  737.   return delete_hlst (a->x, key, klen);
  738. }
  739. /* ------------------------------------------------------------------------- *
  740.  *               public functions: varable access - retrieve                 *
  741.  * ------------------------------------------------------------------------- */
  742. void * /* same as above, but with type check */
  743. harg_get_valuet
  744.   (harglst      *a,
  745.    hargkey_t  *key,
  746.    hargtype_t type)
  747. {
  748.   harg *r ;
  749.   
  750.   if ((r = get_harg_entry (a, key, klen_by_type (type))) == 0)
  751.     return 0;
  752.   /* check for strict type checking */
  753.   if (falsify_given_type (type, r->type)) {
  754.     errno = EPERM ;
  755.     return 0;
  756.   }
  757.   return is_blob_type (r->type) ? r->d.d.data : r->d.d.ptr [0] ;
  758. }
  759. int
  760. harg_inct
  761.   (harglst      *a,
  762.    hargkey_t  *key,
  763.    hargtype_t type,
  764.    incmode_t incop,
  765.    int         inc)
  766. {
  767.   harg *r, **R ;
  768.   int klen = klen_by_type (type);
  769.   /* sanity check */
  770.   if (a == 0) {
  771.     errno = EINVAL;
  772.     return -1; 
  773.   }
  774.   /* type may be 0, or HARG_ANY */
  775.   type = is_ptrkey_type (type) ?HARG_PINT :HARG_INT ;
  776.   
  777.     R = (harg**)find_hlst (a->x, key, klen);
  778.   /* no such entry, yet */
  779.   if (R == 0 || (r = *R) == 0) { 
  780.     if (inc_op_creates_record (incop)) {
  781.       if (R == 0 && (R = (harg**)make_hlst (a->x, key, klen)) == 0)
  782. return -1;
  783.       *R = create_harg (type, (void*)inc, sizeof (int));
  784.       errno = 0;
  785.       return (int)(*R)->d.d.ptr [0];
  786.     }
  787.     errno = ENOENT;
  788.     return -1;
  789.   }
  790.   /* entry exists, already */
  791.   if (!verify_simple_type (r->type, HARG_INT)) {
  792.     errno = EPERM;
  793.     return -1;
  794.   }
  795.   /* increment */
  796.   if (inc_op_increments_record (incop)) {
  797.     if (inc_op_wants_0_record (incop) && r->d.d.ptr [0] != 0) {
  798.       errno = EEXIST;
  799.       return -1;
  800.     }
  801.     r->d.d.ptr [0] = (void*)((int)(r->d.d.ptr [0]) + inc) ;
  802.     return (int)r->d.d.ptr [0];
  803.   }
  804.   /* decrement */
  805.   if (inc_op_notnegtv_record (incop) && (int)r->d.d.ptr [0] < inc) {
  806.     errno = ERANGE;
  807.     return -1;
  808.   }
  809.   if (inc_op_notpostv_record (incop) && (int)r->d.d.ptr [0] > inc) {
  810.     errno = ERANGE;
  811.     return -1;
  812.   }
  813.   if (inc_op_destroy0_record (incop) && (int)r->d.d.ptr [0] <= inc) {
  814.     delete_hlst (a->x, key, klen);
  815.     return errno = 0;
  816.   }
  817.   r->d.d.ptr [0] = (void*)((int)(r->d.d.ptr [0]) - inc) ;
  818.   errno = 0 ;
  819.   return (int)r->d.d.ptr [0];
  820. }
  821. void harg_sort(harglst *a) {
  822. sort_hlst(a->x);
  823. }
  824. int
  825. harg_csort
  826.   (harglst      *a,
  827.    int (*fn)(void*, harglst*,
  828.      hargkey_t  *left_key, hargtype_t  left_type,
  829.      hargkey_t *right_key, hargtype_t right_type),
  830.    void *fn_desc)
  831. {
  832.   csts_desc *s;
  833.   if (a == 0) {
  834.     errno = EINVAL; 
  835.     return 0; 
  836.   }
  837.   if (fn == 0) {
  838.     if (a->sorter == 0) {
  839.       XFREE (a->sorter);
  840.       a->sorter = 0;
  841.     }
  842.     return csort_hlst (a->x, 0, 0);
  843.   }
  844.   /* need some record space */
  845.   if ((s = a->sorter) == 0)
  846.     a->sorter = s = XMALLOC (sizeof (csts_desc));
  847.   s->cmp      = fn ;
  848.   s->cmp_desc = fn_desc;
  849.   return csort_hlst (a->x, __csts_cb, a);
  850. }
  851. hargkey_t *
  852. harg_get_ntht
  853.   (harglst      *a,
  854.    unsigned    inx,
  855.    hargtype_t type)
  856. {
  857.   harg **R ;
  858.   if (a == 0) {
  859.     errno = EINVAL; 
  860.     return 0; 
  861.   }
  862.     sort_hlst (a->x);
  863.     if ((R = (harg**)inx_hlst (a->x, inx)) == 0)
  864.       return 0 ;
  865.   /* check for strict type cheking */
  866.   if (falsify_given_type (type, (*R)->type)) {
  867.     errno = EPERM ;
  868.     return 0;
  869.   }
  870.   return query_key_hlst ((void**)R);    
  871. }
  872. hargtype_t
  873. harg_get_typet
  874.   (harglst      *a,
  875.    hargkey_t  *key,
  876.    hargtype_t type)
  877. {
  878.   harg *r = get_harg_entry (a, key, klen_by_type (type)) ;
  879.   return r == 0
  880.     ? 0 
  881.     : get_local_type (r->type)
  882.     ;
  883. }
  884. unsigned
  885. harg_get_sizet
  886.   (harglst *     a,
  887.    hargkey_t  *key,
  888.    hargtype_t type)
  889. {
  890.   harg *r = get_harg_entry (a, key, klen_by_type (type)) ;
  891.   return r == 0 
  892.     ? -1
  893.     : (r->type & RHARG_ANY & RHARG_PANY) ? sizeof (void*) : r->size
  894.     ;
  895. }
  896. /* ------------------------------------------------------------------------- *
  897.  *               public functions: varable access - retrieve                 *
  898.  * ------------------------------------------------------------------------- */
  899. hargwalk*
  900. harg_walk_init
  901.   (harglst *a)
  902. {
  903.   if (a == 0) {
  904.     errno = EINVAL; 
  905.     return 0; 
  906.   }
  907.   return (hargwalk*)open_hlst_search (a->x);
  908. }
  909. hargkey_t*
  910. harg_walk_nextT
  911. (hargwalk        *w,
  912.    hargtype_t *Type)
  913. {
  914.   harg **P ;
  915.   if ((P =(harg**)harg_walk_next_ptr (w)) == 0)
  916.     return 0;
  917.   if (Type != 0)
  918.     *Type = (*P)->type ;
  919.   return query_key_hlst ((void**)P) ;
  920. }
  921. void
  922. harg_walk_stop
  923.   (hargwalk *w)
  924. {
  925.   close_hlst_search ((hsrch*)w);
  926. }
  927. int
  928. harg_do
  929.   (harglst    *a,
  930.    int (*fn) (void *,void*,hargtype_t,unsigned,hargkey_t*),
  931.    void *state)
  932. {
  933.   do_for_all_cb_state s ;
  934.   if (a == 0) {
  935.     errno = EINVAL; 
  936.     return -1; 
  937.   }
  938.   s.state = state ;
  939.   if ((s.cb_fn = fn) == 0) 
  940.     return -1 ;
  941.   
  942.   return for_hlst_do 
  943.     (a->x, (int(*)(void*,void*,char*,unsigned))do_for_all_cb, &s);
  944. }
  945. void
  946. harg_dump
  947.   (harglst *a)
  948. {
  949.   if (a == 0) return ;
  950.   do_harg_dump (a, 0);
  951.   /* hlst_statistics (a->x, 0, 0); not tested, yet */
  952. }
  953. void
  954. harg_tracker_flush
  955.   (void)
  956. {
  957. # ifdef HARG_LIST_TRACKER
  958.   destroy_hlst (harg_tracker);
  959.   harg_tracker = 0;
  960. # endif
  961. }
  962. void
  963. harg_tracker_dump
  964.   (void)
  965. {
  966. # ifdef HARG_LIST_TRACKER
  967.   void **R;
  968.   int i = 0;
  969.   sort_hlst (harg_tracker);
  970.   while (R = inx_hlst (harg_tracker, i++))
  971.     if (*R != 0) {
  972.       fprintf (stderr, "{0x%lx} = ", (long)*R);
  973.       do_harg_dump (*R, 0);
  974. #     ifdef _WIN32
  975.       fputc ('r', stderr);
  976. #     endif 
  977.       fputc ('n', stderr);
  978.     }
  979. # endif
  980. }
  981. void /* define a logger function */
  982.   (*harg_logger(void(*f)(const char *, ...)))
  983.      (const char *, ...)
  984. {
  985.   void (*g) (const char *, ...) ;
  986.   g = xlog ;
  987.   xlog = f ;
  988.   return g ;
  989. }
  990. int
  991. harg_debuglevel
  992.   (int n)
  993. {
  994.   unsigned d = -1;
  995.   IFDEBUG (d = dbglevel) ;
  996.   IFDEBUG (dbglevel = n);
  997.   return d;
  998. }
  999. /* ------------------------------------------------------------------------- *
  1000.  *                 source ends here                                          *
  1001.  * ------------------------------------------------------------------------- */