home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / pdksh-4.9-src.tgz / tar.out / contrib / pdksh / sh / misc.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  435 lines

  1. /*
  2.  * Miscellaneous functions
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: misc.c,v 1.4 93/05/05 21:16:54 sjg Exp $";
  7. #endif
  8.  
  9. #include "stdh.h"
  10. #include <signal.h>
  11. #include <errno.h>
  12. #include <setjmp.h>
  13. #include "sh.h"
  14. #include "expand.h"
  15. #ifndef NOSTDHDRS
  16. # include <limits.h>
  17. #else
  18. # define UCHAR_MAX    0xFF
  19. #endif
  20.  
  21. char ctypes [UCHAR_MAX+1];    /* type bits for unsigned char */
  22.  
  23. static char *   cclass      ARGS((char *p, int sub));
  24.  
  25. /*
  26.  * Fast character classes
  27.  */
  28. void
  29. setctypes(s, t)
  30.     register /* const */ char *s;
  31.     register int t;
  32. {
  33.     register int i;
  34.  
  35.     if ((t&C_IFS)) {
  36.         for (i = 0; i < UCHAR_MAX+1; i++)
  37.             ctypes[i] &=~ C_IFS;
  38.         ctypes[0] |= C_IFS; /* include \0 in C_IFS */
  39.     }
  40.     ctypes[(unsigned char) *s++] |= t;    /* allow leading \0 in string */
  41.     while (*s != 0)
  42.         ctypes[(unsigned char) *s++] |= t;
  43. }
  44.  
  45. void
  46. initctypes()
  47. {
  48.     register int c;
  49.  
  50.     for (c = 'a'; c <= 'z'; c++)
  51.         ctypes[c] |= C_ALPHA;
  52.     for (c = 'A'; c <= 'Z'; c++)
  53.         ctypes[c] |= C_ALPHA;
  54.     ctypes['_'] |= C_ALPHA;
  55.     setctypes("0123456789", C_DIGIT);
  56.     setctypes("\0 \t\n|&;<>()", C_LEX1);
  57.     setctypes("*@#!$-?", C_VAR1);
  58.     setctypes("=-+?#%", C_SUBOP);
  59. }
  60.  
  61. /* convert unsigned long to base N string */
  62.  
  63. char *
  64. ulton(n, base)
  65.     register unsigned long n;
  66.     int base;
  67. {
  68.     register char *p;
  69.     static char buf [20];
  70.  
  71.     p = &buf[sizeof(buf)];
  72.     *--p = '\0';
  73.     do {
  74.         *--p = "0123456789ABCDEF"[n%base];
  75.         n /= base;
  76.     } while (n != 0);
  77.     return p;
  78. }
  79.  
  80. char *
  81. strsave(s, ap)
  82.     register char *s;
  83.     Area *ap;
  84. {
  85.   return s ? strcpy((char*) alloc((size_t)strlen(s)+1, ap), s) : NULL;
  86. }
  87.  
  88. static struct option {
  89.     char *name;
  90.     int flag;
  91. } options[] = {
  92.     {"allexport",    FEXPORT},
  93.     {"bgnice",    FBGNICE},
  94. #if defined(EDIT) && defined(EMACS)
  95.     {"emacs",    FEMACS},
  96. #endif
  97.     {"errexit",    FERREXIT},
  98.     {"hashall",    FHASHALL},
  99.     {"ignoreeof",    FIGNEOF},
  100.     {"interactive",    FTALKING},
  101.     {"keyword",    FKEYWORD},
  102.     {"markdirs",    FMARKDIRS},
  103.     {"monitor",    FMONITOR},
  104.     {"noexec",    FNOEXEC},
  105.     {"noglob",    FNOGLOB},
  106.     {"nounset",    FNOUNSET},
  107.     {"privileged",    FPRIVILEGED},
  108.     {"stdin",    FSTDIN},
  109.     {"trackall",    FHASHALL},
  110.     {"verbose",    FVERBOSE},
  111. #if defined(EDIT) && defined(VI)
  112.     {"vi",        FVI},
  113. #endif
  114.     {"xtrace",    FXTRACE},
  115.     {NULL,        0}
  116. };    
  117.  
  118. /*
  119.  * translate -o option into F* constant
  120.  */
  121. int
  122. option(n)
  123.     const char *n;
  124. {
  125.     register struct option *op;
  126.  
  127.     for (op = options; op->name != NULL; op++)
  128.         if (strcmp(op->name, n) == 0)
  129.             return op->flag;
  130.     return 0;
  131. }
  132.  
  133. char *
  134. getoptions()
  135. {
  136.     register int c;
  137.     char m [26+1];
  138.     register char *cp = m;
  139.  
  140.     for (c = 'a'; c <= 'z'; c++)
  141.         if (flag[FLAG(c)])
  142.             *cp++ = (char) c;
  143.     *cp = 0;
  144.     return strsave(m, ATEMP);
  145. }
  146.  
  147. void
  148. printoptions()
  149. {
  150.     register struct option *op;
  151.  
  152.     for (op = options; op->name != NULL; op++)
  153.         if (flag[op->flag])
  154.             shellf("%s ", op->name);
  155.     shellf("\n");
  156. }
  157.     
  158. /* atoi with error detection */
  159.  
  160. getn(as)
  161.     char *as;
  162. {
  163.     register char *s;
  164.     register int n;
  165.  
  166.     s = as;
  167.     if (*s == '-')
  168.         s++;
  169.     for (n = 0; digit(*s); s++)
  170.         n = (n*10) + (*s-'0');
  171.     if (*s)
  172.         errorf("%s: bad number\n", as);
  173.     return (*as == '-') ? -n : n;
  174. }
  175.  
  176. /* since I'm using a shared library, there's no reason NOT to use the
  177.    system strerror() function under amigaos. */
  178. #ifndef amigaos
  179. /*
  180.  * stripped down strerror for kill and exec
  181.  */
  182. char *
  183. strerror(i)
  184.     int i;
  185. {
  186.     switch (i) {
  187.       case EINVAL:
  188.         return "Invalid argument";
  189.       case EACCES:
  190.         return "Permission denied";
  191.       case ESRCH:
  192.         return "No such process";
  193.       case EPERM:
  194.         return "Not owner";
  195.       case ENOENT:
  196.         return "No such file or directory";
  197.       case ENOTDIR:
  198.         return "Not a directory";
  199.       case ENOEXEC:
  200.         return "Exec format error";
  201.       case ENOMEM:
  202.         return "Not enough memory";
  203.       case E2BIG:
  204.         return "Argument list too long";
  205.       default:
  206.         return "Unknown system error";
  207.     }
  208. }
  209. #endif
  210.  
  211. /* -------- gmatch.c -------- */
  212.  
  213. /*
  214.  * int gmatch(string, pattern)
  215.  * char *string, *pattern;
  216.  *
  217.  * Match a pattern as in sh(1).
  218.  * pattern character are prefixed with MAGIC by expand.
  219.  */
  220.  
  221. static    char    *cclass ARGS((char *, int c));
  222.  
  223. int
  224. gmatch(s, p)
  225.     register char *s, *p;
  226. {
  227.     register int sc, pc;
  228.  
  229.     if (s == NULL || p == NULL)
  230.         return 0;
  231.     while ((pc = *p++) != 0) {
  232.         sc = *s++;
  233.         if (pc ==  MAGIC)
  234.             switch (*p++) {
  235.               case '[':
  236.                 if (sc == 0 || (p = cclass(p, sc)) == NULL)
  237.                     return (0);
  238.                 break;
  239.  
  240.               case '?':
  241.                 if (sc == 0)
  242.                     return (0);
  243.                 break;
  244.  
  245.               case '*':
  246.                 s--;
  247.                 do {
  248.                     if (*p == '\0' || gmatch(s, p))
  249.                         return (1);
  250.                 } while (*s++ != '\0');
  251.                 return (0);
  252.  
  253.               default:
  254.                 if (sc != p[-1])
  255.                     return 0;
  256.                 break;
  257.             }
  258.         else
  259.             if (sc != pc)
  260.                 return 0;
  261.     }
  262.     return (*s == 0);
  263. }
  264.  
  265. static char *
  266. cclass(p, sub)
  267.     register char *p;
  268.     register int sub;
  269. {
  270.     register int c, d, not, found = 0;
  271.  
  272.     if ((not = (*p == MAGIC && *++p == NOT)))
  273.         p++;
  274.     do {
  275.         if (*p == MAGIC)
  276.             p++;
  277.         if (*p == '\0')
  278.             return NULL;
  279.         c = *p;
  280.         if (p[1] == '-' && p[2] != ']') {
  281.             d = p[2];
  282.             p++;
  283.         } else
  284.             d = c;
  285.         if (c == sub || (c <= sub && sub <= d))
  286.             found = 1;
  287.     } while (*++p != ']');
  288.  
  289.     return (found != not) ? p+1 : NULL;
  290. }
  291.  
  292. /* -------- qsort.c -------- */
  293.  
  294. /*
  295.  * quick sort of array of generic pointers to objects.
  296.  */
  297.  
  298. void
  299. qsortp(base, n, f)
  300.     void **base;        /* base address */
  301.     size_t n;        /* elements */
  302.     int (*f)();        /* compare function */
  303. {
  304.     qsort1(base, base + n, f);
  305. }
  306.  
  307. #define    swap2(a, b)    {\
  308.     register void *t; t = *(a); *(a) = *(b); *(b) = t;\
  309. }
  310. #define    swap3(a, b, c)    {\
  311.     register void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
  312. }
  313.  
  314. qsort1(base, lim, f)
  315.     void **base, **lim;
  316.     int (*f)();
  317. {
  318.     register void **i, **j;
  319.     register void **lptr, **hptr;
  320.     size_t n;
  321.     int c;
  322.  
  323.   top:
  324.     n = (lim - base) / 2;
  325.     if (n == 0)
  326.         return;
  327.     hptr = lptr = base+n;
  328.     i = base;
  329.     j = lim - 1;
  330.  
  331.     for (;;) {
  332.         if (i < lptr) {
  333.             if ((c = (*f)(*i, *lptr)) == 0) {
  334.                 lptr --;
  335.                 swap2(i, lptr);
  336.                 continue;
  337.             }
  338.             if (c < 0) {
  339.                 i += 1;
  340.                 continue;
  341.             }
  342.         }
  343.  
  344.       begin:
  345.         if (j > hptr) {
  346.             if ((c = (*f)(*hptr, *j)) == 0) {
  347.                 hptr ++;
  348.                 swap2(hptr, j);
  349.                 goto begin;
  350.             }
  351.             if (c > 0) {
  352.                 if (i == lptr) {
  353.                     hptr ++;
  354.                     swap3(i, hptr, j);
  355.                     i = lptr += 1;
  356.                     goto begin;
  357.                 }
  358.                 swap2(i, j);
  359.                 j -= 1;
  360.                 i += 1;
  361.                 continue;
  362.             }
  363.             j -= 1;
  364.             goto begin;
  365.         }
  366.  
  367.         if (i == lptr) {
  368.             if (lptr-base >= lim-hptr) {
  369.                 qsort1(hptr+1, lim, f);
  370.                 lim = lptr;
  371.             } else {
  372.                 qsort1(base, lptr, f);
  373.                 base = hptr+1;
  374.             }
  375.             goto top;
  376.         }
  377.  
  378.         lptr -= 1;
  379.         swap3(j, lptr, i);
  380.         j = hptr -= 1;
  381.     }
  382. }
  383.  
  384. int
  385. xstrcmp(p1, p2)
  386.     void *p1, *p2;
  387. {
  388.     return (strcmp((char *)p1, (char *)p2));
  389. }
  390.  
  391. void
  392. cleanpath(pwd, dir, clean)
  393.     char *pwd, *dir, *clean;
  394. {
  395.     register char  *s, *d, *p;
  396.     char *slash = "/";
  397.     register int inslash = 0;
  398.  
  399.     d = clean;
  400.     if (*dir != '/') {
  401.         s = pwd;
  402.         while (*d++ = *s++)
  403.             ;
  404.         if (d >= clean + 2 && *(d - 2) == '/')
  405.             d--;
  406.         else
  407.             *(d - 1) = '/';
  408.     }
  409.  
  410.     s = dir;
  411.     while (*s) {
  412.         if ((*d++ = *s++) == '/' && d > clean + 1) {
  413.             if (*(p = d - 2) == '/') {
  414.                 --d;
  415.             } else if (*p == '.') {
  416.                 if (*--p == '/') {
  417.                     d -= 2;
  418.                 } else if (*p == '.' && *--p == '/') {
  419.                     while (p > clean && *--p != '/')
  420.                         ;
  421.                     d = p + 1;
  422.                 }
  423.             }
  424.         }
  425.         if (!*s && !inslash && *(s - 1) != '/') {
  426.             inslash = 1;
  427.             s = slash;
  428.         }
  429.     }
  430.  
  431.     if (*(d - 1) == '/' && (d - 1) > clean)
  432.         d--;
  433.     *d = '\0';
  434. }
  435.