Annotation of 43BSDTahoe/new/dipress/src/bin/maha/maha.c, revision 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.