#include "stdio.h"
#include "libraries/dos.h"
extern struct Lock *Lock() ;
extern void *malloc() ;
char path[1000] ;
struct FileInfoBlock *fibs[100] ;
extern int Enable_Abort ;
int aborted ;
/*
 *   Implements a `string set'.  Simple linear search.
 */
struct stringset {
   struct stringset *next ;
   char what[1] ;
} ;
struct stringset *add(s, ss)
char *s ;
struct stringset *ss ;
{
   struct stringset *t ;

   t = (struct stringset *)malloc(sizeof(struct stringset) + strlen(s)) ;
   t->next = ss ;
   strcpy(t->what, s) ;
   return t ;
}
int member(s, ss)
register char *s ;
register struct stringset *ss ;
{
   while (ss != 0) {
      if (strcmp(s, ss->what)==0)
         return 1 ;
      ss = ss->next ;
   }
   return 0 ;
}
struct stringset *dirlist, *extlist ;
checkcontrolc() {
   long _SetSignal() ;

   if ((_SetSignal(0L, 0x1000L))&0x1000)
      aborted = 1 ;
}
checkext(s)
register char *s ;
{
   register char *p = 0 ;

   while (*s) {
      if (*s == '.')
         p = s + 1 ;
      s++ ;
   }
   return ((p==0) || ! member(p, extlist)) ;
}
char *mformat = "%s" ;
char outline[2000] ;
tree(s, l)
register char *s ;
register int l ;
{
   register struct Lock *lk ;
   register struct FileInfoBlock *fib = fibs[l] ;
   register char *p, *q, *r ;

   if (fib == 0) {
      fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock)) ;
      fibs[l] = fib ;
   }
   lk = Lock(s) ;
   if (lk == NULL ||
       (Examine(lk, fib) && fib->fib_DirEntryType <= 0)) {
      return ;
   }
   r = s + strlen(s) ;
   while (! aborted && ExNext(lk, fib)) {
      strcpy(r, fib->fib_FileName) ;
      if (fib->fib_DirEntryType <= 0) {
         if (checkext(r)) {
            p = outline ;
            q = mformat ;
            while (*q) {
               if (*q == '%') {
                  q++ ;
                  switch (*q) {
case 's' :
                     strcpy(p, s) ;
                     p += strlen(p) ;
                     q++ ;
                     break ;
case 'd' :
                     sprintf(p, "%10ld", fib->fib_Size) ;
                     p += strlen(p) ;
                     q++ ;
                     break ;
default:
                     *p++ = *q++ ;
                     break ;
                  }
               } else {
                  *p++ = *q++ ;
               }
            }
            *p = 0 ;
            printf("%s\n", outline) ;
         }
      } else {
         if (! member(s, dirlist)) {
            strcat(s, "/") ;
            tree(s, l+1) ;
         }
      }
      checkcontrolc() ;
   }
   UnLock(lk) ;
}
main(argc, argv)
int argc ;
char *argv[] ;
{
   register char *p, *q ;
   int option = 'f' ;

   Enable_Abort = 0 ;
   while (argc > 1) {
      argc-- ;
      argv++ ;
      p = *argv ;
      if (*p == '-') {
         option = p[1] ;
         q = p + 2 ;
         if (*q == 0) {
            argc-- ;
            argv++ ;
            if (argc <= 0)
               break ;
            q = *argv ;
         }
      } else
         q = p ;
      switch (option) {
case 'd': case 'D':
         dirlist = add(q, dirlist) ;
         break ;
case 'x': case 'X': case 'e': case 'E':
         extlist = add(q, extlist) ;
         break ;
case 'f': case 'F':
         mformat = q ;
         break ;
case '?': case 'H': case 'h':
         printf(
"Usage:  tree [-d directoryname] [-x extension] [-f format] [-?]\n") ;
         exit(0) ;
default:
         break ;
      }
   }
   tree(path, 0) ;
}
_wb_parse() {}
