[BACK]Return to vgrindefs.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vgrind

Annotation of src/usr.bin/vgrind/vgrindefs.c, Revision 1.3

1.3     ! mpech       1: /*     $OpenBSD: vgrindefs.c,v 1.2 1996/06/26 05:42:32 deraadt Exp $   */
1.1       deraadt     2: /*     $NetBSD: vgrindefs.c,v 1.5 1994/12/20 12:05:29 cgd Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
                     38: #if 0
                     39: static char sccsid[] = "@(#)vgrindefs.c        8.1 (Berkeley) 6/6/93";
                     40: #endif
1.3     ! mpech      41: static char rcsid[] = "$OpenBSD: vgrindefs.c,v 1.2 1996/06/26 05:42:32 deraadt Exp $";
1.1       deraadt    42: #endif /* not lint */
                     43:
                     44: #define        BUFSIZ  1024
                     45: #define MAXHOP 32      /* max number of tc= indirections */
                     46:
                     47: #include <stdlib.h>
                     48: #include <string.h>
                     49: #include <ctype.h>
                     50: /*
                     51:  * grindcap - routines for dealing with the language definitions data base
                     52:  *     (code stolen almost totally from termcap)
                     53:  *
                     54:  * BUG:                Should use a "last" pointer in tbuf, so that searching
                     55:  *             for capabilities alphabetically would not be a n**2/2
                     56:  *             process when large numbers of capabilities are given.
                     57:  * Note:       If we add a last pointer now we will screw up the
                     58:  *             tc capability. We really should compile termcap.
                     59:  *
                     60:  * Essentially all the work here is scanning and decoding escapes
                     61:  * in string capabilities.  We don't use stdio because the editor
                     62:  * doesn't, and because living w/o it is not hard.
                     63:  */
                     64:
                     65: static char *tbuf;
                     66: static char *filename;
                     67: static int hopcount;   /* detect infinite loops in termcap, init 0 */
                     68: static char *tskip();
                     69: static char *tdecode();
                     70: char   *tgetstr();
                     71:
                     72: /*
                     73:  * Get an entry for terminal name in buffer bp,
                     74:  * from the termcap file.  Parse is very rudimentary;
                     75:  * we just notice escaped newlines.
                     76:  */
                     77: tgetent(bp, name, file)
                     78:        char *bp, *name, *file;
                     79: {
1.3     ! mpech      80:        char *cp;
        !            81:        int c;
        !            82:        int i = 0, cnt = 0;
1.1       deraadt    83:        char ibuf[BUFSIZ];
                     84:        char *cp2;
                     85:        int tf;
                     86:
                     87:        tbuf = bp;
                     88:        tf = 0;
                     89:        filename = file;
                     90:        tf = open(filename, 0);
                     91:        if (tf < 0)
                     92:                return (-1);
                     93:        for (;;) {
                     94:                cp = bp;
                     95:                for (;;) {
                     96:                        if (i == cnt) {
                     97:                                cnt = read(tf, ibuf, BUFSIZ);
                     98:                                if (cnt <= 0) {
                     99:                                        close(tf);
                    100:                                        return (0);
                    101:                                }
                    102:                                i = 0;
                    103:                        }
                    104:                        c = ibuf[i++];
                    105:                        if (c == '\n') {
                    106:                                if (cp > bp && cp[-1] == '\\'){
                    107:                                        cp--;
                    108:                                        continue;
                    109:                                }
                    110:                                break;
                    111:                        }
                    112:                        if (cp >= bp+BUFSIZ) {
                    113:                                write(2,"Vgrind entry too long\n", 23);
                    114:                                break;
                    115:                        } else
                    116:                                *cp++ = c;
                    117:                }
                    118:                *cp = 0;
                    119:
                    120:                /*
                    121:                 * The real work for the match.
                    122:                 */
                    123:                if (tnamatch(name)) {
                    124:                        close(tf);
                    125:                        return(tnchktc());
                    126:                }
                    127:        }
                    128: }
                    129:
                    130: /*
                    131:  * tnchktc: check the last entry, see if it's tc=xxx. If so,
                    132:  * recursively find xxx and append that entry (minus the names)
                    133:  * to take the place of the tc=xxx entry. This allows termcap
                    134:  * entries to say "like an HP2621 but doesn't turn on the labels".
                    135:  * Note that this works because of the left to right scan.
                    136:  */
                    137: tnchktc()
                    138: {
1.3     ! mpech     139:        char *p, *q;
1.1       deraadt   140:        char tcname[16];        /* name of similar terminal */
                    141:        char tcbuf[BUFSIZ];
                    142:        char *holdtbuf = tbuf;
                    143:        int l;
                    144:
                    145:        p = tbuf + strlen(tbuf) - 2;    /* before the last colon */
                    146:        while (*--p != ':')
                    147:                if (p<tbuf) {
                    148:                        write(2, "Bad vgrind entry\n", 18);
                    149:                        return (0);
                    150:                }
                    151:        p++;
                    152:        /* p now points to beginning of last field */
                    153:        if (p[0] != 't' || p[1] != 'c')
                    154:                return(1);
                    155:        strcpy(tcname,p+3);
                    156:        q = tcname;
                    157:        while (q && *q != ':')
                    158:                q++;
                    159:        *q = 0;
                    160:        if (++hopcount > MAXHOP) {
                    161:                write(2, "Infinite tc= loop\n", 18);
                    162:                return (0);
                    163:        }
                    164:        if (tgetent(tcbuf, tcname, filename) != 1)
                    165:                return(0);
                    166:        for (q=tcbuf; *q != ':'; q++)
                    167:                ;
                    168:        l = p - holdtbuf + strlen(q);
                    169:        if (l > BUFSIZ) {
                    170:                write(2, "Vgrind entry too long\n", 23);
                    171:                q[BUFSIZ - (p-tbuf)] = 0;
                    172:        }
                    173:        strcpy(p, q+1);
                    174:        tbuf = holdtbuf;
                    175:        return(1);
                    176: }
                    177:
                    178: /*
                    179:  * Tnamatch deals with name matching.  The first field of the termcap
                    180:  * entry is a sequence of names separated by |'s, so we compare
                    181:  * against each such name.  The normal : terminator after the last
                    182:  * name (before the first field) stops us.
                    183:  */
                    184: tnamatch(np)
                    185:        char *np;
                    186: {
1.3     ! mpech     187:        char *Np, *Bp;
1.1       deraadt   188:
                    189:        Bp = tbuf;
                    190:        if (*Bp == '#')
                    191:                return(0);
                    192:        for (;;) {
                    193:                for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
                    194:                        continue;
                    195:                if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
                    196:                        return (1);
                    197:                while (*Bp && *Bp != ':' && *Bp != '|')
                    198:                        Bp++;
                    199:                if (*Bp == 0 || *Bp == ':')
                    200:                        return (0);
                    201:                Bp++;
                    202:        }
                    203: }
                    204:
                    205: /*
                    206:  * Skip to the next field.  Notice that this is very dumb, not
                    207:  * knowing about \: escapes or any such.  If necessary, :'s can be put
                    208:  * into the termcap file in octal.
                    209:  */
                    210: static char *
                    211: tskip(bp)
