386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zfileio.c
CommitLineData
e5bee91e
WJ
1/* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* zfileio.c */
21/* File I/O operators for Ghostscript */
22#include "ghost.h"
23#include "gp.h"
24#include "errors.h"
25#include "oper.h"
26#include "stream.h"
27#include "estack.h"
28#include "file.h"
29#include "store.h"
30#include "gsmatrix.h" /* for gxdevice.h */
31#include "gxdevice.h"
32#include "gxdevmem.h"
33
34/* Forward references */
35int zreadline_from(P4(byte *, uint, uint *, stream *));
36es_ptr zget_current_file(P0());
37private int write_string(P2(os_ptr, stream *));
38
39/* ------ Operators ------ */
40
41/* read */
42int
43zread(register os_ptr op)
44{ stream *s;
45 int ch;
46 check_read_file(s, op);
47 ch = sgetc(s);
48 if ( ch == EOFC )
49 make_bool(op, 0);
50 else
51 { make_int(op, ch);
52 push(1);
53 make_bool(op, 1);
54 }
55 return 0;
56}
57
58/* write */
59int
60zwrite(register os_ptr op)
61{ stream *s;
62 ulong ch;
63 check_write_file(s, op - 1);
64 check_type(*op, t_integer);
65 ch = op->value.intval;
66 if ( ch > 0xff ) return e_rangecheck;
67 sputc(s, (byte)ch);
68 pop(2);
69 return 0;
70}
71
72/* readhexstring */
73int
74zreadhexstring(register os_ptr op)
75{ stream *s;
76 int code;
77 uint nread;
78 int odd = -1;
79 check_read_file(s, op - 1);
80 check_write_type(*op, t_string);
81 code = sreadhex(s, op->value.bytes, r_size(op), &nread, &odd, 1);
82 switch ( code )
83 {
84 case EOFC:
85 /* Reached end-of-file before filling the string. */
86 /* Return an appropriate substring. */
87 r_set_size(op, nread);
88 code = 1;
89 break;
90 case 0:
91 /* Filled the string. */
92 break;
93 default: /* Error */
94 return e_ioerror;
95 }
96 ref_assign(op - 1, op);
97 make_bool(op, 1 - code);
98 return 0;
99}
100
101/* writehexstring */
102int
103zwritehexstring(register os_ptr op)
104{ register stream *s;
105 register byte ch;
106 register byte *p;
107 register const char _ds *hex_digits = "0123456789abcdef";
108 register uint len;
109 check_write_file(s, op - 1);
110 check_read_type(*op, t_string);
111 p = op->value.bytes;
112 len = r_size(op);
113 while ( len-- )
114 { ch = *p++;
115 sputc(s, hex_digits[ch >> 4]);
116 sputc(s, hex_digits[ch & 0xf]);
117 }
118 pop(2);
119 return 0;
120}
121
122/* readstring */
123int
124zreadstring(register os_ptr op)
125{ stream *s;
126 uint len, rlen;
127 check_read_file(s, op - 1);
128 check_write_type(*op, t_string);
129 len = r_size(op);
130 rlen = sgets(s, op->value.bytes, len);
131 r_set_size(op, rlen);
132 op[-1] = *op;
133 make_bool(op, (rlen == len ? 1 : 0));
134 return 0;
135}
136
137/* writestring */
138int
139zwritestring(register os_ptr op)
140{ stream *s;
141 int code;
142 check_write_file(s, op - 1);
143 code = write_string(op, s);
144 if ( code >= 0 ) pop(2);
145 return code;
146}
147
148/* readline */
149int
150zreadline(register os_ptr op)
151{ stream *s;
152 uint count;
153 int code;
154 check_read_file(s, op - 1);
155 check_write_type(*op, t_string);
156 code = zreadline_from(op->value.bytes, r_size(op), &count, s);
157 if ( code < 0 ) return code;
158 r_set_size(op, count);
159 op[-1] = *op;
160 make_bool(op, code);
161 return 0;
162}
163
164/* Read a line from stdin. This is called from gs.c. */
165int
166zreadline_stdin(byte *ptr, uint size, uint *pcount)
167{ return zreadline_from(ptr, size, pcount, &std_files[0]);
168}
169
170/* Internal readline routine. */
171/* Returns 1 if OK, 0 if end of file, or an error code. */
172int
173zreadline_from(byte *ptr, uint size, uint *pcount, stream *s)
174{ uint count = 0;
175 int ch;
176 for ( ; ; count++ )
177 { switch ( ch = sgetc(s) )
178 {
179 case '\r':
180 ch = sgetc(s);
181 if ( ch != '\n' && ch >= 0 ) sputback(s);
182 /* falls through */
183 case '\n':
184 *pcount = count;
185 return 1;
186 case EOFC:
187 *pcount = count;
188 return 0;
189 }
190 if ( count >= size ) /* filled the string */
191 { sputback(s);
192 return e_rangecheck;
193 }
194 *ptr++ = ch;
195 }
196 return 0;
197}
198
199/* token - this is called from zstring.c */
200int
201ztoken_file(register os_ptr op)
202{ stream *s;
203 ref token;
204 int code;
205 check_read_file(s, op);
206 switch ( code = scan_token(s, 0, &token) )
207 {
208 case 0: /* read a token */
209 *op = token;
210 push(1);
211 make_bool(op, 1);
212 return 0;
213 case 1: /* no tokens */
214 make_bool(op, 0);
215 return 0;
216 default: /* error */
217 return code;
218 }
219}
220
221/* bytesavailable */
222int
223zbytesavailable(register os_ptr op)
224{ stream *s;
225 long avail;
226 check_read_file(s, op);
227 if ( savailable(s, &avail) < 0 ) return e_ioerror;
228 make_int(op, avail);
229 return 0;
230}
231
232/* flush */
233int
234zflush(register os_ptr op)
235{ sflush(&std_files[1]);
236 return 0;
237}
238
239/* flushfile */
240int
241zflushfile(register os_ptr op)
242{ stream *s;
243 check_file(s, op);
244 sflush(s);
245 if ( !s_is_writing(s) )
246 fseek(s->file, 0L, 2); /* set to end */
247 pop(1);
248 return 0;
249}
250
251/* resetfile */
252int
253zresetfile(register os_ptr op)
254{ NYI("resetfile");
255 pop(1);
256 return 0;
257}
258
259/* status */
260int
261zstatus(register os_ptr op)
262{ switch ( r_type(op) )
263 {
264 case t_file:
265 make_bool(op, (fptr(op)->bsize != 0 ? 1 : 0));
266 return 0;
267 case t_string:
268 { char *fname = ref_to_string(op, "status");
269 file_status fstat;
270 if ( fname == 0 ) return e_VMerror;
271 if ( gp_file_status(fname, &fstat) )
272 { push(4);
273 make_int(op - 4, fstat.size_pages);
274 make_int(op - 3, fstat.size_bytes);
275 make_int(op - 2, fstat.time_referenced);
276 make_int(op - 1, fstat.time_created);
277 make_bool(op, 1);
278 }
279 else
280 make_bool(op, 0);
281 alloc_free(fname, r_size(op) + 1, 1, "status");
282 } return 0;
283 default:
284 return e_typecheck;
285 }
286}
287
288/* currentfile */
289int
290zcurrentfile(register os_ptr op)
291{ es_ptr fp;
292 push(1);
293 /* Check the cache first */
294 if ( esfile != 0 )
295 ref_assign(op, esfile);
296 else if ( (fp = zget_current_file()) == 0 )
297 { /* Return an invalid file object. */
298 /* This doesn't make a lot of sense to me, */
299 /* but it's what the PostScript manual specifies. */
300 make_file(op, 0, &invalid_file_entry);
301 }
302 else
303 { ref_assign(op, fp);
304 /* Load the cache */
305 esfile = fp;
306 }
307 /* Make the returned value literal. */
308 r_clear_attrs(op, a_executable);
309 return 0;
310}
311
312/* print */
313int
314zprint(register os_ptr op)
315{ int code = write_string(op, &std_files[1]);
316 if ( code >= 0 ) pop(1);
317 return code;
318}
319
320/* echo */
321int
322zecho(register os_ptr op)
323{ check_type(*op, t_boolean);
324 /****** NOT IMPLEMENTED YET ******/
325 pop(1);
326 return 0;
327}
328
329/* ------ Level 2 extensions ------ */
330
331/* fileposition */
332int
333zfileposition(register os_ptr op)
334{ stream *s;
335 check_file(s, op);
336 if ( !sseekable(s) ) return e_ioerror;
337 make_int(op, stell(s));
338 return 0;
339}
340
341/* setfileposition */
342int
343zsetfileposition(register os_ptr op)
344{ stream *s;
345 check_file(s, op - 1);
346 check_type(*op, t_integer);
347 if ( sseek(s, op->value.intval) < 0 ) return e_ioerror;
348 pop(2);
349 return 0;
350}
351
352/* ------ Ghostscript extensions ------ */
353
354/* unread */
355int
356zunread(register os_ptr op)
357{ stream *s;
358 ulong ch;
359 check_read_file(s, op - 1);
360 check_type(*op, t_integer);
361 ch = op->value.intval;
362 if ( ch > 0xff ) return e_rangecheck;
363 if ( sungetc(s, (byte)ch) < 0 ) return e_ioerror;
364 pop(2);
365 return 0;
366}
367
368/* writeppmfile */
369int
370zwriteppmfile(register os_ptr op)
371{ stream *s;
372 int code;
373 check_write_file(s, op - 1);
374 check_type(*op, t_device);
375 if ( !gs_device_is_memory(op->value.pdevice) ) return e_typecheck;
376 sflush(s);
377 code = gs_writeppmfile((gx_device_memory *)(op->value.pdevice), s->file);
378 if ( code >= 0 ) pop(2);
379 return code;
380}
381
382/* ------ Initialization procedure ------ */
383
384op_def zfileio_op_defs[] = {
385 {"1bytesavailable", zbytesavailable},
386 {"0currentfile", zcurrentfile},
387 {"1echo", zecho},
388 {"1fileposition", zfileposition},
389 {"0flush", zflush},
390 {"1flushfile", zflushfile},
391 {"1print", zprint},
392 {"1read", zread},
393 {"2readhexstring", zreadhexstring},
394 {"2readline", zreadline},
395 {"2readstring", zreadstring},
396 {"1resetfile", zresetfile},
397 {"2setfileposition", zsetfileposition},
398 {"2unread", zunread},
399 {"1status", zstatus},
400 {"2write", zwrite},
401 {"2writehexstring", zwritehexstring},
402 {"2writeppmfile", zwriteppmfile},
403 {"2writestring", zwritestring},
404 op_def_end(0)
405};
406
407/* ------ Non-operator routines ------ */
408
409/* Check a file for reading. */
410/* The interpreter calls this to check an executable file. */
411int
412file_check_read(ref *op, stream **ps)
413{ if ( !s_is_reading(*ps = fptr(op)) ) return e_invalidaccess;
414 return 0;
415}
416
417/* Get the current file from which the interpreter is reading. */
418es_ptr
419zget_current_file()
420{ register es_ptr ep = esp;
421 while ( ep >= esbot )
422 { if ( r_has_type_attrs(ep, t_file, a_executable) )
423 return ep;
424 ep--;
425 }
426 return (es_ptr)0;
427}
428
429/* ------ Internal routines ------ */
430
431/* Write a string on a file. The file has been checked for validity, */
432/* but not the string. */
433private int
434write_string(os_ptr op, stream *s)
435{ uint len;
436 check_read_type(*op, t_string);
437 len = r_size(op);
438 if ( sputs(s, op->value.bytes, len) != len ) return e_ioerror;
439 return 0;
440}