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