home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / printing / ghostscrip / source / _gs / c / stream < prev    next >
Encoding:
Text File  |  1991-10-25  |  12.7 KB  |  489 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* stream.c */
  21. /* Stream package for Ghostscript interpreter */
  22. #include <stdio.h>
  23. #include "memory_.h"
  24. #include "std.h"
  25. #include "stream.h"
  26. #include "scanchar.h"
  27. #include "gxfixed.h"            /* for gstype1.h */
  28. #include "gstype1.h"
  29.  
  30. /* Forward declarations */
  31.     /* Generic */
  32. /* Export these for filters */
  33. void
  34.   s_std_init(P5(stream *, byte *, uint, stream_procs *, int)); /* last is writing flag */
  35. int
  36.   s_std_null(P1(stream *)),
  37.   s_std_noavailable(P2(stream *, long *)),
  38.   s_std_close(P1(stream *));
  39.     /* Strings */
  40. private int
  41.   s_string_read_buf(P1(stream *)),
  42.   s_string_write_buf(P1(stream *)),
  43.   s_string_available(P2(stream *, long *)),
  44.   s_string_seek(P2(stream *, long));
  45. private void
  46.   s_string_init(P4(stream *, byte *, uint, stream_procs *));
  47.     /* Files */
  48. private int
  49.   s_file_read_buf(P1(stream *)),
  50.   s_file_available(P2(stream *, long *)),
  51.   s_file_read_seek(P2(stream *, long)),
  52.   s_file_read_close(P1(stream *));
  53. private int
  54.   s_file_write_buf(P1(stream *)),
  55.   s_file_write_seek(P2(stream *, long)),
  56.   s_file_write_flush(P1(stream *)),
  57.   s_file_write_close(P1(stream *));
  58.     /* decrypting */
  59. private int
  60.   s_eexec_read_buf(P1(stream *)),
  61.   s_eexec_available(P2(stream *, long *));
  62.  
  63. /* ------ Generic procedures ------ */
  64.  
  65. /* Standard stream initialization */
  66. void
  67. s_std_init(register stream *s, byte *ptr, uint len, stream_procs *pp,
  68.   int writing)
  69. {    s->cbuf = ptr;
  70.     s->cptr = ptr - 1;
  71.     s->endptr = (writing ? s->cptr + len : s->cptr);
  72.     s->writing = writing;
  73.     s->bsize = len;
  74.     s->procs = *pp;
  75. }
  76.  
  77. /* Implement a stream procedure as a no-op. */
  78. int
  79. s_std_null(stream *s)
  80. {    return 0;
  81. }
  82.  
  83. /* Indicate an error when asked for available input bytes. */
  84. int
  85. s_std_noavailable(stream *s, long *pl)
  86. {    return -1;
  87. }
  88.  
  89. /* Standard stream finalization.  Disable the stream. */
  90. int
  91. s_std_close(stream *s)
  92. {    s_disable(s);
  93.     return 0;
  94. }
  95. void
  96. s_disable(register stream *s)
  97. {    s->bsize = 0;
  98.     /****** SHOULD DO A LOT MORE THAN THIS ******/
  99. }
  100.  
  101. /* ------ Implementation-independent procedures ------ */
  102.  
  103. /* Implement sgetc when the buffer is empty */
  104. /* by refilling the buffer and then reading a byte. */
  105. int
  106. spgetc(register stream *s)
  107. {    int count;
  108.     if ( s->eof ) 
  109.         return EOFC;
  110.     count = (*s->procs.read_buf)(s);
  111.     if ( count > 0 )
  112.        {    s->endptr = s->cptr + count;
  113.         return (int)*++(s->cptr);
  114.        }
  115.     else if ( count == 0 )
  116.        {    s->endptr = s->cptr;
  117.         s->eof = 1;
  118.         return EOFC;
  119.        }
  120.     else                /* error or EOF */
  121.        {    s->endptr = s->cptr;
  122.         return EOFC;
  123.        }
  124. }
  125.  
  126. /* Implementing sputc when the buffer is full */
  127. /* by flushing the buffer and then writing the byte. */
  128. int
  129. spputc(register stream *s, byte b)
  130. {    int code = (*s->procs.write_buf)(s);
  131.     if ( code < 0 ) return code;
  132.     return sputc(s, b);
  133. }
  134.  
  135. /* Push back a character onto a (read) stream. */
  136. /* Return 0 on success, -1 on failure. */
  137. int
  138. sungetc(register stream *s, byte c)
  139. {    if ( s->writing || s->cptr < s->cbuf ) return -1;
  140.     *(s->cptr)-- = c;
  141.     return 0;
  142. }
  143.  
  144. /* Read a string from a stream. */
  145. /* Return the number of bytes read. */
  146. uint
  147. sgets(register stream *s, byte *str, uint rlen)
  148. {    uint len = rlen;
  149.     while ( len > 0 )
  150.        {    uint count = sbufavailable(s);
  151.         if ( count == 0 )
  152.            {    if ( s->eof ) return rlen - len;
  153.             count = (*s->procs.read_buf)(s);
  154.             if ( count == 0 )
  155.                {    s->eof = 1;
  156.                 return rlen - len;
  157.                }
  158.             s->endptr = s->cptr + count;
  159.            }
  160.         if ( count > len ) count = len;
  161.         memcpy(str, s->cptr + 1, count);
  162.         s->cptr += count;
  163.         str += count;
  164.         len -= count;
  165.        }
  166.     return rlen;
  167. }
  168.  
  169. /* Write a string on a stream. */
  170. /* Return the number of bytes written. */
  171. uint
  172. sputs(register stream *s, byte *str, uint wlen)
  173. {    uint len = wlen;
  174.     if ( wlen > s->bsize && s->procs.write_buf == s_file_write_buf )
  175.        {    /* Write directly on the file. */
  176.         uint write_count;
  177.         (*s->procs.write_buf)(s);
  178.         write_count = fwrite(str, 1, wlen, s->file);
  179.         if ( s->position >= 0 )        /* file is positionable */
  180.             s->position = ftell(s->file);
  181.         return write_count;
  182.        }
  183.     while ( len > 0 )
  184.        {    uint count = sbufavailable(s);
  185.         if ( count > 0 )
  186.            {    if ( count > len ) count = len;
  187.             memcpy(s->cptr + 1, str, count);
  188.             s->cptr += count;
  189.             str += count;
  190.             len -= count;
  191.            }
  192.         else
  193.            {    byte ch = *str++;
  194.             sputc(s, ch);
  195.             if ( s->eof ) return wlen - len;
  196.             len--;
  197.            }
  198.        }
  199.     return wlen;
  200. }
  201.  
  202. /* Read a hex string from a stream. */
  203. /* Skip all characters other than hex digits. */
  204. /* Answer 1 if we reached end-of-file before filling the string, */
  205. /* 0 if we filled the string first, or <0 on error. */
  206. /* *odd_digit should be -1 initially: */
  207. /* if an odd number of hex digits was read, *odd_digit is set to */
  208. /* the odd digit value, otherwise *odd_digit is set to -1. */
  209. int
  210. sreadhex(stream *s, byte *str, uint rlen, uint *nread,
  211.   int *odd_digit)
  212. {    byte *ptr = str;
  213.     byte *limit = ptr + rlen;
  214.     byte val1 = (byte)*odd_digit;
  215.     byte val2;
  216.     register byte _ds *decoder = scan_char_decoder;
  217.     register byte *sptr, *endp;
  218.     int ch;
  219. #define begin_inline(sptr, endp, s)\
  220.   sptr = s->cptr, endp = s->endptr
  221. #define sgetc_inline(sptr, endp, s)\
  222.   (sptr < endp ? *++sptr :\
  223.    (end_inline(sptr, s), ch = spgetc(s), begin_inline(sptr, endp, s), ch))
  224. #define end_inline(sptr, s)\
  225.   s->cptr = sptr
  226.     if ( rlen == 0 )
  227.        {    *nread = 0;
  228.         return 0;
  229.        }
  230.     begin_inline(sptr, endp, s);
  231.     if ( val1 <= 0xf ) goto d2;
  232. d1:    while ( (val1 = decoder[sgetc_inline(sptr, endp, s)]) > 0xf )
  233.        {    if ( val1 == ctype_eof ) { *odd_digit = -1; goto ended; }
  234.        }
  235. d2:    while ( (val2 = decoder[sgetc_inline(sptr, endp, s)]) > 0xf )
  236.        {    if ( val2 == ctype_eof ) { *odd_digit = val1; goto ended; }
  237.        }
  238.     *ptr++ = (val1 << 4) + val2;
  239.     if ( ptr < limit ) goto d1;
  240.     *nread = rlen;
  241.     end_inline(sptr, s);
  242.     return 0;
  243. ended:    *nread = ptr - str;
  244.     end_inline(sptr, s);
  245.     return 1;
  246. }
  247.  
  248. /* ------ String streams ------ */
  249.  
  250. /* Initialize a stream for reading a string. */
  251. void
  252. sread_string(register stream *s, byte *ptr, uint len)
  253. {    static stream_procs p =
  254.        {    s_string_available, s_string_seek, s_std_null, s_std_null,
  255.         s_string_read_buf, NULL
  256.        };
  257.     s_string_init(s, ptr, len, &p);
  258.     s->writing = 0;
  259. }
  260. /* Handle end-of-buffer when reading from a string. */
  261. private int
  262. s_string_read_buf(stream *s)
  263. {    s->cptr = s->endptr;
  264.     return EOFC;
  265. }
  266. /* Return the number of available bytes when reading from a string. */
  267. private int
  268. s_string_available(stream *s, long *pl)
  269. {    *pl = sbufavailable(s);
  270.     if ( *pl == 0 ) *pl = -1;    /* EOF */
  271.     return 0;
  272. }
  273.  
  274. /* Initialize a stream for writing a string. */
  275. void
  276. swrite_string(register stream *s, byte *ptr, uint len)
  277. {    static stream_procs p =
  278.        {    s_std_noavailable, s_string_seek, s_std_null, s_std_null,
  279.         NULL, s_string_write_buf
  280.        };
  281.     s_string_init(s, ptr, len, &p);
  282.     s->writing = 1;
  283. }
  284. /* Handle end-of-buffer when writing a string. */
  285. private int
  286. s_string_write_buf(stream *s)
  287. {    s->cptr = s->endptr;
  288.     return EOFC;
  289. }
  290.  
  291. /* Seek in a string.  Return 0 if OK, -1 if not. */
  292. private int
  293. s_string_seek(register stream *s, long pos)
  294. {    if ( pos < 0 || pos > s->bsize ) return -1;
  295.     s->cptr = s->cbuf + pos - 1;
  296.     return 0;
  297. }
  298.  
  299. /* Private initialization */
  300. private void
  301. s_string_init(register stream *s, byte *ptr, uint len, stream_procs *p)
  302. {    s_std_init(s, ptr, len, p, 1);
  303.     s->eof = 1;            /* this is all there is */
  304.     s->position = 0;
  305.     s->file = 0;            /* not a file stream */
  306.     s->strm = 0;            /* not a filter either */
  307. }
  308.  
  309. /* ------ File streams ------ */
  310.  
  311. /* Initialize a stream for reading an OS file. */
  312. void
  313. sread_file(register stream *s, FILE *file, byte *buf, uint len)
  314. {    static stream_procs p =
  315.        {    s_file_available, s_file_read_seek,
  316.         s_std_null, s_file_read_close,
  317.         s_file_read_buf, NULL
  318.        };
  319.     s_std_init(s, buf, len, &p, 0);
  320.     s->file = file;
  321.     s->eof = 0;
  322.     s->strm = 0;            /* not a filter */
  323.     s->position = (file == stdin ? -1 : 0);
  324. }
  325. /* Procedures for reading from a file */
  326. private int
  327. s_file_read_buf(register stream *s)
  328. {    int nread;
  329.     if ( s->eof )
  330.        {    s->cptr = s->endptr;
  331.         return EOFC;
  332.        }
  333.     if ( s->position >= 0 )        /* file is positionable */
  334.         s->position = ftell(s->file);
  335.     nread = fread(s->cbuf, 1, s->bsize, s->file);
  336.     s->cptr = s->cbuf - 1;
  337.     s->eof = feof(s->file);
  338.     return nread;
  339.    }
  340. private int
  341. s_file_available(register stream *s, long *pl)
  342. {    *pl = sbufavailable(s);
  343.     if ( sseekable(s) )
  344.        {    long pos, end;
  345.         pos = ftell(s->file);
  346.         if ( fseek(s->file, 0L, 2) ) return -1;
  347.         end = ftell(s->file);
  348.         if ( fseek(s->file, pos, 0) ) return -1;
  349.         *pl += end - pos;
  350.         if ( *pl == 0 ) *pl = -1;    /* EOF */
  351.        }
  352.     else
  353.        {    if ( *pl == 0 && feof(s->file) ) *pl = -1;    /* EOF */
  354.        }
  355.     return 0;
  356. }
  357. private int
  358. s_file_read_seek(register stream *s, long pos)
  359. {    uint end = s->endptr - s->cbuf + 1;
  360.     long offset = pos - s->position;
  361.     if ( offset >= 0 && offset <= end )
  362.        {    /* Staying within the same buffer */
  363.         s->cptr = s->cbuf + offset - 1;
  364.         return 0;
  365.        }
  366.     if ( fseek(s->file, pos, 0) != 0 )
  367.         return -1;
  368.     s->endptr = s->cptr = s->cbuf - 1;
  369.     s->eof = 0;
  370.     return 0;
  371. }
  372. private int
  373. s_file_read_close(stream *s)
  374. {    return fclose(s->file);
  375. }
  376.  
  377. /* Initialize a stream for writing an OS file. */
  378. void
  379. swrite_file(register stream *s, FILE *file, byte *buf, uint len)
  380. {    static stream_procs p =
  381.        {    s_std_noavailable, s_file_write_seek,
  382.         s_file_write_flush, s_file_write_close,
  383.         NULL, s_file_write_buf
  384.        };
  385.     s_std_init(s, buf, len, &p, 1);
  386.     s->file = file;
  387.     s->eof = 0;
  388.     s->strm = 0;            /* not a filter */
  389.     s->position = (file == stdout || file == stderr ? -1 : 0);
  390.    }
  391. /* Procedures for writing on a file */
  392. private int
  393. s_file_write_buf(register stream *s)
  394. {    uint count = s->cptr + 1 - s->cbuf;
  395.     uint write_count = fwrite(s->cbuf, 1, count, s->file);
  396.     if ( s->position >= 0 )        /* file is positionable */
  397.         s->position = ftell(s->file);
  398.     s->cptr = s->cbuf - 1;
  399.     s->endptr = s->cptr + s->bsize;
  400.     return (write_count == count ? 0 : EOFC);
  401. }
  402. private int
  403. s_file_write_seek(stream *s, long pos)
  404. {    /* Output files are not positionable */
  405.     return -1;
  406. }
  407. private int
  408. s_file_write_flush(register stream *s)
  409. {    int result = s_file_write_buf(s);
  410.     fflush(s->file);
  411.     return result;
  412. }
  413. private int
  414. s_file_write_close(register stream *s)
  415. {    s_file_write_buf(s);
  416.     return fclose(s->file);
  417. }
  418.  
  419. /* ------ Encrypted streams ------ */
  420.  
  421. /* Initialize a stream for reading and decrypting another stream. */
  422. /* Decrypting streams are not positionable. */
  423. void
  424. sread_decrypt(register stream *s, stream *xs, byte *buf, uint len,
  425.   ushort /*crypt_state*/ state)
  426. {    static stream_procs p =
  427.        {    s_eexec_available, NULL, s_std_null, s_std_null,
  428.         s_eexec_read_buf, NULL
  429.        };
  430.     s_std_init(s, buf, len, &p, 0);
  431.     s->eof = 0;
  432.     s->position = -1;        /* not positionable */
  433.     s->file = 0;
  434.     s->strm = xs;
  435.     s->cstate = state;
  436.     s->odd = -1;
  437.     s->binary = -1;            /* unknown */
  438. }
  439. /* Refill the buffer of a decrypting stream. */
  440. private int
  441. s_eexec_read_buf(register stream *s)
  442. {    byte *buf = s->cbuf;
  443.     uint nread;
  444.     int skip = (s->binary < 0 ? 4 : 0);
  445.     s->cptr = buf - 1;
  446. top:    nread = sgets(s->strm, buf, s->bsize);
  447.     if ( nread == 0 )        /* end of stream */
  448.        {    s->eof = 1;
  449.         return EOFC;
  450.        }
  451.     if ( s->binary < 0 )
  452.        {    /* This is the very first time we're filling the buffer. */
  453.         /* Determine whether this is ASCII or hex encoding. */
  454.         register byte _ds *decoder = scan_char_decoder;
  455.         if ( nread < 4 ) return EOFC;
  456.         if ( decoder[buf[0]] == ctype_space ||
  457.              (decoder[buf[0]] | decoder[buf[1]] | decoder[buf[2]] |
  458.               decoder[buf[3]]) <= 0xf )
  459.            {    /* Would be invalid if binary, hence must be hex. */
  460.             s->binary = 0;
  461.            }
  462.         else    s->binary = 1;
  463.             
  464.        }
  465.     if ( !s->binary )
  466.        {    /* Convert the buffer from binary to hex in place. */
  467.         stream sst;
  468.         sread_string(&sst, buf, nread);
  469.         sreadhex(&sst, buf, nread, &nread, &s->odd);
  470.         if ( nread == 0 ) goto top;    /* try again */
  471.        }
  472.     /* Now decrypt the buffer. */
  473.     gs_type1_decrypt(buf, buf, nread, (crypt_state *)&s->cstate);
  474.     if ( skip )
  475.        {    /* Very first buffer-load, strip off leading bytes. */
  476.         if ( nread < skip ) return EOFC;
  477.         s->cptr += skip;
  478.         nread -= skip;
  479.        }
  480.     return nread;
  481. }
  482. /* Estimate the number of remaining bytes in a decrypting stream. */
  483. private int
  484. s_eexec_available(stream *s, long *pl)
  485. {    if ( savailable(s->strm, pl) < 0 ) return -1;
  486.     if ( *pl >= 0 ) *pl /= 2;
  487.     return 0;
  488. }
  489.