/usr.bin/vgrind/vfontedpr.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 723 lines · 562 code · 80 blank · 81 comment · 207 complexity · 1b4f5fefa80dd255f902ea74bfd4014e MD5 · raw file

  1. /*
  2. * Copyright (c) 1980, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 4. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include <sys/cdefs.h>
  30. __FBSDID("$FreeBSD$");
  31. #ifndef lint
  32. static const char copyright[] =
  33. "@(#) Copyright (c) 1980, 1993\n\
  34. The Regents of the University of California. All rights reserved.\n";
  35. #endif
  36. #ifndef lint
  37. static const char sccsid[] = "@(#)vfontedpr.c 8.1 (Berkeley) 6/6/93";
  38. #endif
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41. #include <ctype.h>
  42. #include <err.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <time.h>
  47. #include "pathnames.h"
  48. #include "extern.h"
  49. #define FALSE 0
  50. #define TRUE !(FALSE)
  51. #define NIL 0
  52. #define STANDARD 0
  53. #define ALTERNATE 1
  54. /*
  55. * Vfontedpr.
  56. *
  57. * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
  58. *
  59. */
  60. #define STRLEN 10 /* length of strings introducing things */
  61. #define PNAMELEN 40 /* length of a function/procedure name */
  62. #define PSMAX 20 /* size of procedure name stacking */
  63. static int iskw(char *);
  64. static boolean isproc(char *);
  65. static void putKcp(char *, char *, boolean);
  66. static void putScp(char *);
  67. static void putcp(int);
  68. static int tabs(char *, char *);
  69. static int width(char *, char *);
  70. /*
  71. * The state variables
  72. */
  73. static boolean filter = FALSE; /* act as a filter (like eqn) */
  74. static boolean inchr; /* in a string constant */
  75. static boolean incomm; /* in a comment of the primary type */
  76. static boolean idx = FALSE; /* form an index */
  77. static boolean instr; /* in a string constant */
  78. static boolean nokeyw = FALSE; /* no keywords being flagged */
  79. static boolean pass = FALSE; /*
  80. * when acting as a filter, pass indicates
  81. * whether we are currently processing
  82. * input.
  83. */
  84. static int blklevel; /* current nesting level */
  85. static int comtype; /* type of comment */
  86. static char * defsfile[2] = { _PATH_VGRINDEFS, 0 };
  87. /* name of language definitions file */
  88. static int margin;
  89. static int plstack[PSMAX]; /* the procedure nesting level stack */
  90. static char pname[BUFSIZ+1];
  91. static boolean prccont; /* continue last procedure */
  92. static int psptr; /* the stack index of the current procedure */
  93. static char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */
  94. /*
  95. * The language specific globals
  96. */
  97. char *l_acmbeg; /* string introducing a comment */
  98. char *l_acmend; /* string ending a comment */
  99. char *l_blkbeg; /* string beginning of a block */
  100. char *l_blkend; /* string ending a block */
  101. char *l_chrbeg; /* delimiter for character constant */
  102. char *l_chrend; /* delimiter for character constant */
  103. char *l_combeg; /* string introducing a comment */
  104. char *l_comend; /* string ending a comment */
  105. char l_escape; /* character used to escape characters */
  106. char *l_keywds[BUFSIZ/2]; /* keyword table address */
  107. char *l_nocom; /* regexp for non-comments */
  108. char *l_prcbeg; /* regular expr for procedure begin */
  109. char *l_strbeg; /* delimiter for string constant */
  110. char *l_strend; /* delimiter for string constant */
  111. boolean l_toplex; /* procedures only defined at top lex level */
  112. const char *language = "c"; /* the language indicator */
  113. #define ps(x) printf("%s", x)
  114. int
  115. main(argc, argv)
  116. int argc;
  117. char *argv[];
  118. {
  119. const char *fname = "";
  120. struct stat stbuf;
  121. char buf[BUFSIZ];
  122. char *defs;
  123. int needbp = 0;
  124. argc--, argv++;
  125. do {
  126. char *cp;
  127. int i;
  128. if (argc > 0) {
  129. if (!strcmp(argv[0], "-h")) {
  130. if (argc == 1) {
  131. printf("'ds =H\n");
  132. argc = 0;
  133. goto rest;
  134. }
  135. printf("'ds =H %s\n", argv[1]);
  136. argc--, argv++;
  137. argc--, argv++;
  138. if (argc > 0)
  139. continue;
  140. goto rest;
  141. }
  142. /* act as a filter like eqn */
  143. if (!strcmp(argv[0], "-f")) {
  144. filter++;
  145. argv[0] = argv[argc-1];
  146. argv[argc-1] = strdup("-");
  147. continue;
  148. }
  149. /* take input from the standard place */
  150. if (!strcmp(argv[0], "-")) {
  151. argc = 0;
  152. goto rest;
  153. }
  154. /* build an index */
  155. if (!strcmp(argv[0], "-x")) {
  156. idx++;
  157. argv[0] = strdup("-n");
  158. }
  159. /* indicate no keywords */
  160. if (!strcmp(argv[0], "-n")) {
  161. nokeyw++;
  162. argc--, argv++;
  163. continue;
  164. }
  165. /* specify the font size */
  166. if (!strncmp(argv[0], "-s", 2)) {
  167. i = 0;
  168. cp = argv[0] + 2;
  169. while (*cp)
  170. i = i * 10 + (*cp++ - '0');
  171. printf("'ps %d\n'vs %d\n", i, i+1);
  172. argc--, argv++;
  173. continue;
  174. }
  175. /* specify the language */
  176. if (!strncmp(argv[0], "-l", 2)) {
  177. language = argv[0]+2;
  178. argc--, argv++;
  179. continue;
  180. }
  181. /* specify the language description file */
  182. if (!strncmp(argv[0], "-d", 2)) {
  183. defsfile[0] = argv[1];
  184. argc--, argv++;
  185. argc--, argv++;
  186. continue;
  187. }
  188. /* open the file for input */
  189. if (freopen(argv[0], "r", stdin) == NULL)
  190. err(1, "%s", argv[0]);
  191. if (idx)
  192. printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
  193. fname = argv[0];
  194. argc--, argv++;
  195. }
  196. rest:
  197. /*
  198. * get the language definition from the defs file
  199. */
  200. i = cgetent(&defs, defsfile, language);
  201. if (i == -1) {
  202. fprintf (stderr, "no entry for language %s\n", language);
  203. exit (0);
  204. } else if (i == -2) { fprintf(stderr,
  205. "cannot find vgrindefs file %s\n", defsfile[0]);
  206. exit (0);
  207. } else if (i == -3) { fprintf(stderr,
  208. "potential reference loop detected in vgrindefs file %s\n",
  209. defsfile[0]);
  210. exit(0);
  211. }
  212. if (cgetustr(defs, "kw", &cp) == -1)
  213. nokeyw = TRUE;
  214. else {
  215. char **cpp;
  216. cpp = l_keywds;
  217. while (*cp) {
  218. while (*cp == ' ' || *cp =='\t')
  219. *cp++ = '\0';
  220. if (*cp)
  221. *cpp++ = cp;
  222. while (*cp != ' ' && *cp != '\t' && *cp)
  223. cp++;
  224. }
  225. *cpp = NIL;
  226. }
  227. cgetustr(defs, "pb", &cp);
  228. l_prcbeg = convexp(cp);
  229. cgetustr(defs, "cb", &cp);
  230. l_combeg = convexp(cp);
  231. cgetustr(defs, "ce", &cp);
  232. l_comend = convexp(cp);
  233. cgetustr(defs, "ab", &cp);
  234. l_acmbeg = convexp(cp);
  235. cgetustr(defs, "ae", &cp);
  236. l_acmend = convexp(cp);
  237. cgetustr(defs, "sb", &cp);
  238. l_strbeg = convexp(cp);
  239. cgetustr(defs, "se", &cp);
  240. l_strend = convexp(cp);
  241. cgetustr(defs, "bb", &cp);
  242. l_blkbeg = convexp(cp);
  243. cgetustr(defs, "be", &cp);
  244. l_blkend = convexp(cp);
  245. cgetustr(defs, "lb", &cp);
  246. l_chrbeg = convexp(cp);
  247. cgetustr(defs, "le", &cp);
  248. l_chrend = convexp(cp);
  249. if (cgetustr(defs, "nc", &cp) >= 0)
  250. l_nocom = convexp(cp);
  251. l_escape = '\\';
  252. l_onecase = (cgetcap(defs, "oc", ':') != NULL);
  253. l_toplex = (cgetcap(defs, "tl", ':') != NULL);
  254. /* initialize the program */
  255. incomm = FALSE;
  256. instr = FALSE;
  257. inchr = FALSE;
  258. _escaped = FALSE;
  259. blklevel = 0;
  260. for (psptr=0; psptr<PSMAX; psptr++) {
  261. pstack[psptr][0] = '\0';
  262. plstack[psptr] = 0;
  263. }
  264. psptr = -1;
  265. ps("'-F\n");
  266. if (!filter) {
  267. printf(".ds =F %s\n", fname);
  268. ps("'wh 0 vH\n");
  269. ps("'wh -1i vF\n");
  270. }
  271. if (needbp) {
  272. needbp = 0;
  273. printf(".()\n");
  274. printf(".bp\n");
  275. }
  276. if (!filter) {
  277. fstat(fileno(stdin), &stbuf);
  278. cp = ctime(&stbuf.st_mtime);
  279. cp[16] = '\0';
  280. cp[24] = '\0';
  281. printf(".ds =M %s %s\n", cp+4, cp+20);
  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. #define isidchr(c) (isalnum(c) || (c) == '_')
  318. static void
  319. putScp(os)
  320. char *os;
  321. {
  322. register char *s = os; /* pointer to unmatched string */
  323. char dummy[BUFSIZ]; /* dummy to be used by expmatch */
  324. char *comptr; /* end of a comment delimiter */
  325. char *acmptr; /* end of a comment delimiter */
  326. char *strptr; /* end of a string delimiter */
  327. char *chrptr; /* end of a character const delimiter */
  328. char *blksptr; /* end of a lexical block start */
  329. char *blkeptr; /* end of a lexical block end */
  330. char *nocomptr; /* end of a non-comment delimiter */
  331. s_start = os; /* remember the start for expmatch */
  332. _escaped = FALSE;
  333. if (nokeyw || incomm || instr)
  334. goto skip;
  335. if (isproc(s)) {
  336. ps("'FN ");
  337. ps(pname);
  338. ps("\n");
  339. if (psptr < PSMAX) {
  340. ++psptr;
  341. strncpy (pstack[psptr], pname, PNAMELEN);
  342. pstack[psptr][PNAMELEN] = '\0';
  343. plstack[psptr] = blklevel;
  344. }
  345. }
  346. skip:
  347. do {
  348. /* check for string, comment, blockstart, etc */
  349. if (!incomm && !instr && !inchr) {
  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. nocomptr = expmatch (s, l_nocom, dummy);
  357. /* start of non-comment? */
  358. if (nocomptr != NIL)
  359. if ((nocomptr <= comptr || comptr == NIL)
  360. && (nocomptr <= acmptr || acmptr == NIL)) {
  361. /* continue after non-comment */
  362. putKcp (s, nocomptr-1, FALSE);
  363. s = nocomptr;
  364. continue;
  365. }
  366. /* start of a comment? */
  367. if (comptr != NIL)
  368. if ((comptr < strptr || strptr == NIL)
  369. && (comptr < acmptr || acmptr == NIL)
  370. && (comptr < chrptr || chrptr == NIL)
  371. && (comptr < blksptr || blksptr == NIL)
  372. && (comptr < blkeptr || blkeptr == NIL)) {
  373. putKcp (s, comptr-1, FALSE);
  374. s = comptr;
  375. incomm = TRUE;
  376. comtype = STANDARD;
  377. if (s != os)
  378. ps ("\\c");
  379. ps ("\\c\n'+C\n");
  380. continue;
  381. }
  382. /* start of a comment? */
  383. if (acmptr != NIL)
  384. if ((acmptr < strptr || strptr == NIL)
  385. && (acmptr < chrptr || chrptr == NIL)
  386. && (acmptr < blksptr || blksptr == NIL)
  387. && (acmptr < blkeptr || blkeptr == NIL)) {
  388. putKcp (s, acmptr-1, FALSE);
  389. s = acmptr;
  390. incomm = TRUE;
  391. comtype = ALTERNATE;
  392. if (s != os)
  393. ps ("\\c");
  394. ps ("\\c\n'+C\n");
  395. continue;
  396. }
  397. /* start of a string? */
  398. if (strptr != NIL)
  399. if ((strptr < chrptr || chrptr == NIL)
  400. && (strptr < blksptr || blksptr == NIL)
  401. && (strptr < blkeptr || blkeptr == NIL)) {
  402. putKcp (s, strptr-1, FALSE);
  403. s = strptr;
  404. instr = TRUE;
  405. continue;
  406. }
  407. /* start of a character string? */
  408. if (chrptr != NIL)
  409. if ((chrptr < blksptr || blksptr == NIL)
  410. && (chrptr < blkeptr || blkeptr == NIL)) {
  411. putKcp (s, chrptr-1, FALSE);
  412. s = chrptr;
  413. inchr = TRUE;
  414. continue;
  415. }
  416. /* end of a lexical block */
  417. if (blkeptr != NIL) {
  418. if (blkeptr < blksptr || blksptr == NIL) {
  419. putKcp (s, blkeptr - 1, FALSE);
  420. s = blkeptr;
  421. if (blklevel > 0 /* sanity */)
  422. blklevel--;
  423. if (psptr >= 0 && plstack[psptr] >= blklevel) {
  424. /* end of current procedure */
  425. if (s != os)
  426. ps ("\\c");
  427. ps ("\\c\n'-F\n");
  428. blklevel = plstack[psptr];
  429. /* see if we should print the last proc name */
  430. if (--psptr >= 0)
  431. prccont = TRUE;
  432. else
  433. psptr = -1;
  434. }
  435. continue;
  436. }
  437. }
  438. /* start of a lexical block */
  439. if (blksptr != NIL) {
  440. putKcp (s, blksptr - 1, FALSE);
  441. s = blksptr;
  442. blklevel++;
  443. continue;
  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. /* check for end of string */
  467. } else if (instr) {
  468. if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
  469. putKcp (s, strptr-1, TRUE);
  470. s = strptr;
  471. instr = FALSE;
  472. continue;
  473. } else {
  474. putKcp (s, s+strlen(s)-1, TRUE);
  475. s = s + strlen(s);
  476. continue;
  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. /* print out the line */
  492. putKcp (s, s + strlen(s) -1, FALSE);
  493. s = s + strlen(s);
  494. } while (*s);
  495. }
  496. static void
  497. putKcp (start, end, force)
  498. char *start; /* start of string to write */
  499. char *end; /* end of string to write */
  500. boolean force; /* true if we should force nokeyw */
  501. {
  502. int i;
  503. int xfld = 0;
  504. while (start <= end) {
  505. if (idx) {
  506. if (*start == ' ' || *start == '\t') {
  507. if (xfld == 0)
  508. printf("\001");
  509. printf("\t");
  510. xfld = 1;
  511. while (*start == ' ' || *start == '\t')
  512. start++;
  513. continue;
  514. }
  515. }
  516. /* take care of nice tab stops */
  517. if (*start == '\t') {
  518. while (*start == '\t')
  519. start++;
  520. i = tabs(s_start, start) - margin / 8;
  521. printf("\\h'|%dn'", i * 10 + 1 - margin % 8);
  522. continue;
  523. }
  524. if (!nokeyw && !force)
  525. if ((*start == '#' || isidchr(*start))
  526. && (start == s_start || !isidchr(start[-1]))) {
  527. i = iskw(start);
  528. if (i > 0) {
  529. ps("\\*(+K");
  530. do
  531. putcp((unsigned char)*start++);
  532. while (--i > 0);
  533. ps("\\*(-K");
  534. continue;
  535. }
  536. }
  537. putcp ((unsigned char)*start++);
  538. }
  539. }
  540. static int
  541. tabs(s, os)
  542. char *s, *os;
  543. {
  544. return (width(s, os) / 8);
  545. }
  546. static int
  547. width(s, os)
  548. register char *s, *os;
  549. {
  550. register int i = 0;
  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. static void
  566. putcp(c)
  567. register int c;
  568. {
  569. switch(c) {
  570. case 0:
  571. break;
  572. case '\f':
  573. break;
  574. case '\r':
  575. break;
  576. case '{':
  577. ps("\\*(+K{\\*(-K");
  578. break;
  579. case '}':
  580. ps("\\*(+K}\\*(-K");
  581. break;
  582. case '\\':
  583. ps("\\e");
  584. break;
  585. case '_':
  586. ps("\\*_");
  587. break;
  588. case '-':
  589. ps("\\*-");
  590. break;
  591. case '`':
  592. ps("\\`");
  593. break;
  594. case '\'':
  595. ps("\\'");
  596. break;
  597. case '.':
  598. ps("\\&.");
  599. break;
  600. case '*':
  601. ps("\\fI*\\fP");
  602. break;
  603. case '/':
  604. ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP");
  605. break;
  606. default:
  607. if (c < 040)
  608. putchar('^'), c |= '@';
  609. case '\t':
  610. case '\n':
  611. putchar(c);
  612. }
  613. }
  614. /*
  615. * look for a process beginning on this line
  616. */
  617. static boolean
  618. isproc(s)
  619. char *s;
  620. {
  621. pname[0] = '\0';
  622. if (!l_toplex || blklevel == 0)
  623. if (expmatch (s, l_prcbeg, pname) != NIL) {
  624. return (TRUE);
  625. }
  626. return (FALSE);
  627. }
  628. /* iskw - check to see if the next word is a keyword
  629. */
  630. static int
  631. iskw(s)
  632. register char *s;
  633. {
  634. register char **ss = l_keywds;
  635. register int i = 1;
  636. register char *cp = s;
  637. while (++cp, isidchr(*cp))
  638. i++;
  639. while ((cp = *ss++))
  640. if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
  641. return (i);
  642. return (0);
  643. }