|
|
1.1 ! root 1: /* ! 2: * Interpress utilities ! 3: * ! 4: * Written for Xerox Corporation by William LeFebvre ! 5: * 24-May-1984 ! 6: * ! 7: * Copyright (c) 1984, 1985, 1986 Xerox Corp. ! 8: * ! 9: * HISTORY ! 10: * 15-Jul-86 Lee Moore (lee) at Xerox Webster Research Center ! 11: * Added AppendString1. ! 12: * ! 13: * 15-Jan-86 lee at Xerox, WRC ! 14: * Removed the rest of the Vax dependencies. ! 15: * ! 16: * 10-sep-85 lee moore ! 17: * Removed some dependencies on the Vax. ! 18: * Plenty more to be removed ! 19: * ! 20: * 29-apr-85 ed flint ! 21: * add conditional compilation for vax-11 c (vms) ! 22: */ ! 23: ! 24: /* ! 25: * Subroutines to help build interpress files: ! 26: * ! 27: * literal interface level - these routines produce interpress output at ! 28: * the token level. ! 29: */ ! 30: ! 31: /* ! 32: * NOTE: Some of these "subroutines" are one-liners, so they are written ! 33: * as macros for better efficiency. ! 34: */ ! 35: ! 36: # define Rational_max 1073741824 ! 37: # define ip_Buffsize 1024 ! 38: ! 39: #ifndef vax11c ! 40: # include <sys/param.h> ! 41: # include <math.h> ! 42: # include <stdio.h> ! 43: # include <ctype.h> ! 44: #endif ! 45: ! 46: # include "iptokens.h" ! 47: # include "literal.h" /* macro definitions for some routines */ ! 48: ! 49: # ifndef NULL ! 50: # define NULL (char *)0 ! 51: # endif ! 52: ! 53: #ifdef vax11c ! 54: # define NOFILE 20 ! 55: #endif ! 56: ! 57: # define No 0 ! 58: # define Yes 1 ! 59: ! 60: static int ip_fd = -1; /* current Interpress file */ ! 61: static char ip_filebuff[ip_Buffsize]; /* file buffer */ ! 62: static char *ip_buffptr = NULL; /* points in to ip_filebuff */ ! 63: static int ip_bytecnt; /* number of bytes in ip_filebuff */ ! 64: static char ip_files[NOFILE] = { 0 }; /* marks which files are ip files */ ! 65: ! 66: /* ! 67: * Definitions for the primitives suggested in the Interpress standard ! 68: * (XSIS 048302). The following primitives are defined with macros in ! 69: * "literal.h": ! 70: * ! 71: * AppendComment ! 72: * AppendIdentifier ! 73: * AppendInsertFile ! 74: * AppendString ! 75: */ ! 76: ! 77: ! 78: /* ! 79: * Append a string but interpret the escape characters (different from ! 80: * "AppendString"). ! 81: * ! 82: * Algorithum: copy the old string, substituting escaped characters. ! 83: */ ! 84: ! 85: AppendString1(string) ! 86: ! 87: char *string; { ! 88: char *op, ! 89: *new, ! 90: *np; ! 91: int i, ! 92: count; ! 93: extern char *malloc(); ! 94: ! 95: op = string; ! 96: new = malloc((unsigned) strlen(string)); ! 97: np = new; ! 98: count = 0; ! 99: ! 100: while (*op) { ! 101: if (*op == '\\') { ! 102: /* an escaped backslash? */ ! 103: if (*++op == '\\') { ! 104: *np++ = *op++; ! 105: count++; ! 106: } else { ! 107: i = 0; ! 108: if (isascii(*op) && isdigit(*op)) ! 109: i = *op++ - '0'; ! 110: if (isascii(*op) && isdigit(*op)) ! 111: i = (*op++ - '0') + i*8; ! 112: if (isascii(*op) && isdigit(*op)) ! 113: i = (*op++ - '0') + i*8; ! 114: *np++ = (char) i; ! 115: count++; ! 116: } ! 117: } else { ! 118: *np++ = *op++; ! 119: count++; ! 120: } ! 121: } ! 122: ! 123: append_Sequence(sequenceString, count, (unsigned char *) new); ! 124: free(new); ! 125: } ! 126: ! 127: ! 128: /* ! 129: * append an Op Code to the end of the master ! 130: */ ! 131: ! 132: AppendOp(opcode) ! 133: ! 134: int opcode; ! 135: ! 136: { ! 137: if (opcode > SHORT_OP_LIMIT) ! 138: { ! 139: /* has to be coded as a long op */ ! 140: append_n_byte_int((long)((LONG_OP << 8) | opcode), 2); ! 141: } ! 142: else ! 143: { ! 144: /* small enough to be a short op */ ! 145: append_byte((unsigned char)(SHORT_OP | opcode)); ! 146: } ! 147: } ! 148: ! 149: ! 150: AppendNumber(number) ! 151: ! 152: double number; ! 153: ! 154: { ! 155: long d; ! 156: double r; ! 157: ! 158: if (number == (double)(d = (long)number)) ! 159: AppendInteger(d); ! 160: else ! 161: { ! 162: d = 1; ! 163: while ((fabs(r = number * d) < Rational_max) && ! 164: (d < Rational_max) && ! 165: (r != (float)((int)(r)))) ! 166: { ! 167: d <<= 1; ! 168: } ! 169: AppendRational((long)r, d); ! 170: } ! 171: } ! 172: ! 173: ! 174: /* ! 175: * note that although the routine is called AppendInteger, it is really ! 176: * AppendLong. This is because alot of code wants to use 32 bit numbers. ! 177: * If you want to pass it a 16bit int on the Vax, that will work too. ! 178: */ ! 179: ! 180: AppendInteger(number) ! 181: ! 182: long number; ! 183: ! 184: { ! 185: if (number < INTEGER_MIN || number > INTEGER_MAX) ! 186: { ! 187: append_integer_sequence(number); ! 188: } ! 189: else ! 190: { ! 191: append_short_number((short) number); ! 192: } ! 193: } ! 194: ! 195: AppendRational(value, divisor) ! 196: ! 197: long value, divisor; ! 198: ! 199: { ! 200: int len_value, len_divisor, len; ! 201: ! 202: len_value = bytes_in_int(value); ! 203: len_divisor = bytes_in_int(divisor); ! 204: ! 205: len = len_value > len_divisor ? len_value : len_divisor; ! 206: append_Sequence(sequenceRational, len << 1, (unsigned char *)NULL); ! 207: append_n_byte_int(value, len); ! 208: append_n_byte_int(divisor, len); ! 209: } ! 210: ! 211: #ifdef notdef ! 212: AppendIntegerVector(vector, num) ! 213: ! 214: int *vector; /* ??? */ ! 215: int number; ! 216: ! 217: { ! 218: ! 219: } ! 220: #endif ! 221: ! 222: ! 223: /* ! 224: * Append Packed Pixel Vector ! 225: * if the data pointer is null, then just append the header and leave it ! 226: * at that. ! 227: */ ! 228: ! 229: AppendPPVector(length, bitsPerPixel, pixelsPerScanLine, data) ! 230: int length, bitsPerPixel, pixelsPerScanLine; ! 231: unsigned char *data; ! 232: { ! 233: int preambleSize = 2*sizeof(short); /* two short ints */ ! 234: ! 235: append_Sequence(sequencePackedPixelVector, length + preambleSize, ! 236: (unsigned char *) 0); ! 237: append_n_byte_int((long) bitsPerPixel, 2); ! 238: append_n_byte_int((long) pixelsPerScanLine, 2); ! 239: ! 240: if (data != NULL) ! 241: append_bytes(length, data); ! 242: } ! 243: ! 244: /* ! 245: * Append a Compressed Pixel Vector ! 246: * if the data pointer is null, then just append the header and leave it ! 247: * at that. ! 248: */ ! 249: AppendCPVector(length, breakTable, nRange, pixelsPerScanLine, data) ! 250: int length, breakTable, nRange, pixelsPerScanLine; ! 251: unsigned char *data; ! 252: { ! 253: int preambleSize = 6; /* three short ints */ ! 254: ! 255: append_Sequence(sequenceCompressedPixelVector, length + preambleSize, ! 256: (unsigned char *) 0); ! 257: append_n_byte_int((long) breakTable, 2); ! 258: append_n_byte_int((long) nRange, 2); ! 259: append_n_byte_int((long) pixelsPerScanLine, 2); ! 260: ! 261: if(data != NULL) ! 262: append_bytes(length, data); ! 263: } ! 264: ! 265: ! 266: /* ! 267: * The remainder of this file contains lower level primitives: ! 268: */ ! 269: ! 270: /* ! 271: * append_Sequence(type, length, buff) ! 272: * ! 273: * Append a sequence descriptor and its data bytes. The descriptor is of ! 274: * type "type" and length "length". "Buff" points to the buffer containing ! 275: * the data. If "Buff" is null, don't write any data. ! 276: */ ! 277: ! 278: append_Sequence(type, length, buff) ! 279: ! 280: int type; ! 281: int length; ! 282: unsigned char *buff; ! 283: ! 284: { ! 285: # ifdef notnow ! 286: /* some day, we should make this check, but not today */ ! 287: if ((length & 0x7f000000) != 0) ! 288: { ! 289: /* too big to fit in a long ... */ ! 290: } ! 291: # endif ! 292: ! 293: /* check for use of an obsolete feature of this program */ ! 294: if (length < 0) ! 295: { ! 296: fprintf(stderr, "negative sequence!\n"); ! 297: abort(); ! 298: } ! 299: ! 300: if ((length & 0x7fffff00) != 0) ! 301: { ! 302: /* too big to fit in a short sequence */ ! 303: append_byte((unsigned char) (LONG_SEQUENCE | type)); ! 304: append_n_byte_int((long) length, 3); ! 305: } ! 306: else ! 307: { ! 308: append_byte((unsigned char) (SHORT_SEQUENCE | type)); ! 309: append_byte((unsigned char) length); ! 310: } ! 311: ! 312: /* tack on data, if any */ ! 313: if (buff != NULL) ! 314: append_bytes(length, buff); ! 315: } ! 316: ! 317: ! 318: /* ! 319: * append_integer_sequence(number) ! 320: * A special version of append_sequence that handles integers. Integers ! 321: * must be treated differently because the natural representation of an ! 322: * integer for a particular machine maybe byte swapped relative to the ! 323: * Xerox standard. ! 324: */ ! 325: append_integer_sequence(number) ! 326: ! 327: long number; ! 328: ! 329: { ! 330: int length = bytes_in_int(number); ! 331: ! 332: append_byte((unsigned char) (SHORT_SEQUENCE | sequenceInteger)); ! 333: append_byte((unsigned char) length); ! 334: append_n_byte_int(number, length); ! 335: } ! 336: ! 337: /* ! 338: * append_n_byte_int(number, length) ! 339: * Append N bytes of an integer to the interpress master. ! 340: */ ! 341: ! 342: append_n_byte_int(number, length) ! 343: ! 344: long number; ! 345: int length; /* measured in bytes */ ! 346: ! 347: { ! 348: switch( length ) { ! 349: case 4: ! 350: append_byte((unsigned char) (number >> 24)); ! 351: case 3: ! 352: append_byte((unsigned char) (number >> 16)); ! 353: case 2: ! 354: append_byte((unsigned char) (number >> 8)); ! 355: case 1: ! 356: append_byte((unsigned char) number); ! 357: break; ! 358: default: ! 359: fprintf(stderr, "append_n_byte_int: asked to append %d bytes\n", length); ! 360: } ! 361: } ! 362: ! 363: ! 364: /* ! 365: * append_byte(value) - write out a byte ! 366: */ ! 367: ! 368: append_byte(value) ! 369: ! 370: unsigned char value; ! 371: ! 372: { ! 373: *ip_buffptr++ = value; ! 374: if (++ip_bytecnt == ip_Buffsize) ! 375: { ! 376: if( write(ip_fd, ip_filebuff, ip_Buffsize) != ip_Buffsize ) ! 377: perror("iplib"); ! 378: ! 379: ip_bytecnt = 0; ! 380: ip_buffptr = ip_filebuff; ! 381: } ! 382: } ! 383: ! 384: /* ! 385: * append_bytes(length, buff) - write the buffer of bytes pointed to by ! 386: * "buff" with length "length". ! 387: */ ! 388: ! 389: append_bytes(length, buff) ! 390: ! 391: int length; ! 392: unsigned char *buff; ! 393: ! 394: { ! 395: while (length-- > 0) ! 396: { ! 397: append_byte(*buff++); ! 398: } ! 399: } ! 400: ! 401: ! 402: /* this routine assumes two's complement notation. ! 403: * this routine sometime over estimates the size of an integer. why? ! 404: * is it the sign bit that must be watched out for? ! 405: */ ! 406: ! 407: bytes_in_int(value) ! 408: ! 409: long value; ! 410: ! 411: { ! 412: int i; ! 413: long mask; ! 414: ! 415: if (value < 0) ! 416: { ! 417: /* takes the same space as its one's complemented value */ ! 418: value = ~value; ! 419: } ! 420: if (value == 0) ! 421: { ! 422: /* avoids infinite looping */ ! 423: return(1); ! 424: } ! 425: for (i = 4, mask = 0xff800000; (value & mask) == 0; i--, mask >>= 8) ! 426: ; ! 427: return(i); ! 428: } ! 429: ! 430: /* ! 431: * ip_select(fd) - select file descriptor "fd" as the Interpress file for ! 432: * later use by the i/o routines supplied in this library. ! 433: */ ! 434: ! 435: ip_select(fd) ! 436: ! 437: int fd; ! 438: ! 439: { ! 440: if (ip_fd != -1) ! 441: { ! 442: ip_flush(); ! 443: } ! 444: ! 445: /* set our idea of current file descriptor and initialize the buffer */ ! 446: ip_fd = fd; ! 447: ip_buffptr = ip_filebuff; ! 448: ip_bytecnt = 0; ! 449: ! 450: /* check for initialization */ ! 451: if (!ip_files[fd]) ! 452: { ! 453: /* not an Intepress or RES file -- initialize it */ ! 454: append_bytes(strlen(IP_Header), (unsigned char *) IP_Header); ! 455: ip_files[fd] = Yes; ! 456: } ! 457: } ! 458: ! 459: ! 460: /* ! 461: * res_select(fd) - select file descriptor "fd" as the RES file for ! 462: * later use by the i/o routines supplied in this library. ! 463: */ ! 464: ! 465: res_select(fd) ! 466: ! 467: int fd; ! 468: ! 469: { ! 470: if (ip_fd != -1) ! 471: { ! 472: ip_flush(); ! 473: } ! 474: ! 475: /* set our idea of current file descriptor and initialize the buffer */ ! 476: ip_fd = fd; ! 477: ip_buffptr = ip_filebuff; ! 478: ip_bytecnt = 0; ! 479: ! 480: /* check for initialization */ ! 481: if (!ip_files[fd]) ! 482: { ! 483: /* not an RES or Interpress file -- initialize it */ ! 484: append_bytes(strlen(RES_Header), (unsigned char *) RES_Header); ! 485: ip_files[fd] = Yes; ! 486: } ! 487: } ! 488: ! 489: /* ! 490: * ip_raw_select(fd) - same as ip_select, but no header is placed at the ! 491: * front of the file. ! 492: */ ! 493: ! 494: ip_raw_select(fd) ! 495: ! 496: int fd; ! 497: ! 498: { ! 499: /* trick ip_select into thinking that it is already initialized */ ! 500: ip_files[fd] = Yes; ! 501: ! 502: /* do a normal select */ ! 503: ip_select(fd); ! 504: } ! 505: ! 506: ip_close() ! 507: ! 508: { ! 509: if (ip_fd != -1) ! 510: { ! 511: ip_flush(); ! 512: ip_files[ip_fd] = No; ! 513: (void) close(ip_fd); ! 514: ip_fd = -1; ! 515: } ! 516: } ! 517: ! 518: ip_flush() ! 519: ! 520: { ! 521: /* flush the buffer */ ! 522: if (ip_Buffsize - ip_bytecnt > 0) ! 523: { ! 524: if( write(ip_fd, ip_filebuff, ip_bytecnt) != ip_bytecnt ) ! 525: perror("iplib"); ! 526: } ! 527: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.