home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / jove / part08 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-03  |  13.1 KB  |  860 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  3.  * provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is *
  5.  * included in all the files.                                           *
  6.  ************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include <signal.h>
  11. #include <varargs.h>
  12.  
  13. #ifdef SYSV /* release 2, at least */
  14. short ospeed ;
  15. #endif
  16.  
  17. struct cmd *
  18. FindCmd(proc)
  19. register int     (*proc)();
  20. {
  21.     register struct cmd    *cp;
  22.  
  23.       for (cp = commands; cp->Name; cp++)
  24.         if (cp->c_proc == proc)
  25.             return cp;
  26.     return 0;
  27. }
  28.  
  29. int    Interactive;    /* True when we invoke with the command handler? */
  30. char    *ProcFmt = ": %f ";
  31.  
  32. ExecCmd(cp)
  33. data_obj    *cp;
  34. {
  35.     LastCmd = cp;
  36.     if (cp->Type & MAJOR_MODE)
  37.         SetMajor((cp->Type >> 8));
  38.     else if (cp->Type & MINOR_MODE)
  39.         TogMinor((cp->Type >> 8));
  40.     else    switch (cp->Type&TYPEMASK) {
  41.         case MACRO:
  42.             do_macro((struct macro *) cp);
  43.             break;
  44.  
  45.         case FUNCTION:
  46.             {
  47.                 struct cmd    *cmd = (struct cmd *) cp;
  48.  
  49.             if (cmd->c_proc)
  50.                 (*cmd->c_proc)();
  51.             }
  52.     }
  53. }
  54.  
  55. Line *
  56. lastline(lp)
  57. register Line    *lp;
  58. {
  59.     while (lp->l_next)
  60.         lp = lp->l_next;
  61.     return lp;
  62. }
  63.  
  64. Upper(c)
  65. register int    c;
  66. {
  67.     return (islower(c) ? toupper(c) : c);
  68. }
  69.  
  70. int    alarmed = 0;
  71.  
  72. char    key_strokes[100];
  73. static char    *key_p = key_strokes;
  74.  
  75. init_strokes()
  76. {
  77.     key_strokes[0] = 0;
  78.     key_p = key_strokes;
  79. }
  80.  
  81. add_stroke(c)
  82. {
  83.     if (key_p + 5 > &key_strokes[(sizeof key_strokes) - 1])
  84.         key_p = key_strokes;
  85.     sprintf(key_p, "%p ", c);
  86.     key_p += strlen(key_p);
  87. }
  88.  
  89. slowpoke()
  90. {
  91.     alarmed++;
  92.     f_mess(key_strokes);
  93. }
  94.  
  95. #ifdef BSD4_2
  96. #    define N_SEC    1    /* will be precisely 1 second on 4.2 */
  97. #else
  98. #    define N_SEC    2    /* but from 0 to 2 seconds otherwise */
  99. #endif
  100.  
  101. waitchar()
  102. {
  103. #ifdef EUNICE
  104.     return getch();
  105. #endif
  106.     unsigned int    old_time;
  107.     int    c;
  108.     int    (*oldproc)();
  109.  
  110.     alarmed = 0;
  111.     oldproc = signal(SIGALRM, slowpoke);
  112.  
  113.     if ((old_time = alarm((unsigned) N_SEC)) == 0)
  114.         old_time = UpdFreq;
  115.     c = getch();
  116.     (void) alarm(old_time);
  117.     (void) signal(SIGALRM, oldproc);
  118.  
  119.     return c;
  120. }
  121.  
  122. /* dir > 0 means forward; else means backward. */
  123.  
  124. char *
  125. StrIndex(dir, buf, charpos, what)
  126. char    *buf,
  127.     what;
  128. {
  129.     char    *cp = &buf[charpos],
  130.         c;
  131.  
  132.     if (dir > 0) {
  133.         while (c = *cp++)
  134.             if (c == what)
  135.                 return (cp - 1);
  136.     } else {
  137.         while (cp >= buf && (c = *cp--))
  138.             if (c == what)
  139.                 return (cp + 1);
  140.     }
  141.     return 0;
  142. }
  143.  
  144. blnkp(buf)
  145. register char    *buf;
  146. {
  147.     register char    c;
  148.  
  149.     while ((c = *buf++) && (c == ' ' || c == '\t'))
  150.         ;
  151.     return c == 0;    /* It's zero if we got to the end of the Line */
  152. }
  153.  
  154. Line *
  155. next_line(line, num)
  156. register Line    *line;
  157. register int    num;
  158. {
  159.     if (num < 0)
  160.         return prev_line(line, -num);
  161.     if (line)
  162.         while (--num >= 0 && line->l_next != 0)
  163.             line = line->l_next;
  164.     return line;
  165. }
  166.  
  167. Line *
  168. prev_line(line, num)
  169. register Line    *line;
  170. register int    num;
  171. {
  172.     if (num < 0)
  173.         return next_line(line, -num);
  174.     if (line)
  175.         while (--num >= 0 && line->l_prev != 0)
  176.             line = line->l_prev;
  177.     return line;
  178. }
  179.  
  180. DotTo(line, col)
  181. Line    *line;
  182. {
  183.     Bufpos    bp;
  184.  
  185.     bp.p_line = line;
  186.     bp.p_char = col;
  187.     SetDot(&bp);
  188. }
  189.  
  190. /* If bp->p_line is != current line, then save current line.  Then set dot
  191.    to bp->p_line, and if they weren't equal get that line into linebuf.  */
  192.  
  193. SetDot(bp)
  194. register Bufpos    *bp;
  195. {
  196.     register int    notequal;
  197.  
  198.     if (bp == 0)
  199.         return;
  200.  
  201.     notequal = bp->p_line != curline;
  202.     if (notequal)
  203.         lsave();
  204.     if (bp->p_line)
  205.         curline = bp->p_line;
  206.     curchar = bp->p_char;
  207.     if (notequal)
  208.         getDOT();
  209. }
  210.  
  211. ToLast()
  212. {
  213.     SetLine(curbuf->b_last);
  214.     Eol();
  215. }
  216.  
  217. int    MarkThresh = 22;    /* Average screen size ... */
  218. static int    line_diff;
  219.  
  220. LineDist(nextp, endp)
  221. register Line    *nextp,
  222.         *endp;
  223. {
  224.     (void) inorder(nextp, 0, endp, 0);
  225.     return line_diff;
  226. }
  227.  
  228. inorder(nextp, char1, endp, char2)
  229. register Line    *nextp,
  230.         *endp;
  231. {
  232.     int    count = 0;
  233.     register Line    *prevp = nextp;
  234.  
  235.     line_diff = 0;
  236.     if (nextp == endp)
  237.         return char1 < char2;
  238.  
  239.     while (nextp || prevp) {
  240.         if (nextp == endp || prevp == endp)
  241.             break;
  242.         if (nextp)
  243.             nextp = nextp->l_next;
  244.         if (prevp)
  245.             prevp = prevp->l_prev;
  246.         count++;
  247.     }
  248.     if (nextp == 0 && prevp == 0)
  249.         return -1;
  250.     line_diff = count;
  251.  
  252.     return nextp == endp;
  253. }
  254.  
  255. PushPntp(line)
  256. register Line    *line;
  257. {
  258.     exp_p = NO;
  259.     if (LineDist(curline, line) >= MarkThresh)
  260.         SetMark();
  261. }
  262.  
  263. ToFirst()
  264. {
  265.     SetLine(curbuf->b_first);
  266. }
  267.  
  268. length(line)
  269. Line    *line;
  270. {
  271.     return strlen(lcontents(line));
  272. };
  273.  
  274. to_word(dir)
  275. register int    dir;
  276. {
  277.     register char    c;
  278.  
  279.     if (dir > 0) {
  280.         while ((c = linebuf[curchar]) != 0 && !isword(c))
  281.             curchar++;
  282.         if (eolp()) {
  283.             if (curline->l_next == 0)
  284.                 return;
  285.             SetLine(curline->l_next);
  286.             to_word(dir);
  287.             return;
  288.         }
  289.     } else {
  290.         while (!bolp() && (c = linebuf[curchar - 1], !isword(c)))
  291.             --curchar;
  292.         if (bolp()) {
  293.             if (curline->l_prev == 0)
  294.                 return;
  295.             SetLine(curline->l_prev);
  296.             Eol();
  297.             to_word(dir);
  298.         }
  299.     }
  300. }
  301.  
  302. /* Are there any modified buffers?  Allp means include B_PROCESS
  303.    buffers in the check. */
  304.  
  305. ModBufs(allp)
  306. {
  307.     register Buffer    *b;
  308.  
  309.     for (b = world; b != 0; b = b->b_next) {
  310.         if (b->b_type == B_SCRATCH)
  311.             continue;
  312.         if ((b->b_type == B_FILE || allp) && IsModified(b))
  313.             return 1;
  314.     }
  315.     return 0;
  316. }
  317.  
  318. char *
  319. filename(b)
  320. register Buffer    *b;
  321. {
  322.     return b->b_fname ? pr_name(b->b_fname) : "[No file]";
  323. }
  324.  
  325. char *
  326. itoa(num)
  327. register int    num;
  328. {
  329.     static char    line[15];
  330.  
  331.     sprintf(line, "%d", num);
  332.     return line;
  333. }
  334.  
  335. min(a, b)
  336. register int    a,
  337.         b;
  338. {
  339.     return (a < b) ? a : b;
  340. }
  341.  
  342. max(a, b)
  343. register int    a,
  344.         b;
  345. {
  346.     return (a > b) ? a : b;
  347. }
  348.  
  349. tiewind(w, bp)
  350. register Window    *w;
  351. register Buffer    *bp;
  352. {
  353.     int    not_tied = (w->w_bufp != bp);
  354.  
  355.     UpdModLine++;    /* Kludge ... but speeds things up considerably */
  356.     w->w_line = bp->b_dot;
  357.     w->w_char = bp->b_char;
  358.     w->w_bufp = bp;
  359.     if (not_tied)
  360.         CalcWind(w);    /* ah, this has been missing since the
  361.                    beginning of time! */
  362. }
  363.  
  364. extern int    Jr_Len;
  365.  
  366. char *
  367. lcontents(line)
  368. register Line    *line;
  369. {
  370.     if (line == curline)
  371.         return linebuf;
  372.     else
  373.         return lbptr(line);
  374. }
  375.  
  376. char *
  377. ltobuf(line, buf)
  378. Line    *line;
  379. char    *buf;
  380. {
  381.     if (line == curline) {
  382.         if (buf != linebuf)
  383.             strcpy(buf, linebuf);
  384.         Jr_Len = strlen(linebuf);
  385.     } else
  386.         getline(line->l_dline, buf);
  387.     return buf;
  388. }
  389.  
  390. DOTsave(buf)
  391. Bufpos *buf;
  392. {
  393.     buf->p_line = curline;
  394.     buf->p_char = curchar;
  395. }
  396.  
  397. /* Return none-zero if we had to rearrange the order. */
  398.  
  399. fixorder(line1, char1, line2, char2)
  400. register Line    **line1,
  401.         **line2;
  402. register int    *char1,
  403.         *char2;
  404. {
  405.     Line    *tline;
  406.     int    tchar;
  407.  
  408.     if (inorder(*line1, *char1, *line2, *char2))
  409.         return 0;
  410.  
  411.     tline = *line1;
  412.     tchar = *char1;
  413.     *line1 = *line2;
  414.     *char1 = *char2;
  415.     *line2 = tline;
  416.     *char2 = tchar;
  417.  
  418.     return 1;
  419. }
  420.  
  421. inlist(first, what)
  422. register Line    *first,
  423.         *what;
  424. {
  425.     while (first) {
  426.         if (first == what)
  427.             return 1;
  428.         first = first->l_next;
  429.     }
  430.     return 0;
  431. }
  432.  
  433. /* Make `buf' modified and tell the redisplay code to update the modeline
  434.    if it will need to be changed. */
  435.  
  436. int    ModCount = 0;
  437.  
  438. modify()
  439. {
  440.     extern int    DOLsave;
  441.  
  442.     if (!curbuf->b_modified)
  443.         UpdModLine++;
  444.     curbuf->b_modified++;
  445.     DOLsave++;
  446.     if (!Asking)
  447.         ModCount++;
  448. }
  449.  
  450. unmodify()
  451. {
  452.     if (curbuf->b_modified)
  453.         UpdModLine++;
  454.     curbuf->b_modified = 0;
  455. }
  456.  
  457. numcomp(s1, s2)
  458. register char    *s1,
  459.         *s2;
  460. {
  461.     register int    count = 0;
  462.  
  463.     while (*s1 != 0 && *s1++ == *s2++)
  464.         count++;
  465.     return count;
  466. }
  467.  
  468. char *
  469. copystr(str)
  470. char    *str;
  471. {
  472.     char    *val = emalloc(strlen(str) + 1);
  473.  
  474.     strcpy(val, str);
  475.     return val;
  476. }
  477.  
  478. #ifndef byte_copy
  479. byte_copy(from, to, count)
  480. register char    *from,
  481.         *to;
  482. register int    count;
  483. {
  484.     while (--count >= 0)
  485.         *to++ = *from++;
  486. }
  487. #endif
  488.  
  489. len_error(flag)
  490. {
  491.     char    *mesg = "[line too long]";
  492.  
  493.     (flag == COMPLAIN) ? complain(mesg) : error(mesg);
  494. }
  495.  
  496. /* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
  497.  
  498. ins_c(c, buf, atchar, num, max)
  499. char    c, *buf;
  500. {
  501.     register char    *pp, *pp1;
  502.     register int    len;
  503.     int    numchars;    /* Number of characters to copy forward */
  504.  
  505.     if (num <= 0)
  506.         return;
  507.     len = atchar + strlen(&buf[atchar]);
  508.     if (len + num >= max)
  509.         len_error(COMPLAIN);
  510.     pp = &buf[len + 1];        /* + 1 so we can --pp (not pp--) */
  511.     pp1 = &buf[len + num + 1];
  512.     numchars = len - atchar;
  513.     while (numchars-- >= 0)
  514.         *--pp1 = *--pp;
  515.     pp = &buf[atchar];
  516.     while (--num >= 0)
  517.         *pp++ = c;
  518. }
  519.  
  520. TwoBlank()
  521. {
  522.     register Line    *next = curline->l_next;
  523.  
  524.     return ((next != 0) &&
  525.         (*(lcontents(next)) == '\0') &&
  526.         (next->l_next != 0) &&
  527.         (*(lcontents(next->l_next)) == '\0'));
  528. }
  529.  
  530. linecopy(onto, atchar, from)
  531. register char    *onto,
  532.         *from;
  533. {
  534.     register char    *endp = &onto[LBSIZE - 2];
  535.  
  536.     onto += atchar;
  537.  
  538.     while (*onto = *from++)
  539.         if (onto++ >= endp)
  540.             len_error(ERROR);
  541. }
  542.  
  543. char *
  544. IOerr(err, file)
  545. char    *err, *file;
  546. {
  547.     return sprint("Couldn't %s \"%s\".", err, file);
  548. }
  549.  
  550. pclose(p)
  551. int    *p;
  552. {
  553.     (void) close(p[0]);
  554.     (void) close(p[1]);
  555. }
  556.  
  557. dopipe(p)
  558. int    p[];
  559. {
  560.     if (pipe(p) == -1)
  561.         complain("[Pipe failed]");
  562. }
  563.  
  564. /* NOSTRICT */
  565.  
  566. char *
  567. emalloc(size)
  568. {
  569.     char    *ptr;
  570.  
  571.     if (ptr = malloc((unsigned) size))
  572.         return ptr;
  573.     /* Try garbage collecting lines */
  574.     GCchunks();
  575.     if (ptr = malloc((unsigned) size))
  576.         return ptr;
  577.     /* Uh ... Oh screw it! */
  578.     error("[Out of memory] ");
  579.     /* NOTREACHED */
  580. }
  581.  
  582. /* Return the basename of file F. */
  583.  
  584. char *
  585. basename(f)
  586. register char    *f;
  587. {
  588.     register char    *cp;
  589.  
  590.     if (cp = rindex(f, '/'))
  591.         return cp + 1;
  592.     else
  593.         return f;
  594. }
  595.  
  596. push_env(savejmp)
  597. jmp_buf    savejmp;
  598. {
  599.     byte_copy((char *) mainjmp, (char *) savejmp, sizeof (jmp_buf));
  600. }
  601.  
  602. pop_env(savejmp)
  603. jmp_buf    savejmp;
  604. {
  605.     byte_copy((char *) savejmp, (char *) mainjmp, sizeof (jmp_buf));
  606. }
  607.  
  608. #ifdef LOAD_AV
  609. #  ifdef BSD4_2
  610. #    ifdef PURDUE_EE
  611.  
  612. get_la(dp)
  613. double *dp;
  614. {
  615.     *dp = (double) loadav(0) / 100.0;
  616. }
  617.  
  618. #    else PURDUE_EE
  619.  
  620. #include <nlist.h>
  621.  
  622. static struct    nlist nl[] = {
  623.     { "_avenrun" },
  624. #define    X_AVENRUN    0
  625.     { "" }
  626. };
  627.  
  628. get_la(dp)
  629. double    *dp;
  630. {
  631.     double    avenrun[3];
  632.     static int    kmem = 0;
  633.  
  634.     if (kmem == -1) {
  635.         *dp = 4.0;    /* So shell commands will say "Chugging" */
  636.         return;
  637.     } else if (kmem == 0) {
  638.         if ((kmem = open("/dev/kmem", 0)) == -1) {
  639.             f_mess("Can't open kmem for load average.");
  640.             *dp = 4.0;
  641.             return;
  642.         }
  643.         nlist("/vmunix", nl);
  644.     }
  645.     lseek(kmem, (long) nl[X_AVENRUN].n_value, 0);
  646.     read(kmem, (char *) avenrun, sizeof(avenrun));
  647.     *dp = avenrun[0];
  648. }
  649.  
  650. #    endif PURDUE_EE
  651. #  else BSD4_2
  652.  
  653. get_la(dp)
  654. double    *dp;
  655. {
  656.     short    avg[3];
  657.  
  658.     gldav(avg);
  659.     *dp = (double) avg[0] / 256;
  660. }
  661.  
  662. #  endif BSD4_2
  663. #endif LOAD_AV
  664.  
  665. /* get the time buf, designated by *timep, from FROM to TO. */
  666. char *
  667. get_time(timep, buf, from, to)
  668. char    *buf;
  669. time_t    *timep;
  670. {
  671.     time_t    now;
  672.     char    *cp;
  673.     extern char    *ctime();
  674.  
  675.     if (timep != 0)
  676.         now = *timep;
  677.     else
  678.         (void) time(&now);
  679.     cp = ctime(&now) + from;
  680.     if (to == -1)
  681.         cp[strlen(cp) - 1] = '\0';        /* Get rid of \n */
  682.     else
  683.         cp[to - from] = '\0';
  684.     if (buf) {
  685.         strcpy(buf, cp);
  686.         return buf;
  687.     } else
  688.         return cp;
  689. }
  690.  
  691. /* Return length of null terminated string. */
  692.  
  693. strlen(s)
  694. register char    *s;
  695. {
  696.     register char    *base = s + 1;    /* Can you say kludge? */
  697.  
  698.     while (*s++)
  699.         ;
  700.     return (s - base);
  701. }
  702.  
  703. char *
  704. index(s, c)
  705. register char    *s;
  706. register int    c;
  707. {
  708.     register int    c1;
  709.  
  710.     if (c != 0)
  711.         while (c1 = *s++)
  712.             if (c == c1)
  713.                 return s - 1;
  714.     return 0;
  715. }
  716.  
  717. strcmp(s1, s2)
  718. register char    *s1,
  719.         *s2;
  720. {
  721.     if (!s1 || !s2)
  722.         return 1;    /* Which is not zero ... */
  723.     while (*s1 == *s2++)
  724.         if (*s1++ == '\0')
  725.             return 0;
  726.     return (*s1 - *--s2);
  727. }
  728.  
  729. casecmp(s1, s2)
  730. register char    *s1,
  731.         *s2;
  732. {
  733.     if (!s1 || !s2)
  734.         return 1;    /* Which is not zero ... */
  735.     while (*s1 == *s2++ || Upper(*s1) == Upper(s2[-1]))
  736.         if (*s1++ == '\0')
  737.             return 0;
  738.     return (*s1 - *--s2);
  739. }
  740.  
  741. casencmp(s1, s2, n)
  742. register char    *s1,
  743.         *s2;
  744. register int    n;
  745. {
  746.     if (!s1 || !s2)
  747.         return 1;    /* Which is not zero ... */
  748.     while (--n >= 0  && (*s1 == *s2++ || Upper(*s1) == Upper(s2[-1])))
  749.         if (*s1++ == '\0')
  750.             return 0;
  751.     return ((n < 0) ? 0 : *s1 - *--s2);
  752. }
  753.  
  754. null_ncpy(to, from, n)
  755. char    *to,
  756.     *from;
  757. {
  758.     (void) strncpy(to, from, n);
  759.     to[n] = '\0';
  760. }
  761.  
  762. strcpy(t, f)
  763. register char    *t,
  764.         *f;
  765. {
  766.     while (*t++ = *f++)
  767.         ;
  768. }
  769.  
  770. /* Tries to pause for delay/10 seconds OR until a character is typed
  771.    at the keyboard.  This works well on BSD4_2 and not so well on the
  772.    rest.  Returns 1 if it returned because of keyboard input, or 0
  773.    otherwise. */
  774.  
  775. SitFor(delay)
  776. int    delay;
  777. {
  778. #ifdef BSD4_2
  779. #include <sys/time.h>
  780.  
  781.     struct timeval    timer;
  782.     int    readfds = 1,
  783.         writefds = 0,
  784.         exceptfds = 0;
  785.  
  786.     timer.tv_sec = (delay / 10);
  787.     timer.tv_usec = (delay % 10) * 100000;
  788.  
  789.     if (charp())
  790.         return;
  791.     /* gross that I had to snarf this from getch() */
  792.     if (!UpdMesg && !Asking) {    /* Don't erase if we are asking */
  793.         if (mesgbuf[0] && !errormsg)
  794.             message(NullStr);
  795.     }
  796.     redisplay();
  797.     select(1, &readfds, &writefds, &exceptfds, &timer);
  798. #else
  799.     static int cps[] = {
  800.         0,
  801.         5,
  802.         7,
  803.         11,
  804.         13,
  805.         15,
  806.         20,
  807.         30,
  808.         60,
  809.         120,
  810.         180,
  811.         240,
  812.         480,
  813.         960,
  814.         1920,
  815.         1920,
  816.     };
  817.     register int    nchars;
  818.  
  819.     if (charp())
  820.         return;
  821.     nchars = (delay * cps[ospeed]) / 10;
  822.     redisplay();
  823.     while ((--nchars > 0) && !InputPending) {
  824.         putchar(0);
  825.         if (OkayAbort) {
  826.             OkayAbort = 0;
  827.             InputPending = charp();
  828.         }
  829.     }
  830. #endif
  831. }
  832.  
  833. sindex(pattern, string)
  834. register char    *pattern,
  835.         *string;
  836. {
  837.     register int    len = strlen(pattern);
  838.  
  839.     while (*string != '\0') {
  840.         if (*pattern == *string && strncmp(pattern, string, len) == 0)
  841.             return TRUE;
  842.         string++;
  843.     }
  844.     return FALSE;
  845. }
  846.  
  847. make_argv(argv, ap)
  848. register char    *argv[];
  849. va_list    ap;
  850. {
  851.     register char    *cp;
  852.     register int    i = 0;
  853.  
  854.     argv[i++] = va_arg(ap, char *);
  855.     argv[i++] = basename(argv[0]);
  856.     while (cp = va_arg(ap, char *))
  857.         argv[i++] = cp;
  858.     argv[i] = 0;
  859. }
  860.