|
|
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.