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