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