8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / vgrind / vgrindefs.c
blobd6cc33703a5536449bca37cbacdfdb0fccfe60b3
1 /*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
7 #pragma ident "%Z%%M% %I% %E% SMI"
9 #define BUFSIZ 1024
10 #define MAXHOP 32 /* max number of tc= indirections */
12 #include <ctype.h>
13 #include <locale.h>
14 #include <string.h>
16 * grindcap - routines for dealing with the language definitions data base
17 * (code stolen almost totally from termcap)
19 * BUG: Should use a "last" pointer in tbuf, so that searching
20 * for capabilities alphabetically would not be a n**2/2
21 * process when large numbers of capabilities are given.
22 * Note: If we add a last pointer now we will screw up the
23 * tc capability. We really should compile termcap.
25 * Essentially all the work here is scanning and decoding escapes
26 * in string capabilities. We don't use stdio because the editor
27 * doesn't, and because living w/o it is not hard.
30 static char *tbuf;
31 static char *filename;
32 static int hopcount; /* detect infinite loops in termcap, init 0 */
33 char *tgetstr();
34 char *getenv();
36 static char *tdecode(char *str, char **area);
37 static char *tskip(char *bp);
38 static int tnchktc(void);
39 static int tnamatch(char *np);
41 static char *vgrind_msg;
44 * Get an entry for terminal name in buffer bp,
45 * from the termcap file. Parse is very rudimentary;
46 * we just notice escaped newlines.
48 int
49 tgetent(char *bp, char *name, char *file)
51 char *cp;
52 int c;
53 int i = 0, cnt = 0;
54 char ibuf[BUFSIZ];
55 char *cp2;
56 int tf;
58 tbuf = bp;
59 tf = 0;
60 filename = file;
61 tf = open(filename, 0);
62 if (tf < 0)
63 return (-1);
64 for (;;) {
65 cp = bp;
66 for (;;) {
67 if (i == cnt) {
68 cnt = read(tf, ibuf, BUFSIZ);
69 if (cnt <= 0) {
70 close(tf);
71 return (0);
73 i = 0;
75 c = ibuf[i++];
76 if (c == '\n') {
77 if (cp > bp && cp[-1] == '\\'){
78 cp--;
79 continue;
81 break;
83 if (cp >= bp+BUFSIZ) {
84 vgrind_msg = gettext("Vgrind entry too long\n");
85 write(2, vgrind_msg, strlen(vgrind_msg));
86 break;
87 } else
88 *cp++ = c;
90 *cp = 0;
93 * The real work for the match.
95 if (tnamatch(name)) {
96 close(tf);
97 return(tnchktc());
103 * tnchktc: check the last entry, see if it's tc=xxx. If so,
104 * recursively find xxx and append that entry (minus the names)
105 * to take the place of the tc=xxx entry. This allows termcap
106 * entries to say "like an HP2621 but doesn't turn on the labels".
107 * Note that this works because of the left to right scan.
109 static int
110 tnchktc(void)
112 char *p, *q;
113 char tcname[16]; /* name of similar terminal */
114 char tcbuf[BUFSIZ];
115 char *holdtbuf = tbuf;
116 int l;
118 p = tbuf + strlen(tbuf) - 2; /* before the last colon */
119 while (*--p != ':')
120 if (p<tbuf) {
121 vgrind_msg = gettext("Bad vgrind entry\n");
122 write(2, vgrind_msg, strlen(vgrind_msg));
123 return (0);
125 p++;
126 /* p now points to beginning of last field */
127 if (p[0] != 't' || p[1] != 'c')
128 return(1);
129 strcpy(tcname,p+3);
130 q = tcname;
131 while (q && *q != ':')
132 q++;
133 *q = 0;
134 if (++hopcount > MAXHOP) {
135 vgrind_msg = gettext("Infinite tc= loop\n");
136 write(2, vgrind_msg, strlen(vgrind_msg));
137 return (0);
139 if (tgetent(tcbuf, tcname, filename) != 1)
140 return(0);
141 for (q=tcbuf; *q != ':'; q++)
143 l = p - holdtbuf + strlen(q);
144 if (l > BUFSIZ) {
145 vgrind_msg = gettext("Vgrind entry too long\n");
146 write(2, vgrind_msg, strlen(vgrind_msg));
147 q[BUFSIZ - (p-tbuf)] = 0;
149 strcpy(p, q+1);
150 tbuf = holdtbuf;
151 return(1);
155 * Tnamatch deals with name matching. The first field of the termcap
156 * entry is a sequence of names separated by |'s, so we compare
157 * against each such name. The normal : terminator after the last
158 * name (before the first field) stops us.
160 static int
161 tnamatch(char *np)
163 char *Np, *Bp;
165 Bp = tbuf;
166 if (*Bp == '#')
167 return(0);
168 for (;;) {
169 for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
170 continue;
171 if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
172 return (1);
173 while (*Bp && *Bp != ':' && *Bp != '|')
174 Bp++;
175 if (*Bp == 0 || *Bp == ':')
176 return (0);
177 Bp++;
182 * Skip to the next field. Notice that this is very dumb, not
183 * knowing about \: escapes or any such. If necessary, :'s can be put
184 * into the termcap file in octal.
186 static char *
187 tskip(char *bp)
190 while (*bp && *bp != ':')
191 bp++;
192 if (*bp == ':')
193 bp++;
194 return (bp);
198 * Return the (numeric) option id.
199 * Numeric options look like
200 * li#80
201 * i.e. the option string is separated from the numeric value by
202 * a # character. If the option is not found we return -1.
203 * Note that we handle octal numbers beginning with 0.
205 static int
206 tgetnum(char *id)
208 int i, base;
209 char *bp = tbuf;
211 for (;;) {
212 bp = tskip(bp);
213 if (*bp == 0)
214 return (-1);
215 if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
216 continue;
217 if (*bp == '@')
218 return(-1);
219 if (*bp != '#')
220 continue;
221 bp++;
222 base = 10;
223 if (*bp == '0')
224 base = 8;
225 i = 0;
226 while (isdigit(*bp))
227 i *= base, i += *bp++ - '0';
228 return (i);
233 * Handle a flag option.
234 * Flag options are given "naked", i.e. followed by a : or the end
235 * of the buffer. Return 1 if we find the option, or 0 if it is
236 * not given.
239 tgetflag(char *id)
241 char *bp = tbuf;
243 for (;;) {
244 bp = tskip(bp);
245 if (!*bp)
246 return (0);
247 if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
248 if (!*bp || *bp == ':')
249 return (1);
250 else if (*bp == '@')
251 return(0);
257 * Get a string valued option.
258 * These are given as
259 * cl=^Z
260 * Much decoding is done on the strings, and the strings are
261 * placed in area, which is a ref parameter which is updated.
262 * No checking on area overflow.
264 char *
265 tgetstr(char *id, char **area)
267 char *bp = tbuf;
269 for (;;) {
270 bp = tskip(bp);
271 if (!*bp)
272 return (0);
273 if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
274 continue;
275 if (*bp == '@')
276 return(0);
277 if (*bp != '=')
278 continue;
279 bp++;
280 return (tdecode(bp, area));
285 * Tdecode does the grung work to decode the
286 * string capability escapes.
288 static char *
289 tdecode(char *str, char **area)
291 char *cp;
292 int c;
293 int i;
295 cp = *area;
296 while (c = *str++) {
297 if (c == ':' && *(cp-1) != '\\')
298 break;
299 *cp++ = c;
301 *cp++ = 0;
302 str = *area;
303 *area = cp;
304 return (str);