Annotation of researchv10no/cmd/postscript/dpost/odpost.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *
        !             3:  * dpost - troff post-processor for PostScript printers.
        !             4:  *
        !             5:  * A program that translates output generated by the device independent troff
        !             6:  * into PostScript. Much was borrowed from dimpress and dps (formally dlzw),
        !             7:  * and even though the code has changed, credit has to be given to Richard
        !             8:  * Flood for his early work on the PostScript driver.
        !             9:  *
        !            10:  * The big change is in the font table routines. The old binary format and
        !            11:  * makedev are gone. dpost and troff now read ASCII tables, and both skip
        !            12:  * unrecognized entries in the ASCII tables. That means problems, like where
        !            13:  * to put the real name of the PostScript font, have disappeared. The added
        !            14:  * flexibility means some overhead translating the ASCII tables, but the
        !            15:  * overhead isn't too bad.
        !            16:  *
        !            17:  * dpost can also now calculate a reasonably tight BoundingBox, which helps
        !            18:  * picture inclusion. The calculations, by default, are disabled. Couldn't
        !            19:  * justify the overhead for a comment, particularly one that's only needed
        !            20:  * occasionally. Use the -B option to get the comment.
        !            21:  *
        !            22:  * Output produced by dpost is still nonconforming. Definitions made in pages
        !            23:  * and exported to the job's global environment are the primary problem. It's
        !            24:  * an efficient approach, but means pages are not independent. Violations are
        !            25:  * bracketed by %%BeginGlobal and %%EndGlobal comments and can be pulled into
        !            26:  * the prologue by utility programs (like postreverse) that recognize the new
        !            27:  * comments.
        !            28:  *
        !            29:  * The program handles files formatted for any device, although the best and
        !            30:  * most efficient output is generated when the font and description files
        !            31:  * match PostScript's resident fonts. Emulation is relatively expensive, and
        !            32:  * can produce output files that are more than twice the size of the input
        !            33:  * files.
        !            34:  *
        !            35:  * Several different methods can be used to encode lines of text. What's done
        !            36:  * depends on the value assigned to encoding. Print time should decrease as
        !            37:  * encoding increases (up to MAXENCODING). Setting encoding to 3 (or higher)
        !            38:  * is not normally recommended. It's fast and produces very compact output,
        !            39:  * but rounding errors in troff's width tables can accumulate and lead to a
        !            40:  * ragged right margin. encoding can be changed on the command line using the
        !            41:  * -e option.
        !            42:  *
        !            43:  * PostScript fonts don't support all of troff's characters. Some are built
        !            44:  * by special PostScript procedures in directory *fontdir/devpost/charlib.
        !            45:  * The charlib approach is not meant to replace user defined fonts. It was
        !            46:  * a quick implementation designed to handle characters that aren't used
        !            47:  * often - charlib should not be overused! The charlib lookup is triggered
        !            48:  * when a character in a font table is assigned a code less than 32.
        !            49:  *
        !            50:  * Most defaults are set in the prologue, but can be changed by options. The
        !            51:  * -P option passes arbitrary PostScript into the setup section of the output
        !            52:  * file. It can be used to set (or change) values that can't be accessed by
        !            53:  * other options. For example,
        !            54:  *
        !            55:  *     dpost -P'/useclippath false def' file > file.ps
        !            56:  *
        !            57:  * defines useclippath to be false. Everything passed through using the -P
        !            58:  * (-C to copy a file) options become part of the job's global environment.
        !            59:  * Definitions override defaults in the prologue.
        !            60:  *
        !            61:  * dpost expects to find the following procedures in the prologue:
        !            62:  *
        !            63:  *     setup
        !            64:  *
        !            65:  *       mark ... setup -
        !            66:  *
        !            67:  *         Initialization procedure mainly responsible for setting up an
        !            68:  *         appropriate coordinate system.
        !            69:  *
        !            70:  *     pagesetup
        !            71:  *
        !            72:  *       page pagesetup -
        !            73:  *
        !            74:  *         Called at the start of each page, immediately after the page
        !            75:  *         level save. Argument is the current page number.
        !            76:  *
        !            77:  *     setdecoding
        !            78:  *
        !            79:  *       num setdecoding -
        !            80:  *
        !            81:  *         Select the decoding procedure used to print text strings encoded
        !            82:  *         by dpost. num is whatever has been assigned to encoding.
        !            83:  *
        !            84:  *     f
        !            85:  *
        !            86:  *       size font f -
        !            87:  *
        !            88:  *         Set the font and size used for character imaging. The font name
        !            89:  *         argument is (normally) the name troff used. Mapping to the real
        !            90:  *         PostScript font name is made using the fontname field in the
        !            91:  *         ASCII width tables.
        !            92:  *
        !            93:  *     m
        !            94:  *
        !            95:  *       x y m -
        !            96:  *
        !            97:  *         Move to point (x, y). Not used for positioning words in text
        !            98:  *         strings.
        !            99:  *
        !           100:  *     t
        !           101:  *
        !           102:  *       mark text t mark
        !           103:  *
        !           104:  *         Everything on the stack (up to the mark) is treated as a line
        !           105:  *         of text to be decoded and printed. What's on the stack depends
        !           106:  *         on encoding.
        !           107:  *
        !           108:  *     w
        !           109:  *
        !           110:  *       string x y w -
        !           111:  *
        !           112:  *         Print a single word starting at position (x, y). Only used in
        !           113:  *         the more complicated encoding schemes, like the ones based on
        !           114:  *         widthshow.
        !           115:  *
        !           116:  *     done
        !           117:  *
        !           118:  *         Make sure the last page prints. Always called, but only needed
        !           119:  *         when printing more than one page on each sheet of paper.
        !           120:  *
        !           121:  * output language from troff:
        !           122:  * all numbers are character strings
        !           123:  * 
        !           124:  * sn  size in points
        !           125:  * fn  font as number from 1-n
        !           126:  * cx  ascii character x
        !           127:  * Cxyz        funny char xyz. terminated by white space
        !           128:  * Hn  go to absolute horizontal position n
        !           129:  * Vn  go to absolute vertical position n (down is positive)
        !           130:  * hn  go n units horizontally (relative)
        !           131:  * vn  ditto vertically
        !           132:  * nnc move right nn, then print c (exactly 2 digits!)
        !           133:  *             (this wart is an optimization that shrinks output file size
        !           134:  *              about 35% and run-time about 15% while preserving ascii-ness)
        !           135:  * Dt ...\n    draw operation 't':
        !           136:  *     Dl x y          line from here by x,y
        !           137:  *     Dc d            circle of diameter d with left side here
        !           138:  *     De x y          ellipse of axes x,y with left side here
        !           139:  *     Da x1 y1 x2 y2  arc counter-clockwise from current point (x, y) to
        !           140:  *                     (x + x1 + x2, y + y1 + y2)
        !           141:  *     D~ x y x y ...  wiggly line by x,y then x,y ...
        !           142:  * nb a        end of line (information only -- no action needed)
        !           143:  *     b = space before line, a = after
        !           144:  * p   new page begins -- set v to 0
        !           145:  * #...\n      comment
        !           146:  * x ...\n     device control functions:
        !           147:  *     x i     init
        !           148:  *     x T s   name of device is s
        !           149:  *     x r n h v       resolution is n/inch
        !           150:  *             h = min horizontal motion, v = min vert
        !           151:  *     x p     pause (can restart)
        !           152:  *     x s     stop -- done forever
        !           153:  *     x t     generate trailer
        !           154:  *     x f n s font position n contains font s
        !           155:  *     x H n   set character height to n
        !           156:  *     x S n   set slant to N
        !           157:  * 
        !           158:  *     Subcommands like "i" are often spelled out like "init".
        !           159:  *
        !           160:  */
        !           161: 
        !           162: #include       <stdio.h>
        !           163: #include       <fcntl.h>
        !           164: #include       <signal.h>
        !           165: #include       <math.h>
        !           166: #include       <ctype.h>
        !           167: #include       <time.h>
        !           168: 
        !           169: #include       "comments.h"            /* structuring comments */
        !           170: #include       "gen.h"                 /* general purpose definitions */
        !           171: #include       "path.h"                /* prologue and a few other files */
        !           172: #include       "ext.h"                 /* external variable declarations */
        !           173: #include       "font.h"                /* font table definitions */
        !           174: #include       "dpost.h"               /* a few definitions just used here */
        !           175: #include       "motion.h"              /* positioning macros */
        !           176: 
        !           177: char   *prologue = DPOST;              /* the PostScript prologue */
        !           178: char   *colorfile = COLOR;             /* color support */
        !           179: char   *drawfile = DRAW;               /* drawing routines */
        !           180: char   *formfile = FORMFILE;           /* multiple pages on each sheet */
        !           181: char   *baselinefile = BASELINE;       /* for text along curved baseline */
        !           182: 
        !           183: char   *fontdir = FONTDIR;             /* font table directories */
        !           184: char   *hostfontdir = NULL;            /* host resident font directory */
        !           185: 
        !           186: char   *realdev = DEVNAME;             /* use these width tables */
        !           187: char   devname[20] = "";               /* job formatted for this device */
        !           188: Fontmap        fontmap[] = FONTMAP;            /* font translation table - emulation */
        !           189: char   *useencoding = NULL;            /* text font encoding - from -E option */
        !           190: 
        !           191: int    copies = 1;                     /* copies of each sheet */
        !           192: int    printed = 0;                    /* pages processed and printed */
        !           193: int    formsperpage = 1;               /* pages on each sheet of paper */
        !           194: int    picflag = ON;                   /* enable/disable picture inclusion */
        !           195: 
        !           196: int    encoding = DFLTENCODING;        /* how text is translated to PostScript */
        !           197: int    realencoding = DFLTENCODING;    /* where we started */
        !           198: int    maxencoding = MAXENCODING;      /* max that users can select */
        !           199: 
        !           200: int    landscape = FALSE;              /* for BoundingBox calculations only */
        !           201: double magnification = 1.0;
        !           202: double xoffset = 0.0;
        !           203: double yoffset = 0.0;
        !           204: 
        !           205: int    smnt;                           /* special fonts start here */
        !           206: int    devres;                         /* device resolution */
        !           207: int    unitwidth;                      /* and unitwidth - from DESC file */
        !           208: 
        !           209: char   downloaded[MAXCH+32+ALPHABET];  /* status of charlib characters */
        !           210: 
        !           211: int    nfonts = 0;                     /* number of font positions */
        !           212: int    size = 10;                      /* current point size */
        !           213: int    font = 0;                       /* and font position */
        !           214: int    hpos = 0;                       /* where troff wants to be */
        !           215: int    vpos = 0;
        !           216: float  lastw = 0;                      /* width of the last input character */
        !           217: int    lastc = 0;                      /* its name (or index) - for charlib() */
        !           218: 
        !           219: int    fontheight = 0;                 /* points from x H ... */
        !           220: int    fontslant = 0;                  /* angle from x S ... */
        !           221: 
        !           222: int    res;                            /* resolution assumed in input file */
        !           223: float  widthfac = 1.0;                 /* for emulation = res/devres */
        !           224: 
        !           225: int    lastsize = -1;                  /* for tracking printer's current size */
        !           226: int    lastfont = -1;                  /* current font */
        !           227: float  lastx = -1;                     /* and current position */
        !           228: int    lasty = -1;
        !           229: int    lastend;                        /* where last character on this line was */
        !           230: 
        !           231: int    seenpage = FALSE;               /* expect fonts are now all mounted */
        !           232: int    gotspecial = FALSE;             /* append special fonts - emulation */
        !           233: 
        !           234: float  pointslop = SLOP;               /* horizontal error in points */
        !           235: int    slop;                           /* and machine units */
        !           236: int    rvslop;                         /* to extend box in reverse video mode */
        !           237: 
        !           238: int    textcount = 0;                  /* strings accumulated so far */
        !           239: int    stringstart = 0;                /* where the next one starts */
        !           240: int    spacecount = 0;                 /* spaces in current string */
        !           241: 
        !           242: Line   line[MAXSTACK+3];               /* data about words accumulated so far */
        !           243: char   strings[STRINGSPACE];           /* strings temporarily saved here */
        !           244: char   *strptr;                        /* next free slot in strings[] */
        !           245: 
        !           246: FILE   *tf = NULL;                     /* most output goes here */
        !           247: FILE   *fp_acct = NULL;                /* accounting file */
        !           248: 
        !           249: char   *optnames = "a:c:e:m:n:o:p:tw:x:y:A:BC:E:J:F:H:L:OP:R:S:T:DI";
        !           250: 
        !           251: extern int     gotcolor;               /* read *colorfile when TRUE */
        !           252: extern Font    fonts[];                /* data about every font we see */
        !           253: extern Font    *mount[];               /* troff mounts fonts here */
        !           254: 
        !           255: /*****************************************************************************/
        !           256: 
        !           257: main(agc, agv)
        !           258: 
        !           259:     int                agc;
        !           260:     char       *agv[];
        !           261: 
        !           262: {
        !           263: 
        !           264: /*
        !           265:  *
        !           266:  * Translates output from troff into PostScript. Input files must be formatted
        !           267:  * for the same device. Each input file begins on a new page.
        !           268:  *
        !           269:  */
        !           270: 
        !           271:     argc = agc;                                /* global so everyone can use them */
        !           272:     argv = agv;
        !           273: 
        !           274:     prog_name = argv[0];               /* for error messages */
        !           275: 
        !           276:     init_signals();                    /* interrupt handling */
        !           277:     header();                          /* structuring comments */
        !           278:     options();                         /* command line options */
        !           279:     arguments();                       /* translate the input files */
        !           280:     done();                            /* add trailing comments etc. */
        !           281:     account();                         /* job accounting data */
        !           282: 
        !           283:     exit(x_stat);
        !           284: 
        !           285: }   /* End of main */
        !           286: 
        !           287: /*****************************************************************************/
        !           288: 
        !           289: init_signals()
        !           290: 
        !           291: {
        !           292: 
        !           293: /*
        !           294:  *
        !           295:  * Make sure we handle interrupts.
        !           296:  *
        !           297:  */
        !           298: 
        !           299:     if ( signal(SIGINT, interrupt) == SIG_IGN ) {
        !           300:        signal(SIGINT, SIG_IGN);
        !           301:        signal(SIGQUIT, SIG_IGN);
        !           302:        signal(SIGHUP, SIG_IGN);
        !           303:     } else {
        !           304:        signal(SIGHUP, interrupt);
        !           305:        signal(SIGQUIT, interrupt);
        !           306:     }   /* End else */
        !           307: 
        !           308:     signal(SIGTERM, interrupt);
        !           309: 
        !           310: }   /* End of init_signals */
        !           311: 
        !           312: /*****************************************************************************/
        !           313: 
        !           314: header()
        !           315: 
        !           316: {
        !           317: 
        !           318:     int                ch;
        !           319:     int                old_optind = optind;
        !           320: 
        !           321: /*
        !           322:  *
        !           323:  * Scan the option list for things needed now (e.g. prologue file), but could
        !           324:  * be changed from defaults. An attempt to follow to Adobe's 2.0 structuring
        !           325:  * conventions.
        !           326:  *
        !           327:  */
        !           328: 
        !           329:     while ( (ch = getopt(argc, argv, optnames)) != EOF )
        !           330:        if ( ch == 'L' )
        !           331:            setpaths(optarg);
        !           332:        else if ( ch == 'B' )
        !           333:            dobbox = TRUE;
        !           334:        else if ( ch == '?' )
        !           335:            error(FATAL, "");
        !           336: 
        !           337:     optind = old_optind;               /* restored for options() */
        !           338: 
        !           339:     fprintf(stdout, "%s", NONCONFORMING);
        !           340:     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
        !           341:     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND);
        !           342:     fprintf(stdout, "%s %s\n", PAGES, ATEND);
        !           343:     if ( dobbox == TRUE )
        !           344:        fprintf(stdout, "%s %s\n", BOUNDINGBOX, ATEND);
        !           345:     fprintf(stdout, "%s", ENDCOMMENTS);
        !           346: 
        !           347:     if ( cat(prologue) == FALSE )
        !           348:        error(FATAL, "can't read %s", prologue);
        !           349: 
        !           350:     if ( DOROUND )
        !           351:        cat(ROUNDPAGE);
        !           352: 
        !           353:     fprintf(stdout, "%s", ENDPROLOG);
        !           354:     fprintf(stdout, "%s", BEGINSETUP);
        !           355:     fprintf(stdout, "mark\n");
        !           356: 
        !           357: }   /* End of header */
        !           358: 
        !           359: /*****************************************************************************/
        !           360: 
        !           361: options()
        !           362: 
        !           363: {
        !           364: 
        !           365:     int                ch;
        !           366: 
        !           367:     extern char        *optarg;
        !           368:     extern int optind;
        !           369: 
        !           370: /*
        !           371:  *
        !           372:  * Command line options - there are too many!
        !           373:  *
        !           374:  */
        !           375: 
        !           376:     while ( (ch = getopt(argc, argv, optnames)) != EOF ) {
        !           377:        switch ( ch ) {
        !           378:            case 'a':                   /* aspect ratio */
        !           379:                    fprintf(stdout, "/aspectratio %s def\n", optarg);
        !           380:                    break;
        !           381: 
        !           382:            case 'c':                   /* number of copies */
        !           383:                    copies = atoi(optarg);
        !           384:                    fprintf(stdout, "/#copies %s store\n", optarg);
        !           385:                    break;
        !           386: 
        !           387:            case 'e':                   /* select the encoding scheme */
        !           388:                    if ( (encoding = atoi(optarg)) < 0 || encoding > MAXENCODING )
        !           389:                        encoding = DFLTENCODING;
        !           390:                    realencoding = encoding;
        !           391:                    break;
        !           392: 
        !           393:            case 'm':                   /* magnification */
        !           394:                    magnification = atof(optarg);
        !           395:                    fprintf(stdout, "/magnification %s def\n", optarg);
        !           396:                    break;
        !           397: 
        !           398:            case 'n':                   /* forms per page */
        !           399:                    formsperpage = atoi(optarg);
        !           400:                    fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
        !           401:                    fprintf(stdout, "/formsperpage %s def\n", optarg);
        !           402:                    break;
        !           403: 
        !           404:            case 'o':                   /* output page list */
        !           405:                    out_list(optarg);
        !           406:                    break;
        !           407: 
        !           408:            case 'p':                   /* landscape or portrait mode */
        !           409:                    landscape = (*optarg == 'l') ? TRUE : FALSE;
        !           410:                    if ( landscape == TRUE )
        !           411:                        fprintf(stdout, "/landscape true def\n");
        !           412:                    else fprintf(stdout, "/landscape false def\n");
        !           413:                    break;
        !           414: 
        !           415:            case 't':                   /* compatibility */
        !           416:                    break;
        !           417: 
        !           418:            case 'w':                   /* line width - for drawing */
        !           419:                    fprintf(stdout, "/linewidth %s def\n", optarg);
        !           420:                    break;
        !           421: 
        !           422:            case 'x':                   /* shift horizontally */
        !           423:                    xoffset = atof(optarg);
        !           424:                    fprintf(stdout, "/xoffset %s def\n", optarg);
        !           425:                    break;
        !           426: 
        !           427:            case 'y':                   /* shift vertically */
        !           428:                    yoffset = atof(optarg);
        !           429:                    fprintf(stdout, "/yoffset %s def\n", optarg);
        !           430:                    break;
        !           431: 
        !           432:            case 'A':                   /* job accounting */
        !           433:            case 'J':
        !           434:                    if ( (fp_acct = fopen(optarg, "a")) == NULL )
        !           435:                        error(FATAL, "can't open accounting file %s", optarg);
        !           436:                    break;
        !           437: 
        !           438:            case 'B':                   /* enable BoundingBox calculations */
        !           439:                    dobbox = TRUE;
        !           440:                    fprintf(stdout, "/rotation 1 def\n");
        !           441:                    fprintf(stdout, "/gotpagebbox true def\n");
        !           442:                    break;
        !           443: 
        !           444:            case 'C':                   /* copy file to output */
        !           445:                    if ( cat(optarg) == FALSE )
        !           446:                        error(FATAL, "can't read %s", optarg);
        !           447:                    break;
        !           448: 
        !           449:            case 'E':                   /* text font encoding - override DESC */
        !           450:                    useencoding = optarg;
        !           451:                    break;
        !           452: 
        !           453:            case 'F':                   /* font table directory */
        !           454:                    fontdir = optarg;
        !           455:                    break;
        !           456: 
        !           457:            case 'H':                   /* host resident font directory */
        !           458:                    hostfontdir = optarg;
        !           459:                    break;
        !           460: 
        !           461:            case 'L':                   /* prologue file */
        !           462:                    setpaths(optarg);   /* already been done in header() */
        !           463:                    break;
        !           464: 
        !           465:            case 'O':                   /* disable picture inclusion */
        !           466:                    picflag = OFF;
        !           467:                    break;
        !           468: 
        !           469:            case 'P':                   /* copy string to output */
        !           470:                    fprintf(stdout, "%s\n", optarg);
        !           471:                    break;
        !           472: 
        !           473:            case 'R':                   /* global or page level request */
        !           474:                    saverequest(optarg);
        !           475:                    break;
        !           476: 
        !           477:            case 'S':                   /* horizontal position error */
        !           478:                    if ( (pointslop = atof(optarg)) < 0 )
        !           479:                        pointslop = 0;
        !           480:                    break;
        !           481: 
        !           482:            case 'T':                   /* target printer */
        !           483:                    realdev = optarg;
        !           484:                    break;
        !           485: 
        !           486:            case 'D':                   /* debug flag */
        !           487:                    debug = ON;
        !           488:                    tf = stdout;
        !           489:                    break;
        !           490: 
        !           491:            case 'I':                   /* ignore FATAL errors */
        !           492:                    ignore = ON;
        !           493:                    break;
        !           494: 
        !           495:            case '?':                   /* don't know the option */
        !           496:                    error(FATAL, "");
        !           497:                    break;
        !           498: 
        !           499:            default:
        !           500:                    error(FATAL, "missing case for option %c", ch);
        !           501:                    break;
        !           502:        }   /* End switch */
        !           503:     }  /* End while */
        !           504: 
        !           505:     argc -= optind;
        !           506:     argv += optind;
        !           507: 
        !           508: }   /* End of options */
        !           509: 
        !           510: /*****************************************************************************/
        !           511: 
        !           512: setpaths(name)
        !           513: 
        !           514:     char       *name;
        !           515: 
        !           516: {
        !           517: 
        !           518:     char       *path;
        !           519: 
        !           520: /*
        !           521:  *
        !           522:  * Extends the -L option to permit modification of more than just the prologue
        !           523:  * file pathname. Syntax is -Lpath or -Lname:path. For debugging and development
        !           524:  * only!
        !           525:  *
        !           526:  */
        !           527: 
        !           528:     for ( path = name; *path; path++ )
        !           529:        if ( *path == ':' || *path == ' ' ) {
        !           530:            while ( *path == ':' || *path == ' ' ) path++;
        !           531:            break;
        !           532:        }   /* End if */
        !           533: 
        !           534:     if ( *path == '\0' )               /* didn't find "name:" prefix */
        !           535:        path = name;
        !           536: 
        !           537:     if ( path == name || strncmp(name, "prologue", strlen("prologue")) == 0 )
        !           538:        prologue = path;
        !           539:     else if ( strncmp(name, "draw", strlen("draw")) == 0 )
        !           540:        drawfile = path;
        !           541:     else if ( strncmp(name, "color", strlen("color")) == 0 )
        !           542:        colorfile = path;
        !           543:     else if ( strncmp(name, "form", strlen("form")) == 0 )
        !           544:        formfile = path;
        !           545:     else if ( strncmp(name, "baseline", strlen("baseline")) == 0 )
        !           546:        baselinefile = path;
        !           547: 
        !           548: }   /* End of setpaths */
        !           549: 
        !           550: /*****************************************************************************/
        !           551: 
        !           552: setup()
        !           553: 
        !           554: {
        !           555: 
        !           556:     double     t;
        !           557: 
        !           558: /*
        !           559:  *
        !           560:  * Job and BoundingBox initialization. Called once from t_init() - must know
        !           561:  * the resolution before generating the PostScript call to setup. dpost only
        !           562:  * includes an encoding file if it's set in the DESC file or requested with
        !           563:  * the -E option.
        !           564:  *
        !           565:  */
        !           566: 
        !           567:     writerequest(0, stdout);           /* global requests e.g. manual feed */
        !           568:     fprintf(stdout, "/resolution %d def\n", res);
        !           569:     if ( useencoding != NULL || fontencoding != NULL )
        !           570:        setencoding((useencoding != NULL) ? useencoding : fontencoding);
        !           571:     fprintf(stdout, "setup\n");
        !           572:     fprintf(stdout, "%d setdecoding\n", realencoding);
        !           573: 
        !           574:     if ( formsperpage > 1 ) {          /* multiple pages */
        !           575:        if ( cat(formfile) == FALSE )
        !           576:            error(FATAL, "can't read %s", formfile);
        !           577:        fprintf(stdout, "%d setupforms\n", formsperpage);
        !           578:     }  /* End if */
        !           579: 
        !           580:     fprintf(stdout, "%s", ENDSETUP);
        !           581: 
        !           582:     if ( dobbox == TRUE ) {            /* ctm[] - must agree with prologue */
        !           583:        translate(pagewidth/2.0, pageheight/2.0);
        !           584:        if ( landscape == TRUE ) {
        !           585:            rotate(90.0);
        !           586:            t = pagewidth;
        !           587:            pagewidth = pageheight;
        !           588:            pageheight = t;
        !           589:        }   /* End if */
        !           590:        translate(-pagewidth/2.0, pageheight/2.0);
        !           591:        translate(72.0 * xoffset, -72.0 * yoffset);
        !           592:        scale(magnification, magnification);
        !           593:        scale(72.0/devres, 72.0/devres);
        !           594:     }  /* End if */
        !           595: 
        !           596: }   /* End of setup */
        !           597: 
        !           598: /*****************************************************************************/
        !           599: 
        !           600: arguments()
        !           601: 
        !           602: {
        !           603: 
        !           604:     FILE       *fp;
        !           605: 
        !           606: /*
        !           607:  *
        !           608:  * Everything else is an input file. No arguments or '-' means stdin.
        !           609:  *
        !           610:  */
        !           611: 
        !           612:     if ( argc < 1 )
        !           613:        conv(stdin);
        !           614:     else
        !           615:        while ( argc > 0 ) {
        !           616:            if ( strcmp(*argv, "-") == 0 )
        !           617:                fp = stdin;
        !           618:            else if ( (fp = fopen(*argv, "r")) == NULL )
        !           619:                error(FATAL, "can't open %s", *argv);
        !           620:            conv(fp);
        !           621:            if ( fp != stdin )
        !           622:                fclose(fp);
        !           623:            argc--;
        !           624:            argv++;
        !           625:        }   /* End while */
        !           626: 
        !           627: }   /* End of arguments */
        !           628: 
        !           629: /*****************************************************************************/
        !           630: 
        !           631: done()
        !           632: 
        !           633: {
        !           634: 
        !           635:     int                i;
        !           636:     int                n;
        !           637: 
        !           638: /*
        !           639:  *
        !           640:  * Force out the last page and add trailing comments.
        !           641:  *
        !           642:  */
        !           643: 
        !           644:     fprintf(stdout, "%s", TRAILER);
        !           645:     fprintf(stdout, "done\n");
        !           646:     fprintf(stdout, "%s %d\n", PAGES, printed);
        !           647: 
        !           648:     for ( i = 0, n = 0; i < MAXFONTS+1; i++ )
        !           649:        if ( (fonts[i].flags & USED) && fonts[i].fontname != NULL ) {
        !           650:            if ( n++ == 0 )
        !           651:                fprintf(stdout, "%s", DOCUMENTFONTS);
        !           652:            else if ( (n - 1) % 8 == 0 )
        !           653:                fprintf(stdout, "\n%s", CONTINUECOMMENT);
        !           654:            fprintf(stdout, " %s", fonts[i].fontname);
        !           655:        }   /* End if */
        !           656:     if ( n > 0 )
        !           657:        putc('\n', stdout);
        !           658: 
        !           659:     if ( dobbox == TRUE )
        !           660:        writebbox(stdout, BOUNDINGBOX, 10);
        !           661: 
        !           662: }   /* End of done */
        !           663: 
        !           664: /*****************************************************************************/
        !           665: 
        !           666: account()
        !           667: 
        !           668: {
        !           669: 
        !           670: /*
        !           671:  *
        !           672:  * Accounting record to fp_acct - provided it's not NULL.
        !           673:  *
        !           674:  */
        !           675: 
        !           676:     if ( fp_acct != NULL )
        !           677:        fprintf(fp_acct, " print %d\n copies %d\n", printed, copies);
        !           678: 
        !           679: }   /* End of account */
        !           680: 
        !           681: /*****************************************************************************/
        !           682: 
        !           683: conv(fp)
        !           684: 
        !           685:     register FILE      *fp;
        !           686: 
        !           687: {
        !           688: 
        !           689:     register int       c;
        !           690:     int                        m, n, n1, m1;
        !           691:     char               str[50];
        !           692: 
        !           693: /*
        !           694:  *
        !           695:  * Read troff output from file fp and translate it into PostScript. The final
        !           696:  * t_page() call means input files start on a new page.
        !           697:  *
        !           698:  */
        !           699: 
        !           700:     redirect(-1);                      /* do output only after a page command */
        !           701:     lineno = 1;
        !           702: 
        !           703:     while ((c = getc(fp)) != EOF) {
        !           704:        switch (c) {
        !           705:            case '\n':                  /* just count this line */
        !           706:                    lineno++;
        !           707:                    break;
        !           708: 
        !           709:            case ' ':                   /* when input is text */
        !           710:            case 0:                     /* occasional noise creeps in */
        !           711:                    break;
        !           712: 
        !           713:            case '0': case '1': case '2': case '3': case '4':
        !           714:            case '5': case '6': case '7': case '8': case '9':
        !           715:                    /* two motion digits plus a character */
        !           716:                    hmot((c-'0')*10 + getc(fp)-'0');
        !           717:                    put1(getc(fp));
        !           718:                    break;
        !           719: 
        !           720:            case 'c':                   /* single ascii character */
        !           721:                    put1(getc(fp));
        !           722:                    break;
        !           723: 
        !           724:            case 'C':                   /* special character */
        !           725:                    fscanf(fp, "%s", str);
        !           726:                    put1(chindex(str));
        !           727:                    break;
        !           728: 
        !           729:            case 'N':                   /* character at position n */
        !           730:                    fscanf(fp, "%d", &m);
        !           731:                    flushtext();
        !           732:                    oput(m);
        !           733:                    break;
        !           734: 
        !           735:            case 'D':                   /* drawing functions */
        !           736:                    flushtext();
        !           737:                    getdraw();
        !           738:                    if ( size != lastsize )
        !           739:                        t_sf();
        !           740:                    switch ((c=getc(fp))) {
        !           741:                        case 'p':       /* draw a path */
        !           742:                            while (fscanf(fp, "%d %d", &n, &m) == 2)
        !           743:                                drawline(n, m);
        !           744:                            lineno++;
        !           745:                            break;
        !           746: 
        !           747:                        case 'l':       /* draw a line */
        !           748:                            fscanf(fp, "%d %d %c", &n, &m, &n1);
        !           749:                            drawline(n, m);
        !           750:                            break;
        !           751: 
        !           752:                        case 'c':       /* circle */
        !           753:                            fscanf(fp, "%d", &n);
        !           754:                            drawcirc(n);
        !           755:                            break;
        !           756: 
        !           757:                        case 'e':       /* ellipse */
        !           758:                            fscanf(fp, "%d %d", &m, &n);
        !           759:                            drawellip(m, n);
        !           760:                            break;
        !           761: 
        !           762:                        case 'a':       /* counter-clockwise arc */
        !           763:                        case 'A':       /* clockwise arc */
        !           764:                            fscanf(fp, "%d %d %d %d", &n, &m, &n1, &m1);
        !           765:                            drawarc(n, m, n1, m1, c);
        !           766:                            break;
        !           767: 
        !           768:                        case 'q':       /* spline without end points */
        !           769:                            drawspline(fp, 1);
        !           770:                            lineno++;
        !           771:                            break;
        !           772: 
        !           773:                        case '~':       /* wiggly line */
        !           774:                            drawspline(fp, 2);
        !           775:                            lineno++;
        !           776:                            break;
        !           777: 
        !           778:                        default:
        !           779:                            error(FATAL, "unknown drawing function %c", c);
        !           780:                            break;
        !           781:                    }   /* End switch */
        !           782:                    break;
        !           783: 
        !           784:            case 's':                   /* use this point size */
        !           785:                    fscanf(fp, "%d", &size);    /* ignore fractional sizes */
        !           786:                    break;
        !           787: 
        !           788:            case 'f':                   /* use font mounted here */
        !           789:                    fscanf(fp, "%s", str);
        !           790:                    setfont(t_font(str));
        !           791:                    break;
        !           792: 
        !           793:            case 'H':                   /* absolute horizontal motion */
        !           794:                    fscanf(fp, "%d", &n);
        !           795:                    hgoto(n);
        !           796:                    break;
        !           797: 
        !           798:            case 'h':                   /* relative horizontal motion */
        !           799:                    fscanf(fp, "%d", &n);
        !           800:                    hmot(n);
        !           801:                    break;
        !           802: 
        !           803:            case 'w':                   /* word space */
        !           804:                    break;
        !           805: 
        !           806:            case 'V':                   /* absolute vertical position */
        !           807:                    fscanf(fp, "%d", &n);
        !           808:                    vgoto(n);
        !           809:                    break;
        !           810: 
        !           811:            case 'v':                   /* relative vertical motion */
        !           812:                    fscanf(fp, "%d", &n);
        !           813:                    vmot(n);
        !           814:                    break;
        !           815: 
        !           816:            case 'p':                   /* new page */
        !           817:                    fscanf(fp, "%d", &n);
        !           818:                    t_page(n);
        !           819:                    break;
        !           820: 
        !           821:            case 'n':                   /* end of line */
        !           822:                    while ( (c = getc(fp)) != '\n' && c != EOF ) ;
        !           823:                    hgoto(0);
        !           824:                    lineno++;
        !           825:                    break;
        !           826: 
        !           827:            case '#':                   /* comment */
        !           828:                    while ( (c = getc(fp)) != '\n' && c != EOF ) ;
        !           829:                    lineno++;
        !           830:                    break;
        !           831: 
        !           832:            case 'x':                   /* device control function */
        !           833:                    devcntrl(fp);
        !           834:                    lineno++;
        !           835:                    break;
        !           836: 
        !           837:            default:
        !           838:                    error(FATAL, "unknown input character %o %c", c, c);
        !           839:                    done();
        !           840:        }   /* End switch */
        !           841:     }  /* End while */
        !           842: 
        !           843:     t_page(-1);                                /* print the last page */
        !           844:     flushtext();
        !           845: 
        !           846: }   /* End of conv */
        !           847: 
        !           848: /*****************************************************************************/
        !           849: 
        !           850: devcntrl(fp)
        !           851: 
        !           852:     FILE       *fp;
        !           853: 
        !           854: {
        !           855: 
        !           856:     char       str[50], buf[256], str1[50];
        !           857:     int                c, n;
        !           858: 
        !           859: /*
        !           860:  *
        !           861:  * Interpret device control commands, ignoring any we don't recognize. The
        !           862:  * "x X ..." commands are a device dependent collection generated by troff's
        !           863:  * \X'...' request.
        !           864:  *
        !           865:  */
        !           866: 
        !           867:     fscanf(fp, "%s", str);
        !           868: 
        !           869:     switch ( str[0] ) {
        !           870:        case 'f':                       /* load font in a position */
        !           871:                fscanf(fp, "%d %s", &n, str);
        !           872:                fgets(buf, sizeof buf, fp);     /* in case there's a filename */
        !           873:                ungetc('\n', fp);       /* fgets() goes too far */
        !           874:                str1[0] = '\0';         /* in case there's nothing to come in */
        !           875:                sscanf(buf, "%s", str1);
        !           876:                loadfont(n, str, str1);
        !           877:                break;
        !           878: 
        !           879:        case 'i':                       /* initialize */
        !           880:                t_init();
        !           881:                break;
        !           882: 
        !           883:        case 'p':                       /* pause */
        !           884:                break;
        !           885: 
        !           886:        case 'r':                       /* resolution assumed when prepared */
        !           887:                fscanf(fp, "%d", &res);
        !           888:                break;
        !           889: 
        !           890:        case 's':                       /* stop */
        !           891:        case 't':                       /* trailer */
        !           892:                flushtext();
        !           893:                break;
        !           894: 
        !           895:        case 'H':                       /* char height */
        !           896:                fscanf(fp, "%d", &n);
        !           897:                t_charht(n);
        !           898:                break;
        !           899: 
        !           900:        case 'S':                       /* slant */
        !           901:                fscanf(fp, "%d", &n);
        !           902:                t_slant(n);
        !           903:                break;
        !           904: 
        !           905:        case 'T':                       /* device name */
        !           906:                fscanf(fp, "%s", devname);
        !           907:                break;
        !           908: 
        !           909:        case 'X':                       /* copy through - from troff */
        !           910:                fscanf(fp, " %[^: \n]:", str);
        !           911:                fgets(buf, sizeof(buf), fp);
        !           912:                ungetc('\n', fp);
        !           913:                if ( strcmp(str, "PI") == 0 || strcmp(str, "PictureInclusion") == 0 )
        !           914:                    picture(buf);
        !           915:                else if ( strcmp(str, "InlinePicture") == 0 )
        !           916:                    inlinepic(fp, buf);
        !           917:                else if ( strcmp(str, "BeginPath") == 0 )
        !           918:                    beginpath(buf, FALSE);
        !           919:                else if ( strcmp(str, "DrawPath") == 0 )
        !           920:                    drawpath(buf, FALSE);
        !           921:                else if ( strcmp(str, "BeginObject") == 0 )
        !           922:                    beginpath(buf, TRUE);
        !           923:                else if ( strcmp(str, "EndObject") == 0 )
        !           924:                    drawpath(buf, TRUE);
        !           925:                else if ( strcmp(str, "NewBaseline") == 0 )
        !           926:                    newbaseline(buf);
        !           927:                else if ( strcmp(str, "DrawText") == 0 )
        !           928:                    drawtext(buf);
        !           929:                else if ( strcmp(str, "SetText") == 0 )
        !           930:                    settext(buf);
        !           931:                else if ( strcmp(str, "SetColor") == 0 ) {
        !           932:                    newcolor(buf);
        !           933:                    setcolor();
        !           934:                } else if ( strcmp(str, "PS") == 0 || strcmp(str, "PostScript") == 0 ) {
        !           935:                    flushtext();
        !           936:                    fprintf(tf, "%s", buf);
        !           937:                }   /* End else */
        !           938:                break;
        !           939:     }  /* End switch */
        !           940: 
        !           941:     while ( (c = getc(fp)) != '\n' && c != EOF ) ;
        !           942: 
        !           943: }   /* End of devcntrl */
        !           944: 
        !           945: /*****************************************************************************/
        !           946: 
        !           947: loadfont(m, f, dir)
        !           948: 
        !           949:     int                m;
        !           950:     char       *f;
        !           951:     char       *dir;
        !           952: 
        !           953: {
        !           954: 
        !           955:     char       path[150];
        !           956: 
        !           957: /*
        !           958:  *
        !           959:  * Load position m with font f. Font file pathname is *fontdir/dev*realdev/*f
        !           960:  * or *dir/*f, if dir isn't empty. Use mapfont() to replace the missing font
        !           961:  * if we're emulating another device, dir is empty, and the first mount fails.
        !           962:  *
        !           963:  */
        !           964: 
        !           965:     if ( dir[0] == '\0' )
        !           966:        sprintf(path, "%s/dev%s/%s", fontdir, realdev, f);
        !           967:     else sprintf(path, "%s/%s", dir, f);
        !           968: 
        !           969:     if ( mountfont(path, m) == -1 ) {
        !           970:        if ( dir[0] == '\0' ) {
        !           971:            sprintf(path, "%s/dev%s/%s", fontdir, realdev, mapfont(f));
        !           972:            if ( mountfont(path, m) == -1 ) {
        !           973:                sprintf(path, "%s/dev%s/%s", fontdir, realdev, f);
        !           974:                error(FATAL, "can't load %s at %d", path, m);
        !           975:            }   /* End if */
        !           976:        } else error(FATAL, "can't load %s at %d", path, m);
        !           977:     }  /* End if */
        !           978: 
        !           979:     if ( smnt == 0 && mount[m]->specfont )
        !           980:        smnt = m;
        !           981: 
        !           982:     if ( m == lastfont )               /* force a call to t_sf() */
        !           983:        lastfont = -1;
        !           984: 
        !           985:     if ( m > nfonts ) {                        /* got more positions */
        !           986:        nfonts = m;
        !           987:        gotspecial = FALSE;
        !           988:     }  /* End if */
        !           989: 
        !           990: }   /* End of loadfont */
        !           991: 
        !           992: /*****************************************************************************/
        !           993: 
        !           994: char *mapfont(name)
        !           995: 
        !           996:     char       *name;
        !           997: 
        !           998: {
        !           999: 
        !          1000:     int                i;
        !          1001: 
        !          1002: /*
        !          1003:  *
        !          1004:  * Map a missing font name into one that should be available. Only used when
        !          1005:  * we're emulating another device and the first mount fails. Consider deleting
        !          1006:  * this routine.
        !          1007:  *
        !          1008:  */
        !          1009: 
        !          1010:     for ( i = 0; fontmap[i].name != NULL; i++ )
        !          1011:        if ( strcmp(name, fontmap[i].name) == 0 )
        !          1012:            return(fontmap[i].use);
        !          1013: 
        !          1014:     switch ( *++name ) {
        !          1015:        case 'I': return("I");
        !          1016:        case 'B': return("B");
        !          1017:        case 'X': return("BI");
        !          1018:        default:  return("R");
        !          1019:     }  /* End switch */
        !          1020: 
        !          1021: }   /* End of mapfont */
        !          1022: 
        !          1023: /*****************************************************************************/
        !          1024: 
        !          1025: loadspecial()
        !          1026: 
        !          1027: {
        !          1028: 
        !          1029: /*
        !          1030:  *
        !          1031:  * Fix - later.
        !          1032:  *
        !          1033:  */
        !          1034: 
        !          1035:     gotspecial = TRUE;
        !          1036: 
        !          1037: }   /* End of loadspecial */
        !          1038: 
        !          1039: /*****************************************************************************/
        !          1040: 
        !          1041: t_init()
        !          1042: 
        !          1043: {
        !          1044: 
        !          1045:     char       path[150];
        !          1046:     static int initialized = FALSE;
        !          1047: 
        !          1048: /*
        !          1049:  *
        !          1050:  * Finish initialization - just read an "x init" command. Assumes we already
        !          1051:  * know the input file resolution.
        !          1052:  *
        !          1053:  */
        !          1054: 
        !          1055:     flushtext();                       /* moved - for cat'ed troff files */
        !          1056: 
        !          1057:     if ( initialized == FALSE ) {
        !          1058:        if ( strcmp(devname, realdev) ) {
        !          1059:            sprintf(path, "%s/dev%s/DESC", fontdir, devname);
        !          1060:            if ( checkdesc(path) )
        !          1061:                realdev = devname;
        !          1062:        }   /* End if */
        !          1063: 
        !          1064:        sprintf(path, "%s/dev%s/DESC", fontdir, realdev);
        !          1065:        if ( getdesc(path) == -1 )
        !          1066:            error(FATAL, "can't open %s", path);
        !          1067:        nfonts = 0;
        !          1068:        gotspecial = FALSE;
        !          1069:        widthfac = (float) res /devres;
        !          1070:        slop = pointslop * res / POINTS + .5;
        !          1071:        rvslop = res * .025;
        !          1072:        setup();
        !          1073:        initialized = TRUE;
        !          1074:     }  /* End if */
        !          1075: 
        !          1076:     hpos = vpos = 0;
        !          1077:     size = 10;
        !          1078:     reset();
        !          1079: 
        !          1080: }   /* End of t_init */
        !          1081: 
        !          1082: /*****************************************************************************/
        !          1083: 
        !          1084: t_page(pg)
        !          1085: 
        !          1086:     int                pg;
        !          1087: 
        !          1088: {
        !          1089: 
        !          1090:     static int lastpg = 0;
        !          1091: 
        !          1092: /*
        !          1093:  *
        !          1094:  * Finish the previous page and get ready for the next one. End page output
        !          1095:  * goes to /dev/null at the start of each input file. Start page output goes
        !          1096:  * to /dev/null at the end of each input file.
        !          1097:  *
        !          1098:  * Consider doing showpage after page level restore (as Adobe recommends). If
        !          1099:  * the order is changed use restore() and save(). forms.ps will likely also
        !          1100:  * need fixing.
        !          1101:  *
        !          1102:  */
        !          1103: 
        !          1104:     if ( tf == stdout )
        !          1105:        printed++;
        !          1106: 
        !          1107:     flushtext();                       /* just in case */
        !          1108: 
        !          1109:     fprintf(tf, "cleartomark\n");
        !          1110:     fprintf(tf, "showpage\n");
        !          1111:     fprintf(tf, "saveobj restore\n");
        !          1112:     if ( dobbox == TRUE )
        !          1113:        writebbox(tf, PAGEBOUNDINGBOX, 10);
        !          1114:     fprintf(tf, "%s %d %d\n", ENDPAGE, lastpg, printed);
        !          1115: 
        !          1116:     redirect(pg);
        !          1117: 
        !          1118:     fprintf(tf, "%s %d %d\n", PAGE, pg, printed+1);
        !          1119:     if ( dobbox == TRUE )
        !          1120:        fprintf(tf, "%s %s\n", PAGEBOUNDINGBOX, ATEND);
        !          1121:     fprintf(tf, "/saveobj save def\n");
        !          1122:     fprintf(tf, "mark\n");
        !          1123:     writerequest(printed+1, tf);
        !          1124:     fprintf(tf, "%d pagesetup\n", printed+1);
        !          1125: 
        !          1126:     if ( encoding != realencoding )
        !          1127:        fprintf(tf, "%d setdecoding\n", encoding);
        !          1128: 
        !          1129:     if ( gotcolor == TRUE )
        !          1130:        setcolor();
        !          1131: 
        !          1132:     lastpg = pg;                       /* for the next ENDPAGE comment */
        !          1133:     hpos = vpos = 0;                   /* get ready for the next page */
        !          1134:     reset();                           /* force position and font stuff - later */
        !          1135: 
        !          1136:     seenpage = TRUE;
        !          1137: 
        !          1138: }   /* End of t_page */
        !          1139: 
        !          1140: /*****************************************************************************/
        !          1141: 
        !          1142: t_font(s)
        !          1143: 
        !          1144:     char       *s;
        !          1145: 
        !          1146: {
        !          1147: 
        !          1148:     int                n;
        !          1149: 
        !          1150: /*
        !          1151:  *
        !          1152:  * Converts the string *s into an integer and checks to make sure it's a legal
        !          1153:  * font position. Also arranges to mount all the special fonts after the last
        !          1154:  * legitimate font (by calling loadspecial()), provided it hasn't already been
        !          1155:  * done.
        !          1156:  *
        !          1157:  */
        !          1158: 
        !          1159:     n = atoi(s);
        !          1160: 
        !          1161:     if ( seenpage == TRUE ) {
        !          1162:        if ( n < 0 || n > nfonts )
        !          1163:            error(FATAL, "illegal font position %d", n);
        !          1164: 
        !          1165:        if ( gotspecial == FALSE )
        !          1166:            loadspecial();
        !          1167:     }  /* End if */
        !          1168: 
        !          1169:     return(n);
        !          1170: 
        !          1171: }   /* End of t_font */
        !          1172: 
        !          1173: /*****************************************************************************/
        !          1174: 
        !          1175: setfont(m)
        !          1176: 
        !          1177:     int                m;
        !          1178: 
        !          1179: {
        !          1180: 
        !          1181: /*
        !          1182:  *
        !          1183:  * Use the font mounted at position m. Bounds checks are probably unnecessary.
        !          1184:  * Changing the font and size used by the printer is handled in t_sf().
        !          1185:  *
        !          1186:  */
        !          1187: 
        !          1188:     if ( m < 0 || m > MAXFONTS )
        !          1189:        error(FATAL, "illegal font %d", m);
        !          1190:     font = m;
        !          1191: 
        !          1192: }   /* End of setfont */
        !          1193: 
        !          1194: /*****************************************************************************/
        !          1195: 
        !          1196: t_sf()
        !          1197: 
        !          1198: {
        !          1199: 
        !          1200:     Font       *fpos;
        !          1201:     char       temp[150];
        !          1202: 
        !          1203: /*
        !          1204:  *
        !          1205:  * Force a new font or size. Generates name definitions for fonts that haven't
        !          1206:  * been named, grabs host resident font files and keeps track of the fonts used
        !          1207:  * by this job. When necessary also adjusts the font's height and slant. Should
        !          1208:  * only be called immediately before printing a character.
        !          1209:  *
        !          1210:  */
        !          1211: 
        !          1212:     if ( tf == stdout && mounted(font) ) {
        !          1213:        flushtext();
        !          1214: 
        !          1215:        fpos = mount[font];
        !          1216:        if ( (fpos->flags & USED) == 0 ) {
        !          1217:            if ( (fpos->flags & NAMED) == 0 && fpos->fontname != NULL ) {
        !          1218:                sprintf(temp, "/%s /%s def\n", fpos->name, fpos->fontname);
        !          1219:                exportstring(temp);
        !          1220:                fpos->flags |= NAMED;           /* unnecessary */
        !          1221:            }   /* End if */
        !          1222: 
        !          1223:            if ( hostfontdir != NULL ) {
        !          1224:                sprintf(temp, "%s/%s", hostfontdir, fpos->name);
        !          1225:                exportfile(temp);
        !          1226:            }   /* End if */
        !          1227:        }   /* End if */
        !          1228: 
        !          1229:        fprintf(tf, "%d %s f\n", size, fpos->name);
        !          1230:        if ( fontheight != 0 || fontslant != 0 )
        !          1231:            fprintf(tf, "%d %d changefont\n", fontslant, (fontheight != 0) ? fontheight : size);
        !          1232: 
        !          1233:        lastfont = font;
        !          1234:        lastsize = size;
        !          1235:        fpos->flags |= USED;
        !          1236:     }  /* End if */
        !          1237: 
        !          1238: }   /* End of t_sf */
        !          1239: 
        !          1240: /*****************************************************************************/
        !          1241: 
        !          1242: t_charht(n)
        !          1243: 
        !          1244:     int                n;
        !          1245: 
        !          1246: {
        !          1247: 
        !          1248: /*
        !          1249:  *
        !          1250:  * Set character height to n points. Disabled if n is 0 or the current size.
        !          1251:  *
        !          1252:  */
        !          1253: 
        !          1254:     fontheight = (n == size) ? 0 : n;
        !          1255:     lastfont = -1;
        !          1256: 
        !          1257: }   /* End of t_charht */
        !          1258: 
        !          1259: /*****************************************************************************/
        !          1260: 
        !          1261: t_slant(n)
        !          1262: 
        !          1263:     int                n;
        !          1264: 
        !          1265: {
        !          1266: 
        !          1267: /*
        !          1268:  *
        !          1269:  * Set slant to n degrees. Disable slanting if n is 0.
        !          1270:  *
        !          1271:  */
        !          1272: 
        !          1273:     fontslant = n;
        !          1274:     lastfont = -1;
        !          1275: 
        !          1276: }   /* End of t_slant */
        !          1277: 
        !          1278: /*****************************************************************************/
        !          1279: 
        !          1280: xymove(x, y)
        !          1281: 
        !          1282:     int                x, y;
        !          1283: 
        !          1284: {
        !          1285: 
        !          1286: /*
        !          1287:  *
        !          1288:  * Make the the printer and post-processor agree about the current position.
        !          1289:  *
        !          1290:  */
        !          1291: 
        !          1292:     flushtext();
        !          1293: 
        !          1294:     hgoto(x);
        !          1295:     vgoto(y);
        !          1296: 
        !          1297:     fprintf(tf, "%d %d m\n", hpos, vpos);
        !          1298: 
        !          1299:     lastx = hpos;
        !          1300:     lasty = vpos;
        !          1301: 
        !          1302: }   /* End of xymove */
        !          1303: 
        !          1304: /*****************************************************************************/
        !          1305: 
        !          1306: put1(c)
        !          1307: 
        !          1308:     register int       c;
        !          1309: 
        !          1310: {
        !          1311: 
        !          1312:     register int       i;
        !          1313:     register int       j;
        !          1314:     register int       k;
        !          1315:     int                        code;
        !          1316:     int                        ofont;
        !          1317: 
        !          1318: /*
        !          1319:  *
        !          1320:  * Print character c. ASCII if c < ALPHABET, otherwise it's special. Look for
        !          1321:  * c in the current font, then in others starting at the first special font.
        !          1322:  * Save c in lastc so it's available when oput() runs. Restore original font
        !          1323:  * before leaving.
        !          1324:  *
        !          1325:  */
        !          1326: 
        !          1327:     lastc = c;                         /* charlib() needs name not code */
        !          1328:     if ( (c -= 32) <= 0 )
        !          1329:        return;
        !          1330: 
        !          1331:     k = ofont = font;
        !          1332: 
        !          1333:     if ( (i = onfont(lastc, k)) == -1 && smnt > 0 )
        !          1334:        for ( k = smnt, j = 0; j < nfonts; j++, k = k % nfonts + 1 ) {
        !          1335:            if ( (i = onfont(lastc, k)) != -1 ) {
        !          1336:                setfont(k);
        !          1337:                break;
        !          1338:            }   /* End if */
        !          1339:        }   /* End for */
        !          1340: 
        !          1341:     if ( i != -1 && (code = mount[k]->wp[i].code) != 0 ) {
        !          1342:        lastw = widthfac * (((int)mount[k]->wp[i].wid * size + unitwidth/2) / unitwidth);
        !          1343:        oput(code);
        !          1344:     }  /* End if */
        !          1345: 
        !          1346:     if ( font != ofont )
        !          1347:        setfont(ofont);
        !          1348: 
        !          1349: }   /* End of put1 */
        !          1350: 
        !          1351: /*****************************************************************************/
        !          1352: 
        !          1353: oput(c)
        !          1354: 
        !          1355:     int                c;
        !          1356: 
        !          1357: {
        !          1358: 
        !          1359:     double     llx, lly, urx, ury;     /* boundingbox corners */
        !          1360: 
        !          1361: /*
        !          1362:  *
        !          1363:  * Arranges to print the character whose code is c in the current font. All the
        !          1364:  * actual positioning is done here, in charlib(), or in the drawing routines.
        !          1365:  *
        !          1366:  */
        !          1367: 
        !          1368:     if ( textcount > MAXSTACK )                /* don't put too much on the stack? */
        !          1369:        flushtext();
        !          1370: 
        !          1371:     if ( font != lastfont || size != lastsize )
        !          1372:        t_sf();
        !          1373: 
        !          1374:     if ( vpos != lasty )
        !          1375:        endline();
        !          1376: 
        !          1377:     starttext();
        !          1378: 
        !          1379:     if ( ABS(hpos - lastx) > slop )
        !          1380:        endstring();
        !          1381: 
        !          1382:     if ( isascii(c) && isprint(c) )
        !          1383:        switch ( c ) {
        !          1384:            case '(':
        !          1385:            case ')':
        !          1386:            case '\\':
        !          1387:                    addchar('\\');
        !          1388: 
        !          1389:            default:
        !          1390:                    addchar(c);
        !          1391:        }   /* End switch */
        !          1392:     else if ( c > 040 )
        !          1393:        addoctal(c);
        !          1394:     else charlib(c);
        !          1395: 
        !          1396:     if ( dobbox == TRUE ) {
        !          1397:        llx = lastx;
        !          1398:        lly = -(vpos + 0.5 * (devres * size / 72.0));
        !          1399:        urx = lastx + lastw;
        !          1400:        ury = -(vpos - (devres * size / 72.0));
        !          1401:        cover(llx, lly);
        !          1402:        cover(urx, ury);
        !          1403:     }  /* End if */
        !          1404: 
        !          1405:     lastx += lastw;
        !          1406: 
        !          1407: }   /* End of oput */
        !          1408: 
        !          1409: /*****************************************************************************/
        !          1410: 
        !          1411: starttext()
        !          1412: 
        !          1413: {
        !          1414: 
        !          1415: /*
        !          1416:  * Called whenever we want to be sure we're ready to start collecting characters
        !          1417:  * for the next call to PostScript procedure t (ie. the one that prints them). If
        !          1418:  * textcount is positive we've already started, so there's nothing to do. The more
        !          1419:  * complicated encoding schemes save text strings in the strings[] array and need
        !          1420:  * detailed information about the strings when they're written to the output file
        !          1421:  * in flushtext().
        !          1422:  *
        !          1423:  */
        !          1424: 
        !          1425:     if ( textcount < 1 ) {
        !          1426:        switch ( encoding ) {
        !          1427:            case 0:
        !          1428:            case 1:
        !          1429:                putc('(', tf);
        !          1430:                break;
        !          1431: 
        !          1432:            case 2:
        !          1433:            case 3:
        !          1434:                strptr = strings;
        !          1435:                spacecount = 0;
        !          1436:                line[1].str = strptr;
        !          1437:                line[1].dx = 0;
        !          1438:                line[1].spaces = 0;
        !          1439:                line[1].start = hpos;
        !          1440:                line[1].width = 0;
        !          1441:                break;
        !          1442: 
        !          1443:            case MAXENCODING+1:                 /* reverse video */
        !          1444:                if ( lastend == -1 )
        !          1445:                    lastend = hpos;
        !          1446:                putc('(', tf);
        !          1447:                break;
        !          1448: 
        !          1449:            case MAXENCODING+2:                 /* follow a funny baseline */
        !          1450:                putc('(', tf);
        !          1451:                break;
        !          1452:        }   /* End switch */
        !          1453: 
        !          1454:        textcount = 1;
        !          1455:        lastx = stringstart = hpos;
        !          1456:     }  /* End if */
        !          1457: 
        !          1458: }   /* End of starttext */
        !          1459: 
        !          1460: /*****************************************************************************/
        !          1461: 
        !          1462: flushtext()
        !          1463: 
        !          1464: {
        !          1465: 
        !          1466:     int                i;
        !          1467: 
        !          1468: /*
        !          1469:  *
        !          1470:  * Generates a call to the PostScript procedure that processes all the text we've
        !          1471:  * accumulated - provided textcount is positive.
        !          1472:  *
        !          1473:  */
        !          1474: 
        !          1475:     if ( textcount > 0 ) {
        !          1476:        switch ( encoding ) {
        !          1477:            case 0:
        !          1478:                fprintf(tf, ")%d t\n", stringstart);
        !          1479:                break;
        !          1480: 
        !          1481:            case 1:
        !          1482:                fprintf(tf, ")%d %d t\n", stringstart, lasty);
        !          1483:                break;
        !          1484: 
        !          1485:            case 2:
        !          1486:                *strptr = '\0';
        !          1487:                line[textcount].width = lastx - line[textcount].start;
        !          1488:                if ( spacecount != 0 || textcount != 1 ) {
        !          1489:                    for ( i = textcount; i > 0; i-- )
        !          1490:                        fprintf(tf, "(%s)%d %d", line[i].str, line[i].spaces, line[i].width);
        !          1491:                    fprintf(tf, " %d %d %d t\n", textcount, stringstart, lasty);
        !          1492:                } else fprintf(tf, "(%s)%d %d w\n", line[1].str, stringstart, lasty);
        !          1493:                break;
        !          1494: 
        !          1495:            case 3:
        !          1496:                *strptr = '\0';
        !          1497:                if ( spacecount != 0 || textcount != 1 ) {
        !          1498:                    for ( i = textcount; i > 0; i-- )
        !          1499:                        fprintf(tf, "(%s)%d", line[i].str, line[i].dx);
        !          1500:                    fprintf(tf, " %d %d %d t\n", textcount, stringstart, lasty);
        !          1501:                } else fprintf(tf, "(%s)%d %d w\n", line[1].str, stringstart, lasty);
        !          1502:                break;
        !          1503: 
        !          1504:            case MAXENCODING+1:
        !          1505:                fprintf(tf, ")%d ", stringstart);
        !          1506:                fprintf(tf, "%d %d drawrvbox ", lastend - rvslop, (int)(lastx + .5) + rvslop);
        !          1507:                fprintf(tf, "t\n", stringstart);
        !          1508:                lastend = (lastx + .5) + 2 * rvslop;
        !          1509:                break;
        !          1510: 
        !          1511:            case MAXENCODING+2:
        !          1512:                fprintf(tf, ")%d %d t\n", stringstart, lasty);
        !          1513:                break;
        !          1514:        }   /* End switch */
        !          1515:     }  /* End if */
        !          1516: 
        !          1517:     textcount = 0;
        !          1518: 
        !          1519: }   /* End of flushtext */
        !          1520: 
        !          1521: /*****************************************************************************/
        !          1522: 
        !          1523: endstring()
        !          1524: 
        !          1525: {
        !          1526: 
        !          1527:     int                dx;
        !          1528: 
        !          1529: /*
        !          1530:  *
        !          1531:  * Horizontal positions are out of sync. End the last open string, adjust the
        !          1532:  * printer's position, and start a new string. Assumes we've already started
        !          1533:  * accumulating text.
        !          1534:  *
        !          1535:  */
        !          1536: 
        !          1537:     switch ( encoding ) {
        !          1538:        case 0:
        !          1539:        case 1:
        !          1540:            fprintf(tf, ")%d(", stringstart);
        !          1541:            textcount++;
        !          1542:            lastx = stringstart = hpos;
        !          1543:            break;
        !          1544: 
        !          1545:        case 2:
        !          1546:        case 3:
        !          1547:            dx = hpos - lastx;
        !          1548:            if ( spacecount++ == 0 )
        !          1549:                line[textcount].dx = dx;
        !          1550:            if ( line[textcount].dx != dx ) {
        !          1551:                *strptr++ = '\0';
        !          1552:                line[textcount].width = lastx - line[textcount].start;
        !          1553:                line[++textcount].str = strptr;
        !          1554:                *strptr++ = ' ';
        !          1555:                line[textcount].dx = dx;
        !          1556:                line[textcount].start = lastx;
        !          1557:                line[textcount].width = 0;
        !          1558:                line[textcount].spaces = 1;
        !          1559:            } else {
        !          1560:                *strptr++ = ' ';
        !          1561:                line[textcount].spaces++;
        !          1562:            }   /* End else */
        !          1563:            lastx += dx;
        !          1564:            break;
        !          1565: 
        !          1566:        case MAXENCODING+1:
        !          1567:            fprintf(tf, ")%d(", stringstart);
        !          1568:            textcount++;
        !          1569:            lastx = stringstart = hpos;
        !          1570:            break;
        !          1571: 
        !          1572:        case MAXENCODING+2:
        !          1573:            flushtext();
        !          1574:            starttext();
        !          1575:            break;
        !          1576:     }  /* End switch */
        !          1577: 
        !          1578: }   /* End of endstring */
        !          1579: 
        !          1580: /*****************************************************************************/
        !          1581: 
        !          1582: endline()
        !          1583: 
        !          1584: {
        !          1585: 
        !          1586: /*
        !          1587:  *
        !          1588:  * The vertical position has changed. Dump any accumulated text, then adjust
        !          1589:  * the printer's vertical position.
        !          1590:  *
        !          1591:  */
        !          1592: 
        !          1593:     flushtext();
        !          1594: 
        !          1595:     if ( encoding == 0 || encoding == MAXENCODING+1 )
        !          1596:        fprintf(tf, "%d %d m\n", hpos, vpos);
        !          1597: 
        !          1598:     lastx = stringstart = lastend = hpos;
        !          1599:     lasty = vpos;
        !          1600: 
        !          1601: }   /* End of endline */
        !          1602: 
        !          1603: /*****************************************************************************/
        !          1604: 
        !          1605: addchar(c)
        !          1606: 
        !          1607:     int                c;
        !          1608: 
        !          1609: {
        !          1610: 
        !          1611: /*
        !          1612:  *
        !          1613:  * Does whatever is needed to add character c to the current string.
        !          1614:  *
        !          1615:  */
        !          1616: 
        !          1617:     switch ( encoding ) {
        !          1618:        case 0:
        !          1619:        case 1:
        !          1620:            putc(c, tf);
        !          1621:            break;
        !          1622: 
        !          1623:        case 2:
        !          1624:        case 3:
        !          1625:            *strptr++ = c;
        !          1626:            break;
        !          1627: 
        !          1628:        case MAXENCODING+1:
        !          1629:        case MAXENCODING+2:
        !          1630:            putc(c, tf);
        !          1631:            break;
        !          1632:     }  /* End switch */
        !          1633: 
        !          1634: }   /* End of addchar */
        !          1635: 
        !          1636: /*****************************************************************************/
        !          1637: 
        !          1638: addoctal(c)
        !          1639: 
        !          1640:     int                c;
        !          1641: 
        !          1642: {
        !          1643: 
        !          1644: /*
        !          1645:  *
        !          1646:  * Add c to the current string as an octal escape.
        !          1647:  *
        !          1648:  */
        !          1649: 
        !          1650:     switch ( encoding ) {
        !          1651:        case 0:
        !          1652:        case 1:
        !          1653:            fprintf(tf, "\\%o", c);
        !          1654:            break;
        !          1655: 
        !          1656:        case 2:
        !          1657:        case 3:
        !          1658:            sprintf(strptr, "\\%o", c);
        !          1659:            strptr += strlen(strptr);
        !          1660:            break;
        !          1661: 
        !          1662:        case MAXENCODING+1:
        !          1663:        case MAXENCODING+2:
        !          1664:            fprintf(tf, "\\%o", c);
        !          1665:            break;
        !          1666:     }  /* End switch */
        !          1667: 
        !          1668: }   /* End of addoctal */
        !          1669: 
        !          1670: /*****************************************************************************/
        !          1671: 
        !          1672: charlib(code)
        !          1673: 
        !          1674:     int                code;                   /* either 1 or 2 */
        !          1675: 
        !          1676: {
        !          1677: 
        !          1678:     char       *name;                  /* name of the character */
        !          1679:     char       tname[10];              /* in case it's a single ASCII character */
        !          1680:     char       temp[150];
        !          1681: 
        !          1682: /*
        !          1683:  *
        !          1684:  * Called from oput() for characters having codes less than 040. Special files
        !          1685:  * that define PostScript procedures for certain characters can be found in
        !          1686:  * directory *fontdir/devpost/charlib. If there's a file that has the same name as
        !          1687:  * the character we're trying to print it's copied to the output file, otherwise
        !          1688:  * nothing, except some positioning, is done.
        !          1689:  *
        !          1690:  * All character definitions are only made once. Subsequent requests to print the
        !          1691:  * character generate a call to a procedure that begins with the prefix build_ and
        !          1692:  * ends with the character's name. Special characters that are assigned codes
        !          1693:  * other than 1 are assumed to have additional data files that should be copied
        !          1694:  * to the output file immediately after the build_ call. Those data files should
        !          1695:  * end in the suffix .map, and usually will be a hex representation of a bitmap.
        !          1696:  *
        !          1697:  */
        !          1698: 
        !          1699:     flushtext();
        !          1700: 
        !          1701:     if ( lastc < ALPHABET ) {          /* ASCII character */
        !          1702:        sprintf(tname, "%.3o", lastc);
        !          1703:        name = tname;
        !          1704:     } else name = chname(lastc);
        !          1705: 
        !          1706:     if ( downloaded[lastc] == 0 ) {
        !          1707:        sprintf(temp, "%s/dev%s/charlib/%s", fontdir, realdev, name);
        !          1708:        if ( exportfile(temp) == TRUE ) {
        !          1709:            downloaded[lastc] = 1;
        !          1710:            t_sf();
        !          1711:        }   /* End if */
        !          1712:     }  /* End if */
        !          1713: 
        !          1714:     if ( downloaded[lastc] == 1 ) {
        !          1715:        xymove(hpos, vpos);
        !          1716:        fprintf(tf, "%d build_%s\n", (int) lastw, name);
        !          1717:        if ( code != 1 ) {              /* get the bitmap or whatever */
        !          1718:            sprintf(temp, "%s/dev%s/charlib/%s.map", fontdir, realdev, name);
        !          1719:            if ( access(temp, 04) == 0 && tf == stdout )
        !          1720:                cat(temp);
        !          1721:        }   /* End if */
        !          1722:        fprintf(tf, "%d %d m\n", stringstart = hpos + lastw, vpos);
        !          1723:     }  /* End if */
        !          1724: 
        !          1725: }   /* End of charlib */
        !          1726: 
        !          1727: /*****************************************************************************/
        !          1728: 
        !          1729: reset()
        !          1730: 
        !          1731: {
        !          1732: 
        !          1733: /*
        !          1734:  *
        !          1735:  * Reset variables that keep track of the printer's current position, size and
        !          1736:  * font. Eventually forces things back in sync before oput() prints the next
        !          1737:  * character.
        !          1738:  *
        !          1739:  */
        !          1740: 
        !          1741:     lastx = -(slop + 1);
        !          1742:     lasty = -1;
        !          1743:     lastfont = lastsize = -1;
        !          1744: 
        !          1745: }   /* End of reset */
        !          1746: 
        !          1747: /*****************************************************************************/
        !          1748: 
        !          1749: resetpos()
        !          1750: 
        !          1751: {
        !          1752: 
        !          1753: /*
        !          1754:  *
        !          1755:  * Reset the position tracking variables. Forces oput() to get positions back
        !          1756:  * in sync before printing the next character.
        !          1757:  *
        !          1758:  */
        !          1759: 
        !          1760:     lastx = -(slop + 1);
        !          1761:     lasty = -1;
        !          1762: 
        !          1763: }   /* End of resetpos */
        !          1764: 
        !          1765: /*****************************************************************************/
        !          1766: 
        !          1767: save()
        !          1768: 
        !          1769: {
        !          1770: 
        !          1771: /*
        !          1772:  *
        !          1773:  * Save the current PostScript environment. Initialize things that may have
        !          1774:  * disappeared after the preceeding restore.
        !          1775:  *
        !          1776:  */
        !          1777: 
        !          1778:     fprintf(tf, "/saveobj save def\n");
        !          1779:     fprintf(tf, "mark\n");
        !          1780: 
        !          1781:     if ( encoding != realencoding )
        !          1782:        fprintf(tf, "%d setdecoding\n", encoding);
        !          1783: 
        !          1784:     if ( gotcolor == TRUE )            /* prevent getcolor() recursion */
        !          1785:        setcolor();
        !          1786: 
        !          1787: }   /* End of save */
        !          1788: 
        !          1789: /*****************************************************************************/
        !          1790: 
        !          1791: restore()
        !          1792: 
        !          1793: {
        !          1794: 
        !          1795: /*
        !          1796:  *
        !          1797:  * Restore the previous PostScript environment.
        !          1798:  *
        !          1799:  */
        !          1800: 
        !          1801:     flushtext();
        !          1802:     fprintf(tf, "cleartomark\n");
        !          1803:     fprintf(tf, "saveobj restore\n");
        !          1804:     reset();
        !          1805: 
        !          1806: }   /* End of restore */
        !          1807: 
        !          1808: /*****************************************************************************/
        !          1809: 
        !          1810: exportfile(path)
        !          1811: 
        !          1812:     char       *path;
        !          1813: 
        !          1814: {
        !          1815: 
        !          1816:     int                val = FALSE;
        !          1817: 
        !          1818: /*
        !          1819:  *
        !          1820:  * Exports the contents of file path to the global environment. Returns TRUE
        !          1821:  * if we're doing output (i.e. tf == stdout) and the copy worked.
        !          1822:  *
        !          1823:  */
        !          1824: 
        !          1825:     if ( tf == stdout && access(path, 04) == 0 ) {
        !          1826:        restore();
        !          1827:        fprintf(tf, "%s", BEGINGLOBAL);
        !          1828:        val = cat(path);
        !          1829:        fprintf(tf, "%s", ENDGLOBAL);
        !          1830:        save();
        !          1831:     }  /* End if */
        !          1832: 
        !          1833:     return(val);
        !          1834: 
        !          1835: }   /* End of exportfile */
        !          1836: 
        !          1837: /*****************************************************************************/
        !          1838: 
        !          1839: exportstring(str)
        !          1840: 
        !          1841:     char       *str;
        !          1842: 
        !          1843: {
        !          1844: 
        !          1845: /*
        !          1846:  *
        !          1847:  * Exports string str to the global environment. No return value needed yet.
        !          1848:  *
        !          1849:  */
        !          1850: 
        !          1851:     if ( tf == stdout && str != NULL && *str != '\0' ) {
        !          1852:        restore();
        !          1853:        fprintf(tf, "%s", BEGINGLOBAL);
        !          1854:        fprintf(tf, "%s", str);
        !          1855:        fprintf(tf, "%s", ENDGLOBAL);
        !          1856:        save();
        !          1857:     }  /* End if */
        !          1858: 
        !          1859: }   /* End of exportstring */
        !          1860: 
        !          1861: /*****************************************************************************/
        !          1862: 
        !          1863: redirect(pg)
        !          1864: 
        !          1865:     int                pg;
        !          1866: 
        !          1867: {
        !          1868: 
        !          1869:     static FILE        *fp_null = NULL;
        !          1870: 
        !          1871: /*
        !          1872:  *
        !          1873:  * If we're not supposed to print page pg, tf will be directed to /dev/null,
        !          1874:  * otherwise output goes to stdout.
        !          1875:  *
        !          1876:  */
        !          1877: 
        !          1878:     if ( pg >= 0 && in_olist(pg) == ON )
        !          1879:        tf = stdout;
        !          1880:     else if ( (tf = fp_null) == NULL )
        !          1881:        tf = fp_null = fopen("/dev/null", "w");
        !          1882: 
        !          1883: }   /* End of redirect */
        !          1884: 
        !          1885: /*****************************************************************************/
        !          1886: 

unix.superglobalmegacorp.com

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