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