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