/************************************************************************ * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * * provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ************************************************************************/ /* * for a non-unix system, you have to supply the sys/dir.h include file * which defines DIR and DIRSIZE(DIR *entry), * and the opendir, closedir, and readdir routines. * See "readdir.h" for all the gory details. */ #include "jove.h" #ifdef F_COMPLETION RCS("$Id: scandir.c,v 14.31 1993/02/17 01:24:19 tom Exp tom $") #define READDIR_IMPLEMENTATION /* to resolve system-dependencies */ #include "readdir.h" private char **resize __(( char **_(base), int _(n) )); private char ** resize(base, n) register char **base; int n; { if ((base = (char **) realloc((char *) base, n * sizeof(char *))) == NULL) complain("[out of memory]"); return base; } /* Scandir returns the number of entries or -1 if the directory cannot be opened; complains if malloc fails. */ #define CHUNKSIZE 32 int scandir(dir, nmptr, qualify, sorter) const char *dir; register char ***nmptr; int (*qualify)__(( const char *_(name) )); int (*sorter)__(( const char **_(a), const char **_(b) )); { register size_t nent = 0; register struct dirent *ent; /* old compilers don't like "entry" */ register DIR *dirp; register size_t nalloc = CHUNKSIZE; register int len; #if !pdp11 /* for error recovery; not needed for compilers that unwind the stack and restore registers on longjmp. (like pdp11 7th Ed. cc) */ volatile union {int i;} _nent; # define v_nent _nent.i #endif if ((dirp = opendir(dir)) == NULL) return -1; CATCH (*nmptr) = NULL; (*nmptr) = (char **) emalloc(CHUNKSIZE * sizeof (char *)); while (ent = readdir(dirp)) { if (qualify && !(*qualify)(ent->d_name)) continue; #ifdef v_nent v_nent = nent; #endif if (nent == nalloc) (*nmptr) = resize((*nmptr), nalloc += CHUNKSIZE); len = DIRSIZE(ent); null_ncpy((*nmptr)[nent] = emalloc(len + 1), ent->d_name, len); nent++; } (*nmptr) = resize((*nmptr), nent + 1); (*nmptr)[nent] = NULL; /* guaranteed 0 pointer */ if (sorter) qsort((*nmptr), nent, sizeof(char **), (int (*)__(( const void *, const void * ))) sorter); /* Yuck! */ ONERROR #ifndef v_nent # define v_nent nent #endif if (*nmptr) freedir(nmptr, v_nent); nent = -1; ENDCATCH closedir(dirp); #undef v_nent return nent; } void freedir(nmptr, nent) register char ***nmptr; int nent; { register char **base = *nmptr; while (--nent >= 0) free(*base++); free((void_*) *nmptr); *nmptr = NULL; } int alphacomp(a, b) const char **a, **b; { return strcmp(*a, *b); } #endif /* F_COMPLETION */ /*====================================================================== * $Log: scandir.c,v $ * Revision 14.31 1993/02/17 01:24:19 tom * fix longjmp register botch in scandir(). * * Revision 14.30 1993/01/29 13:53:51 tom * cleanup whitespace; some random optimizations. * * Revision 14.28 1992/10/24 01:24:22 tom * convert to "port{ansi,defs}.h" conventions. * * Revision 14.26 1992/08/26 23:56:58 tom * Posix-ate (direct => dirent); add RCS directives. * */