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: #if !defined(lint) && defined(DOSCCS)
   8: static char sccsid[] = "@(#)vfontedpr.c	5.1.1 (2.11BSD) 1996/10/23";
   9: #endif
  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/share/misc/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:         fstat(fileno(stdin), &stbuf);
 268:         cp = ctime(&stbuf.st_mtime);
 269:         cp[16] = '\0';
 270:         cp[24] = '\0';
 271:         printf(".ds =M %s %s\n", cp+4, cp+20);
 272:         ps("'wh 0 vH\n");
 273:         ps("'wh -1i vF\n");
 274:     }
 275:     if (needbp) {
 276:         needbp = 0;
 277:         printf(".()\n");
 278:         printf(".bp\n");
 279:     }
 280: 
 281:     /*
 282: 	 *	MAIN LOOP!!!
 283: 	 */
 284:     while (fgets(buf, sizeof buf, stdin) != NULL) {
 285:         if (buf[0] == '\f') {
 286:         printf(".bp\n");
 287:         }
 288:         if (buf[0] == '.') {
 289:         printf("%s", buf);
 290:         if (!strncmp (buf+1, "vS", 2))
 291:             pass = TRUE;
 292:         if (!strncmp (buf+1, "vE", 2))
 293:             pass = FALSE;
 294:         continue;
 295:         }
 296:         prccont = FALSE;
 297:         if (!filter || pass)
 298:         putScp(buf);
 299:         else
 300:         printf("%s", buf);
 301:         if (prccont && (psptr >= 0)) {
 302:         ps("'FC ");
 303:         ps(pstack[psptr]);
 304:         ps("\n");
 305:         }
 306: #ifdef DEBUG
 307:         printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
 308: #endif
 309:         margin = 0;
 310:     }
 311:     needbp = 1;
 312:     } while (argc > 0);
 313:     exit(0);
 314: }
 315: 
 316: #define isidchr(c) (isalnum(c) || (c) == '_')
 317: 
 318: putScp(os)
 319:     char *os;
 320: {
 321:     register char *s = os;      /* pointer to unmatched string */
 322:     char dummy[BUFSIZ];         /* dummy to be used by expmatch */
 323:     char *comptr;           /* end of a comment delimiter */
 324:     char *acmptr;           /* end of a comment delimiter */
 325:     char *strptr;           /* end of a string delimiter */
 326:     char *chrptr;           /* end of a character const delimiter */
 327:     char *blksptr;          /* end of a lexical block start */
 328:     char *blkeptr;          /* end of a lexical block end */
 329: 
 330:     _start = os;            /* remember the start for expmatch */
 331:     _escaped = FALSE;
 332:     if (nokeyw || incomm || instr)
 333:     goto skip;
 334:     if (isproc(s)) {
 335:     ps("'FN ");
 336:     ps(pname);
 337:         ps("\n");
 338:     if (psptr < PSMAX) {
 339:         ++psptr;
 340:         strncpy (pstack[psptr], pname, PNAMELEN);
 341:         pstack[psptr][PNAMELEN] = NULL;
 342:         plstack[psptr] = blklevel;
 343:     }
 344:     }
 345: skip:
 346:     do {
 347:     /* check for string, comment, blockstart, etc */
 348:     if (!incomm && !instr && !inchr) {
 349: 
 350:         blkeptr = expmatch (s, l_blkend, dummy);
 351:         blksptr = expmatch (s, l_blkbeg, dummy);
 352:         comptr = expmatch (s, l_combeg, dummy);
 353:         acmptr = expmatch (s, l_acmbeg, dummy);
 354:         strptr = expmatch (s, l_strbeg, dummy);
 355:         chrptr = expmatch (s, l_chrbeg, dummy);
 356: 
 357:         /* start of a comment? */
 358:         if (comptr != NIL)
 359:         if ((comptr < strptr || strptr == NIL)
 360:           && (comptr < acmptr || acmptr == NIL)
 361:           && (comptr < chrptr || chrptr == NIL)
 362:           && (comptr < blksptr || blksptr == NIL)
 363:           && (comptr < blkeptr || blkeptr == NIL)) {
 364:             putKcp (s, comptr-1, FALSE);
 365:             s = comptr;
 366:             incomm = TRUE;
 367:             comtype = STANDARD;
 368:             if (s != os)
 369:             ps ("\\c");
 370:             ps ("\\c\n'+C\n");
 371:             continue;
 372:         }
 373: 
 374:         /* start of a comment? */
 375:         if (acmptr != NIL)
 376:         if ((acmptr < strptr || strptr == NIL)
 377:           && (acmptr < chrptr || chrptr == NIL)
 378:           && (acmptr < blksptr || blksptr == NIL)
 379:           && (acmptr < blkeptr || blkeptr == NIL)) {
 380:             putKcp (s, acmptr-1, FALSE);
 381:             s = acmptr;
 382:             incomm = TRUE;
 383:             comtype = ALTERNATE;
 384:             if (s != os)
 385:             ps ("\\c");
 386:             ps ("\\c\n'+C\n");
 387:             continue;
 388:         }
 389: 
 390:         /* start of a string? */
 391:         if (strptr != NIL)
 392:         if ((strptr < chrptr || chrptr == NIL)
 393:           && (strptr < blksptr || blksptr == NIL)
 394:           && (strptr < blkeptr || blkeptr == NIL)) {
 395:             putKcp (s, strptr-1, FALSE);
 396:             s = strptr;
 397:             instr = TRUE;
 398:             continue;
 399:         }
 400: 
 401:         /* start of a character string? */
 402:         if (chrptr != NIL)
 403:         if ((chrptr < blksptr || blksptr == NIL)
 404:           && (chrptr < blkeptr || blkeptr == NIL)) {
 405:             putKcp (s, chrptr-1, FALSE);
 406:             s = chrptr;
 407:             inchr = TRUE;
 408:             continue;
 409:         }
 410: 
 411:         /* end of a lexical block */
 412:         if (blkeptr != NIL) {
 413:         if (blkeptr < blksptr || blksptr == NIL) {
 414:             putKcp (s, blkeptr - 1, FALSE);
 415:             s = blkeptr;
 416:             blklevel--;
 417:             if (psptr >= 0 && plstack[psptr] >= blklevel) {
 418: 
 419:             /* end of current procedure */
 420:             if (s != os)
 421:                 ps ("\\c");
 422:             ps ("\\c\n'-F\n");
 423:             blklevel = plstack[psptr];
 424: 
 425:             /* see if we should print the last proc name */
 426:             if (--psptr >= 0)
 427:                 prccont = TRUE;
 428:             else
 429:                 psptr = -1;
 430:             }
 431:             continue;
 432:         }
 433:         }
 434: 
 435:         /* start of a lexical block */
 436:         if (blksptr != NIL) {
 437:         putKcp (s, blksptr - 1, FALSE);
 438:         s = blksptr;
 439:         blklevel++;
 440:         continue;
 441:         }
 442: 
 443:     /* check for end of comment */
 444:     } else if (incomm) {
 445:         comptr = expmatch (s, l_comend, dummy);
 446:         acmptr = expmatch (s, l_acmend, dummy);
 447:         if (((comtype == STANDARD) && (comptr != NIL)) ||
 448:             ((comtype == ALTERNATE) && (acmptr != NIL))) {
 449:         if (comtype == STANDARD) {
 450:             putKcp (s, comptr-1, TRUE);
 451:             s = comptr;
 452:         } else {
 453:             putKcp (s, acmptr-1, TRUE);
 454:             s = acmptr;
 455:         }
 456:         incomm = FALSE;
 457:         ps("\\c\n'-C\n");
 458:         continue;
 459:         } else {
 460:         putKcp (s, s + strlen(s) -1, TRUE);
 461:         s = s + strlen(s);
 462:         continue;
 463:         }
 464: 
 465:     /* check for end of string */
 466:     } else if (instr) {
 467:         if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
 468:         putKcp (s, strptr-1, TRUE);
 469:         s = strptr;
 470:         instr = FALSE;
 471:         continue;
 472:         } else {
 473:         putKcp (s, s+strlen(s)-1, TRUE);
 474:         s = s + strlen(s);
 475:         continue;
 476:         }
 477: 
 478:     /* check for end of character string */
 479:     } else if (inchr) {
 480:         if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) {
 481:         putKcp (s, chrptr-1, TRUE);
 482:         s = chrptr;
 483:         inchr = FALSE;
 484:         continue;
 485:         } else {
 486:         putKcp (s, s+strlen(s)-1, TRUE);
 487:         s = s + strlen(s);
 488:         continue;
 489:         }
 490:     }
 491: 
 492:     /* print out the line */
 493:     putKcp (s, s + strlen(s) -1, FALSE);
 494:     s = s + strlen(s);
 495:     } while (*s);
 496: }
 497: 
 498: putKcp (start, end, force)
 499:     char    *start;     /* start of string to write */
 500:     char    *end;       /* end of string to write */
 501:     boolean force;      /* true if we should force nokeyw */
 502: {
 503:     int i;
 504:     int xfld = 0;
 505: 
 506:     while (start <= end) {
 507:     if (index) {
 508:         if (*start == ' ' || *start == '\t') {
 509:         if (xfld == 0)
 510:             printf("");
 511:         printf("\t");
 512:         xfld = 1;
 513:         while (*start == ' ' || *start == '\t')
 514:             start++;
 515:         continue;
 516:         }
 517:     }
 518: 
 519:     /* take care of nice tab stops */
 520:     if (*start == '\t') {
 521:         while (*start == '\t')
 522:         start++;
 523:         i = tabs(_start, start) - margin / 8;
 524:         printf("\\h'|%dn'", i * 10 + 1 - margin % 8);
 525:         continue;
 526:     }
 527: 
 528:     if (!nokeyw && !force)
 529:         if ((*start == '#' || isidchr(*start))
 530:         && (start == _start || !isidchr(start[-1]))) {
 531:         i = iskw(start);
 532:         if (i > 0) {
 533:             ps("\\*(+K");
 534:             do
 535:             putcp(*start++);
 536:             while (--i > 0);
 537:             ps("\\*(-K");
 538:             continue;
 539:         }
 540:         }
 541: 
 542:     putcp (*start++);
 543:     }
 544: }
 545: 
 546: 
 547: tabs(s, os)
 548:     char *s, *os;
 549: {
 550: 
 551:     return (width(s, os) / 8);
 552: }
 553: 
 554: width(s, os)
 555:     register char *s, *os;
 556: {
 557:     register int i = 0;
 558: 
 559:     while (s < os) {
 560:         if (*s == '\t') {
 561:             i = (i + 8) &~ 7;
 562:             s++;
 563:             continue;
 564:         }
 565:         if (*s < ' ')
 566:             i += 2;
 567:         else
 568:             i++;
 569:         s++;
 570:     }
 571:     return (i);
 572: }
 573: 
 574: putcp(c)
 575:     register int c;
 576: {
 577: 
 578:     switch(c) {
 579: 
 580:     case 0:
 581:         break;
 582: 
 583:     case '\f':
 584:         break;
 585: 
 586:     case '{':
 587:         ps("\\*(+K{\\*(-K");
 588:         break;
 589: 
 590:     case '}':
 591:         ps("\\*(+K}\\*(-K");
 592:         break;
 593: 
 594:     case '\\':
 595:         ps("\\e");
 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("\\'");
 612:         break;
 613: 
 614:     case '.':
 615:         ps("\\&.");
 616:         break;
 617: 
 618:     case '*':
 619:         ps("\\fI*\\fP");
 620:         break;
 621: 
 622:     case '/':
 623:         ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP");
 624:         break;
 625: 
 626:     default:
 627:         if (c < 040)
 628:             putchar('^'), c |= '@';
 629:     case '\t':
 630:     case '\n':
 631:         putchar(c);
 632:     }
 633: }
 634: 
 635: /*
 636:  *	look for a process beginning on this line
 637:  */
 638: boolean
 639: isproc(s)
 640:     char *s;
 641: {
 642:     pname[0] = NULL;
 643:     if (!l_toplex || blklevel == 0)
 644:     if (expmatch (s, l_prcbeg, pname) != NIL) {
 645:         return (TRUE);
 646:     }
 647:     return (FALSE);
 648: }
 649: 
 650: 
 651: /*  iskw -	check to see if the next word is a keyword
 652:  */
 653: 
 654: iskw(s)
 655:     register char *s;
 656: {
 657:     register char **ss = l_keywds;
 658:     register int i = 1;
 659:     register char *cp = s;
 660: 
 661:     while (++cp, isidchr(*cp))
 662:         i++;
 663:     while (cp = *ss++)
 664:         if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
 665:             return (i);
 666:     return (0);
 667: }

