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

unix.superglobalmegacorp.com

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