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