Annotation of researchv10no/cmd/postscript/postprint/Lpostprint.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.