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