home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff330.lzh / Vt100 / Src.lzh / Src / expand.c next >
C/C++ Source or Header  |  1990-03-01  |  8KB  |  365 lines

  1. static char rcsid[] = "$RCSfile: expand.c,v $ $Revision: 1.2 $";
  2.  
  3. /*************************************************************
  4.  * vt100 terminal emulator - Wild card and Directory support
  5.  *            :ts=8
  6.  *
  7.  * $Log:    expand.c,v $
  8.  * Revision 1.2  89/12/19  20:38:41  acs
  9.  * Added RCS id and change log.
  10.  * 
  11.  *    v2.9 ACS - See change summary.
  12.  *    v2.7 870825 ACS - Use the *InfoMsg*() routines in window.c rather
  13.  *              than req().
  14.  *    v2.6 870227 DBW - bug fixes for all the stuff in v2.5
  15.  *    v2.5 870214 DBW - more additions (see readme file)
  16.  *    v2.4 861214 DBW - lots of fixes/additions (see readme file)
  17.  *    v2.3 861101 DBW - minor bug fixes
  18.  *    v2.2 861012 DBW - more of the same
  19.  *    v2.1 860915 DBW    - new features (see README)
  20.  *           860830 Steve Drew Added Wild card support,
  21.  *            features(expand.c)
  22.  *    v2.0 860809 DBW - Major rewrite
  23.  *    v1.1 860720 DBW    - Switches, 80 cols, colors, bug fixes
  24.  *    v1.0 860712 DBW    - First version released
  25.  *
  26.  *      Much of the code from this module extracted from
  27.  *      Matt Dillons Shell program. (Thanxs Matt.)
  28.  *************************************************************/
  29.  
  30. #include "vt100.h"
  31.  
  32. struct DPTR {                    /* Format of directory fetch ptr */
  33.    struct FileLock *lock;        /* lock on directory   */
  34.    struct FileInfoBlock *fib;    /* mod'd fib for entry */
  35. };
  36.  
  37. /*
  38.  * Disk directory routines
  39.  *
  40.  *
  41.  * diropen() returns a struct DPTR, or NULL if the given file does not
  42.  * exist.  stat will be set to 1 if the file is a directory.  If the
  43.  * name is "", then the current directory is openned.
  44.  *
  45.  * dirnext() returns 1 until there are no more entries.  The **name and
  46.  * *stat are set.  *stat = 1 if the file is a directory.
  47.  *
  48.  * dirclose() closes a directory channel.
  49.  *
  50.  */
  51.  
  52. struct DPTR *
  53. diropen(name, stat)
  54. char *name;
  55. int *stat;
  56. {
  57.    struct DPTR *dp;
  58.    int namelen, endslash = 0;
  59.    struct FileLock *MyLock;
  60.  
  61.    MyLock = (struct FileLock *)( (ULONG) ((struct Process *)
  62.                  (FindTask(NULL)))->pr_CurrentDir);
  63.    namelen = strlen(name);
  64.    if (namelen && name[namelen - 1] == '/') {
  65.       name[namelen - 1] = '\0';
  66.       endslash = 1;
  67.    }
  68.    *stat = 0;
  69.    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  70.    if (*name == '\0')
  71.       dp->lock = (struct FileLock *)DupLock (MyLock);
  72.    else
  73.       dp->lock = (struct FileLock *)Lock (name, ACCESS_READ);
  74.    if (endslash)
  75.       name[namelen - 1] = '/';
  76.    if (dp->lock == NULL) {
  77.       free (dp);
  78.       return (NULL);
  79.    }
  80.    dp->fib = (struct FileInfoBlock *)
  81.      AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  82.    if (!Examine (dp->lock, dp->fib)) {
  83.       dirclose (dp);
  84.       return (NULL);
  85.    }
  86.    if (dp->fib->fib_DirEntryType >= 0)
  87.       *stat = 1;
  88.    return (dp);
  89. }
  90.  
  91. dirnext(dp, pname, stat)
  92. struct DPTR *dp;
  93. char **pname;
  94. int *stat;
  95. {
  96.    if (dp == NULL)
  97.       return (0);
  98.    if (ExNext (dp->lock, dp->fib)) {
  99.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  100.       *pname = dp->fib->fib_FileName;
  101.       return (1);
  102.    }
  103.    return (0);
  104. }
  105.  
  106.  
  107. dirclose(dp)
  108. struct DPTR *dp;
  109. {
  110.    if (dp == NULL)
  111.       return (1);
  112.    if (dp->fib)
  113.       FreeMem (dp->fib, (long)sizeof(*dp->fib));
  114.    if (dp->lock)
  115.       UnLock (dp->lock);
  116.    free (dp);
  117.    return (1);
  118. }
  119.  
  120. void
  121. free_expand(av)
  122. char **av;
  123. {
  124.    char **base = av;
  125.  
  126.    if (av) {
  127.       while (*av) {
  128.      free (*av);
  129.      ++av;
  130.       }
  131.       free (base);
  132.    }
  133. }
  134.  
  135. /*
  136.  * EXPAND(wild_name, pac)
  137.  *    wild_name      - char * (example: "df0:*.c")
  138.  *    pac            - int  *  will be set to # of arguments.
  139.  *
  140.  */
  141.  
  142.  
  143. char **
  144. expand(base, pac)
  145. char *base;
  146. int *pac;
  147. {
  148.    char **eav = (char **)malloc (sizeof(char *));
  149.    int  eleft, eac;
  150.  
  151.    char *ptr, *name;
  152.    char *bname, *ename, *tail;
  153.    int stat, scr;
  154.    struct DPTR *dp;
  155.  
  156.    *pac = eleft = eac = 0;
  157.    base = strcpy(malloc(strlen(base)+1), base);
  158.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  159.    for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  160.    if (ptr < base) {
  161.       bname = strcpy (malloc(1), "");
  162.    } else {
  163.       scr = ptr[1];
  164.       ptr[1] = '\0';
  165.       bname = strcpy (malloc(strlen(base)+1), base);
  166.       ptr[1] = scr;
  167.    }
  168.    ename = ptr + 1;
  169.    for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
  170.    scr = *ptr;
  171.    *ptr = '\0';
  172.    tail = (scr) ? ptr + 1 : NULL;
  173.  
  174.    if ((dp = diropen (bname, &stat)) == NULL  ||  stat == 0) {
  175.       free (bname);
  176.       free (base);
  177.       free (eav);
  178.       InfoMsg1Line("Could not open directory");
  179.       return (NULL);
  180.    }
  181.    while (dirnext (dp, &name, &stat)) {
  182.       if (compare_ok(ename, name)) {
  183.      if (tail) {
  184.         int alt_ac;
  185.         char *search, **alt_av, **scrav;
  186.         struct FileLock *lock;
  187.  
  188.         if (!stat)      /* expect more dirs, but this not a dir */
  189.            continue;
  190.         lock = (struct FileLock *)CurrentDir (dp->lock);
  191.         search = malloc(strlen(name)+strlen(tail)+2);
  192.         strcpy (search, name);
  193.         strcat (search, "/");
  194.         strcat (search, tail);
  195.         scrav = alt_av = expand (search, &alt_ac);
  196.         CurrentDir (lock);
  197.         if (scrav) {
  198.            while (*scrav) {
  199.           if (eleft < 2) {
  200.              char **scrav = (char **)
  201.             malloc(sizeof(char *) * (eac + 10));
  202.              movmem ((char *)eav, (char *)scrav, sizeof(char *) * (eac + 1));
  203.              free (eav);
  204.              eav = scrav;
  205.              eleft = 10;
  206.           }
  207.           eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
  208.           strcpy(eav[eac], bname);
  209.           strcat(eav[eac], *scrav);
  210.           free (*scrav);
  211.           ++scrav;
  212.           --eleft, ++eac;
  213.            }
  214.            free (alt_av);
  215.         }
  216.      } else {
  217.         if (eleft < 2) {
  218.            char **scrav = (char **)
  219.             malloc(sizeof(char *) * (eac + 10));
  220.            movmem ((char *)eav, (char *)scrav, sizeof(char *) * (eac + 1));
  221.            free (eav);
  222.            eav = scrav;
  223.            eleft = 10;
  224.         }
  225.         eav[eac] = malloc (strlen(bname)+strlen(name)+1);
  226.         eav[eac] = strcpy(eav[eac], bname);
  227.         strcat(eav[eac], name);
  228.         --eleft, ++eac;
  229.      }
  230.       }
  231.    }
  232.    dirclose (dp);
  233.    *pac = eac;
  234.    eav[eac] = NULL;
  235.    free (bname);
  236.    free (base);
  237.    if (eac)
  238.       return (eav);
  239.    free (eav);
  240.    return (NULL);
  241. }
  242.  
  243. /*
  244.  * Compare a wild card name with a normal name
  245.  */
  246.  
  247. #define MAXB   8
  248.  
  249. compare_ok(wild, name)
  250. char *wild, *name;
  251. {
  252.    char *w = wild;
  253.    char *n = name;
  254.    char *back[MAXB][2];
  255.    int  bi = 0;
  256.  
  257.    while (*n || *w) {
  258.       switch (*w) {
  259.       case '*':
  260.      if (bi == MAXB) {
  261.         InfoMsg1Line("Too many levels of '*'");
  262.         return (0);
  263.      }
  264.      back[bi][0] = w;
  265.      back[bi][1] = n;
  266.      ++bi;
  267.      ++w;
  268.      continue;
  269. goback:
  270.      --bi;
  271.      while (bi >= 0 && *back[bi][1] == '\0')
  272.         --bi;
  273.      if (bi < 0)
  274.         return (0);
  275.      w = back[bi][0] + 1;
  276.      n = ++back[bi][1];
  277.      ++bi;
  278.      continue;
  279.       case '?':
  280.      if (!*n) {
  281.         if (bi)
  282.            goto goback;
  283.         return (0);
  284.      }
  285.      break;
  286.       default:
  287.      if (toupper(*n) != toupper(*w)) {
  288.         if (bi)
  289.            goto goback;
  290.         return (0);
  291.      }
  292.      break;
  293.       }
  294.       if (*n)  ++n;
  295.       if (*w)  ++w;
  296.    }
  297.    return (1);
  298. }
  299.  
  300. void
  301. set_dir(new)
  302. char *new;
  303. {
  304.    register     char         *s;
  305.    int               i;
  306.    struct     FileLock     *lock;
  307.    char             temp[60];
  308.    struct       FileInfoBlock   *fib;
  309.  
  310.    if (*new != '\000') {
  311.       strcpy(temp, MyDir);
  312.       s = new;
  313.       if (*s == '/') {
  314.      s++;
  315.      for (i=strlen(MyDir);
  316.           MyDir[i] != '/' && MyDir[i] != ':';
  317.           i--);
  318.      MyDir[i+1] = '\0';
  319.      strcat(MyDir, s);
  320.      }
  321.       else if (exists(s, ':') == 0) {
  322.      if (MyDir[strlen(MyDir)-1] != ':')
  323.         strcat(MyDir, "/");
  324.      strcat(MyDir, s);
  325.      }
  326.       else
  327.      strcpy(MyDir, s);
  328.  
  329.       if ((lock = (struct FileLock *)Lock(MyDir, (long)ACCESS_READ)) == 0) {
  330.      InfoMsg2Line("Directory not found:",MyDir);
  331.      strcpy(MyDir, temp);
  332.      }
  333.       else {
  334.      fib = (struct FileInfoBlock *)AllocMem(
  335.         (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  336.      if (fib) {
  337.         if (Examine(lock, fib)) {
  338.         if (fib->fib_DirEntryType > 0) {
  339.             UnLock(CurrentDir(lock));
  340.             if (MyDir[strlen(MyDir)-1] == '/')
  341.             MyDir[strlen(MyDir)-1] = '\000';
  342.             }
  343.         else {
  344.             InfoMsg2Line("Not a Directory:",MyDir);
  345.             strcpy(MyDir,temp);
  346.             }
  347.         }
  348.         FreeMem(fib, (long)sizeof(struct FileInfoBlock));
  349.         }
  350.     else {
  351.         InfoMsg1Line("Can't change directory...No free memory!");
  352.         strcpy(MyDir,temp);
  353.         }
  354.     }
  355.     }
  356. }
  357.  
  358. exists(s,c)
  359. char *s,c;
  360.     {
  361.     while (*s != '\000')
  362.     if (*s++ == c) return(1);
  363.     return(0);
  364.     }
  365.