1.3     ! mpech     212:        char *bp;
1.1       deraadt   213: {
                    214:
                    215:        while (*bp && *bp != ':')
                    216:                bp++;
                    217:        if (*bp == ':')
                    218:                bp++;
                    219:        return (bp);
                    220: }
                    221:
                    222: /*
                    223:  * Return the (numeric) option id.
                    224:  * Numeric options look like
                    225:  *     li#80
                    226:  * i.e. the option string is separated from the numeric value by
                    227:  * a # character.  If the option is not found we return -1.
                    228:  * Note that we handle octal numbers beginning with 0.
                    229:  */
                    230: tgetnum(id)
                    231:        char *id;
                    232: {
1.3     ! mpech     233:        int i, base;
        !           234:        char *bp = tbuf;
1.1       deraadt   235:
                    236:        for (;;) {
                    237:                bp = tskip(bp);
                    238:                if (*bp == 0)
                    239:                        return (-1);
                    240:                if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
                    241:                        continue;
                    242:                if (*bp == '@')
                    243:                        return(-1);
                    244:                if (*bp != '#')
                    245:                        continue;
                    246:                bp++;
                    247:                base = 10;
                    248:                if (*bp == '0')
                    249:                        base = 8;
                    250:                i = 0;
                    251:                while (isdigit(*bp))
                    252:                        i *= base, i += *bp++ - '0';
                    253:                return (i);
                    254:        }
                    255: }
                    256:
                    257: /*
                    258:  * Handle a flag option.
                    259:  * Flag options are given "naked", i.e. followed by a : or the end
                    260:  * of the buffer.  Return 1 if we find the option, or 0 if it is
                    261:  * not given.
                    262:  */
                    263: tgetflag(id)
                    264:        char *id;
                    265: {
1.3     ! mpech     266:        char *bp = tbuf;
1.1       deraadt   267:
                    268:        for (;;) {
                    269:                bp = tskip(bp);
                    270:                if (!*bp)
                    271:                        return (0);
                    272:                if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
                    273:                        if (!*bp || *bp == ':')
                    274:                                return (1);
                    275:                        else if (*bp == '@')
                    276:                                return(0);
                    277:                }
                    278:        }
                    279: }
                    280:
                    281: /*
                    282:  * Get a string valued option.
                    283:  * These are given as
                    284:  *     cl=^Z
                    285:  * Much decoding is done on the strings, and the strings are
                    286:  * placed in area, which is a ref parameter which is updated.
                    287:  * No checking on area overflow.
                    288:  */
                    289: char *
                    290: tgetstr(id, area)
                    291:        char *id, **area;
                    292: {
1.3     ! mpech     293:        char *bp = tbuf;
1.1       deraadt   294:
                    295:        for (;;) {
                    296:                bp = tskip(bp);
                    297:                if (!*bp)
                    298:                        return (0);
                    299:                if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
                    300:                        continue;
                    301:                if (*bp == '@')
                    302:                        return(0);
                    303:                if (*bp != '=')
                    304:                        continue;
                    305:                bp++;
                    306:                return (tdecode(bp, area));
                    307:        }
                    308: }
                    309:
                    310: /*
                    311:  * Tdecode does the grung work to decode the
                    312:  * string capability escapes.
                    313:  */
                    314: static char *
                    315: tdecode(str, area)
1.3     ! mpech     316:        char *str;
1.1       deraadt   317:        char **area;
                    318: {
1.3     ! mpech     319:        char *cp;
        !           320:        int c;
1.1       deraadt   321:        int i;
                    322:
                    323:        cp = *area;
                    324:        while (c = *str++) {
                    325:            if (c == ':' && *(cp-1) != '\\')
                    326:                break;
                    327:            *cp++ = c;
                    328:        }
                    329:        *cp++ = 0;
                    330:        str = *area;
                    331:        *area = cp;
                    332:        return (str);
                    333: }