    NAME
         lAddElemStr, lDelElemStr, lGetElemStr - list operations
         lAddSubStr, lDelSubStr, lGetSubStr - sub-list operations

    SYNOPSIS
         #include "cull.h"

         lListElem* lAddElemStr(
              lList** lpp,
              int nm,
              char *s,
              lDescr *dp
         );

         int lDelElemStr(
              lList** lpp,
              int nm,
              char *s
         );

         lListElem *lGetElemStr(
              lList* lp,
              int nm,
              char *s
         );

         lListElem* lAddSubStr(
              lListElem* ep,
              int nm,
              char *s,
              B
              int snm,
              lDescr *dp
         );

         int lDelSubStr(
              lListElem* ep,
              int nm,
              char *s,
              int snm
         );

         lListElem *lGetSubStr(
              lListElem* ep,
              int nm,
              char *s,
              int snm
         );

         lListElem *lDiffListStr(
              int nm,
              lList** lpp1,
              lList** lpp1,
         );

    DESCRIPTION
         lListElem *lAddElemStr(lpp, nm, s, dp)
              Appends an element to the list *lpp.  The  new  element
              gets  the  type dp (using lCreateElem(3)).  Field nm of
              the  new  elements  gets  the  value  s  (using   lSet-
              String(3)).   No  test are made to ensure uniqueness of
              elements in the list. If *lpp is NULL a new  list  head
              gets  created  (using  lCreateList(3)).   lAddElemStr()
              fails if the given list or descriptor has no field nm.

         int lDelElemStr(lpp, nm, s)
              Removes one element containing s at  field  nm  in  the
              list *lpp.  lGetElemStr is used to find the element. It
              gets unchained and freed. If no more  elements  are  in
              the  list after unchaining the list head gets freed and
              NULL is written to  *lpp.   lDelElemStr  fails  if  the
              given list has no field nm.

         lListElem *lGetElemStr(lp, nm, s)
              Searches the first element containing s at field nm  in
              the  list lp.  strcmp(3) s used to perform the compare.
              lGetElemStr returns the element.

         lListElem *lAddSubStr(ep, nm, s, snm, dp)
              Uses lAddElemStr to append an element to  the  sub-list
              field snm of the element ep.

         int lDelSubStr(ep, nm, s, snm)
              Uses lDelElemStr to remove an element from the sub-list
              field snm of the element ep.

         lListElem *lGetSubStr(ep, nm, s, snm)
              Uses lGetElemStr to find an  element  in  the  sub-list
              field snm of the element ep.

         int lDiffListStr(nm, lpp1, lpp2)
              lDiffListStr removes and frees elements in  both  lists
              with the same string key in field nm.

    EXAMPLES
         The first example shows the usage of list functions:

         =======================================================================

         #include "cull.h"

         f()
         {
              lList *lp = NULL;
              lListElem *ep;

              /* add a queue element where QU_qname is "balin.q" to the list lp */
              if (!(ep=lAddElemStr(&lp, QU_qname, "balin.q", QU_Type))) {
                   /* ... */
              }
              lSetString(ep, QU_qhostname, "balin.mydomain");

              /* get the element of lp where QU_qname is "balin.q" */
              if (!(ep=lGetElemStr(lp, QU_qname, "balin.q"))) {
                   /* ... */
              }

              /* remove the element of lp where QU_qname is "balin.q" */
              if (!lDelElemStr(&lp, QU_qname, "balin.q")) {
                   /* ... */
              }

              /* here lp will be NULL again */

              return;
         }

         =======================================================================

         The second example shows the usage of sub-list functions:

         =======================================================================

         #include "cull.h"

         g(queue)
         lListElem *queue;
         {
              lListElem *ep;

              /* add an owner element with OW_name "bill" to the */
              /* sub-list QU_ownerlist of the element ep          */
              ep = lAddSubStr(ep, OW_name, "bill", QU_ownerlist, OW_Type);
              if ( !ep ) {
                   /* ... */
              }
              lSetString(ep, OW_permissions, "everything");

              /* get the element in the sub-list QU_ownerlist of  */
              /* the element ep where OW_name is "bill"          */
              if (!(ep=lGetSubStr(ep, OW_name, "bill", QU_ownerlist))) {
                   /* ... */
              }
              printf("Owner: %s0, lGetString(ep, OW_name));

              /* remove the element in the sub-list of element ep */
              /* where OW_name is "bill"                         */
              if (!lDelSubStr(ep, OW_name, "bill", QU_ownerlist)) {
                   /* ... */
              }

              return;
         }

         =======================================================================

    RETURN VALUES
         lAddElemStr and lAddSubStr return a  pointer  to  the  added
         list  element  or NULL on error.  lDelElemStr and lDelSubStr
         return 1 on success and 0 on error.  lGetElemStr  and  lGet-
         SubStr return a pointer to the found list element or NULL on
         error.  lDiffListStr returns 0 on success and -1 on error.

    SEE ALSO
         sge_intro(1), list_intro(3),  lSetString(3),  lGetString(3),
         lAppendElem(3),  lDechainElem(3),  lCreateElem(3), lCreateL-
         ist(3).

    COPYRIGHT
         See sge_intro(1) for a full statement of rights and  permis-
         sions.