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