home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / xdme1820.lha / XDME / varsbases.c < prev    next >
C/C++ Source or Header  |  1993-03-09  |  19KB  |  971 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     varsbases.c
  5.  
  6.     DESCRIPTION
  7.     lowlevel Variable support for DME/XDME
  8.     (Basic List/AVL-Tree Functions)
  9.  
  10.  
  11.     NOTES
  12.     Either use AVLTREES or MLISTS
  13.  
  14.     For ALL commands (even to the searches) You must use
  15.     the address of a tree/list, not the tree/list itself
  16.     (that was done to simplify source-modification: just
  17.      replace 'List'/[M]LIST by 'Tree'/APTR, and go)
  18.  
  19.     BUGS
  20.     <none known>
  21.  
  22.     TODO
  23.     More homogene Interface - Use of an opaque type
  24.     (So that silly redefinition in other modules can go away)
  25.  
  26.     EXAMPLES
  27.     -/-
  28.  
  29.     SEE ALSO
  30.     vars.c
  31.  
  32.     INDEX
  33.  
  34.     HISTORY
  35.     <see RCS-File>
  36.  
  37.  
  38. ******************************************************************************/
  39.  
  40. /*
  41. **  (C)Copyright 1992 by Bernd Noll for null/zero-soft
  42. **  All Rights Reserved
  43. **
  44. **  RCS Header: $Id: varsbases.c,v 1.65 92/12/04 21:00:32 b_noll Exp $
  45. **
  46. **  Basic Functions to work with trees/lists of DME-Variables
  47. **  Put together to start a little bit of modularisation
  48. **  in the sources.
  49. **
  50. */
  51.  
  52. /**************************************
  53.         Includes
  54. **************************************/
  55. #include "defs.h"
  56.  
  57.  
  58. /**************************************
  59.        Exports
  60. **************************************/
  61. /* --- You can only use either LISTS or AVL-Trees!!! */
  62. /* Tree Operations in common */
  63. Prototype void * FindTreeNode        ( void ** tree, CHAR * name );
  64. Prototype void * AddTreeNode        ( void ** tree, void * obj );
  65. Prototype void * RemTreeNode        ( void ** tree, void * obj );
  66.  
  67. /* Vars Operations on trees */
  68. Prototype void     DelAllVarsFromTree ( void ** tree );
  69. Prototype void     DelVarFromTree     ( void ** tree, CHAR * name );
  70. Prototype CHAR * GetVarFromTree     ( void ** tree, CHAR * name );
  71. Prototype void     SetVarIntoTree     ( void ** tree, CHAR * name, CHAR * value );
  72.  
  73.  
  74. #ifdef NOTDEF
  75. /* Lists Operations in Common */
  76. Prototype CHAR* names2string   ( MLIST* list, CHAR* buffer, CHAR delimiter, void* filter );  /* assumes buffer is 1/4k * BUFFERS chgars long */
  77. Prototype int    numnodes       ( MLIST* list );
  78. Prototype NODE* findnode       ( MLIST* list, CHAR* name, short len );
  79.  
  80. /* Vars Operations on lists */
  81. Prototype void    DelAllVarsFromList ( MLIST* list );
  82. Prototype void    DelVarFromList ( MLIST* list, CHAR* name );
  83. Prototype CHAR* GetVarFromList ( MLIST* list, CHAR* name );
  84. Prototype void    SetVarIntoList ( MLIST* list, CHAR* name, CHAR* value );
  85. #endif
  86.  
  87.  
  88. /**************************************
  89.       Interne Defines & Strukturen
  90. **************************************/
  91. #ifdef TEST
  92. # define error printf
  93. # define nomemory()
  94. #endif
  95.  
  96. typedef struct TreeNode
  97. {    /* that struct should exactly fit into a Node */
  98.     void * tn_Left;
  99.     void * tn_Right;
  100.     char   tn_Balance;
  101.     char   pad; /* tn_Type; */
  102.     CHAR * tn_Name;
  103. } TNODE;
  104.  
  105.  
  106. typedef struct _VARS
  107. {
  108.     TNODE  Node;
  109.     CHAR * Str;
  110. } VARS;
  111.  
  112. #define VBASE VARS*
  113.  
  114. #ifdef NOT_DEF
  115.  
  116. typedef struct _VARS
  117. {
  118.     NODE  Node;
  119.     CHAR * Str;
  120. } VARS;
  121.  
  122. #define VBASE MLIST
  123.  
  124. #endif /* (not) PATCH_AVL */
  125.  
  126.  
  127.  
  128. /**************************************
  129.       Implementation
  130. **************************************/
  131.  
  132.  
  133. TNODE * FindTreeNode (TNODE** tree, CHAR* name)
  134. {
  135.     TNODE* n;
  136.  
  137.     if (!tree || !(*tree))
  138.     {
  139.     return(NULL);
  140.     } /* if */
  141.  
  142.     for (n = *tree; n; )
  143.     {
  144.     switch (strcmp (name, n->tn_Name))
  145.     {
  146.     case 0:
  147.         return(n);
  148.     case 1:
  149.         n = n->tn_Right;
  150.         break;
  151.     case -1:
  152.         n = n->tn_Left;
  153.         break;
  154.     default:
  155.         error ("VARS:\ninvalid result from strcmp");
  156.         return(NULL);
  157.     } /* switch */
  158.     } /* for */
  159.  
  160.     return(NULL);
  161. } /* FindTreeNode */
  162.  
  163.  
  164. static char
  165. BalanceTree (TNODE** t)
  166. {
  167.     TNODE * ot = *t;
  168.     TNODE * lt = ot->tn_Left;
  169.     TNODE * rt = ot->tn_Right;
  170.     char    b  = ot->tn_Balance;
  171.  
  172. /* printf("balancing\n"); */
  173.  
  174.     switch (b)
  175.     {
  176.     case -1:
  177.     case  0:
  178.     case +1:
  179.  
  180.     error ("called without need\n");
  181.     return (b);
  182.  
  183.     case +2:
  184.     b = lt->tn_Balance;
  185.     switch (b)
  186.     {
  187.     case -1:
  188. /* printf("LR\n"); */
  189.         rt = lt->tn_Right;
  190.         *t = rt;
  191.         ot->tn_Left    = rt->tn_Right;
  192.         lt->tn_Right   = rt->tn_Left;
  193.         rt->tn_Left    = lt;
  194.         rt->tn_Right   = ot;
  195.  
  196.  
  197.         b = rt->tn_Balance;
  198.         rt->tn_Balance = 0;
  199.         lt->tn_Balance =  (1-b)/2; /* -:1 0:0 +:0 */
  200.         ot->tn_Balance = -(1+b)/2; /*   0   0  -1 */
  201.  
  202.         return(0);
  203.  
  204.     case  0:
  205.     case +1: /* LL */
  206. /* printf("LL\n"); */
  207.         *t = lt;
  208.         ot->tn_Left    = lt->tn_Right;
  209.         lt->tn_Right   = ot;
  210.  
  211.         ot->tn_Balance = -(b-1); /* 0:+1; +1:0 */
  212.         lt->tn_Balance = +(b-1); /*   -1;    0 */
  213.  
  214.         return (b-1);
  215.  
  216.     default:
  217.         error ("VARS:\nBalance called with corrupt tree");
  218.     } /* switch */
  219.  
  220.     break;
  221.  
  222.     case -2:
  223.     b = rt->tn_Balance;
  224.     switch (b)
  225.     {
  226.     case +1:
  227. /* printf("RL\n"); */
  228.         lt = rt->tn_Left;
  229.         *t = lt;
  230.         ot->tn_Right   = lt->tn_Left;
  231.         rt->tn_Left    = lt->tn_Right;
  232.         lt->tn_Left    = ot;
  233.         lt->tn_Right   = rt;
  234.  
  235.         b = lt->tn_Balance;
  236.         lt->tn_Balance = 0;
  237.         rt->tn_Balance =  (1+b)/2; /* -:0 0:0 +: */
  238.         ot->tn_Balance =  (1-b)/2; /*   1   0    */
  239. /* printf ("b== %d\n",b); */
  240.  
  241.         return(0);
  242.  
  243.     case  0:
  244.     case -1: /* RR */
  245.  
  246. /* printf("RR\n"); */
  247.         *t = rt;
  248.         ot->tn_Right   = rt->tn_Left;
  249.         rt->tn_Left    = ot;
  250.  
  251.         /* Vorzeichen ??? */
  252.         ot->tn_Balance = -(b+1); /* 0:-1; -1:0 */
  253.         rt->tn_Balance = +(b+1); /*   +1;    0 */
  254. /* printf("ot%d rt%d\n", -(b+1), (b+1)); */
  255.         return -(b-1);
  256.  
  257.     default:
  258.         error ("VARS:\nBalance called with corrupt tree");
  259.     } /* switch */
  260.  
  261.     break;
  262.     default:
  263.     error ("VARS:\nBalance called with corrupt tree");
  264.     } /* switch */
  265.  
  266.     return(0);
  267. } /* BalanceTree */
  268.  
  269.  
  270.  
  271. static char
  272. swap_best_right (TNODE** swapme)
  273. {
  274.     TNODE* root = *swapme;
  275.     TNODE* curr = root;
  276.     TNODE* prev = NULL;
  277.     TNODE* z;
  278.     char bal = root->tn_Balance;
  279.  
  280. /* printf("swappin'\n"); */
  281.  
  282.     if ((curr = root->tn_Right) == NULL)
  283.     {
  284.     return(0);
  285.     } /* if */
  286.  
  287.     while (z = curr->tn_Left)
  288.     {
  289.     prev = curr;
  290.     curr = z;
  291.     } /* while */
  292.  
  293.     z = curr->tn_Right;
  294.     if (prev)
  295.     {
  296.     prev->tn_Left = root;
  297.     curr->tn_Right = root->tn_Right;
  298.     } else
  299.     {
  300.     curr->tn_Right = root;
  301.     } /* if */
  302.  
  303.     root->tn_Right = z;
  304.  
  305.     *swapme = curr;
  306.     curr->tn_Left = root->tn_Left;
  307.     root->tn_Left = NULL;
  308.  
  309.     /* swap the balances!!!! */
  310.     root->tn_Balance = curr->tn_Balance;
  311.     curr->tn_Balance = bal;
  312.  
  313.     return(1);
  314. } /* swap_best_right */
  315.  
  316.  
  317.  
  318. static char
  319. R_remtreenode (TNODE** tree, TNODE* obj)
  320. {
  321.  
  322.     TNODE * n    = *tree;
  323.     char    mod =  0;
  324.  
  325.     if (!n)
  326.     {
  327.     error ("VARS:\nCan't remove not-exsiting node");
  328.     return(0);
  329.     } /* if */
  330.  
  331.     switch (strcmp (obj->tn_Name, n->tn_Name))
  332.     {
  333.     case  0:
  334.     if (n != obj)
  335.     {
  336.         error ("VARS:\nCan't manage multiple entries in a tree");
  337.         return(0);
  338.     } /* if */
  339.  
  340.     if (swap_best_right(tree))
  341.     { /* noch nich' am boden */
  342.         n = *tree;
  343.         goto remright;        /* ab hier koennte es beschleunigt werden */
  344.     } else
  345.     {             /* schon am rand - abschneiden */
  346.         *tree = n->tn_Right;
  347.         return(1);
  348.     } /* if am rand */
  349.  
  350.     case  1:
  351. remright:
  352.     if ( R_remtreenode(&n->tn_Right, obj) )
  353.     {
  354.         n->tn_Balance ++;
  355.         if (n->tn_Balance == 2)
  356.         {
  357.         BalanceTree(tree);
  358.         } /* if */
  359.         return(!(*tree)->tn_Balance);
  360.     } /* if */
  361.     return(0);
  362.  
  363.     case -1:
  364.     if ( R_remtreenode(&n->tn_Left, obj) )
  365.     {
  366.         n->tn_Balance --;
  367.         if (n->tn_Balance == -2)
  368.         {
  369.         BalanceTree(tree);
  370.         } /* if */
  371.         return(!(*tree)->tn_Balance);
  372.     } /* if */
  373.     return(0);
  374.  
  375.     default:
  376.     error ("VARS:\ninvalid result from strcmp");
  377.     return(0);
  378.     } /* switch */
  379. } /* R_remtreenode */
  380.  
  381.  
  382.  
  383.  
  384. static char
  385. R_addtreenode (TNODE** tree, TNODE* obj)
  386. {
  387.     TNODE * n    = *tree;
  388.  
  389.     if (!n)
  390.     {
  391.     *tree = obj;
  392.     obj->tn_Right = NULL;
  393.     obj->tn_Left = NULL;
  394.     obj->tn_Balance = 0;
  395.     return(1);
  396.     } /* if */
  397.  
  398.     switch (strcmp (obj->tn_Name, n->tn_Name))
  399.     {
  400.     case 0:
  401.     error ("VARS:\nCan't manage multiple entries in a tree");
  402.     return(0);
  403.  
  404.     case 1:
  405.     if (R_addtreenode(&n->tn_Right, obj))
  406.     {
  407.         n->tn_Balance --;
  408.         if (n->tn_Balance == -2)
  409.         {
  410.         BalanceTree(tree);
  411.         } else
  412.         {
  413.         return(n->tn_Balance);
  414.         } /* if */
  415.     } /* if */
  416.     return(0);
  417.  
  418.     case -1:
  419.     if (R_addtreenode(&n->tn_Left, obj))
  420.     {
  421.         n->tn_Balance ++;
  422.         if (n->tn_Balance == 2)
  423.         {
  424.         BalanceTree(tree);
  425.         } else
  426.         {
  427.         return(n->tn_Balance);
  428.         } /* if */
  429.     } /* if */
  430.     return(0);
  431.  
  432.     default:
  433.     error ("VARS:\ninvalid result from strcmp");
  434.     return(0);
  435.     } /* switch */
  436. } /* R_addtreenode */
  437.  
  438.  
  439.  
  440.  
  441. /*
  442. **  RemTreeNode
  443. **    Remove a node from an avl-tree; the right
  444. **    position is searched with strcmp()
  445. **
  446. **  NOTE U first have to search for the node which
  447. **     is to be deleted e.g.:
  448. **     RemTreeNode(&tree, FindTreeNode(&tree, name ));
  449. */
  450.  
  451. TNODE * RemTreeNode (TNODE** tree, TNODE* obsolete)
  452. {
  453.     if ((!tree) || (!(*tree)))
  454.     return (NULL);
  455.     if (obsolete)
  456.     R_remtreenode (tree, obsolete);
  457.     return (*tree);
  458. } /* RemTreeNode */
  459.  
  460.  
  461.  
  462. /*
  463. **  AddTreeNode
  464. **    Append a new node to an avl-tree; the right
  465. **    position is calculated with strcmp()
  466. **
  467. **  NOTE U cannot define two nodes with the same
  468. **     name in one tree
  469. */
  470.  
  471. TNODE * AddTreeNode (TNODE** tree, TNODE* new)
  472. {
  473.     if (!tree)
  474.     return (NULL);
  475.     if (new)
  476.     R_addtreenode (tree, new);
  477.     return (*tree);
  478. } /* AddTreeNode */
  479.  
  480.  
  481.  
  482.  
  483.  
  484. /*
  485. **  DelAllVarsFromTree()
  486. **    recursively remove all nodes from a certain tree
  487. **    and free them and their associated names&values
  488. */
  489.  
  490. void
  491. DelAllVarsFromTree (VARS** tree)
  492. {
  493.     if (!tree || !(*tree))
  494.     {
  495.     return;
  496.     } /* if */
  497.  
  498.     DelAllVarsFromTree(&(*tree)->Node.tn_Left);  /* first free its sons */
  499.     DelAllVarsFromTree(&(*tree)->Node.tn_Right);
  500.  
  501.     free((*tree)->Node.tn_Name);                  /* then free it and all its subs */
  502.     free((*tree)->Str);
  503.     free((*tree));
  504.  
  505. } /* DelAllVarsFromTree */
  506.  
  507.  
  508.  
  509. /*
  510. **  SetVarIntoTree()
  511. **    define a node with a cetain name and value in
  512. **    a given tree if therew is already a node of the
  513. **    chosen name the previous node is removed
  514. **    (actually only the old value is removed)
  515. **    if any allocation went wrong, call nomemory()
  516. */
  517.  
  518. void
  519. SetVarIntoTree (VBASE* tree, CHAR* name, CHAR* value)
  520. {
  521.     VARS* v  = NULL;
  522.     CHAR* vn = NULL;
  523.     CHAR* vv = NULL;
  524.  
  525.     if (v = (VARS*)FindTreeNode(tree, name))
  526.     {
  527.     if (vv = strdup(value))
  528.     {
  529.         free(v->Str);
  530.         v->Str = vv;
  531.         return;
  532.     } /* if malloced */
  533.     v = NULL; /* avoid freeing the found node */
  534.     } else
  535.     {
  536.     v = malloc(sizeof(VARS));
  537.     vv = strdup(value);
  538.     vn = strdup(name);
  539.     if (v && vv && vn)
  540.     {
  541.         v->Str = vv;
  542.         v->Node.tn_Name = vn;
  543.         AddTreeNode (tree, (TNODE *)v);
  544.         return;
  545.     } /* if malloced */
  546.     } /* if (no) old node */
  547.  
  548.     /* --- if we didn't return prior, (if everything worked fine) remove all allocated data */
  549.     if (v)  free(v);
  550.     if (vv) free(vv);
  551.     if (vn) free(vn);
  552.     nomemory();
  553.     abort();
  554. } /* SetVarIntoTree */
  555.  
  556.  
  557.  
  558.  
  559. /*
  560. **  DelVarFromTree()
  561. **    remove a certain node (found w/ FindTreeNode)
  562. **    from a given tree; do not panik, if there is no
  563. **    node found
  564. */
  565.  
  566. void
  567. DelVarFromTree (VBASE* tree, CHAR* name)
  568. {
  569.     VARS *v = NULL;
  570.  
  571.     if (v = (VARS*)FindTreeNode(tree, name))
  572.     {  /* if there is a node of the right name */
  573.     RemTreeNode (tree, (TNODE *)v);         /* remove it and all its subs */
  574.     free(v->Node.tn_Name);
  575.     free(v->Str);
  576.     free(v);
  577.     } /* if */
  578. } /* DelVarFromTree */
  579.  
  580.  
  581.  
  582.  
  583.  
  584. /*
  585. **  GetVarFromTree()
  586. **    find a node in a certain tree (w/ FindTreeNode)
  587. **    duplicate its value and return the copy
  588. **    return NULL if there was no node found
  589. **    and call nomemory() if duplicate failed
  590. */
  591.  
  592. CHAR*
  593. GetVarFromTree (VBASE* tree, CHAR* name)
  594. {
  595.     CHAR* str = NULL;
  596.     VARS* v   = NULL;
  597.  
  598.     if (v = (VARS*)FindTreeNode(tree, name))
  599.     { /* if there is a node of the right name */
  600.     if (str = strdup(v->Str))
  601.     {        /* return a copy of its value */
  602.         return(str);
  603.     } else
  604.     {
  605.         nomemory();
  606.         abort(NULL);
  607.     } /* if */
  608.     } /* if */
  609.     return(NULL);
  610. } /* GetVarFromTree */
  611.  
  612.  
  613.  
  614. #ifdef TEST
  615.  
  616.  
  617. void zeigebaum(TNODE* t)
  618. {
  619.     if (t==NULL)
  620.     {
  621.     printf( "-" );
  622.     return;
  623.     }
  624.  
  625.     printf("(%d%s ",t->tn_Balance,t->tn_Name);
  626.     printf("L");
  627.     zeigebaum(t->tn_Left);
  628.     printf("R");
  629.     zeigebaum(t->tn_Right);
  630.     printf(")");
  631. } /* zeigebaum */
  632.  
  633.  
  634.  
  635.  
  636. CHAR* testnamen[] =
  637. {
  638.     "prag",
  639.     "lima",
  640.     "tokio",
  641.     "bonn",
  642.     "paris",
  643.     "sofia",
  644.     "wien",
  645.     "bern",
  646.     "kairo",
  647.     "oslo",
  648.     "rom",
  649.     "athen",
  650.     NULL };
  651.  
  652.  
  653.  
  654. int main(int ac, char* av[])
  655. {
  656.     CHAR** tt;
  657.     CHAR buffer [100];
  658.  
  659.     TNODE* staedte = NULL;
  660.     TNODE* rem = NULL;
  661.  
  662.     for (tt = testnamen; *tt; tt++)
  663.     {
  664.     printf(">%s\n",*tt);
  665.     SetVarIntoTree(&staedte, *tt, "");
  666. /* gets      (buffer); */
  667.     } /* for */
  668.  
  669.     zeigebaum (staedte);
  670.     rem = FindTreeNode(&staedte, "bonn");
  671.     printf ("\nrem == %08lx %s\n", rem, rem->tn_Name);
  672.  
  673.     RemTreeNode(&staedte, rem);
  674.  
  675.  
  676.     zeigebaum(staedte);
  677.     printf("\n");
  678. } /* main */
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685. #endif TEST
  686.  
  687.  
  688. #ifdef NOT_DEF
  689.  
  690.  
  691. /*
  692. **  GetVarFromList()
  693. **    find a node in a certain list (w/ FindName)
  694. **    duplicate its value and return the copy
  695. **    return NULL if there was no node found
  696. **    and call nomemory() if duplicate failed
  697. */
  698.  
  699. CHAR*
  700. GetVarFromList (VBASE* list, CHAR* name)
  701. {
  702.     CHAR* str = NULL;
  703.     VARS* v   = NULL;
  704.  
  705.     if (v = (VARS*)FindName((LIST*)list, name))
  706.     { /* if there is a node of the right name */
  707.     if (str = strdup(v->Str))
  708.     {        /* return a copy of its value */
  709.         return(str);
  710.     } else
  711.     {
  712.         nomemory();
  713.         abort(NULL);
  714.     } /* if */
  715.     } /* if */
  716.     return(NULL);
  717. } /* GetVarFromList */
  718.  
  719.  
  720.  
  721. /*
  722. **  DelVarFromList()
  723. **    remove a certain node (found w/ FindName)
  724. **    from a given list; do not panik, if there is no
  725. **    node found
  726. */
  727.  
  728. void
  729. DelVarFromList (VBASE* list, CHAR* name)
  730. {
  731.     VARS *v = NULL;
  732.  
  733.     if (v = (VARS*)FindName((LIST*)list, name))
  734.     { /* if there is a node of the right name */
  735.     Remove((NODE *)v);                        /* remove it and all its subs */
  736.     free(v->Node.ln_Name);
  737.     free(v->Str);
  738.     free(v);
  739.     } /* if */
  740. } /* DelVarFromList */
  741.  
  742.  
  743.  
  744. /*
  745. **  DelAllVarsFromList()
  746. **    remove all nodes from a certain list
  747. **    and free them and their associated names&values
  748. */
  749.  
  750. void
  751. DelAllVarsFromList (VBASE* list)
  752. {
  753.     VARS* v = NULL;
  754.  
  755.     while (v = (VARS*)RemHead((LIST*)list))
  756.     {    /* while there is an entry left in the list */
  757.     free(v->Node.ln_Name);                  /* free it and all its subs */
  758.     free(v->Str);
  759.     free(v);
  760.     } /* while */
  761. } /* DelAllVarsFromList */
  762.  
  763.  
  764.  
  765. /*
  766. **  SetVarIntoList()
  767. **    define a node with a cetain name and value in
  768. **    a given list if therew is already a node of the
  769. **    chosen name the previous node is removed
  770. **    (actually only the old value is removed)
  771. **    if any allocation went wrong, call nomemory()
  772. */
  773.  
  774. void
  775. SetVarIntoList (VBASE* list, CHAR* name, CHAR* value)
  776. {
  777.     VARS* v  = NULL;
  778.     CHAR* vn = NULL;
  779.     CHAR* vv = NULL;
  780.  
  781. #ifdef N_DEF /* old method *//* POSITION DIFFERS BETWEEN XDME AND DME (+-12) */
  782.     /* --- First it is checked, if You have a Special variable */
  783.     /*
  784.     ** these checks may be object of some changes in near future
  785.     ** - I do now think, that it would be quite better
  786.     ** to introduce a new function SETSPC for special variables
  787.     ** and to call "SETLOCAL <num>" to set a local flag instead of "SET i<num>"
  788.     */
  789.     if (SetAnyFlag(name, value) || SetSpecialInt(name, value)
  790.     || SetSpecialVar(name, value) )
  791.     {
  792.     return();
  793.     } /* if */
  794.  
  795.     /* --- The Current variable - if exists - is deleted */
  796.     DelVarFromList(list, name);
  797.  
  798.     /* --- Then a new one is created and appended to the list */
  799.     if (v = malloc(sizeof(VARS)))
  800.     {
  801.     if (v->Node.ln_Name = strdup(name))
  802.     {
  803.         if (v->Str = strdup(value))
  804.         {
  805.         AddHead((LIST *)list, (NODE *)v);
  806.         return;
  807.         } /* if */
  808.         free(v->Node.ln_Name);
  809.     } /* if */
  810.     free(v);
  811.     } /* if */
  812.     nomemory();
  813. #endif /* N_DEF */
  814.  
  815.     /*
  816.     **    that routine is a little bit longer than the old one,
  817.     **    but we need not free all data of older entries any
  818.     **    more, so memory fragmentation should be reduced a bit:
  819.     **    if there's an older entry, simply replace its value
  820.     **    by the new one, else create a full new entry.
  821.     */
  822.     if (v = (VARS*)FindName((LIST*)list, name))
  823.     {
  824.     if (vv = strdup(value))
  825.     {
  826.         free(v->Str);
  827.         v->Str = vv;
  828.         /* --- it might be senseful moving the changed entry to startoflist */
  829.         /* Remove(v); */
  830.         /* AddHead((LIST*)list, v) */
  831.         return;
  832.     } /* if malloced */
  833.     v = NULL; /* avoid removing the found node */
  834.     } else
  835.     {
  836.     v = malloc(sizeof(VARS));
  837.     vv = strdup(value);
  838.     vn = strdup(name);
  839.     if (v && vv && vn)
  840.     {
  841.         v->Str = vv;
  842.         v->Node.ln_Name = vn;
  843.         AddHead((LIST *)list, (NODE *)v);
  844.         return;
  845.     } /* if malloced */
  846.     } /* if (no) old node */
  847.  
  848.     /* --- if we didn't return prior, (if everything worked fine) remove all allocated data */
  849.     if (v)  free(v);
  850.     if (vv) free(vv);
  851.     if (vn) free(vn);
  852.     nomemory();
  853.     abort();
  854. } /* SetVarIntoList */
  855.  
  856.  
  857.  
  858. /*
  859. **        Names 2 String
  860. **  copies all ln_Name s of a given List into a String and returns it
  861. **  (if filter != NULL the names are filtered before)
  862. **  There _must_ be a buffer big enough to fit all the Strings:
  863. **    definements in defs.h:
  864. **  BUFFERS is the number of "LINES" reserved for buffer
  865. **  and LINE_LENGTH (== 256) is the length of one such line
  866. **  <exec/lists.h> should be included
  867. **
  868. **  name2string does _not_ allocate memory!!!!
  869. **  currently filter MUST BE SET to NULL to guarantee compatibility to later versions!
  870. **  list MUST BE VALID! (there is no check)
  871. */
  872.  
  873. CHAR*
  874. names2string (MLIST* list, CHAR* buffer, CHAR delimiter, CHAR* (*filter)())
  875. {
  876.     struct Node* node;
  877.     CHAR*     buf      = buffer;
  878.     int      i      = 0;
  879.     CHAR     delim[2] =
  880.     {delimiter,0};
  881.     /* CHAR    inter[128]; */
  882.  
  883.     node = (NODE*)list->mlh_Head;
  884.     while (node->ln_Succ && node != (NODE*)&list->mlh_Tail)
  885.     {
  886.     buffer = buf+i;
  887. /* ************************************ Hier gehoert noch der filter hin, ich brauchte ihn nur bisher noch nicht, daher liess ich ihn weg * */
  888.     if ((i += strlen(node->ln_Name)) < BUFFERS*LINE_LENGTH-1)
  889.     {
  890.         strcpy(buffer, node->ln_Name);
  891.         if (i < BUFFERS*LINE_LENGTH-1)
  892.         {
  893.         buffer = buf+i;
  894.         strcpy(buffer, delim);
  895.         i++;
  896.         } else
  897.         {
  898.         return(buf);
  899.         } /* if */
  900.     } else
  901.     {
  902.         break;
  903.     } /* if */
  904.     node = node->ln_Succ;
  905.     } /* while */
  906.  
  907.     *buffer = 0;
  908.     return(buf);
  909. } /* names2string */
  910.  
  911.  
  912.  
  913. /*
  914. ** numnodes() - return the number of entries in a list
  915. **
  916. **  list MUST BE VALID! (there is no check)
  917. */
  918.  
  919. int
  920. numnodes(MLIST* list)
  921. {
  922.     register int    i = 0;
  923.     register MNODE* n;
  924.  
  925.     for (n = list->mlh_Head; (n != NULL) && (n->mln_Succ != NULL); n = n->mln_Succ)
  926.     {
  927.     i++;
  928.     } /* for */
  929.     return(i);
  930. } /* numnodes */
  931.  
  932.  
  933.  
  934. /*
  935. ** findnode() - find a certain node in a list
  936. **
  937. **  search may be done up to a certain strlength (own function) or via FindName
  938. **
  939. **  list MUST BE VALID! (there is no check)
  940. */
  941.  
  942. NODE*
  943. findnode(MLIST* list, CHAR* name, short len)
  944. {
  945.     register NODE* node;
  946.  
  947.     if (len)
  948.     {
  949.     for (node = (NODE*)list->mlh_Head; node && node->ln_Succ; node = node->ln_Succ)
  950.     {
  951.         if (strncmp(node->ln_Name, name, len) == 0)
  952.         {
  953.         return(node);
  954.         } /* if */
  955.     } /* for */
  956.     } else
  957.     {
  958.     return(FindName((LIST*)list, name));
  959.     } /* if */
  960.     return(NULL);
  961. } /* findnode */
  962.  
  963.  
  964. #endif /* (not) PATCH_AVL */
  965.  
  966.  
  967. /******************************************************************************
  968. *****  ENDE varsbases.c
  969. ******************************************************************************/
  970.  
  971.