home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / lgrind.zoo / vgrindefs.c < prev   
C/C++ Source or Header  |  1992-09-28  |  7KB  |  319 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)vgrindefs.c    4.3 (Berkeley) 12/11/84";
  3. static char Version[] =
  4.    "$Id: vgrindefs.c,v 1.2 91/10/01 00:29:08 gvr Exp $";
  5. #endif
  6.  
  7. /* Copyright (c) 1979 Regents of the University of California */
  8.  
  9. #define    BUFFERSIZE    4096
  10. #define MAXHOP    32    /* max number of %|tc=|% indirections */
  11.  
  12. #include <stdlib.h>
  13. #include <ctype.h>
  14. /*
  15.  * grindcap --- routines for dealing with the language definitions data base
  16.  *    (code stolen almost totally from termcap)
  17.  *
  18.  * BUG:        Should use a "last" pointer in @tbuf@, so that searching
  19.  *        for capabilities alphabetically would not be a %$n^2/2$%
  20.  *        process when large numbers of capabilities are given.
  21.  * Note:    If we add a last pointer now we will screw up the
  22.  *        %|tc|% capability. We really should compile termcap.
  23.  *
  24.  * Essentially all the work here is scanning and decoding escapes
  25.  * in string capabilities.  We don't use stdio because the editor
  26.  * doesn't, and because living w/o it is not hard.
  27.  */
  28.  
  29. static    char *tbuf;
  30. static    char *filename;
  31. static    int hopcount = 0; /* detect infinite loops in termcap */
  32.  
  33. char    *tskip();
  34. char    *tgetstr();
  35. char    *tdecode();
  36.  
  37.  
  38.  
  39. /*
  40.  * Get an entry for terminal name in buffer @bp@,
  41.  * from the termcap file.  Parse is very rudimentary;
  42.  * we just notice escaped newlines.
  43.  */
  44.    int
  45. tgetent(bp, name, file)
  46.    char *bp, *name, *file;
  47. {
  48.    register char *cp;
  49.    register int c;
  50.    register int i = 0, cnt = 0;
  51.    char ibuf[BUFFERSIZE];
  52.    char *cp2;
  53.    int tf;
  54.    
  55.    tbuf = bp;
  56.    tf = 0;
  57.    filename = file;
  58.    tf = open(filename, 0);
  59.    if (tf < 0)
  60.       return -1;
  61.    for (;;) {
  62.       cp = bp;
  63.       for (;;) {
  64.      if (i == cnt) {
  65.         cnt = read(tf, ibuf, BUFFERSIZE);
  66.         if (cnt <= 0) {
  67.            close(tf);
  68.            return 0;
  69.         }
  70.         i = 0;
  71.      }
  72.      c = ibuf[i++];
  73.      if (c == '\n') {
  74.         if (cp > bp && cp[-1] == '\\'){
  75.            cp--;
  76.            continue;
  77.         }
  78.         break;
  79.      }
  80.      if (cp >= bp+BUFFERSIZE) {
  81.         write(2,"Vgrind entry too long\n", 23);
  82.         break;
  83.      } else
  84.         *cp++ = c;
  85.       }
  86.       *cp = '\0';
  87.       
  88.       /*
  89.        * The real work for the match.
  90.        */
  91.       if (tnamatch(name)) {
  92.      close(tf);
  93.      return tnchktc();
  94.       }
  95.    }
  96. }
  97.  
  98.  
  99.  
  100. /*
  101.  * @tnchktc@: check the last entry, see if it's %|tc=xxx|%. If so,
  102.  * recursively find %|xxx|% and append that entry (minus the names)
  103.  * to take the place of the %|tc=xxx|% entry. This allows termcap
  104.  * entries to say "like an HP2621 but doesn't turn on the labels".
  105.  * Note that this works because of the left to right scan.
  106.  */
  107.    static int
  108. tnchktc()
  109. {
  110.    register char *p, *q;
  111.    char tcname[16];    /* name of similar terminal */
  112.    char tcbuf[BUFFERSIZE];
  113.    char *holdtbuf = tbuf;
  114.    int l;
  115.    
  116.    p = tbuf + strlen(tbuf) - 2;    /* before the last colon */
  117.    while (*--p != ':')
  118.       if (p < tbuf) {
  119.      write(2, "Bad vgrind entry\n", 18);
  120.      return 0;
  121.       }
  122.    p++;
  123.    /* @p@ now points to beginning of last field */
  124.    if (p[0] != 't' || p[1] != 'c')
  125.       return 1;
  126.    strcpy(tcname,p+3);
  127.    q = tcname;
  128.    while (q && *q != ':')
  129.       q++;
  130.    *q = '\0';
  131.    if (++hopcount > MAXHOP) {
  132.       write(2, "Infinite tc= loop\n", 18);
  133.       return 0;
  134.    }
  135.    if (tgetent(tcbuf, tcname, filename) != 1)
  136.       return 0;
  137.    for (q = tcbuf; *q != ':'; q++)
  138.       ;
  139.    l = p - holdtbuf + strlen(q);
  140.    if (l > BUFFERSIZE) {
  141.       write(2, "Vgrind entry too long\n", 23);
  142.       q[BUFFERSIZE - (p-tbuf)] = '\0';
  143.    }
  144.    strcpy(p, q+1);
  145.    tbuf = holdtbuf;
  146.    return 1;
  147. }
  148.  
  149.  
  150.  
  151. /*
  152.  * @tnamatch@ deals with name matching.  The first field of the termcap
  153.  * entry is a sequence of names separated by %|||%'s, so we compare
  154.  * against each such name.  The normal %|:|% terminator after the last
  155.  * name (before the first field) stops us.
  156.  */
  157.    static int
  158. tnamatch(np)
  159.    char *np;
  160. {
  161.    register char *Np, *Bp;
  162.    
  163.    Bp = tbuf;
  164.    if (*Bp == '#')
  165.       return 0;
  166.    for (;;) {
  167.       for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
  168.      continue;
  169.       if (*Np == '\0' && (*Bp == '|' || *Bp == ':' || *Bp == '\0'))
  170.      return 1;
  171.       while (*Bp != '\0' && *Bp != ':' && *Bp != '|')
  172.      Bp++;
  173.       if (*Bp == '\0' || *Bp == ':')
  174.      return 0;
  175.       Bp++;
  176.    }
  177. }
  178.  
  179.  
  180.  
  181. /*
  182.  * Skip to the next field.  Notice that this is very dumb, not
  183.  * knowing about %|\:|% escapes or any such.  If necessary, %|:|%'s can
  184.  * be put into the termcap file in octal.
  185.  */
  186.    static char *
  187. tskip(bp)
  188.    register char *bp;
  189. {
  190.    while (*bp && *bp != ':')
  191.       bp++;
  192.    if (*bp == ':')
  193.       bp++;
  194.    return bp;
  195. }
  196.  
  197.  
  198.  
  199. /*
  200.  * Return the (numeric) option id.
  201.  * Numeric options look like
  202.  *    %|li#80|%
  203.  * i.e. the option string is separated from the numeric value by
  204.  * a %|#|% character.  If the option is not found we return %$-1$%.
  205.  * Note that we handle octal numbers beginning with %$0$%.
  206.  */
  207.    int
  208. tgetnum(id)
  209.    char *id;
  210. {
  211.    register int i, base;
  212.    register char *bp = tbuf;
  213.    
  214.    for (;;) {
  215.       bp = tskip(bp);
  216.       if (*bp == '\0')
  217.      return -1;
  218.       if (*bp++ != id[0] || *bp == '\0' || *bp++ != id[1])
  219.      continue;
  220.       if (*bp == '@')
  221.      return -1;
  222.       if (*bp != '#')
  223.      continue;
  224.       bp++;
  225.       base = 10;
  226.       if (*bp == '0')
  227.      base = 8;
  228.       i = 0;
  229.       while (isdigit(*bp))
  230.      i *= base, i += *bp++ - '0';
  231.       return i;
  232.    }
  233. }
  234.  
  235.  
  236.  
  237. /*
  238.  * Handle a flag option.
  239.  * Flag options are given "naked", i.e. followed by a %|:|% or the end
  240.  * of the buffer.  Return 1 if we find the option, or 0 if it is
  241.  * not given.
  242.  */
  243.    int
  244. tgetflag(id)
  245.    char *id;
  246. {
  247.    register char *bp = tbuf;
  248.    
  249.    for (;;) {
  250.       bp = tskip(bp);
  251.       if (!*bp)
  252.      return 0;
  253.       if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
  254.      if (!*bp || *bp == ':')
  255.         return 1;
  256.      else if (*bp == '@')
  257.         return 0;
  258.       }
  259.    }
  260. }
  261.  
  262.  
  263.  
  264. /*
  265.  * Get a string valued option.
  266.  * These are given as
  267.  *    %|cl=^Z|%
  268.  * Much decoding is done on the strings, and the strings are
  269.  * placed in area, which is a ref parameter which is updated.
  270.  * No checking on area overflow.
  271.  */
  272.    char *
  273. tgetstr(id, area)
  274.    char *id, **area;
  275. {
  276.    register char *bp = tbuf;
  277.    
  278.    for (;;) {
  279.       bp = tskip(bp);
  280.       if (!*bp)
  281.      return 0;
  282.       if (*bp++ != id[0] || *bp == '\0' || *bp++ != id[1])
  283.      continue;
  284.       if (*bp == '@')
  285.      return 0;
  286.       if (*bp != '=')
  287.      continue;
  288.       bp++;
  289.       return tdecode(bp, area);
  290.    }
  291. }
  292.  
  293.  
  294.  
  295. /*
  296.  * @tdecode@ does the grunge work to decode the
  297.  * string capability escapes.
  298.  */
  299.    static char *
  300. tdecode(str, area)
  301.    register char *str;
  302.    char **area;
  303. {
  304.    register char *cp;
  305.    register int c;
  306.    int i;
  307.    
  308.    cp = *area;
  309.    while (c = *str++) {
  310.       if (c == ':' && *(cp-1) != '\\')
  311.      break;
  312.       *cp++ = c;
  313.    }
  314.    *cp++ = '\0';
  315.    str = *area;
  316.    *area = cp;
  317.    return str;
  318. }
  319.