Annotation of cci/usr/src/usr.bin/bsc/cmd/batch/bscpr.c, revision 1.1.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.