home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk458.lzh / Csh / src / sub.c < prev   
C/C++ Source or Header  |  1991-02-15  |  13KB  |  617 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * (c)1986 Matthew Dillon     9 October 1986
  6.  *
  7.  * Version 2.07M by Steve Drew 10-Sep-87
  8.  *
  9.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  10.  *
  11.  */
  12.  
  13. #define HM_STR 0              /* various HISTORY retrieval modes */
  14. #define HM_REL 1
  15. #define HM_ABS 2
  16.  
  17. seterr()
  18. {
  19. char buf[32];
  20. int stat;
  21.  
  22. sprintf(buf, "%d", Lastresult);
  23. set_var(LEVEL_SET, v_lasterr, buf);
  24. stat = atoi(get_var(LEVEL_SET, v_stat));
  25. if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
  26. }
  27.  
  28. #define ISSPACE(c) ((c)==' ' || (c)==9 || (unsigned char)(c)==0xA0)
  29.  
  30. char *next_word(str)
  31. register char *str;
  32. {
  33. while (*str && ! ISSPACE(*str)) ++str;
  34. while (*str &&   ISSPACE(*str)) ++str;
  35. return str;
  36. }
  37.  
  38. hasspace(s)
  39. register char *s;
  40. {
  41. for ( ; *s; s++)
  42.     if (ISSPACE(*s)) return 1;
  43. return 0;
  44. }
  45.  
  46. char *compile_av(av, start, end, delim, quote)
  47. char **av;
  48. unsigned char delim;
  49. {
  50. register char *cstr, *p;
  51. int len;
  52. register unsigned int i;
  53.  
  54. len = 1;
  55. for (i = start; i < end; ++i) len += strlen(av[i]) + 3;
  56. p = cstr = malloc(len);
  57. *cstr = '\0';
  58. for (i = start; i < end; ++i) {
  59.     if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
  60.     if (quote && hasspace(av[i]))
  61.         p += sprintf(p, "\"%s\"", av[i]);
  62.     else
  63.         p += sprintf(p, "%s",     av[i]);
  64.     if (i+1 < end) *p++=delim;
  65.     }
  66. *p='\0';
  67. return cstr;
  68. }
  69.  
  70. /*
  71.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  72.  *               immediately after the free.
  73.  */
  74.  
  75.  
  76. Free(ptr)
  77. char *ptr;
  78. {
  79. static char *old_ptr;
  80.  
  81. if (old_ptr) free (old_ptr);
  82. old_ptr = ptr;
  83. }
  84.  
  85. /*
  86.  * Add new string to history (H_head, H_tail, H_len,
  87.  *  S_histlen
  88.  */
  89.  
  90. add_history(str)
  91. char *str;
  92. {
  93.    register struct HIST *hist;
  94.  
  95.    if (H_head != NULL && strcmp(H_head->line, str) == 0)
  96.        return(0);
  97.    while (H_len > S_histlen)
  98.       del_history();
  99.    hist = (struct HIST *)malloc (sizeof(struct HIST));
  100.    if (H_head == NULL) {
  101.       H_head = H_tail = hist;
  102.       hist->next = NULL;
  103.    } else {
  104.       hist->next = H_head;
  105.       H_head->prev = hist;
  106.       H_head = hist;
  107.    }
  108.    hist->prev = NULL;
  109.    hist->line = malloc (strlen(str) + 1);
  110.    strcpy (hist->line, str);
  111.    ++H_len;
  112. }
  113.  
  114. del_history()
  115. {
  116.    if (H_tail) {
  117.       --H_len;
  118.       ++H_tail_base;
  119.       free (H_tail->line);
  120.       if (H_tail->prev) {
  121.          H_tail = H_tail->prev;
  122.          free (H_tail->next);
  123.          H_tail->next = NULL;
  124.       } else {
  125.          free (H_tail);
  126.          H_tail = H_head = NULL;
  127.       }
  128.    }
  129. }
  130.  
  131. char *
  132. get_history(ptr)
  133. char *ptr;
  134. {
  135.    register struct HIST *hist;
  136.    register int len;
  137.    int mode = HM_REL;
  138.    int num  = 1;
  139.    char *str;
  140.    char *result = NULL;
  141.  
  142.    if (ptr[1] >= '0' && ptr[1] <= '9') {
  143.       mode = HM_ABS;
  144.       num  = atoi(&ptr[1]);
  145.       goto skip;
  146.    }
  147.    switch (ptr[1]) {
  148.    case '!':
  149.       break;
  150.    case '-':
  151.       num += atoi(&ptr[2]);
  152.       break;
  153.    default:
  154.       mode = HM_STR;
  155.       str  = ptr + 1;
  156.       break;
  157.    }
  158. skip:
  159.    switch (mode) {
  160.    case HM_STR:
  161.       len = strlen(str);
  162.       for (hist = H_head; hist; hist = hist->next) {
  163.          if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  164.             result = hist->line;
  165.             break;
  166.          }
  167.       }
  168.       break;
  169.    case HM_REL:
  170.       for (hist = H_head; hist && num--; hist = hist->next);
  171.       if (hist)
  172.          result = hist->line;
  173.       break;
  174.    case HM_ABS:
  175.       len = H_tail_base;
  176.       for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  177.       if (hist)
  178.          result = hist->line;
  179.       break;
  180.    }
  181.    if (result) {
  182.       fprintf(stderr,"%s\n",result);
  183.       return(result);
  184.    }
  185.    printf("History failed\n");
  186.    return ("");
  187. }
  188.  
  189. replace_head(str)
  190. char *str;
  191. {
  192.    if (str == NULL)
  193.       str = "";
  194.    if (H_head) {
  195.       free (H_head->line);
  196.       H_head->line = malloc (strlen(str)+1);
  197.       strcpy (H_head->line, str);
  198.    }
  199. }
  200.  
  201.  
  202. pError(str)
  203. char *str;
  204. {
  205. int ierr = (long)IoErr();
  206. ierror(str, ierr);
  207. }
  208.  
  209. ierror(str, err)
  210. register char *str;
  211. {
  212.    register struct PERROR *per = Perror;
  213.  
  214.    if (err) {
  215.       for (; per->errstr; ++per) {
  216.          if (per->errnum == err) {
  217.             fprintf (stderr, "%s%s%s\n",
  218.                   per->errstr,
  219.                   (str) ? ": " : "",
  220.                   (str) ? str : "");
  221.             return ((short)err);
  222.          }
  223.       }
  224.       fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
  225.    }
  226.    return ((short)err);
  227. }
  228.  
  229. /*
  230.  * Disk directory routines
  231.  *
  232.  * dptr = dopen(name, stat)
  233.  *    struct DPTR *dptr;
  234.  *    char *name;
  235.  *    int *stat;
  236.  *
  237.  * dnext(dptr, name, stat)
  238.  *    struct DPTR *dptr;
  239.  *    char **name;
  240.  *    int  *stat;
  241.  *
  242.  * dclose(dptr)                  -may be called with NULL without harm
  243.  *
  244.  * dopen() returns a struct DPTR, or NULL if the given file does not
  245.  * exist.  stat will be set to 1 if the file is a directory.  If the
  246.  * name is "", then the current directory is openned.
  247.  *
  248.  * dnext() returns 1 until there are no more entries.  The **name and
  249.  * *stat are set.  *stat = 1 if the file is a directory.
  250.  *
  251.  * dclose() closes a directory channel.
  252.  *
  253.  */
  254.  
  255. struct DPTR *
  256. dopen(name, stat)
  257. char *name;
  258. int *stat;
  259. {
  260. struct DPTR *dp;
  261.  
  262. *stat = 0;
  263. dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  264. if (*name == '\0')
  265.     dp->lock = DupLock(Myprocess->pr_CurrentDir);
  266. else
  267.     dp->lock = Lock (name,ACCESS_READ);
  268. if (dp->lock == NULL) {
  269.     free (dp);
  270.     return NULL;
  271.     }
  272. dp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  273. if (!Examine (dp->lock, dp->fib)) {
  274.     pError (name);
  275.     dclose (dp);
  276.     return NULL;
  277.     }
  278. if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
  279. return dp;
  280. }
  281.  
  282. dnext(dp, pname, stat)
  283. struct DPTR *dp;
  284. char **pname;
  285. int *stat;
  286. {
  287. if (dp == NULL) return (0);
  288.    if (ExNext (dp->lock, dp->fib)) {
  289.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  290.       *pname = dp->fib->fib_FileName;
  291.       return (1);
  292.    }
  293.    return (0);
  294. }
  295.  
  296.  
  297. dclose(dp)
  298. struct DPTR *dp;
  299. {
  300.    if (dp == NULL)
  301.       return (1);
  302.    if (dp->fib)
  303.       FreeMem (dp->fib,(long)sizeof(*dp->fib));
  304.    if (dp->lock)
  305.       UnLock (dp->lock);
  306.    free (dp);
  307.    return (1);
  308. }
  309.  
  310.  
  311. isdir(file)
  312. char *file;
  313. {
  314.    register struct DPTR *dp;
  315.    int stat;
  316.  
  317.    stat = 0;
  318.    if (dp = dopen (file, &stat))
  319.       dclose(dp);
  320.    return (stat == 1);
  321. }
  322.  
  323.  
  324. free_expand(av)
  325. register char **av;
  326. {
  327.    char **base = av;
  328.  
  329.    if (av) {
  330.       while (*av) {
  331.          free (*av);
  332.          ++av;
  333.       }
  334.       free (base);
  335.    }
  336. }
  337.  
  338. /*
  339.  * EXPAND(base,pac)
  340.  *    base           - char * (example: "df0:*.c")
  341.  *    pac            - int  *  will be set to # of arguments.
  342.  *
  343.  * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  344.  *                 simple directory/file lookups. Returns a pointer to
  345.  *                 an array of pointers that contains the full file spec
  346.  *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  347.  *
  348.  *                 Now no longer necessary to Examine the files a second time
  349.  *                 in do_dir since expand will return the full file info
  350.  *                 appended to the file name. Set by formatfile().
  351.  *                 eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
  352.  *
  353.  *                 Caller must call free_expand when done with the array.
  354.  *
  355.  * base             bname =       ename =
  356.  * ------           -------       -------
  357.  *  "*"               ""            "*"
  358.  *  "!*.info"         ""            "*.info" (wild_exclude set)
  359.  *  "su*d/*"          ""            "*"      (tail set)
  360.  *  "file.*"          ""            "file.*"
  361.  *  "df0:c/*"         "df0:c"       "*"
  362.  *  ""                ""            "*"
  363.  *  "df0:.../*"       "df0:"        "*"      (recur set)
  364.  *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
  365.  *
  366.  * ---the above base would be provided by execom.c or do_dir().
  367.  * ---the below base would only be called from do_dir().
  368.  *
  369.  *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
  370.  *  "df0:"            "df0:"        "*"
  371.  *  "file/file"       "file/file"   ""       (dp == 0) so fail
  372.  *  "df0:.../"        "df0:"        "*"      (recur set)
  373.  *
  374.  */
  375.  
  376.  
  377. char **
  378. expand(base, pac)
  379. char *base;
  380. int *pac;
  381. {
  382.    register char *ptr;
  383.    char **eav = (char **)malloc(sizeof(char *) * (2));
  384.    short eleft, eac;
  385.    char *name;
  386.    char *svfile();
  387.    char *bname, *ename, *tail;
  388.    int stat, recur, scr, bl;
  389.    register struct DPTR *dp;
  390.  
  391.    *pac = recur = eleft = eac = 0;
  392.  
  393.    base = strcpy(malloc(strlen(base)+1), base);
  394.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  395.  
  396.    if (!*ptr)   /* no wild cards */
  397.       --ptr;
  398.    else
  399.       for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  400.  
  401.    if (ptr < base) {
  402.       bname = strcpy (malloc(1), "");
  403.    } else {
  404.       scr = ptr[1];
  405.       ptr[1] = '\0';
  406.       if (!strcmp(ptr-3,".../")) {
  407.          recur = 1;
  408.          *(ptr-3) = '\0';
  409.       }
  410.       bname = strcpy (malloc(strlen(base)+2), base);
  411.       ptr[1] = scr;
  412.    }
  413.    bl = strlen(bname);
  414.    ename = ++ptr;
  415.    for (; *ptr && *ptr != '/'; ++ptr);
  416.    scr = *ptr;
  417.    *ptr = '\0';
  418.    if (scr) ++ptr;
  419.    tail = ptr;
  420.  
  421.    if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  422.       free (bname);
  423.       free (base);
  424.       free (eav);
  425.       return (NULL);
  426.    }
  427.  
  428.    if (!stat) {                /* eg. 'dir file' */
  429.       char *p,*s;
  430.       for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  431.       if (s != bname) ++s;
  432.       *s ='\0';
  433.       eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  434.       goto done;
  435.    }
  436.    if (!*ename) ename = "*";    /* eg. dir df0: */
  437.    if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  438.       bname[bl] = '/';
  439.       bname[++bl] = '\0';
  440.    }
  441.    while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  442.         int match = compare_ok(ename,name,0);
  443.       if (match && !(!recur && *tail)) {
  444.          if (eleft < 2) {
  445.                char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  446.                movmem (eav, scrav, (eac + 1) << 2);
  447.                free (eav);
  448.                eav = scrav;
  449.                eleft = 10;
  450.          }
  451.          eav[eac++] = svfile(bname,name,dp->fib);
  452.          --eleft;
  453.       }
  454.       if ((*tail && match) || recur) {
  455.          int alt_ac;
  456.          char *search, **alt_av, **scrav;
  457.          BPTR lock;
  458.  
  459.          if (!stat)           /* expect more dirs, but this not a dir */
  460.             continue;
  461.          lock = CurrentDir (dp->lock);
  462.          search = malloc(strlen(ename)+strlen(name)+strlen(tail)+5);
  463.          strcpy (search, name);
  464.          strcat (search, "/");
  465.          if (recur) {
  466.             strcat(search, ".../");
  467.             strcat(search, ename);
  468.          }
  469.          strcat (search, tail);
  470.          scrav = alt_av = expand (search, &alt_ac);
  471.          /* free(search); */
  472.          CurrentDir (lock);
  473.          if (scrav) {
  474.             while (*scrav) {
  475.                int l;
  476.                if (eleft < 2) {
  477.                   char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  478.                   movmem (eav, scrav, (eac + 1) << 2);
  479.                   free (eav);
  480.                   eav = scrav;
  481.                   eleft = 10;
  482.                }
  483.  
  484.                l = strlen(*scrav);
  485.                scrav[0][l] = ' ';
  486.                eav[eac] = malloc(bl+l+45);
  487.                strcpy(eav[eac], bname);
  488.                strcat(eav[eac], *scrav);
  489.                eav[eac][l+bl] = '\0';
  490.  
  491.                free (*scrav);
  492.                ++scrav;
  493.                --eleft, ++eac;
  494.             }
  495.             free (alt_av);
  496.          }
  497.       }
  498.    }
  499. done:
  500.    dclose (dp);
  501.    *pac = eac;
  502.    eav[eac] = NULL;
  503.    free (bname);
  504.    free (base);
  505.    if (eac) {
  506.       return (eav);
  507.    }
  508.    free (eav);
  509.    return (NULL);
  510. }
  511.  
  512. char *strupr(s)
  513. register char *s;
  514. {
  515. while (*s) *s=toupper(*s), s++;
  516. return s;
  517. }
  518.  
  519. char *strlwr(s)
  520. register char *s;
  521. {
  522. while (*s) *s=tolower(*s), s++;
  523. return s;
  524. }
  525.  
  526. /*
  527.  * Compare a wild card name with a normal name
  528.  */
  529.  
  530. compare_ok(wild, name, casedep)
  531. char *wild, *name;
  532. {
  533. int queryflag;
  534. char buf[260], wildbuf[260], *lowname;
  535.  
  536. if (queryflag=(*wild=='&')) wild++;
  537. if (*wild=='!') *wild='~';
  538.  
  539. if (! casedep) {
  540.     strupr(wild);
  541.     strcpy(buf,name);
  542.     strupr(buf);
  543.     lowname=buf;
  544.     }
  545. else lowname=name;
  546.  
  547. PreParse(wild, wildbuf);
  548. if ( ! PatternMatch(wildbuf,lowname)) return 0;
  549.  
  550. if (queryflag) {
  551.     printf("Select \23337m%-16s\2330m [y/n] ? ",name);
  552.     gets(buf);
  553.     return (toupper(*buf)=='Y');
  554.     }
  555. return 1;
  556. }
  557.  
  558. char *svfile(s1,s2,fib)
  559. char *s1,*s2;
  560. FIB *fib;
  561. {
  562. char *p = malloc (strlen(s1)+strlen(s2)+45);
  563. strcpy(p, s1);
  564. strcat(p, s2);
  565. formatfile(p,fib);
  566. return p;
  567. }
  568.  
  569. /* will have either of these formats:
  570.  *
  571.  *    fullfilename'\0'hsparwed   <Dir>       DD-MMM-YY HH:MM:SS\n'\0'
  572.  *    fullfilename'\0'hsparwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
  573.  *                              1111111111222222222233333333334 4  4
  574.  *                    01234567890123456789012345678901234567890 1  2
  575.  */
  576. formatfile(str,fib)
  577. char *str;
  578. FIB *fib;
  579. {
  580. char *dates();
  581. int i;
  582. while(*str++);
  583. for (i=7; i>=0; i--)
  584.     *str++ = ((fib->fib_Protection & (1L<<i)) ? "hspa----" : "----rwed")[7-i];
  585. if (fib->fib_DirEntryType < 0)
  586.   sprintf(str,"  %6ld %4ld  ", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
  587. else strcpy(str,"   <Dir>       ");
  588. strcat(str,dates(&fib->fib_Date));
  589. }
  590.  
  591. /* Sort routines */
  592.  
  593. long cmp(s1, s2)
  594. char **s1, **s2;
  595. {
  596. return (long)Strcmp(*s1, *s2);
  597. }
  598.  
  599. Cmp() {
  600. #asm
  601.     public    _geta4
  602.     movem.l    d2-d3/a4/a6,-(sp)
  603.     movem.l    a0/a1,-(sp)
  604.     bsr    _geta4
  605.     bsr    _cmp
  606.     addq.l    #8,sp
  607.     movem.l    (sp)+,d2-d3/a4/a6
  608. #endasm
  609. }
  610.  
  611. QuickSort(av, n)
  612. char *av[];
  613. int n;
  614. {
  615. QSort(av, (long)n, 4L, Cmp);
  616. }
  617.