home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff114.lzh / Vt100 / expand.c < prev    next >
C/C++ Source or Header  |  1987-11-22  |  8KB  |  361 lines

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