Annotation of cci/usr/src/usr.bin/bsc/cmd/batch/bscpr.c, revision 1.1

1.1     ! root        1: /*     D.L.Buck and Associates, Inc. - 10/16/84
        !             2:  *
        !             3:  *     COPYRIGHT NOTICE:
        !             4:  *             Copyright c 10/16/84 - An unpublished work by 
        !             5:  *             D.L.Buck and Associates, Inc.
        !             6:  *
        !             7:  *     PROPRIETARY RIGHTS NOTICE:
        !             8:  *             All rights reserved. This document and program contains
        !             9:  *             proprietary information of D.L.Buck and Associates,Inc.
        !            10:  *             of San Jose, California, U.S.A., embodying confidential
        !            11:  *             information,  ideas, and expressions,  no part of which
        !            12:  *             may be reproduced, or transmitted in any form or by any
        !            13:  *             means,  electronic,  mechanical,  or otherwise, without
        !            14:  *             the written permission of D.L.Buck and Associates, Inc.
        !            15:  *
        !            16:  * NAME
        !            17:  *     bscpr -- BISYNC batch file print utility
        !            18:  *
        !            19:  * SYNOPSIS
        !            20:  *     bscpr [-ascii] [-page=pp] [chan=lineno ...] [file]
        !            21:  *
        !            22:  * DESCRIPTION
        !            23:  *     bscpr paginates a file which contains IBM 2780 or 3780 terminal
        !            24:  *     control characters and escape sequences which control paper motion
        !            25:  *     on a line printer.
        !            26:  *
        !            27:  * ALGORITHM
        !            28:  *     I. initialize, get options from command line
        !            29:  *             A. special instructions coded in ASCII or EBCDIC
        !            30:  *             B. page length
        !            31:  *             C. channel assignments
        !            32:  *             D. get and open file, if specified
        !            33:  *
        !            34:  *     II. while not at end of file:
        !            35:  *             A. read a line
        !            36:  *             B. set character pointer (s1) to beginning of line
        !            37:  *             C. if s1 points to an ESC character, this is the
        !            38:  *                beginning of a special instruction (Escape) sequence.
        !            39:  *             D. if the next character is an HT (horizontal tab) character:
        !            40:  *                     1. set up tabs in the tab rack according to
        !            41:  *                        instructions on this line
        !            42:  *             E. output the line a character at a time, expanding the tabs
        !            43:  *                along the way
        !            44:  *             F. do line feeds
        !            45:  *
        !            46:  *    III. close the file
        !            47:  */
        !            48: 
        !            49: #include <stdio.h>
        !            50: #include "local.h"
        !            51: 
        !            52: #ifndef lint
        !            53: static char sccsid[] = "@(#)bscpr.c    1.8 REL";
        !            54: #endif
        !            55: 
        !            56: #define RCDLN  512     /* max allowed record length */
        !            57: #define DEFLINES 66    /* default max lines allowed per page */
        !            58: 
        !            59: #define        ESC     0x1b    /* ASCII escape                                 */
        !            60: #define        HT      0x09    /* ASCII Horizontal Tab format effector         */
        !            61: #define        VT      0x0b    /* ASCII Vertical Tab format effector           */
        !            62: #define        FF      0x0c    /* ASCII Form Feed format effector              */
        !            63: #define DC1    0x11    /* select printer code                          */
        !            64: 
        !            65: #define YES 1
        !            66: #define NO 0
        !            67: char tabrack[RCDLN];   /* contains horizontal tab positions */
        !            68: char line[RCDLN];      /* simple data record */
        !            69: char *index(); 
        !            70: int channel[13];        /* contains "vertical tabbing" instructions -- line
        !            71:                        numbers on the page corresponding to printer channels */
        !            72: 
        !            73: /* the arrays asctab and ebctab are used to decode vertical tab instructions and
        !            74: line skip instructions embedded in input lines in ASCII or EBCDIC, respectively.
        !            75: negative numbers correspond to vertical tab instructions (ESC<alpha> sequences);
        !            76: e.g. ESC B corresponds to asctab or ebctab -2, meaning "skip to channel 2".
        !            77: the positive numbers correspond to line skip instructions; 1=skip 1 line, 2=skip
        !            78: 2 lines, 3=skip 3 lines (all after printing the current one).
        !            79: 
        !            80:               A  B  C  D  E  F  G  H  I   J   K   L M N O P Q R S T U V W X Y*/
        !            81: int asctab[]={-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,0,1,1,1,1,2,3,1,1,1,1,1,1,
        !            82:        1}; /* <-Z */
        !            83: 
        !            84: /*            A  B  C  D  E  F  G  H  I   J   K   L M N O P Q R S T U V W X Y*/
        !            85: int ebctab[]={-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,0,1,1,1,1,1,2,3,1,1,1,1,1,
        !            86:        1}; /* <-Z */
        !            87: 
        !            88: int linect = 1;                /* current position on page                     */
        !            89: int maxlines;          /* maximum # of lines per page */
        !            90: void exit();
        !            91: 
        !            92: main (argc,argv)
        !            93: int argc;
        !            94: char *argv[];
        !            95: {
        !            96:        int i;
        !            97:        int chan;       /* pulled-out channel goes here */
        !            98:        int lineno;     /* pulled-out line# channel corresponds to goes here */
        !            99:        int maxused;    /* max line # referred to in chan=line */
        !           100:        int usedin;     /* chan having max line# above */
        !           101:        char *pos;
        !           102:        register char *s1,*s2;
        !           103:        int ascii;      /* flags ASCII or EBCDIC esc sequence (YES or NO) */
        !           104:        FILE *bscfile;          /* input file to be paginated           */
        !           105:        FILE *fopen();          /* file open function                   */
        !           106: 
        !           107:        bscfile = stdin;        /* default input file is the terminal   */
        !           108:        ascii = NO;             /* default transmission code is EBCDIC  */
        !           109:        channel[1] = 1;         /* channel 1 is always top-of-form      */
        !           110:        maxlines = channel[12] =DEFLINES;  /* default page length       */
        !           111:        maxused = 1;
        !           112:        usedin = 1;
        !           113: 
        !           114:        for (i=1;i<argc;++i) {  /* get options from command line        */
        !           115:                 if (strcmp(argv[i],"-ascii") == 0) {
        !           116:                        ascii = YES;
        !           117:                        continue;
        !           118:                }
        !           119: 
        !           120:                /* pull out maxlines here if in command line */
        !           121:                 if (strncmp(argv[i],"-page=",6) == 0) {
        !           122:                        if (argv[i][6] >= '0' && argv[i][6] <= '9')
        !           123:                                maxlines = atoi(&argv[i][6]);
        !           124:                        else {
        !           125:                                fprintf(stderr,
        !           126:                                 "bscpr: not a numeric <%s>\n",argv[i]);
        !           127:                                exit(1);
        !           128:                        }
        !           129: 
        !           130:                        channel[12] = maxlines;
        !           131:                        if (maxused > maxlines) {
        !           132:                                 fprintf(stderr,"%s %d %s\n",
        !           133:                                 "bscpr: line assignment for channel",usedin,
        !           134:                                 "is greater than page length");
        !           135:                                exit(1);
        !           136:                        }
        !           137:                        continue;
        !           138:                }
        !           139: 
        !           140:                /* get channel assignments */
        !           141:                if ((pos=index(argv[i],'=')) != NULL) {
        !           142:                        if (argv[i][0] >= '0' && argv[i][0] <= '9' &&
        !           143:                            pos[1] >= '0' && pos[1] <= '9') {
        !           144:                                chan = atoi(argv[i]);
        !           145:                                lineno = atoi(&pos[1]);
        !           146:                        } else {
        !           147:                                fprintf(stderr,
        !           148:                                 "bscpr: not a numeric <%s>\n",argv[i]);
        !           149:                                exit(1);
        !           150:                        }
        !           151: 
        !           152:                        if (chan < 2 || chan > 12) {
        !           153:                                fprintf(stderr,
        !           154:                                "bscpr: channel number not 2 to 12 <%s>\n",
        !           155:                                        argv[i]);
        !           156:                                exit(1);
        !           157:                        }
        !           158:                        /* check that assignment's less than page length */
        !           159:                        if (lineno > maxlines) {
        !           160:                                 fprintf(stderr,"%s %d %s\n",
        !           161:                                 "bscpr: line assignment for channel",chan,
        !           162:                                 "is greater than page length");
        !           163:                                exit(1);
        !           164:                        }
        !           165: 
        !           166:                        channel[chan] = lineno;
        !           167:                        if (lineno > maxused) { /* set max line# used */
        !           168:                                maxused = lineno;
        !           169:                                usedin = chan;
        !           170:                        }
        !           171:                        continue;
        !           172:                }
        !           173: 
        !           174:                /* ...get filename (if any specified)...
        !           175:                   first check that, if this arg isn't a flag or a
        !           176:                   channel assignment, that it's the last arg. If it
        !           177:                   isn't, it's an illegal option specification */
        !           178: 
        !           179: 
        !           180:                if (argv[i][0] == '-' || i < argc-1) {
        !           181:                        fprintf(stderr,
        !           182:                                "bscpr: unrecognized option (%s)\n",argv[i]);
        !           183:                        exit(1);
        !           184:                }
        !           185: 
        !           186:                /* open it if it's okay */
        !           187:                 if ((bscfile=fopen(argv[i],"r")) == NULL) {
        !           188:                        fprintf(stderr,"bscpr: %s not found\n",argv[i]);
        !           189:                        exit(1);
        !           190:                }
        !           191:        }
        !           192: 
        !           193: /* now print the file */
        !           194: 
        !           195:        while (fgets(line,(RCDLN),bscfile) != NULL) {
        !           196:                s1 = line;
        !           197:                /* Check for Tab Rack: ESC HT .....                     */
        !           198:                if (s1[0] == ESC && s1[1] == HT) {
        !           199:                        s1 = &line[2];  /* point beyond ESC HT sequence */
        !           200:                        s2 = tabrack;   /* point to beginning of tabrack */
        !           201: 
        !           202: /* set up output tabrack (used to do horizontal tabbing):
        !           203:    while the input tabrack position != newline, if the input position s1 pts to
        !           204:    is HT, then the corresponding output position s2 pts to is HT; otherwise,
        !           205:    output position is ' ' (blank). */
        !           206: 
        !           207:                  while (*s1 != '\n')
        !           208:                        *s2++ = (*s1++ == HT)?HT:' ';
        !           209: 
        !           210: /* NULL-out rest of output tabrack (s2) */
        !           211:                  while (s2 < &tabrack[RCDLN])
        !           212:                        *s2++ = '\0';
        !           213: 
        !           214:                        continue;
        !           215:                }
        !           216: 
        !           217:                output();
        !           218: 
        !           219: /* do line feeds (dolfs): if line length<2, or there are no special instructions
        !           220:    for this line (s1 != ESC), or the ESC sequence isn't valid 
        !           221:    (<alpha> less than A or greater than Z), do single spacing. Otherwise, if 
        !           222:    this file is ASCII coded, get the number of line feeds to do from 
        !           223:    asctab(*s1-'A'). If it's EBCDIC coded, get the number of line feeds to do 
        !           224:    from ebctab(*s1-'A'). */
        !           225: 
        !           226:                if (strlen(line) < 2 || *s1 != ESC ||
        !           227:                    (*s1 == ESC && (*(s1+1) < 'A' || *(s1+1) > 'Z')))
        !           228:                        dolfs(1);        /* do single spacing */
        !           229:                else
        !           230:                        dolfs((ascii?asctab:ebctab)[s1[1]-'A']);
        !           231:        }
        !           232: }
        !           233: 
        !           234: /* Here is dolfs -- do linefeeds (lines get hungry too) */
        !           235: dolfs(action)
        !           236: register int action;
        !           237: {
        !           238:        register int loop;
        !           239:        register int lfeeds;    /* contains # of line feeds to do */
        !           240: 
        !           241:        if (action == 0) {      /* do carriage return only */
        !           242:                putchar('\r');
        !           243:                return;
        !           244:        }
        !           245: 
        !           246:        if (action > 0) {       /* output 'action' newlines if positive */
        !           247:                for (loop=0;loop < action;++loop) {
        !           248:                        putchar('\n');
        !           249:                        ++linect;
        !           250:                        if (linect >= maxlines)
        !           251:                                putchar('\f');
        !           252:                }
        !           253:                return;
        !           254:        }
        !           255: 
        !           256:        /* If `action' negative, skip to line given in channel table    */
        !           257:        /* If already past that line, skip to top of next page          */
        !           258:        if ((lfeeds = channel[-action])) {
        !           259:                if (linect >= lfeeds) {
        !           260:                        putchar('\r');
        !           261:                        putchar('\f');
        !           262:                        linect = 1;
        !           263:                }
        !           264:                while (linect < lfeeds) {
        !           265:                        putchar('\n');
        !           266:                        ++linect;
        !           267:                }
        !           268:                return;
        !           269:        }
        !           270: 
        !           271:        putchar('\n');
        !           272:        ++linect;
        !           273: }
        !           274: /* Here is output -- the magic tab expander and character-outputter.
        !           275:  *
        !           276:  * 1. set lnptr to point to beginning of input line, tabptr to beginning of
        !           277:  * output tabrack.
        !           278:  *
        !           279:  * 2. if the first char lnptr points to is ESC, there are special instructions
        !           280:  * embedded in the line. Set lnptr to point beyond them (lnptr = &line[2]).
        !           281:  * Upon return to caller, the ESC will be handled.
        !           282:  *
        !           283:  * 3. Until reaching end of line:
        !           284:  *
        !           285:  *     a. If char is HT (or '\t'):
        !           286:  *              increment tabptr by counter (tabptr += counter) to set it to
        !           287:  *              the current output column.
        !           288:  *
        !           289:  *              use tabptr to output blanks until a corresponding HT is
        !           290:  *              found in the tabrack.
        !           291:  *
        !           292:  *              set counter back to zero.
        !           293:  *
        !           294:  *     b. If char is VT:
        !           295:  *        terminate the line, skip to channel 2, then move remainder of
        !           296:  *        line to beginning of line and restart.
        !           297:  *     c. If char is FF:
        !           298:  *        terminate the line, skip to channel 1, then move remainder of
        !           299:  *        line to beginning of line and restart.
        !           300:  *     d. If char is NL:
        !           301:  *        skip the character ... caller will do newlines as necessary.
        !           302:  *     e. Otherwise:
        !           303:  *        output lnptr's char, increment lnptr, increment counter.
        !           304:  */
        !           305: 
        !           306: output()
        !           307: {
        !           308:        register char *lnptr;   /* points to beginning of line */
        !           309:        register char *tabptr;  /* points to beginning of tabrack */
        !           310: 
        !           311:        lnptr = line;
        !           312:        tabptr = tabrack;
        !           313: 
        !           314:        if (*lnptr == DC1)              /* Skip "select printer"        */
        !           315:                ++lnptr;
        !           316:        if (*lnptr == ESC)              /* Skip ESC, command            */
        !           317:                lnptr += 2;
        !           318:        while (*lnptr)  {
        !           319:                switch(*lnptr) {
        !           320:                case HT:
        !           321:                        if (*tabptr == HT)
        !           322:                                tabptr++;
        !           323: 
        !           324:                        while (*tabptr != HT && *tabptr != '\0') {
        !           325:                                putchar(' ');
        !           326:                                tabptr++;
        !           327:                        }
        !           328:                        tabptr--;
        !           329:                        break;
        !           330: 
        !           331:                case '\n':
        !           332:                        break;
        !           333: 
        !           334:                default:
        !           335:                        putchar(*lnptr);
        !           336:                        break;
        !           337: 
        !           338:                case VT:
        !           339:                        dolfs(-2);
        !           340:                        goto redo;
        !           341:                case FF:
        !           342:                        dolfs(-1);
        !           343: redo:
        !           344:                        strcpy(line,++lnptr);
        !           345:                        lnptr = &line[-1];
        !           346:                        tabptr = &tabrack[-1];
        !           347:                        break;
        !           348:                }
        !           349:                ++lnptr;
        !           350:                if (*tabptr)
        !           351:                        ++tabptr;
        !           352:        }
        !           353: }

unix.superglobalmegacorp.com

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