|
|
1.1 ! root 1: /* ! 2: * ! 3: * postprint - PostScript translator for ASCII files. ! 4: * ! 5: * A simple program that translates ASCII files into PostScript. All it really ! 6: * does is expand tabs and backspaces, handle character quoting, print text lines, ! 7: * and control when pages are started based on the requested number of lines per ! 8: * page. ! 9: * ! 10: * The PostScript prologue is copied from *prologue before any of the input files ! 11: * are translated. The program expects that the following procedures are defined ! 12: * in that file: ! 13: * ! 14: * setup ! 15: * ! 16: * mark ... setup - ! 17: * ! 18: * Handles special initialization stuff that depends on how the program ! 19: * was called. Expects to find a mark followed by key/value pairs on the ! 20: * stack. The def operator is applied to each pair up to the mark, then ! 21: * the default state is set up. ! 22: * ! 23: * pagesetup ! 24: * ! 25: * page pagesetup - ! 26: * ! 27: * Does whatever is needed to set things up for the next page. Expects ! 28: * to find the current page number on the stack. ! 29: * ! 30: * l ! 31: * ! 32: * string l - ! 33: * ! 34: * Prints string starting in the first column and then goes to the next ! 35: * line. ! 36: * ! 37: * L ! 38: * ! 39: * mark string column string column ... L mark ! 40: * ! 41: * Prints each string on the stack starting at the horizontal position ! 42: * selected by column. Used when tabs and spaces can be sufficiently well ! 43: * compressed to make the printer overhead worthwhile. Always used when ! 44: * we have to back up. ! 45: * ! 46: * LL ! 47: * ! 48: * mark string column string column ... LL mark ! 49: * ! 50: * Like L, but only used to prevent potential PostScript stack overflow ! 51: * from too many string/column pairs. Stays on the current line. It will ! 52: * not be needed often!! ! 53: * ! 54: * done ! 55: * ! 56: * done ! 57: * ! 58: * Makes sure the last page is printed. Only needed when we're printing ! 59: * more than one page on each sheet of paper. ! 60: * ! 61: * Almost everything has been changed in this version of postprint. The program ! 62: * is more intelligent, especially about tabs, spaces, and backspacing, and as a ! 63: * result output files usually print faster. Output files also now conform to ! 64: * Adobe's file structuring conventions, which is undoubtedly something I should ! 65: * have done in the first version of the program. If the number of lines per page ! 66: * is set to 0, which can be done using the -l option, pointsize will be used to ! 67: * guess a reasonable value. The estimate is based on the values of LINESPP, ! 68: * POINTSIZE, and pointsize, and assumes LINESPP lines would fit on a page if ! 69: * we printed in size POINTSIZE. Selecting a point size using the -s option and ! 70: * adding -l0 to the command line forces the guess to be made. ! 71: * ! 72: * Many default values, like the magnification and orientation, are defined in ! 73: * the prologue, which is where they belong. If they're changed (by options), an ! 74: * appropriate definition is made after the prologue is added to the output file. ! 75: * The -P option passes arbitrary PostScript through to the output file. Among ! 76: * other things it can be used to set (or change) values that can't be accessed by ! 77: * other options. ! 78: * ! 79: */ ! 80: ! 81: #include <stdio.h> ! 82: #include <signal.h> ! 83: #include <ctype.h> ! 84: #include <fcntl.h> ! 85: ! 86: #include "comments.h" /* PostScript file structuring comments */ ! 87: #include "gen.h" /* general purpose definitions */ ! 88: #include "path.h" /* for the prologue */ ! 89: #include "ext.h" /* external variable declarations */ ! 90: #include "postprint.h" /* a few special definitions */ ! 91: ! 92: char *optnames = "a:c:ef:l:m:n:o:p:r:s:t:x:y:A:C:E:J:L:P:R:DI"; ! 93: ! 94: char *prologue = POSTPRINT; /* default PostScript prologue */ ! 95: char *formfile = FORMFILE; /* stuff for multiple pages per sheet */ ! 96: ! 97: int formsperpage = 1; /* page images on each piece of paper */ ! 98: int copies = 1; /* and this many copies of each sheet */ ! 99: ! 100: int linespp = LINESPP; /* number of lines per page */ ! 101: int pointsize = POINTSIZE; /* in this point size */ ! 102: int tabstops = TABSTOPS; /* tabs set at these columns */ ! 103: int crmode = 0; /* carriage return mode - 0, 1, or 2 */ ! 104: int extended = TRUE; /* use escapes for unprintable chars */ ! 105: ! 106: int col = 1; /* next character goes in this column */ ! 107: int line = 1; /* on this line */ ! 108: ! 109: int stringcount = 0; /* number of strings on the stack */ ! 110: int stringstart = 1; /* column where current one starts */ ! 111: ! 112: Fontmap fontmap[] = FONTMAP; /* for translating font names */ ! 113: char *fontname = "Courier"; /* use this PostScript font */ ! 114: ! 115: int page = 0; /* page we're working on */ ! 116: int printed = 0; /* printed this many pages */ ! 117: ! 118: FILE *fp_in = stdin; /* read from this file */ ! 119: FILE *fp_out = stdout; /* and write stuff here */ ! 120: FILE *fp_acct = NULL; /* for accounting data */ ! 121: ! 122: /*****************************************************************************/ ! 123: ! 124: main(agc, agv) ! 125: ! 126: int agc; ! 127: char *agv[]; ! 128: ! 129: { ! 130: ! 131: /* ! 132: * ! 133: * A simple program that translates ASCII files into PostScript. If there's more ! 134: * than one input file, each begins on a new page. ! 135: * ! 136: */ ! 137: ! 138: argc = agc; /* other routines may want them */ ! 139: argv = agv; ! 140: ! 141: prog_name = argv[0]; /* really just for error messages */ ! 142: ! 143: init_signals(); /* sets up interrupt handling */ ! 144: header(); /* PostScript header and prologue */ ! 145: options(); /* handle the command line options */ ! 146: setup(); /* for PostScript */ ! 147: arguments(); /* followed by each input file */ ! 148: done(); /* print the last page etc. */ ! 149: account(); /* job accounting data */ ! 150: ! 151: exit(x_stat); /* not much could be wrong */ ! 152: ! 153: } /* End of main */ ! 154: ! 155: /*****************************************************************************/ ! 156: ! 157: init_signals() ! 158: ! 159: { ! 160: ! 161: /* ! 162: * ! 163: * Makes sure we handle interrupts. ! 164: * ! 165: */ ! 166: ! 167: if ( signal(SIGINT, interrupt) == SIG_IGN ) { ! 168: signal(SIGINT, SIG_IGN); ! 169: signal(SIGQUIT, SIG_IGN); ! 170: signal(SIGHUP, SIG_IGN); ! 171: } else { ! 172: signal(SIGHUP, interrupt); ! 173: signal(SIGQUIT, interrupt); ! 174: } /* End else */ ! 175: ! 176: signal(SIGTERM, interrupt); ! 177: ! 178: } /* End of init_signals */ ! 179: ! 180: /*****************************************************************************/ ! 181: ! 182: header() ! 183: ! 184: { ! 185: ! 186: int ch; /* return value from getopt() */ ! 187: int old_optind = optind; /* for restoring optind - should be 1 */ ! 188: ! 189: /* ! 190: * ! 191: * Scans the option list looking for things, like the prologue file, that we need ! 192: * right away but could be changed from the default. Doing things this way is an ! 193: * attempt to conform to Adobe's latest file structuring conventions. In particular ! 194: * they now say there should be nothing executed in the prologue, and they have ! 195: * added two new comments that delimit global initialization calls. Once we know ! 196: * where things really are we write out the job header, follow it by the prologue, ! 197: * and then add the ENDPROLOG and BEGINSETUP comments. ! 198: * ! 199: */ ! 200: ! 201: while ( (ch = getopt(argc, argv, optnames)) != EOF ) ! 202: if ( ch == 'L' ) ! 203: prologue = optarg; ! 204: else if ( ch == '?' ) ! 205: error(FATAL, ""); ! 206: ! 207: optind = old_optind; /* get ready for option scanning */ ! 208: ! 209: fprintf(stdout, "%s", CONFORMING); ! 210: fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION); ! 211: fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND); ! 212: fprintf(stdout, "%s %s\n", PAGES, ATEND); ! 213: fprintf(stdout, "%s", ENDCOMMENTS); ! 214: ! 215: if ( cat(prologue) == FALSE ) ! 216: error(FATAL, "can't read %s", prologue); ! 217: ! 218: if ( DOROUND ) ! 219: cat(ROUNDPAGE); ! 220: ! 221: fprintf(stdout, "%s", ENDPROLOG); ! 222: fprintf(stdout, "%s", BEGINSETUP); ! 223: fprintf(stdout, "mark\n"); ! 224: ! 225: } /* End of header */ ! 226: ! 227: /*****************************************************************************/ ! 228: ! 229: options() ! 230: ! 231: { ! 232: ! 233: int ch; /* return value from getopt() */ ! 234: ! 235: /* ! 236: * ! 237: * Reads and processes the command line options. Added the -P option so arbitrary ! 238: * PostScript code can be passed through. Expect it could be useful for changing ! 239: * definitions in the prologue for which options have not been defined. ! 240: * ! 241: * Although any PostScript font can be used, things will only work well for ! 242: * constant width fonts. ! 243: * ! 244: */ ! 245: ! 246: while ( (ch = getopt(argc, argv, optnames)) != EOF ) { ! 247: switch ( ch ) { ! 248: ! 249: case 'a': /* aspect ratio */ ! 250: fprintf(stdout, "/aspectratio %s def\n", optarg); ! 251: break; ! 252: ! 253: case 'c': /* copies */ ! 254: copies = atoi(optarg); ! 255: fprintf(stdout, "/#copies %s store\n", optarg); ! 256: break; ! 257: ! 258: case 'e': /* obsolete - it's now always on */ ! 259: extended = TRUE; ! 260: break; ! 261: ! 262: case 'f': /* use this PostScript font */ ! 263: fontname = get_font(optarg); ! 264: fprintf(stdout, "/font /%s def\n", fontname); ! 265: break; ! 266: ! 267: case 'l': /* lines per page */ ! 268: linespp = atoi(optarg); ! 269: break; ! 270: ! 271: case 'm': /* magnification */ ! 272: fprintf(stdout, "/magnification %s def\n", optarg); ! 273: break; ! 274: ! 275: case 'n': /* forms per page */ ! 276: formsperpage = atoi(optarg); ! 277: fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg); ! 278: fprintf(stdout, "/formsperpage %s def\n", optarg); ! 279: break; ! 280: ! 281: case 'o': /* output page list */ ! 282: out_list(optarg); ! 283: break; ! 284: ! 285: case 'p': /* landscape or portrait mode */ ! 286: if ( *optarg == 'l' ) ! 287: fprintf(stdout, "/landscape true def\n"); ! 288: else fprintf(stdout, "/landscape false def\n"); ! 289: break; ! 290: ! 291: case 'r': /* carriage return mode */ ! 292: crmode = atoi(optarg); ! 293: break; ! 294: ! 295: case 's': /* point size */ ! 296: pointsize = atoi(optarg); ! 297: fprintf(stdout, "/pointsize %s def\n", optarg); ! 298: break; ! 299: ! 300: case 't': /* tabstops */ ! 301: tabstops = atoi(optarg); ! 302: break; ! 303: ! 304: case 'x': /* shift things horizontally */ ! 305: fprintf(stdout, "/xoffset %s def\n", optarg); ! 306: break; ! 307: ! 308: case 'y': /* and vertically on the page */ ! 309: fprintf(stdout, "/yoffset %s def\n", optarg); ! 310: break; ! 311: ! 312: case 'A': /* force job accounting */ ! 313: case 'J': ! 314: if ( (fp_acct = fopen(optarg, "a")) == NULL ) ! 315: error(FATAL, "can't open accounting file %s", optarg); ! 316: break; ! 317: ! 318: case 'C': /* copy file straight to output */ ! 319: if ( cat(optarg) == FALSE ) ! 320: error(FATAL, "can't read %s", optarg); ! 321: break; ! 322: ! 323: case 'E': /* text font encoding */ ! 324: fontencoding = optarg; ! 325: break; ! 326: ! 327: case 'L': /* PostScript prologue file */ ! 328: prologue = optarg; ! 329: break; ! 330: ! 331: case 'P': /* PostScript pass through */ ! 332: fprintf(stdout, "%s\n", optarg); ! 333: break; ! 334: ! 335: case 'R': /* special global or page level request */ ! 336: saverequest(optarg); ! 337: break; ! 338: ! 339: case 'D': /* debug flag */ ! 340: debug = ON; ! 341: break; ! 342: ! 343: case 'I': /* ignore FATAL errors */ ! 344: ignore = ON; ! 345: break; ! 346: ! 347: case '?': /* don't understand the option */ ! 348: error(FATAL, ""); ! 349: break; ! 350: ! 351: default: /* don't know what to do for ch */ ! 352: error(FATAL, "missing case for option %c\n", ch); ! 353: break; ! 354: } /* End switch */ ! 355: } /* End while */ ! 356: ! 357: argc -= optind; /* get ready for non-option args */ ! 358: argv += optind; ! 359: ! 360: } /* End of options */ ! 361: ! 362: /*****************************************************************************/ ! 363: ! 364: char *get_font(name) ! 365: ! 366: char *name; /* name the user asked for */ ! 367: ! 368: { ! 369: ! 370: int i; /* for looking through fontmap[] */ ! 371: ! 372: /* ! 373: * ! 374: * Called from options() to map a user's font name into a legal PostScript name. ! 375: * If the lookup fails *name is returned to the caller. That should let you choose ! 376: * any PostScript font, although things will only work well for constant width ! 377: * fonts. ! 378: * ! 379: */ ! 380: ! 381: for ( i = 0; fontmap[i].name != NULL; i++ ) ! 382: if ( strcmp(name, fontmap[i].name) == 0 ) ! 383: return(fontmap[i].val); ! 384: ! 385: return(name); ! 386: ! 387: } /* End of get_font */ ! 388: ! 389: /*****************************************************************************/ ! 390: ! 391: setup() ! 392: ! 393: { ! 394: ! 395: /* ! 396: * ! 397: * Handles things that must be done after the options are read but before the ! 398: * input files are processed. linespp (lines per page) can be set using the -l ! 399: * option. If it's not positive we calculate a reasonable value using the ! 400: * requested point size - assuming LINESPP lines fit on a page in point size ! 401: * POINTSIZE. ! 402: * ! 403: */ ! 404: ! 405: writerequest(0, stdout); /* global requests eg. manual feed */ ! 406: setencoding(fontencoding); ! 407: fprintf(stdout, "setup\n"); ! 408: ! 409: if ( formsperpage > 1 ) { ! 410: if ( cat(formfile) == FALSE ) ! 411: error(FATAL, "can't read %s", formfile); ! 412: fprintf(stdout, "%d setupforms\n", formsperpage); ! 413: } /* End if */ ! 414: ! 415: fprintf(stdout, "%s", ENDSETUP); ! 416: ! 417: if ( linespp <= 0 ) ! 418: linespp = LINESPP * POINTSIZE / pointsize; ! 419: ! 420: } /* End of setup */ ! 421: ! 422: /*****************************************************************************/ ! 423: ! 424: arguments() ! 425: ! 426: { ! 427: ! 428: /* ! 429: * ! 430: * Makes sure all the non-option command line arguments are processed. If we get ! 431: * here and there aren't any arguments left, or if '-' is one of the input files ! 432: * we'll translate stdin. ! 433: * ! 434: */ ! 435: ! 436: if ( argc < 1 ) ! 437: text(); ! 438: else { /* at least one argument is left */ ! 439: while ( argc > 0 ) { ! 440: if ( strcmp(*argv, "-") == 0 ) ! 441: fp_in = stdin; ! 442: else if ( (fp_in = fopen(*argv, "r")) == NULL ) ! 443: error(FATAL, "can't open %s", *argv); ! 444: text(); ! 445: if ( fp_in != stdin ) ! 446: fclose(fp_in); ! 447: argc--; ! 448: argv++; ! 449: } /* End while */ ! 450: } /* End else */ ! 451: ! 452: } /* End of arguments */ ! 453: ! 454: /*****************************************************************************/ ! 455: ! 456: done() ! 457: ! 458: { ! 459: ! 460: /* ! 461: * ! 462: * Finished with all the input files, so mark the end of the pages with a TRAILER ! 463: * comment, make sure the last page prints, and add things like the PAGES comment ! 464: * that can only be determined after all the input files have been read. ! 465: * ! 466: */ ! 467: ! 468: fprintf(stdout, "%s", TRAILER); ! 469: fprintf(stdout, "done\n"); ! 470: fprintf(stdout, "%s %s\n", DOCUMENTFONTS, fontname); ! 471: fprintf(stdout, "%s %d\n", PAGES, printed); ! 472: ! 473: } /* End of done */ ! 474: ! 475: /*****************************************************************************/ ! 476: ! 477: account() ! 478: ! 479: { ! 480: ! 481: /* ! 482: * ! 483: * Writes an accounting record to *fp_acct provided it's not NULL. Accounting is ! 484: * requested using the -A or -J options. ! 485: * ! 486: */ ! 487: ! 488: if ( fp_acct != NULL ) ! 489: fprintf(fp_acct, " print %d\n copies %d\n", printed, copies); ! 490: ! 491: } /* End of account */ ! 492: ! 493: /*****************************************************************************/ ! 494: ! 495: text() ! 496: ! 497: { ! 498: ! 499: int ch; /* next input character */ ! 500: ! 501: /* ! 502: * ! 503: * Translates *fp_in into PostScript. Intercepts space, tab, backspace, newline, ! 504: * return, and formfeed. Everything else goes to oput(), which handles quoting ! 505: * (if needed) and escapes for nonascii characters if extended is TRUE. The ! 506: * redirect(-1) call forces the initial output to go to /dev/null - so stuff ! 507: * that formfeed() does at the end of each page goes to /dev/null rather than ! 508: * the real output file. ! 509: * ! 510: */ ! 511: ! 512: redirect(-1); /* get ready for the first page */ ! 513: formfeed(); /* force PAGE comment etc. */ ! 514: ! 515: while ( (ch = getc(fp_in)) != EOF ) ! 516: switch ( ch ) { ! 517: case '\n': ! 518: newline(); ! 519: break; ! 520: ! 521: case '\t': ! 522: case '\b': ! 523: case ' ': ! 524: spaces(ch); ! 525: break; ! 526: ! 527: case '\014': ! 528: formfeed(); ! 529: break; ! 530: ! 531: case '\r': ! 532: if ( crmode == 1 ) ! 533: spaces(ch); ! 534: else if ( crmode == 2 ) ! 535: newline(); ! 536: break; ! 537: ! 538: default: ! 539: oput(ch); ! 540: break; ! 541: } /* End switch */ ! 542: ! 543: formfeed(); /* next file starts on a new page? */ ! 544: ! 545: } /* End of text */ ! 546: ! 547: /*****************************************************************************/ ! 548: ! 549: formfeed() ! 550: ! 551: { ! 552: ! 553: /* ! 554: * ! 555: * Called whenever we've finished with the last page and want to get ready for the ! 556: * next one. Also used at the beginning and end of each input file, so we have to ! 557: * be careful about what's done. The first time through (up to the redirect() call) ! 558: * output goes to /dev/null. ! 559: * ! 560: * Adobe now recommends that the showpage operator occur after the page level ! 561: * restore so it can be easily redefined to have side-effects in the printer's VM. ! 562: * Although it seems reasonable I haven't implemented it, because it makes other ! 563: * things, like selectively setting manual feed or choosing an alternate paper ! 564: * tray, clumsy - at least on a per page basis. ! 565: * ! 566: */ ! 567: ! 568: if ( fp_out == stdout ) /* count the last page */ ! 569: printed++; ! 570: ! 571: endline(); /* print the last line */ ! 572: ! 573: fprintf(fp_out, "cleartomark\n"); ! 574: fprintf(fp_out, "showpage\n"); ! 575: fprintf(fp_out, "saveobj restore\n"); ! 576: fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed); ! 577: ! 578: if ( ungetc(getc(fp_in), fp_in) == EOF ) ! 579: redirect(-1); ! 580: else redirect(++page); ! 581: ! 582: fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1); ! 583: fprintf(fp_out, "/saveobj save def\n"); ! 584: fprintf(fp_out, "mark\n"); ! 585: writerequest(printed+1, fp_out); ! 586: fprintf(fp_out, "%d pagesetup\n", printed+1); ! 587: ! 588: line = 1; ! 589: ! 590: } /* End of formfeed */ ! 591: ! 592: /*****************************************************************************/ ! 593: ! 594: newline() ! 595: ! 596: { ! 597: ! 598: /* ! 599: * ! 600: * Called when we've read a newline character. The call to startline() ensures ! 601: * that at least an empty string is on the stack. ! 602: * ! 603: */ ! 604: ! 605: startline(); ! 606: endline(); /* print the current line */ ! 607: ! 608: if ( ++line > linespp ) /* done with this page */ ! 609: formfeed(); ! 610: ! 611: } /* End of newline */ ! 612: ! 613: /*****************************************************************************/ ! 614: ! 615: spaces(ch) ! 616: ! 617: int ch; /* next input character */ ! 618: ! 619: { ! 620: ! 621: int endcol; /* ending column */ ! 622: int i; /* final distance - in spaces */ ! 623: ! 624: /* ! 625: * ! 626: * Counts consecutive spaces, tabs, and backspaces and figures out where the next ! 627: * string should start. Once that's been done we try to choose an efficient way ! 628: * to output the required number of spaces. The choice is between using procedure ! 629: * l with a single string on the stack and L with several string and column pairs. ! 630: * We usually break even, in terms of the size of the output file, if we need four ! 631: * consecutive spaces. More means using L decreases the size of the file. For now ! 632: * if there are less than 6 consecutive spaces we just add them to the current ! 633: * string, otherwise we end that string, follow it by its starting position, and ! 634: * begin a new one that starts at endcol. Backspacing is always handled this way. ! 635: * ! 636: */ ! 637: ! 638: startline(); /* so col makes sense */ ! 639: endcol = col; ! 640: ! 641: do { ! 642: if ( ch == ' ' ) ! 643: endcol++; ! 644: else if ( ch == '\t' ) ! 645: endcol += tabstops - ((endcol - 1) % tabstops); ! 646: else if ( ch == '\b' ) ! 647: endcol--; ! 648: else if ( ch == '\r' ) ! 649: endcol = 1; ! 650: else break; ! 651: } while ( ch = getc(fp_in) ); /* if ch is 0 we'd quit anyway */ ! 652: ! 653: ungetc(ch, fp_in); /* wasn't a space, tab, or backspace */ ! 654: ! 655: if ( endcol < 1 ) /* can't move past left edge */ ! 656: endcol = 1; ! 657: ! 658: if ( (i = endcol - col) >= 0 && i < 6 ) ! 659: for ( ; i > 0; i-- ) ! 660: oput((int)' '); ! 661: else { ! 662: endstring(); ! 663: col = stringstart = endcol; ! 664: } /* End else */ ! 665: ! 666: } /* End of spaces */ ! 667: ! 668: /*****************************************************************************/ ! 669: ! 670: startline() ! 671: ! 672: { ! 673: ! 674: /* ! 675: * ! 676: * Called whenever we want to be certain we're ready to start pushing characters ! 677: * into an open string on the stack. If stringcount is positive we've already ! 678: * started, so there's nothing to do. The first string starts in column 1. ! 679: * ! 680: */ ! 681: ! 682: if ( stringcount < 1 ) { ! 683: putc('(', fp_out); ! 684: stringstart = col = 1; ! 685: stringcount = 1; ! 686: } /* End if */ ! 687: ! 688: } /* End of startline */ ! 689: ! 690: /*****************************************************************************/ ! 691: ! 692: endstring() ! 693: ! 694: { ! 695: ! 696: /* ! 697: * ! 698: * End the current string and start a new one. ! 699: * ! 700: */ ! 701: ! 702: if ( stringcount > 100 ) { /* don't put too much on the stack */ ! 703: fprintf(fp_out, ")%d LL\n(", stringstart-1); ! 704: stringcount = 2; /* kludge - don't let endline() use l */ ! 705: } else { ! 706: fprintf(fp_out, ")%d(", stringstart-1); ! 707: stringcount++; ! 708: } /* End else */ ! 709: ! 710: } /* End of endstring */ ! 711: ! 712: /*****************************************************************************/ ! 713: ! 714: endline() ! 715: ! 716: { ! 717: ! 718: /* ! 719: * ! 720: * Generates a call to the PostScript procedure that processes all the text on ! 721: * the stack - provided stringcount is positive. If one string is on the stack ! 722: * the fast procedure (ie. l) is used to print the line, otherwise the slower ! 723: * one that processes string and column pairs is used. ! 724: * ! 725: */ ! 726: ! 727: if ( stringcount == 1 ) ! 728: fprintf(fp_out, ")l\n"); ! 729: else if ( stringcount > 1 ) ! 730: fprintf(fp_out, ")%d L\n", stringstart-1); ! 731: ! 732: stringcount = 0; ! 733: ! 734: } /* End of endline */ ! 735: ! 736: /*****************************************************************************/ ! 737: ! 738: oput(ch) ! 739: ! 740: int ch; /* next output character */ ! 741: ! 742: { ! 743: ! 744: /* ! 745: * ! 746: * Responsible for adding all printing characters from the input file to the ! 747: * open string on top of the stack. ! 748: * ! 749: */ ! 750: ! 751: if ( isascii(ch) && isprint(ch) ) { ! 752: startline(); ! 753: if ( ch == '(' || ch == ')' || ch == '\\' ) ! 754: putc('\\', fp_out); ! 755: putc(ch, fp_out); ! 756: col++; ! 757: } else if ( extended == TRUE ) { ! 758: startline(); ! 759: fprintf(fp_out, "\\%.3o", ch & 0377); ! 760: col++; ! 761: } /* End if */ ! 762: ! 763: } /* End of oput */ ! 764: ! 765: /*****************************************************************************/ ! 766: ! 767: redirect(pg) ! 768: ! 769: int pg; /* next page we're printing */ ! 770: ! 771: { ! 772: ! 773: static FILE *fp_null = NULL; /* if output is turned off */ ! 774: ! 775: /* ! 776: * ! 777: * If we're not supposed to print page pg, fp_out will be directed to /dev/null, ! 778: * otherwise output goes to stdout. ! 779: * ! 780: */ ! 781: ! 782: if ( pg >= 0 && in_olist(pg) == ON ) ! 783: fp_out = stdout; ! 784: else if ( (fp_out = fp_null) == NULL ) ! 785: fp_out = fp_null = fopen("/dev/null", "w"); ! 786: ! 787: } /* End of redirect */ ! 788: ! 789: /*****************************************************************************/ ! 790:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.