## NAME

         ef_expand_file,        del_ExpandFile,        ef_last_error,
         ef_list_expansions,  new_ExpandFile  - expand filenames con-
         taining ~user/$envvar and wildcard expressions

## SYNOPSIS

         #include <libtecla.h>

         ExpandFile *new_ExpandFile(void);

         ExpandFile *del_ExpandFile(ExpandFile *ef);

         FileExpansion *ef_expand_file(ExpandFile *ef,
                                       const char *path,
                                       int pathlen);

         int ef_list_expansions(FileExpansion *result, FILE *fp,
                                int term_width);

         const char *ef_last_error(ExpandFile *ef);

## DESCRIPTION

         The ef_expand_file() function is part of the  tecla  library
         (see  the  libtecla(3)  man  page).  It  expands a specified
         filename, converting ~user/ and ~/ expressions at the  start
         of  the  filename  to  the  corresponding  home directories,
         replacing  $envvar  with  the  value  of  the  corresponding
         environment  variable, and then, if there are any wildcards,
         matching these against existing  filenames.  Backslashes  in
         the  input  filename are interpreted as escaping any special
         meanings  of  the  characters  that   follow   them.    Only
         backslahes  that  are themselves preceded by backslashes are
         preserved in the expanded filename.

         In the presence of wildcards, the returned list of filenames
         only  includes  the  names of existing files which match the
         wildcards. Otherwise,  the  original  filename  is  returned
         after  expansion  of  tilde  and dollar expressions, and the
         result is not checked against existing  files.  This  mimics
         the file-globbing behavior of the unix tcsh shell.

         The supported wildcards and their meanings are:
           *        -  Match any sequence of zero or more characters.
           ?        -  Match any single character.
           [chars]  -  Match any single character that appears in
                       'chars'.  If 'chars' contains an expression of
                       the form a-b, then any character between a and
                       b, including a and b, matches. The '-'
                       character looses its special meaning as a
                       range specifier when it appears at the start
                       of the sequence of characters. The ']'
                       character also looses its significance as the
                       terminator of the range expression if it
                       appears immediately after the opening '[', at
                       which point it is treated one of the
                       characters of the range. If you want both '-'
                       and ']' to be part of the range, the '-'
                       should come first and the ']' second.

           [^chars] -  The same as [chars] except that it matches any
                       single character that doesn't appear in
                       'chars'.

         Note that wildcards never match the initial dot in filenames
         that  start  with  '.'.  The  initial '.' must be explicitly
         specified in the filename. This again  mimics  the  globbing
         behavior  of  most unix shells, and its rational is based in
         the fact that in unix, files with names that start with  '.'
         are usually hidden configuration files, which are not listed
         by default by the ls command.

         The following is a complete example of how to use  the  file
         expansion function.

           #include <stdio.h>
           #include <libtecla.h>

           int main(int argc, char *argv[])
           {
             ExpandFile *ef;      /* The expansion resource object */
             char *filename;      /* The filename being expanded */
             FileExpansion *expn; /* The results of the expansion */
             int i;

             ef = new_ExpandFile();
             if(!ef)
               return 1;

             for(arg = *(argv++); arg; arg = *(argv++)) {
               if((expn = ef_expand_file(ef, arg, -1)) == NULL) {
                 fprintf(stderr, "Error expanding %s (%s).\n", arg,
                                  ef_last_error(ef));
               } else {
                 printf("%s matches the following files:\n", arg);
                 for(i=0; i<expn->nfile; i++)
                   printf(" %s\n", expn->files[i]);
               }
             }

             ef = del_ExpandFile(ef);
             return 0;
           }

         Descriptions of the functions used above are as follows:

           ExpandFile *new_ExpandFile(void)

         This  function   creates   the   resources   used   by   the
         ef_expand_file()  function.  In particular, it maintains the
         memory  that  is  used  to  record  the  array  of  matching
         filenames  that  is returned by ef_expand_file(). This array
         is expanded as needed, so there is no built in limit to  the
         number of files that can be matched.

           ExpandFile *del_ExpandFile(ExpandFile *ef)

         This function deletes the resources that were returned by  a
         previous  call  to  new_ExpandFile(). It always returns NULL
         (ie a deleted object). It does nothing if the ef argument is
         NULL.

         A  container  of  the  following   type   is   returned   by
         ef_expand_file().

           typedef struct {
             int exists;   /* True if the files in files[] exist */
             int nfile;    /* The number of files in files[] */
             char **files; /* An array of 'nfile' filenames. */
           } FileExpansion;

           FileExpansion *ef_expand_file(ExpandFile *ef,
                                         const char *path,
                                         int pathlen)

         The ef_expand_file() function performs  filename  expansion,
         as  documented at the start of this section. Its first argu-
         ment is a resource object returned  by  new_ExpandFile().  A
         pointer to the start of the filename to be matched is passed
         via the path argument. This must be a normal NUL  terminated
         string, but unless a length of -1 is passed in pathlen, only
         the first pathlen characters will be used  in  the  filename
         expansion.   If  the length is specified as -1, the whole of
         the string will be expanded.

         The function returns a pointer to a container who's contents
         are the results of the expansion. If there were no wildcards
         in the filename, the nfile member will be 1, and the  exists
         member  should  be queried if it is important to know if the
         expanded file currently exists or not. If there  were  wild-
         cards,  then  the  contained  files[] array will contain the
         names of the nfile existing files  that  matched  the  wild-
         carded  filename,  and the exists member will have the value
         1. Note that the returned container belongs to the specified
         ef  object, and its contents will change on each call, so if
         you need to retain the results of  more  than  one  call  to
         ef_expand_file(),  you  should either make a private copy of
         the returned  results,  or  create  multiple  file-expansion
         resource objects via multiple calls to new_ExpandFile().

         On error, NULL is returned, and an explanation of the  error
         can be determined by calling ef_last_error(ef).

           const char *ef_last_error(ExpandFile *ef)

         This function returns the message which describes the  error
         that  occurred on the last call to ef_expand_file(), for the
         given (ExpandFile *ef) resource object.

           int ef_list_expansions(FileExpansion *result, FILE *fp,
                                  int terminal_width);

         The ef_list_expansions() function provides a convenient  way
         to    list    the    filename    expansions    returned   by
         ef_expand_file(). Like the unix ls command, it arranges  the
         filenames  into  equal width columns, each column having the
         width of the largest file. The number  of  columns  used  is
         thus  determined  by the length of the longest filename, and
         the specified terminal width. Beware that filenames that are
         longer than the specified terminal width are printed without
         being truncated, so output longer than the specified  termi-
         nal width can occur. The list is written to the stdio stream
         specified by the fp argument.

## THREAD SAFETY

         In multi-threaded programs, you should use the  libtecla_r.a
         version  of the library. This uses POSIX reentrant functions
         where available (hence the _r suffix), and disables features
         that rely on non-reentrant system functions. Currently there
         are no features disabled in this module.

         Using the libtecla_r.a version of the library, it is safe to
         use  the facilities of this module in multiple threads, pro-
         vided that each thread uses a separately  allocated  Expand-
         File  object. In other words, if two threads want to do file
         expansion, they should each call new_ExpandFile()  to  allo-
         cate their own file-expansion objects.

## FILES

         libtecla.a    -    The tecla library
         libtecla.h    -    The tecla header file.

## SEE ALSO

         libtecla(3),      gl_get_line(3),      cpl_complete_word(3),
         pca_lookup_file(3)

## AUTHOR

         Martin Shepherd  (mcs@astro.caltech.edu)