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 } 659