date and time created 91/10/27 14:14:54 by bostic
[unix-history] / usr / src / usr.bin / vgrind / vfontedpr.c
CommitLineData
76797561 1/*
616af90a
KB
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
6ecf3d85 5 * %sccs.include.redist.c%
76797561
DF
6 */
7
8#ifndef lint
616af90a
KB
9char copyright[] =
10"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
11 All rights reserved.\n";
12#endif /* not lint */
13
14#ifndef lint
6ecf3d85 15static char sccsid[] = "@(#)vfontedpr.c 5.5 (Berkeley) %G%";
616af90a 16#endif /* not lint */
edd148a9 17
0b79a041
BJ
18#include <sys/types.h>
19#include <sys/stat.h>
24e36722
KB
20#include <ctype.h>
21#include <stdio.h>
22#include "pathnames.h"
0b79a041 23
a388f2af
BJ
24#define boolean int
25#define TRUE 1
26#define FALSE 0
27#define NIL 0
d72dd43f
DP
28#define STANDARD 0
29#define ALTERNATE 1
a388f2af 30
0b79a041
BJ
31/*
32 * Vfontedpr.
33 *
a388f2af 34 * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
f5fa559c
BJ
35 *
36 */
f5fa559c
BJ
37
38#define STRLEN 10 /* length of strings introducing things */
39#define PNAMELEN 40 /* length of a function/procedure name */
a388f2af 40#define PSMAX 20 /* size of procedure name stacking */
f5fa559c 41
a388f2af 42/* regular expression routines */
b48967e6 43
a388f2af
BJ
44char *expmatch(); /* match a string to an expression */
45char *STRNCMP(); /* a different kindof strncmp */
46char *convexp(); /* convert expression to internal form */
1a8c1b81 47char *tgetstr();
a388f2af
BJ
48
49boolean isproc();
f5fa559c 50
f5fa559c 51
0b79a041 52char *ctime();
a388f2af
BJ
53
54/*
55 * The state variables
56 */
57
58boolean incomm; /* in a comment of the primary type */
59boolean instr; /* in a string constant */
60boolean inchr; /* in a string constant */
61boolean nokeyw = FALSE; /* no keywords being flagged */
62boolean index = FALSE; /* form an index */
63boolean filter = FALSE; /* act as a filter (like eqn) */
64boolean pass = FALSE; /* when acting as a filter, pass indicates
65 * whether we are currently processing
66 * input.
67 */
68boolean prccont; /* continue last procedure */
d72dd43f 69int comtype; /* type of comment */
0b79a041 70int margin;
a388f2af
BJ
71int psptr; /* the stack index of the current procedure */
72char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */
73int plstack[PSMAX]; /* the procedure nesting level stack */
74int blklevel; /* current nesting level */
24e36722 75char *defsfile = _PATH_VGRINDEFS; /* name of language definitions file */
a388f2af 76char pname[BUFSIZ+1];
b48967e6 77
a388f2af
BJ
78/*
79 * The language specific globals
80 */
81
82char *language = "c"; /* the language indicator */
83char *l_keywds[BUFSIZ/2]; /* keyword table address */
84char *l_prcbeg; /* regular expr for procedure begin */
85char *l_combeg; /* string introducing a comment */
86char *l_comend; /* string ending a comment */
d72dd43f
DP
87char *l_acmbeg; /* string introducing a comment */
88char *l_acmend; /* string ending a comment */
a388f2af
BJ
89char *l_blkbeg; /* string begining of a block */
90char *l_blkend; /* string ending a block */
91char *l_strbeg; /* delimiter for string constant */
92char *l_strend; /* delimiter for string constant */
93char *l_chrbeg; /* delimiter for character constant */
94char *l_chrend; /* delimiter for character constant */
95char l_escape; /* character used to escape characters */
96boolean l_toplex; /* procedures only defined at top lex level */
97
98/*
99 * global variables also used by expmatch
100 */
101boolean _escaped; /* if last character was an escape */
102char *_start; /* start of the current string */
103boolean l_onecase; /* upper and lower case are equivalent */
f5fa559c
BJ
104
105#define ps(x) printf("%s", x)
0b79a041
BJ
106
107main(argc, argv)
a388f2af
BJ
108 int argc;
109 char *argv[];
0b79a041 110{
a388f2af
BJ
111 int lineno;
112 char *fname = "";
113 char *ptr;
114 struct stat stbuf;
115 char buf[BUFSIZ];
116 char strings[2 * BUFSIZ];
117 char defs[2 * BUFSIZ];
118 int needbp = 0;
119
120 argc--, argv++;
121 do {
122 char *cp;
123 int i;
124
125 if (argc > 0) {
126 if (!strcmp(argv[0], "-h")) {
127 if (argc == 1) {
128 printf("'ds =H\n");
129 argc = 0;
130 goto rest;
0b79a041 131 }
a388f2af 132 printf("'ds =H %s\n", argv[1]);
91146c92
DP
133 argc--, argv++;
134 argc--, argv++;
a388f2af
BJ
135 if (argc > 0)
136 continue;
137 goto rest;
138 }
139
140 /* act as a filter like eqn */
141 if (!strcmp(argv[0], "-f")) {
142 filter++;
143 argv[0] = argv[argc-1];
144 argv[argc-1] = "-";
145 continue;
146 }
147
148 /* take input from the standard place */
149 if (!strcmp(argv[0], "-")) {
150 argc = 0;
151 goto rest;
152 }
153
154 /* build an index */
155 if (!strcmp(argv[0], "-x")) {
156 index++;
157 argv[0] = "-n";
158 }
159
160 /* indicate no keywords */
161 if (!strcmp(argv[0], "-n")) {
162 nokeyw++;
163 argc--, argv++;
164 continue;
165 }
166
167 /* specify the font size */
168 if (!strncmp(argv[0], "-s", 2)) {
169 i = 0;
170 cp = argv[0] + 2;
171 while (*cp)
172 i = i * 10 + (*cp++ - '0');
173 printf("'ps %d\n'vs %d\n", i, i+1);
174 argc--, argv++;
175 continue;
176 }
177
178 /* specify the language */
179 if (!strncmp(argv[0], "-l", 2)) {
180 language = argv[0]+2;
181 argc--, argv++;
182 continue;
183 }
184
185 /* specify the language description file */
186 if (!strncmp(argv[0], "-d", 2)) {
187 defsfile = argv[1];
188 argc--, argv++;
189 argc--, argv++;
190 continue;
191 }
192
193 /* open the file for input */
194 if (freopen(argv[0], "r", stdin) == NULL) {
195 perror(argv[0]);
196 exit(1);
197 }
198 if (index)
199 printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
200 fname = argv[0];
201 argc--, argv++;
202 }
203 rest:
204
205 /*
206 * get the language definition from the defs file
207 */
208 i = tgetent (defs, language, defsfile);
209 if (i == 0) {
210 fprintf (stderr, "no entry for language %s\n", language);
211 exit (0);
212 } else if (i < 0) {
213 fprintf (stderr, "cannot find vgrindefs file %s\n", defsfile);
214 exit (0);
215 }
216 cp = strings;
217 if (tgetstr ("kw", &cp) == NIL)
218 nokeyw = TRUE;
219 else {
220 char **cpp;
221
222 cpp = l_keywds;
223 cp = strings;
224 while (*cp) {
225 while (*cp == ' ' || *cp =='\t')
226 *cp++ = NULL;
227 if (*cp)
228 *cpp++ = cp;
229 while (*cp != ' ' && *cp != '\t' && *cp)
230 cp++;
231 }
232 *cpp = NIL;
233 }
234 cp = buf;
235 l_prcbeg = convexp (tgetstr ("pb", &cp));
236 cp = buf;
237 l_combeg = convexp (tgetstr ("cb", &cp));
238 cp = buf;
239 l_comend = convexp (tgetstr ("ce", &cp));
240 cp = buf;
d72dd43f
DP
241 l_acmbeg = convexp (tgetstr ("ab", &cp));
242 cp = buf;
243 l_acmend = convexp (tgetstr ("ae", &cp));
244 cp = buf;
a388f2af
BJ
245 l_strbeg = convexp (tgetstr ("sb", &cp));
246 cp = buf;
247 l_strend = convexp (tgetstr ("se", &cp));
248 cp = buf;
249 l_blkbeg = convexp (tgetstr ("bb", &cp));
250 cp = buf;
251 l_blkend = convexp (tgetstr ("be", &cp));
252 cp = buf;
253 l_chrbeg = convexp (tgetstr ("lb", &cp));
254 cp = buf;
255 l_chrend = convexp (tgetstr ("le", &cp));
256 l_escape = '\\';
257 l_onecase = tgetflag ("oc");
258 l_toplex = tgetflag ("tl");
d72dd43f 259
a388f2af
BJ
260 /* initialize the program */
261
262 incomm = FALSE;
263 instr = FALSE;
264 inchr = FALSE;
265 _escaped = FALSE;
266 blklevel = 0;
267 for (psptr=0; psptr<PSMAX; psptr++) {
268 pstack[psptr][0] = NULL;
269 plstack[psptr] = 0;
270 }
271 psptr = -1;
272 ps("'-F\n");
273 if (!filter) {
274 printf(".ds =F %s\n", fname);
91146c92
DP
275 ps("'wh 0 vH\n");
276 ps("'wh -1i vF\n");
a388f2af
BJ
277 }
278 if (needbp) {
279 needbp = 0;
280 printf(".()\n");
281 printf(".bp\n");
282 }
546e1f78
DS
283 if (!filter) {
284 fstat(fileno(stdin), &stbuf);
285 cp = ctime(&stbuf.st_mtime);
286 cp[16] = '\0';
287 cp[24] = '\0';
288 printf(".ds =M %s %s\n", cp+4, cp+20);
289 }
a388f2af
BJ
290
291 /*
292 * MAIN LOOP!!!
293 */
294 while (fgets(buf, sizeof buf, stdin) != NULL) {
295 if (buf[0] == '\f') {
296 printf(".bp\n");
297 }
298 if (buf[0] == '.') {
299 printf("%s", buf);
300 if (!strncmp (buf+1, "vS", 2))
301 pass = TRUE;
302 if (!strncmp (buf+1, "vE", 2))
303 pass = FALSE;
304 continue;
305 }
306 prccont = FALSE;
307 if (!filter || pass)
308 putScp(buf);
309 else
310 printf("%s", buf);
311 if (prccont && (psptr >= 0)) {
312 ps("'FC ");
313 ps(pstack[psptr]);
314 ps("\n");
315 }
316#ifdef DEBUG
317 printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
318#endif
319 margin = 0;
320 }
321 needbp = 1;
322 } while (argc > 0);
323 exit(0);
0b79a041
BJ
324}
325
0b79a041
BJ
326#define isidchr(c) (isalnum(c) || (c) == '_')
327
328putScp(os)
a388f2af 329 char *os;
0b79a041 330{
a388f2af
BJ
331 register char *s = os; /* pointer to unmatched string */
332 char dummy[BUFSIZ]; /* dummy to be used by expmatch */
a388f2af 333 char *comptr; /* end of a comment delimiter */
d72dd43f 334 char *acmptr; /* end of a comment delimiter */
a388f2af
BJ
335 char *strptr; /* end of a string delimiter */
336 char *chrptr; /* end of a character const delimiter */
337 char *blksptr; /* end of a lexical block start */
338 char *blkeptr; /* end of a lexical block end */
339
340 _start = os; /* remember the start for expmatch */
341 _escaped = FALSE;
342 if (nokeyw || incomm || instr)
343 goto skip;
344 if (isproc(s)) {
345 ps("'FN ");
346 ps(pname);
09aabb70 347 ps("\n");
a388f2af
BJ
348 if (psptr < PSMAX) {
349 ++psptr;
350 strncpy (pstack[psptr], pname, PNAMELEN);
351 pstack[psptr][PNAMELEN] = NULL;
a388f2af
BJ
352 plstack[psptr] = blklevel;
353 }
354 }
0b79a041 355skip:
a388f2af 356 do {
a388f2af
BJ
357 /* check for string, comment, blockstart, etc */
358 if (!incomm && !instr && !inchr) {
359
360 blkeptr = expmatch (s, l_blkend, dummy);
361 blksptr = expmatch (s, l_blkbeg, dummy);
362 comptr = expmatch (s, l_combeg, dummy);
d72dd43f 363 acmptr = expmatch (s, l_acmbeg, dummy);
a388f2af
BJ
364 strptr = expmatch (s, l_strbeg, dummy);
365 chrptr = expmatch (s, l_chrbeg, dummy);
366
367 /* start of a comment? */
368 if (comptr != NIL)
369 if ((comptr < strptr || strptr == NIL)
d72dd43f 370 && (comptr < acmptr || acmptr == NIL)
a388f2af
BJ
371 && (comptr < chrptr || chrptr == NIL)
372 && (comptr < blksptr || blksptr == NIL)
373 && (comptr < blkeptr || blkeptr == NIL)) {
374 putKcp (s, comptr-1, FALSE);
375 s = comptr;
376 incomm = TRUE;
d72dd43f
DP
377 comtype = STANDARD;
378 if (s != os)
379 ps ("\\c");
380 ps ("\\c\n'+C\n");
381 continue;
382 }
383
384 /* start of a comment? */
385 if (acmptr != NIL)
386 if ((acmptr < strptr || strptr == NIL)
387 && (acmptr < chrptr || chrptr == NIL)
388 && (acmptr < blksptr || blksptr == NIL)
389 && (acmptr < blkeptr || blkeptr == NIL)) {
390 putKcp (s, acmptr-1, FALSE);
391 s = acmptr;
392 incomm = TRUE;
393 comtype = ALTERNATE;
a388f2af
BJ
394 if (s != os)
395 ps ("\\c");
396 ps ("\\c\n'+C\n");
397 continue;
cca8d17e 398 }
a388f2af
BJ
399
400 /* start of a string? */
401 if (strptr != NIL)
402 if ((strptr < chrptr || chrptr == NIL)
d81ba424
BJ
403 && (strptr < blksptr || blksptr == NIL)
404 && (strptr < blkeptr || blkeptr == NIL)) {
a388f2af
BJ
405 putKcp (s, strptr-1, FALSE);
406 s = strptr;
407 instr = TRUE;
408 continue;
0b79a041 409 }
b48967e6 410
a388f2af
BJ
411 /* start of a character string? */
412 if (chrptr != NIL)
d81ba424
BJ
413 if ((chrptr < blksptr || blksptr == NIL)
414 && (chrptr < blkeptr || blkeptr == NIL)) {
a388f2af
BJ
415 putKcp (s, chrptr-1, FALSE);
416 s = chrptr;
417 inchr = TRUE;
418 continue;
0b79a041 419 }
b48967e6 420
a388f2af
BJ
421 /* end of a lexical block */
422 if (blkeptr != NIL) {
423 if (blkeptr < blksptr || blksptr == NIL) {
424 putKcp (s, blkeptr - 1, FALSE);
425 s = blkeptr;
426 blklevel--;
427 if (psptr >= 0 && plstack[psptr] >= blklevel) {
b48967e6 428
a388f2af 429 /* end of current procedure */
b48967e6 430 if (s != os)
a388f2af
BJ
431 ps ("\\c");
432 ps ("\\c\n'-F\n");
433 blklevel = plstack[psptr];
434
435 /* see if we should print the last proc name */
436 if (--psptr >= 0)
437 prccont = TRUE;
438 else
439 psptr = -1;
440 }
441 continue;
0b79a041 442 }
a388f2af 443 }
b48967e6 444
a388f2af
BJ
445 /* start of a lexical block */
446 if (blksptr != NIL) {
447 putKcp (s, blksptr - 1, FALSE);
448 s = blksptr;
449 blklevel++;
450 continue;
451 }
452
453 /* check for end of comment */
454 } else if (incomm) {
d72dd43f
DP
455 comptr = expmatch (s, l_comend, dummy);
456 acmptr = expmatch (s, l_acmend, dummy);
457 if (((comtype == STANDARD) && (comptr != NIL)) ||
458 ((comtype == ALTERNATE) && (acmptr != NIL))) {
459 if (comtype == STANDARD) {
460 putKcp (s, comptr-1, TRUE);
461 s = comptr;
462 } else {
463 putKcp (s, acmptr-1, TRUE);
464 s = acmptr;
465 }
a388f2af
BJ
466 incomm = FALSE;
467 ps("\\c\n'-C\n");
468 continue;
469 } else {
1a8c1b81 470 putKcp (s, s + strlen(s) -1, TRUE);
a388f2af
BJ
471 s = s + strlen(s);
472 continue;
473 }
474
475 /* check for end of string */
476 } else if (instr) {
477 if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
478 putKcp (s, strptr-1, TRUE);
479 s = strptr;
480 instr = FALSE;
481 continue;
482 } else {
483 putKcp (s, s+strlen(s)-1, TRUE);
484 s = s + strlen(s);
485 continue;
486 }
487
488 /* check for end of character string */
489 } else if (inchr) {
490 if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) {
491 putKcp (s, chrptr-1, TRUE);
492 s = chrptr;
493 inchr = FALSE;
494 continue;
495 } else {
496 putKcp (s, s+strlen(s)-1, TRUE);
497 s = s + strlen(s);
498 continue;
499 }
0b79a041 500 }
a388f2af
BJ
501
502 /* print out the line */
503 putKcp (s, s + strlen(s) -1, FALSE);
504 s = s + strlen(s);
505 } while (*s);
0b79a041
BJ
506}
507
a388f2af
BJ
508putKcp (start, end, force)
509 char *start; /* start of string to write */
510 char *end; /* end of string to write */
511 boolean force; /* true if we should force nokeyw */
512{
513 int i;
d22f197f 514 int xfld = 0;
a388f2af
BJ
515
516 while (start <= end) {
d22f197f
BJ
517 if (index) {
518 if (*start == ' ' || *start == '\t') {
519 if (xfld == 0)
520 printf("\ 1");
521 printf("\t");
522 xfld = 1;
523 while (*start == ' ' || *start == '\t')
524 start++;
525 continue;
526 }
527 }
a388f2af
BJ
528
529 /* take care of nice tab stops */
530 if (*start == '\t') {
531 while (*start == '\t')
532 start++;
533 i = tabs(_start, start) - margin / 8;
534 printf("\\h'|%dn'", i * 10 + 1 - margin % 8);
535 continue;
536 }
537
538 if (!nokeyw && !force)
539 if ((*start == '#' || isidchr(*start))
540 && (start == _start || !isidchr(start[-1]))) {
541 i = iskw(start);
542 if (i > 0) {
543 ps("\\*(+K");
544 do
545 putcp(*start++);
546 while (--i > 0);
547 ps("\\*(-K");
548 continue;
549 }
550 }
551
552 putcp (*start++);
553 }
554}
555
556
0b79a041 557tabs(s, os)
a388f2af 558 char *s, *os;
0b79a041
BJ
559{
560
a388f2af 561 return (width(s, os) / 8);
0b79a041
BJ
562}
563
564width(s, os)
565 register char *s, *os;
566{
567 register int i = 0;
568
569 while (s < os) {
570 if (*s == '\t') {
571 i = (i + 8) &~ 7;
572 s++;
573 continue;
574 }
575 if (*s < ' ')
576 i += 2;
577 else
578 i++;
579 s++;
580 }
581 return (i);
582}
583
584putcp(c)
585 register int c;
586{
587
588 switch(c) {
589
a388f2af
BJ
590 case 0:
591 break;
592
593 case '\f':
594 break;
595
0b79a041
BJ
596 case '{':
597 ps("\\*(+K{\\*(-K");
598 break;
599
600 case '}':
601 ps("\\*(+K}\\*(-K");
602 break;
603
604 case '\\':
605 ps("\\e");
606 break;
607
608 case '_':
609 ps("\\*_");
610 break;
611
612 case '-':
613 ps("\\*-");
614 break;
615
616 case '`':
617 ps("\\`");
618 break;
619
620 case '\'':
621 ps("\\'");
622 break;
623
624 case '.':
625 ps("\\&.");
626 break;
627
341765b5
BJ
628 case '*':
629 ps("\\fI*\\fP");
630 break;
631
a388f2af 632 case '/':
341765b5 633 ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP");
a388f2af
BJ
634 break;
635
0b79a041
BJ
636 default:
637 if (c < 040)
638 putchar('^'), c |= '@';
639 case '\t':
640 case '\n':
641 putchar(c);
642 }
643}
644
a388f2af
BJ
645/*
646 * look for a process beginning on this line
b48967e6 647 */
a388f2af
BJ
648boolean
649isproc(s)
650 char *s;
b48967e6 651{
a388f2af
BJ
652 pname[0] = NULL;
653 if (!l_toplex || blklevel == 0)
654 if (expmatch (s, l_prcbeg, pname) != NIL) {
655 return (TRUE);
656 }
657 return (FALSE);
b48967e6
BJ
658}
659
a388f2af 660
b48967e6
BJ
661/* iskw - check to see if the next word is a keyword
662 */
663
0b79a041
BJ
664iskw(s)
665 register char *s;
666{
a388f2af 667 register char **ss = l_keywds;
0b79a041
BJ
668 register int i = 1;
669 register char *cp = s;
670
671 while (++cp, isidchr(*cp))
672 i++;
673 while (cp = *ss++)
a388f2af 674 if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
0b79a041
BJ
675 return (i);
676 return (0);
677}