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