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