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