home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / rc / part03 / utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  5.1 KB  |  284 lines

  1. /* utils.c: general utility functions like fprint, ealloc etc. */
  2.  
  3. #include <stdarg.h>
  4. #include <errno.h>
  5. #include <setjmp.h>
  6. #include <signal.h>
  7. #include "rc.h"
  8. #include "utils.h"
  9. #include "nalloc.h"
  10. #include "status.h"
  11. #include "input.h"
  12. #include "except.h"
  13. #include "lex.h"    /* import char nw[]; used by strprint to see if it needs to quote a word */
  14. #include "walk.h"
  15.  
  16. static void dprint(va_list, char *, char *);
  17. static int n2u(char *, int);
  18.  
  19. /* exception handlers */
  20.  
  21. void rc_error(char *s) {
  22.     if (s != NULL) {
  23.         if (interactive)
  24.             fprint(2,"%s\n",s);
  25.         else
  26.             fprint(2,"line %d: %s\n", lineno - 1, s);
  27.     }
  28.     set(FALSE);
  29.     redirq = NULL;
  30.     cond = FALSE; /* no longer inside conditional */
  31.     empty_fifoq();
  32.     rc_raise(ERROR);
  33. }
  34.  
  35. void sig(int s) {
  36.     signal(SIGINT, sig); /* some unices require re-signaling */
  37.  
  38.     if (errno == EINTR)
  39.         return; /* allow wait() to complete */
  40.  
  41.     fprint(2,"\n"); /* this is the newline you see when you hit ^C while typing a command */
  42.     redirq = NULL;
  43.     cond = FALSE;
  44.     empty_fifoq();
  45.     rc_raise(ERROR);
  46. }
  47.  
  48. /* our perror */
  49.  
  50. void uerror(char *s) {
  51.     extern int sys_nerr;
  52.     extern char *sys_errlist[];
  53.  
  54.     if (errno > sys_nerr)
  55.         return;
  56.  
  57.     if (s != NULL)
  58.         fprint(2,"%s: %s\n",s,sys_errlist[errno]);
  59.     else
  60.         fprint(2,"%s\n",sys_errlist[errno]);
  61. }
  62.  
  63. /* printing functions */
  64.  
  65. void fprint(int fd, char *f,...) {
  66.         va_list ap;
  67.     char str[FPRINT_SIZE];
  68.  
  69.     va_start(ap,f);
  70.     dprint(ap, str, f);
  71.     va_end(ap);
  72.     writeall(fd,str,strlen(str));
  73. }
  74.  
  75. char *sprint(char *b, char *f,...) {
  76.     va_list ap;
  77.  
  78.     va_start(ap, f);
  79.     dprint(ap, b, f);
  80.     va_end(ap);
  81.     return b;
  82. }
  83.  
  84. static void dprint(va_list ap, char *strbuf, char *f) {
  85.     int i;
  86.  
  87.     for (i = 0; *f != '\0'; f++) {
  88.         if (*f != '%') {
  89.             strbuf[i++] = *f;
  90.             continue; /* avoid an ugly extra level of indentation */
  91.         }
  92.         switch (*++f) {
  93.         case 'a': {
  94.             char **a = va_arg(ap, char **);
  95.  
  96.             if (*a == NULL)
  97.                 break;
  98.             strcpy(strbuf + i, *a);
  99.             i += strlen(*a);
  100.             while (*++a != NULL) {
  101.                 strbuf[i++] = ' ';
  102.                 strcpy(strbuf + i, *a);
  103.                 i += strlen(*a);
  104.             }
  105.             break;
  106.         }
  107.         case 'c':
  108.             strbuf[i++] = va_arg(ap, int);
  109.             break;
  110.         case 'd': case 'o': {
  111.             int v = va_arg(ap, int);
  112.             int j = 0;
  113.             int base = (*f == 'd' ? 10 : 8);
  114.             char num[16];
  115.  
  116.             if (v == 0)
  117.                 num[j++] = '0';
  118.             while (v != 0) {
  119.                 num[j++] = (v % base) + '0';
  120.                 v /= base;
  121.             }
  122.             while (--j >= 0)
  123.                 strbuf[i++] = num[j];
  124.             break;
  125.         }
  126.         case 's': {
  127.             char *s = va_arg(ap, char *);
  128.             while (*s != '\0')
  129.                 strbuf[i++] = *s++;
  130.                 break;
  131.         }
  132.         default: /* on format error, just print the bad format */
  133.             strbuf[i++] = '%';
  134.             /* FALLTHROUGH */
  135.         case '%':
  136.             strbuf[i++] = *f;
  137.         }
  138.     }
  139.     strbuf[i] = '\0';
  140. }
  141.  
  142. /* prints a string in rc-quoted form. e.g., a string with spaces in it must be quoted */
  143.  
  144. char *strprint(char *s, int quotable, int metaquote) { /* really boolean, but y.tab.c includes utils.h */
  145.     SIZE_T i,j;
  146.     char *t;
  147.  
  148.     if (*s == '\0')
  149.         return "''";
  150.  
  151.     for (i = 0; s[i] != '\0'; i++)
  152.         if (nw[s[i]] == 1 && (metaquote || (s[i] != '*' && s[i] != '?' && s[i] != '[')))
  153.             quotable = TRUE;
  154.  
  155.     if (!quotable)
  156.         return s;
  157.  
  158.     for(i = j = 0; s[i] != '\0'; i++, j++)
  159.         if (s[i] == '\'')
  160.             j++;
  161.  
  162.     t = nalloc(j + 3);
  163.  
  164.     t[0] = '\'';
  165.  
  166.     for (j = 1, i = 0; s[i] != '\0'; i++, j++) {
  167.         t[j] = s[i];
  168.         if (s[i] == '\'')
  169.             t[++j] = '\'';
  170.     }
  171.  
  172.     t[j++] = '\'';
  173.     t[j] = '\0';
  174.  
  175.     return t;
  176. }
  177.  
  178. /* ascii -> unsigned conversion routines. -1 indicates conversion error. */
  179.  
  180. static int n2u(char *s, int base) {
  181.     int i;
  182.  
  183.     for (i = 0; *s != '\0'; s++) {
  184.         /* small hack with unsigned ints -- one compare for range test */
  185.         if (((unsigned int) *s) - '0' >= (unsigned int) base)
  186.             return -1;
  187.         i = (i * base) + (*s - '0');
  188.     }
  189.     return i;
  190. }
  191.  
  192. /* decimal -> uint */
  193.  
  194. int a2u(char *s) {
  195.     return n2u(s, 10);
  196. }
  197.  
  198. /* octal -> uint */
  199.  
  200. int o2u(char *s) {
  201.     return n2u(s, 8);
  202. }
  203.  
  204. /* memory allocation functions */
  205.  
  206. void *ealloc(SIZE_T n) {
  207.     char *p = malloc(n);
  208.  
  209.     if (p == NULL) {
  210.         uerror("malloc");
  211.         rc_exit(1);
  212.     }
  213.  
  214.     return p;
  215. }
  216.  
  217. void *erealloc(void *p, SIZE_T n) {
  218.     p = realloc(p, n);
  219.  
  220.     if (p == NULL) {
  221.         uerror("realloc");
  222.         rc_exit(1);
  223.     }
  224.  
  225.     return p;
  226. }
  227.  
  228. void efree(void *p) {
  229.     if (p != NULL)
  230.         free(p);
  231. }
  232.  
  233. /* useful functions */
  234.  
  235. /* The last word in portable ANSI: a strcmp wrapper for qsort */
  236.  
  237. int starstrcmp(const void *s1, const void *s2) {
  238.     return strcmp(*(char **)s1, *(char **)s2);
  239. }
  240.  
  241. /* tests to see if pathname begins with "/", "./", or "../" */
  242.  
  243. int isabsolute(char *path) {
  244.     return path[0] == '/' || (path[0] == '.' && (path[1] == '/' || (path[1] == '.' && path[2] == '/')));
  245. }
  246.  
  247. /* write a given buffer allowing for partial writes from write(2) */
  248.  
  249. void writeall(int fd, char *buf, SIZE_T remain) {
  250.     int i;
  251.  
  252.     for (i = 0; remain > 0; buf += i, remain -= i)
  253.         i = write(fd, buf, remain);
  254. }
  255.  
  256. /* clear out z bytes from character string s */
  257.  
  258. void clear(char *s, SIZE_T z) {
  259.     while (z != 0)
  260.         s[--z] = 0;
  261. }
  262.  
  263. /* zero out the fifo queue, removing the fifos from /tmp as you go (also prints errors arising from signals) */
  264.  
  265. void empty_fifoq() {
  266.     int sp;
  267.  
  268.     while (fifoq != NULL) {
  269.         unlink(fifoq->w);
  270.         wait(&sp);
  271.         statprint(sp);
  272.         fifoq = fifoq->n;
  273.     }
  274. }
  275.  
  276. SIZE_T strarraylen(char **a) {
  277.     SIZE_T i;
  278.  
  279.     for (i = 0; *a != NULL; a++)
  280.         i += strlen(*a) + 1;
  281.  
  282.     return i;
  283. }
  284.