Defined functions

iskw defined in line 654; used 1 times
isproc defined in line 638; used 2 times
main defined in line 99; never used
putKcp defined in line 498; used 14 times
putScp defined in line 318; used 1 times
putcp defined in line 574; used 2 times
tabs defined in line 547; used 1 times
width defined in line 554; used 1 times

Defined variables

_start defined in line 94; used 3 times
blklevel defined in line 66; used 7 times
comtype defined in line 61; used 5 times
defsfile defined in line 67; used 3 times
l_acmbeg defined in line 79; used 2 times
l_acmend defined in line 80; used 2 times
l_blkbeg defined in line 81; used 2 times
l_blkend defined in line 82; used 2 times
l_chrbeg defined in line 85; used 2 times
l_chrend defined in line 86; used 2 times
l_combeg defined in line 77; used 2 times
l_comend defined in line 78; used 2 times
l_escape defined in line 87; used 1 times
l_keywds defined in line 75; used 2 times
l_prcbeg defined in line 76; used 2 times
l_strbeg defined in line 83; used 2 times
l_strend defined in line 84; used 2 times
language defined in line 74; used 3 times
margin defined in line 62; used 3 times
plstack defined in line 65; used 4 times
pname defined in line 68; used 4 times
psptr defined in line 63; used 19 times
pstack defined in line 64; used 4 times
sccsid defined in line 8; never used

Defined macros

ALTERNATE defined in line 21; used 2 times
FALSE defined in line 18; used 22 times
NIL defined in line 19; used 28 times
PNAMELEN defined in line 31; used 3 times
PSMAX defined in line 32; used 4 times
STANDARD defined in line 20; used 3 times
STRLEN defined in line 30; never used
TRUE defined in line 17; used 15 times
boolean defined in line 16; used 14 times
isidchr defined in line 316; used 4 times
ps defined in line 97; used 28 times
Last modified: 1996-10-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2501
Valid CSS Valid XHTML 1.0 Strict