Annotation of 43BSDTahoe/new/dipress/src/bin/maha/maha.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  maharani - a czarina-like program that generates interpress files
                      3:  *
                      4:  *  Written for Xerox Corporation by William LeFebvre
                      5:  *
                      6:  *  Copyright (c)  1984, 1985, 1986 Xerox Corporation
                      7:  *
                      8:  *  HISTORY
                      9:  * 23-Sep-86  Lee Moore (lee) at Xerox Webster Research Center
                     10:  *     Added Jim Mayer's fix to the space allocator.
                     11:  *
                     12:  * 13-apr-86  Ed Flint (ed) at Xerox Webster Research Center
                     13:  *     do_file will reset to left margin when encountering carriage return
                     14:  *
                     15:  * 11-Feb-86  Lee Moore (lee) at Xerox Webster Research Center
                     16:  *     Added various suggestions from Larry Parmalee at Cornell U.
                     17:  *     1)  Margin adjustments.  Margins vary according to portrait or
                     18:  *         landscape mode.  If headings are suppressed, then that area
                     19:  *         is used for text.  Room left to punch holes at left.
                     20:  *     2)  Baseline spacing is tightened up for smaller font sizes
                     21:  *     3)  options can now reset each other
                     22:  *     4)  added "-P" option to specifiy output device (for compatibility
                     23:  *         with lpr system stuff.)
                     24:  *     5)  Improved maha environment variable handling (pair up and eliminate
                     25:  *         double and single quotes).
                     26:  *     6)  Interpress file now has mode 600 (for security reasons)
                     27:  *     7)  Maximum line length increased.
                     28:  *
                     29:  * 13-Jan-86  Lee Moore (lee) at Xerox Webster Research Center
                     30:  *     Changed a call to strcpyn to strncpy.
                     31:  *
                     32:  *  8-apr-85  ed flint
                     33:  *     conditional compilation for vax11-c (vms)
                     34:  *
                     35:  *  26-mar-85 ed flint @ Xerox, WRC
                     36:  *     add fclose after do_file to prevent running out of open file descriptors
                     37:  */
                     38: 
                     39: #ifdef vax11c
                     40: # include stdio
                     41: # include ssdef
                     42: # include ctype
                     43: # include descrip
                     44: #else
                     45: # include <stdio.h>
                     46: # include <pwd.h>
                     47: # include <strings.h>
                     48: # include <sys/types.h>
                     49: # include <sys/stat.h>
                     50: # include <sys/time.h>
                     51: #endif
                     52: 
                     53: # include "iptokens.h"
                     54: # include "literal.h"
                     55: # include "operator.h"
                     56: 
                     57: 
                     58: /*
                     59:  * the following defines a program that will queue an Interpress master
                     60:  * for printing
                     61:  */
                     62: # define  QIP          "qip"
                     63: 
                     64: # define  Break_size   1024
                     65: # define  Default_universal_prefix     "Xerox/XC1-1-1/"
                     66: # define  Line_size    192             /* upped from 132 */
                     67: 
                     68: /* All page boundaries are computed in the 1/10 point co-ordinate system */
                     69: /*
                     70:  *  Orig_y is an offset from the top of the page.  It must be converted
                     71:  *  to a measurement from the bottom of the page (a calculation that is
                     72:  *  rotation-dependent).
                     73:  */
                     74: 
                     75: # define  INCH         720
                     76: # define  Half_INCH    360
                     77: # define  Sixth_INCH   120                     /* one line at 6 lpi */
                     78: # define  Page_width   (8 * INCH + Half_INCH)
                     79: # define  Page_length  (11 * INCH)
                     80:                        /* rflg  ?  Landscape mode : Portrait mode */
                     81: # define  Orig_x       (rflg ? (1.5 * INCH/10) : (9 * INCH/10))
                     82: # define  Orig_y       (rflg ? (Sixth_INCH * 8) : (Sixth_INCH * 5))
                     83: # define  Header_to_orig_x     0
                     84: # define  Header_to_orig_y     (2 * Sixth_INCH)
                     85: 
                     86: /* Frame variable defines */
                     87: # define  F_transform  0
                     88: # define  F_headfont   1
                     89: # define  F_bodyfont   2
                     90: # define  F_italicfont 3
                     91: 
                     92: # define  No   0
                     93: # define  Yes  1
                     94: 
                     95: extern int errno;
                     96: 
                     97: /* enum, perhaps? */
                     98: typedef char boolean;
                     99: 
                    100: /* routines that return something other than int */
                    101: char *strecpy();
                    102: char *allocate();
                    103: char *next_arg();
                    104: char *sbrk();
                    105: char *getenv();
                    106: char *itoa();
                    107: char *rindex();
                    108: 
                    109: /* option flags */
                    110: boolean lflg = No;     /* line printer mode */
                    111: boolean rflg = No;     /* rotation - landscape mode */
                    112: boolean tflg = No;     /* omit title */
                    113: 
                    114: /* valued options */
                    115: int  columns   = 1;
                    116: char *bodyfont_name = "Vintage-Printwheel/10";
                    117: char *headfont_name = "Modern-Bold/12";
                    118: char *italicfont_name = "Modern-Bold-Italic/12";
                    119: char *banner   = NULL;
                    120: char *copies   = "1";
                    121: char *printer  = NULL;                 /* destination printer */
                    122: char *header   = "%f            %t            Page %p, line %l";
                    123: char *name     = NULL;
                    124: char *output   = NULL;
                    125: char *pages    = NULL;
                    126: 
                    127: #ifdef vax11c
                    128: char *template = "IPPXXXXXX";
                    129: #endif
                    130: 
                    131: /*
                    132:  *  page characteristics:  these variables define the extremes for the
                    133:  *  current page or column.  'column_separation' is the distance between
                    134:  *  the left sides of each column on the page.
                    135:  */
                    136: #ifndef notdef
                    137: int left_margin = (9 * INCH / 10);     /* x origin in portrait mode */
                    138: #else
                    139: int left_margin = Orig_x;
                    140: #endif
                    141: int right_margin;
                    142: int top_margin;
                    143: int bottom_margin;
                    144: int column_separation;
                    145: 
                    146: /* sundries */
                    147: boolean send_to_printer = Yes;
                    148: char real_header[256];         /* header built here */
                    149: char *myname;                  /* name invoked with */
                    150: char *filename;
                    151: int  *page_select = NULL;      /* array of page selections */
                    152: int  *curr_page_select;
                    153: int  page_low;
                    154: int  page_high;
                    155: int  ipress_file;              /* interpress file descriptor */
                    156: int  null_file;                        /* fd for /dev/null */
                    157: int  line_number;
                    158: int  page_number;
                    159: int  pages_printed = 0;                /* total pages for this interpress file */
                    160: int  special_font = 0;         /* fonts that require special handling */
                    161: int  line_spacing;
                    162: int  tab_amount = 8;
                    163: #ifndef vax11c
                    164: struct passwd *pwd;            /* passwd entry for this user */
                    165: struct stat   file_stat;       /* stat of current file */
                    166: #endif
                    167: 
                    168: # define  Font_Terminal  1
                    169: 
                    170: /* current arguments */
                    171: int  argc;
                    172: char **argv;
                    173: 
                    174: /* font structure definition */
                    175: struct font
                    176: {
                    177:     char *ft_universal_name;
                    178:     char *ft_leaf_name;
                    179:     int  ft_size;
                    180: };
                    181: 
                    182: /* fonts used */
                    183: struct font headfont;
                    184: struct font bodyfont;
                    185: struct font italicfont;
                    186: 
                    187: main(_argc, _argv)
                    188: 
                    189: int  _argc;
                    190: char **_argv;
                    191: 
                    192: {
                    193:     char *ptr;         /* temporary pointers used for loops and such */
                    194:     char *src;
                    195:     char *dest;
                    196:     int length;
                    197:     int i;
                    198:     FILE *file;                /* file currently processing */
                    199: #ifdef vax11c
                    200:     int error;
                    201:     int retlen;
                    202:     char command[256];
                    203:     $DESCRIPTOR(mahadesc,"MAHAENV");
                    204:     $DESCRIPTOR(cmddesc,command);
                    205: #endif
                    206: 
                    207:     /* get our name */
                    208:     if (_argc < 1)
                    209:     {
                    210:        exit(1);
                    211:     }
                    212: 
                    213: #ifdef vax11c
                    214:     myname= _argv[0];
                    215: #else
                    216:     if ((myname = rindex(_argv[0], '/')) == NULL)
                    217:     {
                    218:        myname = _argv[0];
                    219:     }
                    220:     else
                    221:     {
                    222:        myname++;
                    223:     }
                    224: #endif
                    225: 
                    226:     /* get the options specified in the environment (defaults) */
                    227: 
                    228: #ifdef vax11c
                    229:     if ( (error= lib$get_symbol(&mahadesc,&cmddesc,&retlen)) == SS$_NORMAL )
                    230:     {
                    231:        if ( retlen != 0 )
                    232:        {
                    233:            command[retlen & 0xff]= '\0';               /* null terminate string */
                    234:            src= command;
                    235:        /* break the string up into null terminated arguments */
                    236:        /* half the length is a good upper bound on number of arguments */
                    237:                argv = (char **)allocate(strlen(src) / 2);
                    238:                for (argc = 1, ptr = src; *ptr != '\0'; argc++)
                    239:                {
                    240:                    while (*ptr == ' ')
                    241:                        ptr++;
                    242:                    argv[argc] = ptr;
                    243:                    while (*ptr != ' ' && *ptr != '\0')
                    244:                    {
                    245:                        if (*ptr == '"')
                    246:                        {
                    247:                            while (*++ptr != '"' && *ptr != '\0');
                    248:                        }
                    249:                        else if (*ptr == '\'')
                    250:                        {
                    251:                            while (*++ptr != '\'' && *ptr != '\0');
                    252:                        }
                    253:                        ptr++;
                    254:                    }
                    255:                    *ptr++ = '\0';
                    256:                }
                    257: 
                    258:        /* terminate the argument list */
                    259:                argv[argc] = NULL;
                    260: 
                    261:        /* process the options found in the environment */
                    262:                get_options();
                    263:        }
                    264:     }
                    265: 
                    266: #else
                    267:     if ((src = getenv("MAHA")) != NULL)
                    268:     {
                    269:        /* break the string up into null terminated arguments */
                    270:        /* half the length is a good upper bound on number of arguments */
                    271:        argv = (char **)allocate(strlen(src) / 2);
                    272:        for (argc = 1, ptr = src; *ptr != '\0'; argc++)
                    273:        {
                    274:            register char *dst;
                    275:            char quote;
                    276: 
                    277:            while (*ptr == ' ')
                    278:                ptr++;
                    279:            argv[argc] = dst = ptr;
                    280:            while (*ptr != ' ' && *ptr != '\0')
                    281:            {
                    282:                if (*ptr == '"' || *ptr == '\'')
                    283:                {
                    284:                    quote = *ptr++;     /* Save + skip quote */
                    285: 
                    286:                    while( *ptr != quote && *ptr != '\0')
                    287:                        *dst++ = *ptr++;
                    288: 
                    289:                    if (*ptr != '\0')
                    290:                        ptr++;          /* Skip closing quote */
                    291:                }
                    292:                else
                    293:                    *dst++ = *ptr++;
                    294:            }
                    295:            if (*ptr != '\0')
                    296:                ptr++;          /* skip 1st trailing space */
                    297: 
                    298:            *dst = '\0';        /* end arg. */
                    299:        }
                    300: 
                    301:        /* terminate the argument list */
                    302:        argv[argc] = NULL;
                    303: 
                    304:        /* process the options found in the environment */
                    305:        get_options();
                    306:     }
                    307: #endif
                    308: 
                    309:     /* use the real arguments */
                    310:     argc = _argc;
                    311:     argv = _argv;
                    312: 
                    313:     /* process (real) arguments */
                    314:     get_options();
                    315: 
                    316:     /* establish and verify the requested fonts */
                    317:     establish_font(headfont_name, &headfont);
                    318:     establish_font(bodyfont_name, &bodyfont);
                    319:     establish_font(italicfont_name, &italicfont);
                    320: 
                    321: #ifndef vax11c
                    322:     /* get passwd entry for future reference */
                    323:     pwd = getpwuid(geteuid());
                    324: #endif
                    325: 
                    326:     /* setup output file */
                    327:     if (output == NULL)
                    328:     {
                    329: 
                    330:        /* build a temporary file name */
                    331: 
                    332: #ifdef vax11c
                    333:        output= mktemp(template);
                    334: #else
                    335:        output = allocate(1 + 5 + 1 + 2 + 1);
                    336:        (void) sprintf(output, "/tmp/@%d.ip", getpid());
                    337: #endif
                    338:     }
                    339: 
                    340: #ifdef vax11c
                    341:     if ((ipress_file = creat(output, 0, "rfm=udf")) == -1)
                    342: #else
                    343:     if ((ipress_file = creat(output, 0600)) == -1)
                    344: #endif
                    345:     {
                    346:        system_error(output);
                    347:        exit(1);
                    348:     }
                    349:     ip_select(ipress_file);
                    350: 
                    351: #ifndef vax11c
                    352:     /* open the null device for throwing away output */
                    353:     null_file = open("/dev/null", 1);
                    354: 
                    355:     /* set null strings to default values */
                    356:     if (name == NULL)
                    357:     {
                    358:        /* banner name defaults to full name from gecos field */
                    359:        name = pwd->pw_gecos;
                    360: 
                    361:        /* perform expansion and stripping */
                    362:        if ((ptr = index(name, ',')) != NULL)
                    363:        {
                    364:            *ptr = '\0';        /* this affects pwd->pw_gecos, too! */
                    365:        }
                    366:        if (index(name, '&') != NULL)
                    367:        {
                    368:            name = allocate(strlen(name) + strlen(pwd->pw_name) + 1);
                    369:            for (src = pwd->pw_gecos, dest = name; *src != '\0'; src++, dest++)
                    370:            {
                    371:                if (*src == '&')
                    372:                {
                    373:                    for (ptr = pwd->pw_name; *ptr != '\0'; ptr++)
                    374:                    {
                    375:                        *dest++ = *ptr;
                    376:                    }
                    377:                }
                    378:                else
                    379:                {
                    380:                    *dest = *src;
                    381:                }
                    382:            }
                    383:        }
                    384:     }
                    385: #endif
                    386: 
                    387:     if (banner == NULL)
                    388:     {
                    389:        /* banner defaults to file name(s) */
                    390:        if (argc == 0)
                    391:        {
                    392:            banner = "out of the blue";
                    393:        }
                    394:        else
                    395:        {
                    396:            for (length = 0, i = 0; i < argc; i++)
                    397:            {
                    398:                length += strlen(argv[i]) + 2;
                    399:            }
                    400:            banner = allocate(length + 1);
                    401:            for (ptr = banner, i = 0; i < argc; i++)
                    402:            {
                    403:                ptr = strecpy(ptr, argv[i]);
                    404:                ptr = strecpy(ptr, ", ");
                    405:            }
                    406:            ptr -= 2;
                    407:            *ptr = '\0';
                    408:        }
                    409:     }
                    410: 
                    411:     /* unravel the page specifiation */
                    412:     /* we will never need more than strlen(pages) ints to hold the info */
                    413:     if (pages != NULL)
                    414:     {
                    415:        page_select = (int *)allocate(strlen(pages) * sizeof(int));
                    416:        unravel_pages(pages, page_select);
                    417:     }
                    418: 
                    419:     /* write the preamble for the interpress file */
                    420:     AppendOp(OP_beginBlock);
                    421:     AppendOp(OP_beginBody);    /* preamble start */
                    422: 
                    423:     /* setup font definitions in frame */
                    424:     SetupFont(headfont.ft_universal_name,
                    425:              headfont.ft_size * 10.,
                    426:              F_headfont);
                    427:     SetupFont(bodyfont.ft_universal_name,
                    428:              bodyfont.ft_size * 10.,
                    429:              F_bodyfont);
                    430:     SetupFont(italicfont.ft_universal_name,
                    431:              headfont.ft_size * 10.,           /* use headfont's size */
                    432:              F_italicfont);
                    433: 
                    434:     /* remember special fonts */
                    435:     if (strcmp(bodyfont.ft_leaf_name, "Terminal") == 0)
                    436:     {
                    437:        special_font = Font_Terminal;
                    438:     }
                    439: 
                    440:     /* save scaling transform that uses 1/10 point co-ordinate system */
                    441:     top_margin = (rflg ? Page_width : Page_length) - Orig_y;
                    442: 
                    443:     if (tflg)          /* the user may not want headings... */
                    444:        top_margin += Header_to_orig_y; /* use heading area */
                    445: 
                    446:     bottom_margin = 2 * Sixth_INCH;
                    447:     right_margin = (rflg ? Page_length : Page_width) - Orig_x;
                    448:     column_separation = (right_margin - Orig_x) / columns;
                    449:     line_spacing = (bodyfont.ft_size +
                    450:                  ((bodyfont.ft_size > 8) ? 2 : 0)) * 10;
                    451:     if (rflg)
                    452:     {
                    453:        /* we need a rotation transform, too */
                    454:        Rotate(90.);
                    455:        Translate((double)Page_width, (double)0);
                    456:     }
                    457:     AppendRational(353L,10000000L);
                    458:     AppendOp(OP_scale);
                    459:     if (rflg)
                    460:     {
                    461:        AppendOp(OP_concat);
                    462:        AppendOp(OP_concat);
                    463:     }
                    464:     AppendInteger((long) F_transform);
                    465:     AppendOp(OP_fset);
                    466: 
                    467:     AppendOp(OP_endBody);      /* end preamble */
                    468: 
                    469:     if (argc == 0)
                    470:     {
                    471:        /* no filenames -- do standard input */
                    472:        filename = NULL;
                    473:        do_file(stdin);
                    474:     }
                    475: 
                    476:     for (; argc > 0; argc--, argv++)
                    477:     {
                    478:        filename = argv[0];
                    479:        if (strcmp(filename, "-") == 0)
                    480:        {
                    481:            /* this is really standard input */
                    482:            filename = NULL;
                    483:            do_file(stdin);
                    484:        }
                    485:        else
                    486:        {
                    487:            /* open the file */
                    488:            if ((file = fopen(filename, "r")) == NULL)
                    489:            {
                    490:                system_error(filename);
                    491:            }
                    492:            else
                    493:            {
                    494:                do_file(file);
                    495:                (void) fclose(file);
                    496:            }
                    497:        }
                    498:     }
                    499: 
                    500:     /* wrap up the output */
                    501:     ip_select(ipress_file);
                    502:     AppendOp(OP_endBlock);
                    503:     ip_close();
                    504: 
                    505:     /* send to the printer */
                    506:     if (send_to_printer)
                    507:     {
                    508:        if (pages_printed == 0)
                    509:        {
                    510:            /* don't print anything but remove temporary */
                    511: #ifdef vax11c
                    512:            delete(output);
                    513: #else
                    514:            (void) unlink(output);
                    515: #endif
                    516:        }
                    517:        else
                    518:        {
                    519: #ifdef vax11c
                    520:            char buff[256];
                    521:            int wait= 0;
                    522:            $DESCRIPTOR(buffdesc,buff);
                    523: 
                    524:            (void) strcpy(buff,"xpress/noformat ");
                    525:            (void) strcat(buff,output);
                    526:            buffdesc.dsc$w_length= strlen(buff);
                    527:            if ( (error= lib$spawn(&buffdesc,0,0,&wait)) != SS$_NORMAL )
                    528:            {
                    529:                fprintf(stderr,"\nFile %s contains interpress master\n",output);
                    530:                exit(error);
                    531:            }
                    532:            delete(output);
                    533: #else
                    534:            char *buff;
                    535:    
                    536:            /* exec a "qip" to queue the file */
                    537:            buff = allocate(strlen(name) + 1 + 1);
                    538:            (void) strcpy(buff, "F");
                    539:            (void) strcat(buff, name);
                    540: 
                    541:            if (printer)
                    542:                execlp(QIP, "qip", "-q", printer, "-c", copies, "-nc", "-nk",
                    543:                    "-t", banner, "-x", buff, output, 0);
                    544:            else
                    545:                execlp(QIP, "qip", "-c", copies, "-nc", "-nk",
                    546:                    "-t", banner, "-x", buff, output, 0);
                    547: 
                    548:            fprintf(stderr, "Can't execl the queing program: %s\n", QIP);
                    549:            perror(QIP);
                    550:            fprintf(stderr, "File %s contains interpress master.\n", output);
                    551:            exit(1);
                    552: #endif
                    553:        }
                    554:     }
                    555: }
                    556: 
                    557: get_options()
                    558: 
                    559: {
                    560:     while (--argc > 0)
                    561:     {
                    562:        argv++;
                    563:        if (!process_arg())
                    564:        {
                    565:            break;
                    566:        }
                    567:     }
                    568: }
                    569: 
                    570: /*
                    571:  *  unravel_pages(str, spec) - unravel the page range specification in "str"
                    572:  *                            into integer pairs in "spec".  The first two
                    573:  *                            ints in "spec" bound the first range of pages,
                    574:  *                            the next two bound the second range, and so on.
                    575:  *                            The array is terminated with the pair 0, 0.
                    576:  */
                    577: 
                    578: unravel_pages(str, spec)
                    579: 
                    580: char *str;
                    581: int  *spec;
                    582: 
                    583: {
                    584:     int last_num = 0;
                    585:     int this_num = 0;
                    586:     register char ch;
                    587:     boolean is_range = No;
                    588:     boolean bad_spec = No;
                    589:     boolean done = No;
                    590: 
                    591: # define    Start_new_num      (last_num = this_num, this_num = 0)
                    592: 
                    593:     while (!done)
                    594:     {
                    595:        if ((ch = *str++) == '\0')
                    596:        {
                    597:            /* set "done" flag and pretend it's the end of a number */
                    598:            done = Yes;
                    599:            ch = ',';
                    600:        }
                    601:        if (ch >= '0' && ch <= '9')
                    602:        {
                    603:            this_num *= 10;
                    604:            this_num += ch - '0';
                    605:        }
                    606:        else if (ch == '-')
                    607:        {
                    608:            if (this_num < last_num && *str != '\0')
                    609:            {
                    610:                bad_spec = Yes;
                    611:            }
                    612:            *spec++ = this_num;
                    613:            Start_new_num;
                    614:            is_range = Yes;
                    615:        }
                    616:        else if (ch == ',')
                    617:        {
                    618:            if (this_num < last_num)
                    619:            {
                    620:                bad_spec = Yes;
                    621:            }
                    622:            *spec++ = this_num;
                    623:            if (is_range)
                    624:            {
                    625:                is_range = No;
                    626:            }
                    627:            else
                    628:            {
                    629:                *spec++ = this_num;
                    630:            }
                    631:            Start_new_num;
                    632:        }
                    633:        else
                    634:        {
                    635:            fprintf(stderr, "%s: bad character in page specification\n",
                    636:                myname);
                    637:            exit(1);
                    638:        }
                    639:     }
                    640:     if (*--spec == 0)
                    641:     {
                    642:        *spec = 1 << 15;        /* infinity */
                    643:     }
                    644:     if (bad_spec)
                    645:     {
                    646:        fprintf(stderr,
                    647:            "%s: pages should be given in non-descending order.\n",
                    648:            myname);
                    649:     }
                    650: }
                    651: 
                    652: process_arg()
                    653: 
                    654: {
                    655:     register char ch;
                    656:     register int  temp;
                    657:     register char *p1;
                    658:     register char *p2;
                    659: 
                    660:     if (argv[0][0] == '-')
                    661:     {
                    662:        if ((ch = argv[0][1]) > '0' && ch <= '9')
                    663:        {
                    664:            /* this is a column count specifier */
                    665:            columns = ch - '0';
                    666:        }
                    667:        else switch(ch)
                    668:        {
                    669:            case '\0':          /* not an option */
                    670:                return(No);
                    671: 
                    672:            case 'b':
                    673:                banner = next_arg();
                    674:                break;
                    675: 
                    676:            case 'c':
                    677:                temp = atoi(copies = next_arg());
                    678:                if (temp < 1)
                    679:                {
                    680:                    fprintf(stderr,
                    681:                        "%s: bogus number of copies; you only get one!\n",
                    682:                        myname);
                    683:                        copies = "1";
                    684:                }
                    685:                break;
                    686: 
                    687:            case 'f':
                    688:                bodyfont_name = next_arg();
                    689:                break;
                    690: 
                    691:            case 'F':
                    692:                headfont_name = next_arg();
                    693:                break;
                    694: 
                    695:            case 'H':                   /* replace header */
                    696:                tflg = No;
                    697:                header = next_arg();
                    698:                break;
                    699: 
                    700:            case 'h':                   /* append to header */
                    701:                tflg = No;
                    702:                p1 = next_arg();
                    703:                p2 = allocate(strlen(header) + strlen(p1) + 1);
                    704:                (void) strcpy(p2, header);
                    705:                (void) strcat(p2, "      ");
                    706:                (void) strcat(p2, p1);
                    707:                header = p2;
                    708:                break;
                    709: 
                    710:            case 'l':
                    711:                tflg = lflg = Yes;
                    712:                break;
                    713: 
                    714:            case 'n':
                    715:                name = next_arg();
                    716:                break;
                    717: 
                    718:            case 'o':
                    719:                output = next_arg();
                    720:                send_to_printer = No;
                    721:                break;
                    722: 
                    723:            case 'P':
                    724:                printer = next_arg();
                    725:                break;
                    726: 
                    727:            case 'r':
                    728:                rflg = Yes;
                    729:                break;
                    730: 
                    731:            case 'R':
                    732:                rflg = No;
                    733:                break;
                    734: 
                    735:            case 's':
                    736:                pages = next_arg();
                    737:                break;
                    738: 
                    739:            case 't':
                    740:                tflg = Yes;
                    741:                break;
                    742: 
                    743:            default:
                    744:                fprintf(stderr, "%s: unknown option '%c'\n", myname, ch);
                    745:        }
                    746:        return(Yes);
                    747:     }
                    748:     else
                    749:     {
                    750:        return(No);
                    751:     }
                    752: }
                    753: 
                    754: char *next_arg()
                    755: 
                    756: {
                    757:     if (argv[0][2] == '\0')
                    758:     {
                    759:        if (--argc > 0)
                    760:        {
                    761:            return((++argv)[0]);
                    762:        }
                    763:        else
                    764:        {
                    765:            argv++;
                    766:            return(NULL);
                    767:        }
                    768:     }
                    769:     else
                    770:     {
                    771:        return(&(argv[0][2]));
                    772:     }
                    773: }
                    774: 
                    775: /*
                    776:  *  establish_font(name, font) - break apart the parts of the string "name"
                    777:  *                              and fill in the structure pointed to by
                    778:  *                              "font".  Also, verify that the font requested
                    779:  *                              actually exists.  This routine also
                    780:  *                              understands universal font names.
                    781:  */
                    782: 
                    783: establish_font(name, font)
                    784: 
                    785: char *name;
                    786: struct font *font;
                    787: 
                    788: {
                    789:     register char *unamep;
                    790:     register char *ptr;
                    791:     char *slashp;
                    792:     register int size;
                    793: 
                    794:     if (name[0] != '/')
                    795:     {
                    796:        /* not a universal name -- put the default on the front */
                    797:        font->ft_universal_name = unamep =
                    798:                allocate(strlen(Default_universal_prefix) +
                    799:                         strlen(name) + 1);
                    800:        (void) strcpy(unamep, Default_universal_prefix);
                    801:        (void) strcat(unamep, name);
                    802:     }
                    803:     else
                    804:     {
                    805:        /* already is a universal name -- just allocate space for it */
                    806:        font->ft_universal_name = unamep = allocate(strlen(name));
                    807: 
                    808:        /* copy in the whole name, without the leading slash */
                    809:        (void) strcpy(unamep, name + 1);
                    810:     }
                    811: 
                    812:     /* strip size off the end, if it is there */
                    813:     if ((slashp = ptr = rindex(unamep, '/')) != NULL)
                    814:     {
                    815:        register char ch;
                    816: 
                    817:        size = 0;
                    818:        while ((ch = *++ptr) != '\0')
                    819:        {
                    820:            if (ch < '0' || ch > '9')
                    821:            {
                    822:                /* last element is not a number -- no point size */
                    823:                size = 0;
                    824:                break;
                    825:            }
                    826: 
                    827:            /* shift this digit in */
                    828:            size *= 10;
                    829:            size += (ch - '0');
                    830:        }
                    831: 
                    832:        /* if no point size, use default */
                    833:        if (size == 0)
                    834:        {
                    835:            font->ft_size = 10;
                    836:        }
                    837:        else
                    838:        {
                    839:            font->ft_size = size;
                    840:            *slashp = '\0';
                    841:        }
                    842:     }
                    843: 
                    844:     /* set pointer to last element */
                    845:     if ((ptr = rindex(unamep, '/')) != NULL)
                    846:     {
                    847:        font->ft_leaf_name = ptr + 1;
                    848:     }
                    849:     else
                    850:     {
                    851:        font->ft_leaf_name = font->ft_universal_name;
                    852:     }
                    853: }
                    854: 
                    855: do_file(file)
                    856: 
                    857: FILE *file;
                    858: 
                    859: {
                    860:     char *src;
                    861:     char *dest;
                    862:     char input_line[Line_size];
                    863:     char line_buffer[Line_size];
                    864:     char ch;
                    865:     int current_line;
                    866:     int lines_on_page;
                    867:     int length;
                    868:     int column;
                    869:     
                    870: #ifndef vax11c
                    871:     /* fstat it to get information displayed in the header */
                    872:     if (fstat(fileno(file), &file_stat) == -1)
                    873:     {
                    874:        system_error("fstat botched");
                    875:        return;
                    876:     }
                    877: #endif
                    878: 
                    879:     /* reset essentials */
                    880:     page_number = 0;
                    881:     line_number = 1;
                    882:     lines_on_page = 0;
                    883:     curr_page_select = page_select;
                    884:     if (pages != NULL)
                    885:     {
                    886:        page_low  = page_select[0];
                    887:        page_high = page_select[1];
                    888:     }
                    889:     current_line = top_margin;
                    890: 
                    891:     /*
                    892:      *  Strangeness:  page_number is incremented by page_start and
                    893:      *  line_number is incremented in the "while(fgets..." loop.
                    894:      */
                    895: 
                    896:     /* start the first page */
                    897:     page_start();
                    898: 
                    899:     /*
                    900:      *  More strangeness:  we had to set line_number to 1 to trick
                    901:      *  page_start into reporting the right line count in the header.  Now
                    902:      *  we reset it to 0 before entering the read/print loop.
                    903:      */
                    904:     line_number = 0;
                    905: 
                    906:     while (fgets(input_line, Line_size, file) != NULL)
                    907:     {
                    908:        /* new line */
                    909:        line_number++;
                    910: 
                    911:        /* remember the length */
                    912:        length = strlen(input_line);
                    913: 
                    914:        /* nuke any trailing newline */
                    915:        if (input_line[length - 1] == '\n')
                    916:        {
                    917:            input_line[--length] = '\0';
                    918:        }
                    919: 
                    920:        if (lflg ? lines_on_page >= 66 : current_line < bottom_margin)
                    921:        {
                    922:            /* start a new page */
                    923:            page_end(No);
                    924:            page_start();
                    925:            lines_on_page = 0;
                    926: 
                    927:            /* remember, y goes backwards */
                    928:            current_line = top_margin;
                    929:        }
                    930: 
                    931:        /* make sure that the line actually contains something */
                    932:        if (input_line[0] != '\0')
                    933:        {
                    934:            /* set x and y for the beginning of the line */
                    935:            Setxy((double)left_margin, (double)current_line);
                    936: 
                    937:            /* copy from input_line to line_buffer making any necessary
                    938:               changes along the way */
                    939:            column = 0;
                    940:            src = input_line;
                    941:            dest = line_buffer;
                    942:            while ((ch = *src) != '\0')
                    943:            {
                    944:                switch(ch)
                    945:                {
                    946:                    case '\r':          /* carriage return */
                    947:                        *dest = '\0';
                    948:                        if (line_buffer[0] != '\0')
                    949:                        {
                    950:                            ShowString(line_buffer);
                    951:                        }
                    952:                        Setxy((double)left_margin, (double)current_line);
                    953:                        dest= line_buffer;
                    954:                        break;
                    955: 
                    956:                    case '\f':          /* new page after this line */
                    957:                        current_line = bottom_margin;
                    958:                        lines_on_page = 66;
                    959:                        break;
                    960: 
                    961:                    case '\t':          /* tab expansion */
                    962:                        do
                    963:                        {
                    964:                            *dest++ = ' ';
                    965:                            column++;
                    966:                        } while (column % tab_amount != 0);
                    967:                        break;
                    968: 
                    969:                    case '$':
                    970:                        *dest++ = '\244';
                    971:                        column++;
                    972:                        break;
                    973: 
                    974:                    case '-':
                    975:                        if (special_font == Font_Terminal)
                    976:                        {
                    977:                            /* heavy hackery here */
                    978:                            *dest = '\0';
                    979:                            ShowString(line_buffer);
                    980:                            Setyrel(-20.);
                    981:                            ShowString("\305");
                    982:                            Setyrel(20.);
                    983:                            dest = line_buffer;
                    984:                            column++;
                    985:                            break;
                    986:                        }
                    987:                        /* else fall thru ... */
                    988: 
                    989:                    default:
                    990:                        *dest++ = ch;
                    991:                        column++;
                    992:                }
                    993:                src++;
                    994:            }
                    995:            *dest = '\0';
                    996:            if (line_buffer[0] != '\0')
                    997:            {
                    998:                ShowString(line_buffer);
                    999:            }
                   1000:        }
                   1001: 
                   1002:        /* advance the line counters */
                   1003:        current_line -= line_spacing;
                   1004:        lines_on_page++;
                   1005:     }
                   1006: 
                   1007:     /* wrap up the file */
                   1008:     page_end(Yes);
                   1009: }
                   1010: 
                   1011: /*
                   1012:  *  page handling:  a distinction is made between virtual pages and actual
                   1013:  *  pages.  A virtual page is one series of lines from the file that appears
                   1014:  *  vertically on the printed page.  The actual page is the page as the
                   1015:  *  printer prints it (a printed page, if you will).  There may be several
                   1016:  *  virtual pages on one actual page.  The page_start and page_end routines
                   1017:  *  that follow start and terminate virtual pages.  The mapping between
                   1018:  *  virtual and actual pages is a function of the options specified by the
                   1019:  *  user.  If the user requests two column output then there will be two
                   1020:  *  virtual pages for every actual page.  These pages will sit side-by-side on
                   1021:  *  the actual page.  The mapping is accomplished by changing the variables
                   1022:  *  left_margin and right_margin.  "page_start" also handles printing of the
                   1023:  *  page header, since there is only one of these on every actual page.
                   1024:  */
                   1025: 
                   1026: static int current_column;
                   1027: 
                   1028: page_start()
                   1029: 
                   1030: {
                   1031:     boolean in_set;
                   1032: 
                   1033: #ifdef vax11c
                   1034:     long bintim;
                   1035: #endif
                   1036: 
                   1037:     /* reset the column count if starting a new file */
                   1038:     if (line_number == 1)
                   1039:     {
                   1040:        current_column = 0;
                   1041:     }
                   1042: 
                   1043:     /* either move the left margin or put out a new page */
                   1044:     if (current_column != 0)
                   1045:     {
                   1046:        left_margin += column_separation;
                   1047:     }
                   1048:     else
                   1049:     {
                   1050:        /* increment page count and reset margin */
                   1051:        page_number++;
                   1052:        left_margin = Orig_x;
                   1053: 
                   1054:        /* is it in the page specification set? */
                   1055:        if (page_select == NULL)
                   1056:        {
                   1057:            /* every page is in the set if there is no specification */
                   1058:            in_set = Yes;
                   1059:        }
                   1060:        else
                   1061:        {
                   1062:            if (page_low <= page_number && page_number <= page_high)
                   1063:            {
                   1064:                in_set = Yes;
                   1065:                ip_select(ipress_file);
                   1066:                if (page_number == page_high)
                   1067:                {
                   1068:                    /* at the top of the current range -- time to move up */
                   1069:                    curr_page_select += 2;
                   1070:                    page_low  = curr_page_select[0];
                   1071:                    page_high = curr_page_select[1];
                   1072:                }
                   1073:            }
                   1074:            else
                   1075:            {
                   1076:                /* not in set -- redirect output to null device */
                   1077:                in_set = No;
                   1078:                ip_select(null_file);
                   1079:            }
                   1080:        }
                   1081: 
                   1082:        if (in_set)
                   1083:        {
                   1084:            register char *src;
                   1085:            register char *dst;
                   1086:            register char ch;
                   1087: 
                   1088:            /* increment total page count */
                   1089:            pages_printed++;
                   1090: 
                   1091:            /* output stuff for new ip page */
                   1092:            AppendOp(OP_beginBody);
                   1093:        
                   1094:            /* set the transformation */
                   1095:            Fget(F_transform);
                   1096:            AppendOp(OP_concatt);
                   1097: 
                   1098:            /* build the header if we need to print it */
                   1099:            if (!tflg)
                   1100:            {
                   1101:                /* move characters from header to real_header */
                   1102:                /* and expand format items along the way.     */
                   1103:                src = header;
                   1104:                dst = real_header;
                   1105:                while ((ch = *src) != '\0')
                   1106:                {
                   1107:                    if (ch == '%')
                   1108:                    {
                   1109:                        switch(ch = *++src)
                   1110:                        {
                   1111:                            case 'f':           /* file name */
                   1112:                                dst = strecpy(dst,
                   1113:                                            filename == NULL ? 
                   1114:                                                "Standard input" :
                   1115:                                                filename);
                   1116:                                break;
                   1117:     
                   1118:                            case 't':           /* mtime */
                   1119: #ifdef vax11c
                   1120: 
                   1121:                                time(&bintim);
                   1122:                                strncpy(dst,ctime(&bintim), 24);
                   1123:                                dst += 24;
                   1124: #else
                   1125:                                /*
                   1126:                                 *  ctime returns a 26 character string that
                   1127:                                 *  has a newline and null at the end.
                   1128:                                 *  26 - 2 == 24.
                   1129:                                 */
                   1130:                                if (file_stat.st_mtime != 0)
                   1131:                                {
                   1132:                                    (void) strncpy(dst,ctime(&file_stat.st_mtime),24);
                   1133:                                    dst += 24;
                   1134:                                }
                   1135: #endif
                   1136:                                break;
                   1137:     
                   1138:                            case 'p':           /* page number */
                   1139:                                dst = itoa(dst, page_number);
                   1140:                                break;
                   1141:     
                   1142:                            case 'l':           /* line number */
                   1143:                                dst = itoa(dst, line_number);
                   1144:                                break;
                   1145:     
                   1146:                            case '\0':          /* end of the string */
                   1147:                                src--;          /* maintain loop invariant */
                   1148:                                break;
                   1149:     
                   1150:                            default:            /* copy the character */
                   1151:                                *dst++ = ch;
                   1152:                                /* break; */
                   1153:                        }
                   1154:                    }
                   1155:                    else
                   1156:                    {
                   1157:                        *dst++ = ch;
                   1158:                    }
                   1159:                    src++;
                   1160:                }
                   1161:     
                   1162:                /* terminate the real header */
                   1163:                *dst = '\0';
                   1164:            
                   1165:                /* display the header */
                   1166:                Setxy((double)(left_margin - Header_to_orig_x),
                   1167:                      (double)(top_margin + Header_to_orig_y));
                   1168:                Setfont(F_headfont);
                   1169:                ShowString(real_header);
                   1170:            }
                   1171:        }
                   1172:     }
                   1173: 
                   1174:     /* select the body font */
                   1175:     Setfont(F_bodyfont);
                   1176: }
                   1177: 
                   1178: page_end(eof)
                   1179: 
                   1180: int eof;
                   1181: 
                   1182: {
                   1183:     if ((current_column = ++current_column % columns) == 0 || eof)
                   1184:     {
                   1185:        AppendOp(OP_endBody);
                   1186:     }
                   1187: }
                   1188: 
                   1189: char *strecpy(dest, src)
                   1190: 
                   1191: register char *src;
                   1192: register char *dest;
                   1193: 
                   1194: {
                   1195:     while (*dest++ = *src++)
                   1196:        ;
                   1197:     return(--dest);
                   1198: }
                   1199: 
                   1200: char *itoa(buff, val)
                   1201: 
                   1202: char *buff;
                   1203: int  val;
                   1204: 
                   1205: {
                   1206:     char tbuff[12];    /* will build number here -- max of 10 digits */
                   1207:     register char *ptr = tbuff + 11;
                   1208: 
                   1209:     *ptr-- = '\0';
                   1210:     while (val != 0)
                   1211:     {
                   1212:        *ptr-- = (val % 10) + '0';
                   1213:        val /= 10;
                   1214:     }
                   1215:     return(strecpy(buff, ++ptr));
                   1216: }
                   1217: 
                   1218: /*
                   1219:  *  allocate(space) - allocate "space" bytes with sbrk.  This routine uses a
                   1220:  *                   fairly naive algorithm.  It sbrk-s space in Break_size
                   1221:  *                   chunks and allocates space from a chunk until a request
                   1222:  *                   for more space than is left in the chunk is made.  Then,
                   1223:  *                   it allocates a new chunk.  The unused space at the end
                   1224:  *                   of the old chunk remains unused.  This does NOT depend
                   1225:  *                   on sbrk returning contiguous chunks of memory during the
                   1226:  *                   life of the program.  If the request is greater than
                   1227:  *                   Break_size, the next multiple of Break_size greater
                   1228:  *                   than the request size is chosen.
                   1229:  */
                   1230: 
                   1231: char *allocate(space)
                   1232: 
                   1233: int space;
                   1234: 
                   1235: {
                   1236:     static char *hi_water = NULL;
                   1237:     static char *max_alloc = NULL;
                   1238:     register char *ptr;
                   1239: 
                   1240:     if (hi_water == NULL || max_alloc + space > hi_water)
                   1241:     {
                   1242:        int alloc_size = (space <= Break_size
                   1243:                          ? Break_size
                   1244:                          : ((space + Break_size-1) / Break_size) * Break_size);
                   1245: 
                   1246:        hi_water = sbrk(alloc_size);
                   1247: 
                   1248:        if ((int)hi_water == -1)
                   1249:        {
                   1250:            system_error("out of space");
                   1251:            exit(1);
                   1252:        }
                   1253: 
                   1254:        max_alloc = hi_water + alloc_size - 1;
                   1255:     }
                   1256: 
                   1257:     ptr = hi_water;
                   1258:     hi_water += space;
                   1259:     return(ptr);
                   1260: }
                   1261: 
                   1262: system_error(message)
                   1263: 
                   1264: char *message;
                   1265: 
                   1266: {
                   1267:     int saved_errno;
                   1268: 
                   1269:     /* value of errno not preserved by fprintf */
                   1270:     saved_errno = errno;
                   1271:     fprintf(stderr, "%s: ", myname);
                   1272:     errno = saved_errno;
                   1273:     perror(message);
                   1274: }
                   1275: 
                   1276: #ifdef vax11c
                   1277: char *rindex(string, c)
                   1278: char *string, c;
                   1279: {
                   1280:        register char *pos;
                   1281: 
                   1282:        pos = 0;
                   1283:        do {
                   1284:                if (*string == c)
                   1285:                        pos = string;
                   1286:        } while (*string++);
                   1287:        return(pos);
                   1288: }
                   1289: 
                   1290: #endif
                   1291: 

unix.superglobalmegacorp.com

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