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: }

Defined functions

AppendInteger defined in line 124; used 7 times
AppendIntegerVector defined in line 156; never used
AppendNumber defined in line 92; used 14 times
AppendOp defined in line 75; used 12 times
AppendRational defined in line 139; used 1 times
append_Sequence defined in line 179; used 1 times
append_byte defined in line 296; used 14 times
append_bytes defined in line 315; used 2 times
append_integer_sequence defined in line 226; used 1 times
append_n_byte_int defined in line 243; used 5 times
append_word defined in line 279; used 1 times
  • in line 83
bytes_in_int defined in line 332; used 3 times
ip_close defined in line 401; never used
ip_flush defined in line 413; used 2 times
ip_raw_select defined in line 389; never used
ip_select defined in line 360; used 1 times

Defined variables

ip_buffptr defined in line 55; used 3 times
ip_bytecnt defined in line 56; used 5 times
ip_fd defined in line 53; used 8 times
ip_filebuff defined in line 54; used 4 times
ip_files defined in line 57; used 4 times

Defined macros

NOFILE defined in line 47; used 1 times
  • in line 57
NULL defined in line 43; used 4 times
No defined in line 50; used 1 times
Rational_max defined in line 30; used 2 times
Yes defined in line 51; used 2 times
ip_Buffsize defined in line 31; used 4 times
Last modified: 1986-01-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1782
Valid CSS Valid XHTML 1.0 Strict