|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.