|
|
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 Xerox Corp. ! 8: * ! 9: * HISTORY ! 10: * 15-Jan-86 lee at Xerox, WRC ! 11: * Removed the rest of the Vax dependencies. ! 12: * ! 13: * 10-sep-85 lee moore Removed some dependencies on the Vax. ! 14: * Plenty more to be removed ! 15: * 29-apr-85 ed flint add conditional compilation for vax-11 c (vms) ! 16: */ ! 17: ! 18: /* ! 19: * Subroutines to help build interpress files: ! 20: * ! 21: * literal interface level - these routines produce interpress output at ! 22: * the token level. ! 23: */ ! 24: ! 25: /* ! 26: * NOTE: Some of these "subroutines" are one-liners, so they are written ! 27: * as macros for better efficiency. ! 28: */ ! 29: ! 30: # define Rational_max 1073741824 ! 31: # define ip_Buffsize 1024 ! 32: ! 33: #ifndef vax11c ! 34: # include <sys/param.h> ! 35: # include <math.h> ! 36: # include <stdio.h> ! 37: #endif ! 38: ! 39: # include "iptokens.h" ! 40: # include "literal.h" /* macro definitions for some routines */ ! 41: ! 42: # ifndef NULL ! 43: # define NULL (char *)0 ! 44: # endif ! 45: ! 46: #ifdef vax11c ! 47: # define NOFILE 20 ! 48: #endif ! 49: ! 50: # define No 0 ! 51: # define Yes 1 ! 52: ! 53: static int ip_fd = -1; /* current Interpress file */ ! 54: static char ip_filebuff[ip_Buffsize]; /* file buffer */ ! 55: static char *ip_buffptr = NULL; /* points in to ip_filebuff */ ! 56: static int ip_bytecnt; /* number of bytes in ip_filebuff */ ! 57: static char ip_files[NOFILE] = { 0 }; /* marks which files are ip files */ ! 58: ! 59: /* ! 60: * Definitions for the primitives suggested in the Interpress standard ! 61: * (XSIS 048302). The following primitives are defined with macros in ! 62: * "literal.h": ! 63: * ! 64: * AppendComment ! 65: * AppendIdentifier ! 66: * AppendInsertFile ! 67: * AppendString ! 68: * ! 69: * Currently, AppendString will only handle byte values -- it will not ! 70: * try to insert any escape characters. The rationale for this is that ! 71: * ASCII (which is what this system uses) doesn't have character codes that ! 72: * high. ! 73: */ ! 74: ! 75: AppendOp(opcode) ! 76: ! 77: int opcode; ! 78: ! 79: { ! 80: if (opcode > SHORT_OP_LIMIT) ! 81: { ! 82: /* has to be coded as a long op */ ! 83: append_word((unsigned short)((LONG_OP << 8) | opcode)); ! 84: } ! 85: else ! 86: { ! 87: /* small enough to be a short op */ ! 88: append_byte((unsigned char)(SHORT_OP | opcode)); ! 89: } ! 90: } ! 91: ! 92: AppendNumber(number) ! 93: ! 94: double number; ! 95: ! 96: { ! 97: long d; ! 98: double r; ! 99: ! 100: if (number == (double)(d = (long)number)) ! 101: { ! 102: AppendInteger(d); ! 103: } ! 104: else ! 105: { ! 106: d = 1; ! 107: while ((fabs(r = number * d) < Rational_max) && ! 108: (d < Rational_max) && ! 109: (r != (float)((int)(r)))) ! 110: { ! 111: d <<= 1; ! 112: } ! 113: AppendRational((long)r, d); ! 114: } ! 115: } ! 116: ! 117: ! 118: /* ! 119: * note that although the routine is called AppendInteger, it is really ! 120: * AppendLong. This is because alot of code wants to use 32 bit numbers. ! 121: * If you want to pass it a 16bit int, that will work too. ! 122: */ ! 123: ! 124: AppendInteger(number) ! 125: ! 126: long number; ! 127: ! 128: { ! 129: if (number < INTEGER_MIN || number > INTEGER_MAX) ! 130: { ! 131: append_integer_sequence(number); ! 132: } ! 133: else ! 134: { ! 135: append_short_number((short) number); ! 136: } ! 137: } ! 138: ! 139: AppendRational(value, divisor) ! 140: ! 141: long value, divisor; ! 142: ! 143: { ! 144: int len_value, len_divisor, len; ! 145: ! 146: len_value = bytes_in_int(value); ! 147: len_divisor = bytes_in_int(divisor); ! 148: ! 149: len = len_value > len_divisor ? len_value : len_divisor; ! 150: append_Sequence(sequenceRational, len << 1, (unsigned char *)NULL); ! 151: append_n_byte_int(value, len); ! 152: append_n_byte_int(divisor, len); ! 153: } ! 154: ! 155: #ifdef notdef ! 156: AppendIntegerVector(vector, num) ! 157: ! 158: int *vector; /* ??? */ ! 159: int number; ! 160: ! 161: { ! 162: ! 163: } ! 164: #endif ! 165: ! 166: /* ! 167: * The remainder of this file contains lower level primitives: ! 168: */ ! 169: ! 170: /* ! 171: * append_Sequence(type, length, buff) ! 172: * ! 173: * Append a sequence descriptor and its data bytes. The descriptor is of ! 174: * type "type" and length "length". "Buff" points to the buffer containing ! 175: * the data. If "length" is negative, then bytes from "buffer" are written ! 176: * back to front (this makes writing integers easy). ! 177: */ ! 178: ! 179: append_Sequence(type, length, buff) ! 180: ! 181: int type; ! 182: int length; ! 183: unsigned char *buff; ! 184: ! 185: { ! 186: # ifdef notnow ! 187: /* some day, we should make this check, but not today */ ! 188: if ((length & 0x7f000000) != 0) ! 189: { ! 190: /* too big to fit in a long ... */ ! 191: } ! 192: # endif ! 193: ! 194: /* check for swapped byte correction */ ! 195: if (length < 0) ! 196: { ! 197: fprintf(stderr, "negative sequence!\n"); ! 198: abort(); ! 199: } ! 200: ! 201: if ((length & 0x7fffff00) != 0) ! 202: { ! 203: /* too big to fit in a short sequence */ ! 204: append_byte((unsigned char) (LONG_SEQUENCE | type)); ! 205: append_n_byte_int((long) length, 3); ! 206: } ! 207: else ! 208: { ! 209: append_byte((unsigned char) (SHORT_SEQUENCE | type)); ! 210: append_byte((unsigned char) length); ! 211: } ! 212: ! 213: /* tack on data, if any */ ! 214: if (buff != NULL) ! 215: append_bytes(length, buff); ! 216: } ! 217: ! 218: ! 219: /* ! 220: * append_integer_sequence(number) ! 221: * A special version of append_sequence that handles integers. Integers ! 222: * must be treated differently because the natural representation of an ! 223: * integer for a particular machine maybe byte swapped relative to the ! 224: * Xerox standard. ! 225: */ ! 226: append_integer_sequence(number) ! 227: ! 228: long number; ! 229: ! 230: { ! 231: int length = bytes_in_int(number); ! 232: ! 233: append_byte((unsigned char) (SHORT_SEQUENCE | sequenceInteger)); ! 234: append_byte((unsigned char) length); ! 235: append_n_byte_int(number, length); ! 236: } ! 237: ! 238: /* ! 239: * append_n_byte_int(number, length) ! 240: * Append N bytes of an integer to the interpress master. ! 241: */ ! 242: ! 243: append_n_byte_int(number, length) ! 244: ! 245: long number; ! 246: int length; /* measured in bytes */ ! 247: ! 248: { ! 249: int shift; ! 250: ! 251: #ifdef notdef ! 252: switch( length ) { ! 253: case 4: ! 254: append_byte((unsigned char) (number >> 24)); ! 255: case 3: ! 256: append_byte((unsigned char) (number >> 16)); ! 257: case 2: ! 258: append_byte((unsigned char) (number >> 8)); ! 259: case 1: ! 260: append_byte((unsigned char) number); ! 261: break; ! 262: default: ! 263: fprintf(stderr, "append_n_byte_int: asked to append %d bytes\n", length); ! 264: } ! 265: #else ! 266: if( length > sizeof(long) ) ! 267: fprintf(stderr, "append_n_byte_int: asked to append %d bytes\n", length); ! 268: ! 269: for( shift = (length - 1)*8; shift >= 0; shift -= 8 ) ! 270: append_byte((unsigned char) (number >> shift)); ! 271: #endif ! 272: } ! 273: ! 274: ! 275: /* ! 276: * append_word(value) - write the two byte (word) value "value" ! 277: */ ! 278: ! 279: append_word(value) ! 280: ! 281: unsigned short value; ! 282: ! 283: { ! 284: #ifdef notdef ! 285: append_n_byte_int(value, 2); ! 286: #else ! 287: append_byte((unsigned char) (value >> 8)); ! 288: append_byte((unsigned char) value); ! 289: #endif ! 290: } ! 291: ! 292: /* ! 293: * append_byte(value) - write out a byte ! 294: */ ! 295: ! 296: append_byte(value) ! 297: ! 298: unsigned char value; ! 299: ! 300: { ! 301: *ip_buffptr++ = value; ! 302: if (++ip_bytecnt == ip_Buffsize) ! 303: { ! 304: write(ip_fd, ip_filebuff, ip_Buffsize); ! 305: ip_bytecnt = 0; ! 306: ip_buffptr = ip_filebuff; ! 307: } ! 308: } ! 309: ! 310: /* ! 311: * append_bytes(length, buff) - write the buffer of bytes pointed to by ! 312: * "buff" with length "length". ! 313: */ ! 314: ! 315: append_bytes(length, buff) ! 316: ! 317: int length; ! 318: unsigned char *buff; ! 319: ! 320: { ! 321: while (length-- > 0) ! 322: { ! 323: append_byte(*buff++); ! 324: } ! 325: } ! 326: ! 327: ! 328: /* this routine assumes 4 bytes in an int and two's complement notation */ ! 329: /* this routine should be replaced! -lee */ ! 330: /* this routine sometime over estimates the size of an integer. why? */ ! 331: ! 332: bytes_in_int(value) ! 333: ! 334: long value; ! 335: ! 336: { ! 337: int i; ! 338: long mask; ! 339: ! 340: if (value < 0) ! 341: { ! 342: /* takes the same space as its one's complemented value */ ! 343: value = ~value; ! 344: } ! 345: if (value == 0) ! 346: { ! 347: /* avoids infinite looping */ ! 348: return(1); ! 349: } ! 350: for (i = 4, mask = 0xff800000; (value & mask) == 0; i--, mask >>= 8) ! 351: ; ! 352: return(i); ! 353: } ! 354: ! 355: /* ! 356: * ip_select(fd) - select file descriptor "fd" as the Interpress file for ! 357: * later use by the i/o routines supplied in this library. ! 358: */ ! 359: ! 360: ip_select(fd) ! 361: ! 362: int fd; ! 363: ! 364: { ! 365: if (ip_fd != -1) ! 366: { ! 367: ip_flush(); ! 368: } ! 369: ! 370: /* set our idea of current file descriptor and initialize the buffer */ ! 371: ip_fd = fd; ! 372: ip_buffptr = ip_filebuff; ! 373: ip_bytecnt = 0; ! 374: ! 375: /* check for initialization */ ! 376: if (!ip_files[fd]) ! 377: { ! 378: /* not an Intepress file -- initialize it */ ! 379: append_bytes(strlen(IP_Header), (unsigned char *) IP_Header); ! 380: ip_files[fd] = Yes; ! 381: } ! 382: } ! 383: ! 384: /* ! 385: * ip_raw_select(fd) - same as ip_select, but no header is placed at the ! 386: * front of the file. ! 387: */ ! 388: ! 389: ip_raw_select(fd) ! 390: ! 391: int fd; ! 392: ! 393: { ! 394: /* trick ip_select into thinking that it is already initialized */ ! 395: ip_files[fd] = Yes; ! 396: ! 397: /* do a normal select */ ! 398: ip_select(fd); ! 399: } ! 400: ! 401: ip_close() ! 402: ! 403: { ! 404: if (ip_fd != -1) ! 405: { ! 406: ip_flush(); ! 407: ip_files[ip_fd] = No; ! 408: close(ip_fd); ! 409: ip_fd = -1; ! 410: } ! 411: } ! 412: ! 413: ip_flush() ! 414: ! 415: { ! 416: /* flush the buffer */ ! 417: if (ip_Buffsize - ip_bytecnt > 0) ! 418: { ! 419: write(ip_fd, ip_filebuff, ip_bytecnt); ! 420: } ! 421: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.