    NAME
         lSelect, lSelectDestroy, lSplit, lJoinSubList, lJoin, lWhere
         (_lWhere),  lOrWhere,  lAndWhere,  lFreeWhere, lWhat, lFree-
         What, lWriteWhere, lWriteWhat, lCountWhat

         generic list database functions

    SYNOPSIS
         #include "cull.h"

         lList* lSelect(
              char *newname,
              lList *sourcelist,
              lCondition *condition,
              lEnumeration *enumeration
         );

         lList* lSelectDestroy(
              lList *sourcelist,
              lCondition *condition,
         );

         int lSplit(
              lList **sourcelist,
              lList **not_matched_list,
              char *not_matched_list_name,
              lCondition *condition,
         );

         lList* lJoinSublist(
              char *newname,
              int joinfield,
              lList *list1,
              lCondition *where1,
              lEnumeration *what1,
              lDescr *subdescr,
              lCondition *where2,
              lEnumeration *what2
         );

         lList* lJoin(
              char *newname,
              int joinfield1,
              lList *lp0,
              lCondition *where1,
              lEnumeration *what1,
              int joinfield2,
              lList *lp1,
              lCondition *where2,
              lEnumeration *what2
         );

         lCondition* lWhere( char *format, ... );

         lCondition* _lWhere(char *format, WhereArgList arglist);

         lCondition* lOrWhere( lCondition *cp0, lCondition *cp1);

         lCondition* lAndWhere( lCondition *cp0, lCondition *cp1);

         void lFreeWhere( lCondition *condition );

         void lWriteWhere( lCondition *condition );

         lEnumeration* lWhat( char *format, ... );

         void lFreeWhat( lEnumeration *enumeration );

         void lWriteWhat( lEnumeration *enumeration );

         int lCountWhat(
              lEnumeration *enumeration,
              lDescr *descriptor
         );

    DESCRIPTION
         lSelect
              creates a new list extracting those elements  from  the
              source  list fulfilling the conditions stated in condi-
              tion. The new list elements  contain  only  the  fields
              given  by  enumeration.  The first argument is the name
              of the newly created list, the second argument  is  the
              source list, the third argument are the conditions that
              the selection requires and the fourth argument  chooses
              the  fields  that shall be contained in the result list
              elements. Thus  the  new  list  is  restricted  to  the
              interesting  fields  contained in the list element.  If
              there are matching elements a  pointer  to  the  result
              list  is returned, otherwise NULL is returned.  For the
              construction of conditions and enumerations see  lWhere
              and lWhat below.

         lSelectDestroy
              removes the  elements  not  fulfilling  the  conditions
              stated  in  condition  from  the source list. The first
              argument is the source list, the  second  argument  are
              the  conditions  that  the selection requires. Thus the
              new list  consists  only  of  elements  fulfilling  the
              stated  condition  (Attention:  for  further use of the
              original list,  you  have  to  do  a  lCopyList  before
              lSelectDestroy).   A  pointer  to  the  result  list is
              returned. If the reduced list contains no elements  the
              list is completely freed and NULL is returned.  For the
              construction of conditions see lWhere below.

         lSplit
              splits the source list into  two  distinct  parts.  The
              source list contains all elements fulfilling the condi-
              tion stated in condition and the elements  not  fulfil-
              ling this condition are contained in the list specified
              as second argument. The first argument is  the  address
              of  the source list, the second argument is the address
              of a list pointer which must be NULL. If  you  are  not
              interested in the not matched list set not_matched_list
              and not_matched_list_name to NULL.  The third  argument
              is  the  name of the not_matched list. The fourth argu-
              ment is a condition. (Attention: for further use of the
              original list, you have to do a lCopyList
               before lSplit).  The all elements of the  source  list
              match  the  condition the source list remains unchanged
              and the unmatched list is NULL.  If no element  matches
              the  condition  the  not_matched list contains all ele-
              ments and the source list is NULL.  In case of  success
              0  is  returned, otherwise -1.  For the construction of
              conditions see lWhere below.

         lJoinSublist
              joins a list with one of its  sub-lists.   lJoinSublist
              gets  as  the  first  argument  the  name  of the newly
              created list. The second argument is the join field (of
              type  lListT), the third argument is the main list, the
              following two arguments are the condition and  enumera-
              tion  for the main list, the sixth argument is the sub-
              list descriptor and the last two fields are the  condi-
              tions and field enumerations for the sub-list.
              For every main list element  fulfilling  the  condition
              where1  there is a join performed with the by joinfield
              specified sub-list of the  list  element.   Only  those
              elements  in  the  sub-list  that  match the conditions
              stated in  where2.  The  joined  elements  contain  the
              fields enumerated in what1 and what2.
              The joined list is returned when  there  were  matching
              elements  in  the list and the sub-list. Otherwise NULL
              is returned.
              For the construction of conditions and enumerations see
              lWhere and lWhat below.

         lJoin
              joins two different lists together. The first  argument
              is  the  name  of  the joined list, the second argument
              specifies the field over which the join has to be taken
              as  it  is addressed in list1, it follow the conditions
              and field selectors where1 and what1 and  the  same  is
              repeated for the second list list2.
              Every list element of list1 is combined with every ele-
              ment  of list2 if the contents of the join fields join-
              field1 and joinfield2 is equal and if  they  match  the
              conditions  stated  in  where1 (list elements of list1)
              and where2 (list elements of list2).  The combined list
              elements  contain  the  fields  enumerated in what1 and
              what2.
              The joined list is returned if matching  elements  have
              been created. Otherwise NULL is returned.
              For the construction of conditions and enumerations see
              lWhere and lWhat below.

         lWhere / _lWhere
              build a structure describing a set of conditions  which
              are used by several list library functions.
              lWhere gets as argument a format string expressing  the
              conditions.  It  is possible to have cascaded levels of
              conditions using brackets, the  logical  AND  (&&),  OR
              (||)  and  NOT  (!)  operator.  If NULL is delivered as
              condition structure no restrictions  on  the  list  are
              performed (i.e. all elements match).

              The syntax of the format  string  takes  the  following
              form:

                   cond: %T ( negsimple [{ && | || } {negsimple |
                             %I -> cond } ] )
                   negsimple: {simple | ! ( simple ) }
                   simple: %I relop valuetype [{&& | ||} simple ...]
                   relop: { < | > | == | != | <= | >= | m= | c= |  p=
              }
                   valuetype: { %d | %s | %u | %f | %g | %o | %c }

              For valuetype the specifiers represent in the order  as
              above

                   { int | string | unsigned long | float | double |
                        long | char }

              The relop specifiers have the following meaning:

                   <
                   >
                   <=
                   >=
                   ==
                   !=   comparison of numeric types as in the
                        C language
                   ==   case sensitive comparison of strings
                   c=   case insensitive comparison of strings
                   m=   bitmask evaluation operator
                   p=   pattern matching string comparison

              The following examples will show the usage:

                   where1 = lWhere( "%T(%I==%s && %I->%T(%I<%d ||
                             %I>%u || %I m= %u ))",
                             type1, field1, "Hello", field2, subtype,
                             subfield1, 12, subfield2, 34,
                             bitmasksubfield, IDLE | RUNNING );
                   where2 = lWhere( "%T(!(%I==%s))", type1, field1,
                             "Hello");

              The condition 'where1' says:

              field1 of list element with descriptor type1 must  con-
              tain  "Hello"  AND  the  sub-list stored in field2 with
              descriptor subtype has a field subfield1 and  subfield2
              shall  fulfill  subfield1  < 12 OR subfield2 > 34 OR in
              the bitmasksubfield the bits for RUNNING and  IDLE  are
              set.    Bitmasks   are   stored  in  an  unsigned  long
              (ulong_32).

              The condition 'where2' says:

              NOT ( field1 == "Hello" ) for field1  of  a  list  with
              descriptor type1.

              _lWhere is equal to lWhere concerning the format string
              describing the condition. The variable argument list of
              lWhere is replaced by an array of arguments  delivering
              the required information.

              The WhereArg struct is built as follows:

                   struct _WhereArg {
                        lDescr      *descriptor;
                        int         field;
                        lMultitype  *value;
                   };

              The translation of the varargs lWhere functionality  to
              the WhereArgList mechanism is shown below:

                   where = lWhere("%T( %I == %s && %I ->
                             %T ( %I < %d ) )",
                             QueueT, Q_hostname, "durin.q",
                             Q_ownerlist, OwnerT, O_ownerage, 22);

              The corresponding WhereArgList is:

                   WhereArg whereargs[20];

                   whereargs[0].descriptor = QueueT;
                   whereargs[1].field      = Q_hostname;
                   whereargs[1].value.str  = "durin.q";
                   whereargs[2].field      = Q_ownerlist;
                   whereargs[2].descriptor = OwnerT;
                   whereargs[3].field      = O_ownerage;
                   whereargs[3].value.i    = 22;

                   where = _lWhere("%T( %I == %s && %I ->
                             %T ( %I < %d ) )",
                             whereargs);

         lOrWhere
              build a new condition from  two  conditions  connecting
              them  with  a logical or. If one of the incoming condi-
              tions is NULL, NULL is returned.

         lAndWhere
              build a new condition from  two  conditions  connecting
              them with a logical and.  If one of the incoming condi-
              tions is NULL, NULL is returned.

         lFreeWhere
              release the memory allocated by lWhere for a  condition
              structure.   If  the  specified  condition structure is
              NULL the function simply returns.

         lWriteWhere
              writes a condition structure to  stdout  for  debugging
              purposes.  As  argument  a lCondition pointer is speci-
              fied.

         lWhat
              builds a field enumeration structure to choose a subset
              of  fields,  no  fields  at all or all fields in a list
              element.  The function gets as first argument a  format
              string describing the following variable argument list.
              The built field enumeration is type specific,  also  if
              all  or  no fields are specified (i.e. one needs a what
              structure for every descriptor type)

              The syntax of the format string is:

                   what: %T ( {  ALL  |  NONE  |  {%I  [  %I  ...]  |
                        ! ( %I [%I...] ) } } )

              %T specifies the descriptor type for  lWhat,  the  rest
              specifies  ALL  fields,  no fields or the fields listed
              with %I [%I...].

              The following examples shall make things clearer:

                   all_what = lWhat("%T(ALL)", QueueT);

              select all fields in QueueT.

                   some_what  =   lWhat("%T(%I   %I   %I)",   QueueT,
                        Q_load, Q_name, Q_hostname);

              select  the  fields  Q_load,  Q_name,  Q_hostname  from
              QueueT.

                   notsome_what   =   lWhat("%T(   !(%I   %I   %I))",
                        QueueT, Q_load, Q_name, Q_hostname);

              select all the fields of QueueT without QueueT, Q_load,
              Q_name, Q_hostname.

                   none_what = lWhat("%T(NONE)",QueueT);

              select no field at all.

         lFreeWhat
              release the memory allocated for  a  field  enumeration
              structure. If the argument is NULL, the function simply
              returns.

         lWriteWhat
              writes a field  enumeration  structure  to  stdout  for
              debugging purposes.

         lCountWhat
              count the number of fields defined in a field  enumera-
              tion  structure.   As  argument  a  pointer  to a field
              enumeration structure and a  list  descriptor  must  be
              provided.   If  one  of  the  arguments  is NULL, -1 is
              returned. Otherwise the number of fields is returned.

    RETURN VALUES
         In case of error the return value is -1 or NULL, otherwise 0
         or a valid pointer to the corresponding struct is returned.

    ERRORS
         The following errors may occur. The  touched  functions  are
         stated in parentheses.

         LELISTNULL
              List pointer is NULL. (lSelect)

         LEENUMNULL
              Field enumeration is NULL. (lSelect, lFreeWhat, lWrite-
              What, lCountWhat)

         LECOUNTWHAT
              lCountWhat failed. (lSelect)

         LEMALLOC
              Malloc(3) failed. (lSelect, lWhat)

         LEPARTIALDESCR
              Building a new partial descriptor failed. (lSelect)

         LECREATELIST
              lCreateList failed. (lSelect, lJoinSublist, lJoin)

         LEELEMNULL
              List element is NULL. (lSelect)

         LECOPYELEMPART
              Copying parts of the element failed. (lSelect)

         LEAPPENDELEM
              lAppendElem failed. (lSelect, lJoinSublist, lJoin)

         LEGETNROFELEM
              lGetNumberOfElem failed. (lSelect)

         LENULLARGS
              Unallowed use of NULL arguments. (lJoinSublist, lJoin)

         LEDESCRNULL
              List descriptor is NULL. (lJoinSublist, lWhere, lCount-
              What)

         LENAMENOT
              Name not contained in descriptor. (lJoinSublist, lJoin,
              lWhat)

         LEFALSEFIELD
              Not  a  valid  field  name  specified  in  enumeration.
              (lJoinSublist)

         LEJOINDESCR
              Joining of descriptors failed. (lJoinSublist, lJoin)

         LEJOIN
              lJoin failed. (lJoinSublist)

         LEADDLIST
              lAddList failed. (lJoinSublist)

         LEDIFFDESCR
              List descriptors are unequal. (lJoin)

         LEJOINCOPYELEM
              lJoinCopyElem failed. (lJoin)

         LENOFORMATSTR
              No format string specified. (lWhere, lWhat)

         LEPARSECOND
              Parsing a condition structure failed. (lWhere)

         LECONDNULL
              lCondition pointer is NULL. (lFreeWhere, lWriteWhere)

         LEOPUNKNOWN
              Unknown operator found. (lFreeWhere, lWriteWhere)

         LESYNTAX
              A syntax error occurred. (lWhat)

         LECOUNTDESCR
              Counting  the  number  of  descriptor  fields   failed.
              (lWhat, lCountWhat)

    SEE ALSO
         sge_intro(1), list_intro(3).

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