1 /* $Header$ */
2 
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 
27 /*
28  * TIFF Library RISC OS specific Routines.
29  * Developed out of the Unix version.
30  * Peter Greenham, May 1995
31  */
32 #include "tiffiop.h"
33 #include <stdio.h>
34 #include <stdlib.h>
35 
36 /*
37 Low-level file handling
38 ~~~~~~~~~~~~~~~~~~~~~~~
39 The functions in osfcn.h are unavailable when compiling under C, as it's a
40 C++ header. Therefore they have been implemented here.
41 
42 Now, why have I done it this way?
43 
44 The definitive API library for RISC OS is Jonathan Coxhead's OSLib, which
45 uses heavily optimised ARM assembler or even plain inline SWI calls for
46 maximum performance and minimum runtime size. However, I don't want to make
47 LIBTIFF need that to survive. Therefore I have also emulated the functions
48 using macros to _swi() and _swix() defined in the swis.h header, and
49 borrowing types from kernel.h, which is less efficient but doesn't need any
50 third-party libraries.
51  */
52 
53 #ifdef INCLUDE_OSLIB
54 
55 #include "osfile.h"
56 #include "osgbpb.h"
57 #include "osargs.h"
58 #include "osfind.h"
59 
60 #else
61 
62 /* OSLIB EMULATION STARTS */
63 
64 #include "kernel.h"
65 #include "swis.h"
66 
67 /* From oslib:types.h */
68 typedef unsigned int                            bits;
69 typedef unsigned char                           byte;
70 #ifndef TRUE
71 #define TRUE                                    1
72 #endif
73 #ifndef FALSE
74 #define FALSE                                   0
75 #endif
76 #ifndef NULL
77 #define NULL                                    0
78 #endif
79 #ifndef SKIP
80 #define SKIP                                    0
81 #endif
82 
83 /* From oslib:os.h */
84 typedef _kernel_oserror os_error;
85 typedef byte os_f;
86 
87 /* From oslib:osfile.h */
88 #undef  OS_File
89 #define OS_File                                 0x8
90 
91 /* From oslib:osgbpb.h */
92 #undef  OS_GBPB
93 #define OS_GBPB                                 0xC
94 #undef  OSGBPB_Write
95 #define OSGBPB_Write                            0x2
96 #undef  OSGBPB_Read
97 #define OSGBPB_Read                             0x4
98 
99 extern os_error *xosgbpb_write (os_f file,
100       byte *data,
101       int size,
102       int *unwritten);
103 extern int osgbpb_write (os_f file,
104       byte *data,
105       int size);
106 
107 #define	xosgbpb_write(file, data, size, unwritten) \
108 	(os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_IN(4)|_OUT(3), \
109 		OSGBPB_WriteAt, \
110 		file, \
111 		data, \
112 		size, \
113 		unwritten)
114 
115 #define	osgbpb_write(file, data, size) \
116 	_swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \
117 		OSGBPB_Write, \
118 		file, \
119 		data, \
120 		size)
121 
122 extern os_error *xosgbpb_read (os_f file,
123       byte *buffer,
124       int size,
125       int *unread);
126 extern int osgbpb_read (os_f file,
127       byte *buffer,
128       int size);
129 
130 #define	xosgbpb_read(file, buffer, size, unread) \
131 	(os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_OUT(3), \
132 		OSGBPB_Read, \
133 		file, \
134 		buffer, \
135 		size, \
136 		unread)
137 
138 #define	osgbpb_read(file, buffer, size) \
139 	_swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \
140 		OSGBPB_Read, \
141 		file, \
142 		buffer, \
143 		size)
144 
145 /* From oslib:osfind.h */
146 #undef  OS_Find
147 #define OS_Find                                 0xD
148 #undef  OSFind_Openin
149 #define OSFind_Openin                           0x40
150 #undef  OSFind_Openout
151 #define OSFind_Openout                          0x80
152 #undef  OSFind_Openup
153 #define OSFind_Openup                           0xC0
154 #undef  OSFind_Close
155 #define OSFind_Close                            0x0
156 
157 #define	xosfind_open(reason, file_name, path, file) \
158 	(os_error*) _swix(OS_Find, _IN(0)|_IN(1)|_IN(2)|_OUT(0), \
159 		reason, file_name, path, file)
160 
161 #define	osfind_open(reason, file_name, path) \
162 	(os_f) _swi(OS_Find, _IN(0)|_IN(1)|_IN(2)|_RETURN(0), \
163 		reason, file_name, path)
164 
165 extern os_error *xosfind_openin (bits flags,
166       char *file_name,
167       char *path,
168       os_f *file);
169 extern os_f osfind_openin (bits flags,
170       char *file_name,
171       char *path);
172 
173 #define	xosfind_openin(flags, file_name, path, file) \
174 	xosfind_open(flags | OSFind_Openin, file_name, path, file)
175 
176 #define	osfind_openin(flags, file_name, path) \
177 	osfind_open(flags | OSFind_Openin, file_name, path)
178 
179 extern os_error *xosfind_openout (bits flags,
180       char *file_name,
181       char *path,
182       os_f *file);
183 extern os_f osfind_openout (bits flags,
184       char *file_name,
185       char *path);
186 
187 #define	xosfind_openout(flags, file_name, path, file) \
188 	xosfind_open(flags | OSFind_Openout, file_name, path, file)
189 
190 #define	osfind_openout(flags, file_name, path) \
191 	osfind_open(flags | OSFind_Openout, file_name, path)
192 
193 extern os_error *xosfind_openup (bits flags,
194       char *file_name,
195       char *path,
196       os_f *file);
197 extern os_f osfind_openup (bits flags,
198       char *file_name,
199       char *path);
200 
201 #define	xosfind_openup(flags, file_name, path, file) \
202 	xosfind_open(flags | OSFind_Openup, file_name, path, file)
203 
204 #define	osfind_openup(flags, file_name, path) \
205 	osfind_open(flags | OSFind_Openup, file_name, path)
206 
207 extern os_error *xosfind_close (os_f file);
208 extern void osfind_close (os_f file);
209 
210 #define	xosfind_close(file) \
211 	(os_error*) _swix(OS_Find, _IN(0)|_IN(1), \
212 		OSFind_Close, \
213 		file)
214 
215 #define	osfind_close(file) \
216 	(void) _swi(OS_Find, _IN(0)|_IN(1), \
217 		OSFind_Close, \
218 		file)
219 
220 /* From oslib:osargs.h */
221 #undef  OS_Args
222 #define OS_Args                                 0x9
223 #undef  OSArgs_ReadPtr
224 #define OSArgs_ReadPtr                          0x0
225 #undef  OSArgs_SetPtr
226 #define OSArgs_SetPtr                           0x1
227 #undef  OSArgs_ReadExt
228 #define OSArgs_ReadExt                          0x2
229 
230 extern os_error *xosargs_read_ptr (os_f file,
231       int *ptr);
232 extern int osargs_read_ptr (os_f file);
233 
234 #define	xosargs_read_ptr(file, ptr) \
235 	(os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \
236 		OSArgs_ReadPtr, \
237 		file, \
238 		ptr)
239 
240 #define	osargs_read_ptr(file) \
241 	_swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \
242 		OSArgs_ReadPtr, \
243 		file)
244 
245 extern os_error *xosargs_set_ptr (os_f file,
246       int ptr);
247 extern void osargs_set_ptr (os_f file,
248       int ptr);
249 
250 #define	xosargs_set_ptr(file, ptr) \
251 	(os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_IN(2), \
252 		OSArgs_SetPtr, \
253 		file, \
254 		ptr)
255 
256 #define	osargs_set_ptr(file, ptr) \
257 	(void) _swi(OS_Args, _IN(0)|_IN(1)|_IN(2), \
258 		OSArgs_SetPtr, \
259 		file, \
260 		ptr)
261 
262 extern os_error *xosargs_read_ext (os_f file,
263       int *ext);
264 extern int osargs_read_ext (os_f file);
265 
266 #define	xosargs_read_ext(file, ext) \
267 	(os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \
268 		OSArgs_ReadExt, \
269 		file, \
270 		ext)
271 
272 #define	osargs_read_ext(file) \
273 	_swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \
274 		OSArgs_ReadExt, \
275 		file)
276 
277 /* OSLIB EMULATION ENDS */
278 
279 #endif
280 
281 #ifndef __osfcn_h
282 /* Will be set or not during tiffcomp.h */
283 /* You get this to compile under C++? Please say how! */
284 
open(const char * name,int flags,int mode)285 extern int open(const char* name, int flags, int mode)
286 {
287 	/* From what I can tell, should return <0 for failure */
288 	os_error* e = (os_error*) 1; /* Cheeky way to use a pointer eh? :-) */
289 	os_f file = (os_f) -1;
290 
291 	flags = flags;
292 
293 	switch(mode)
294 	{
295 		case O_RDONLY:
296 		{
297 			e = xosfind_openin(SKIP, name, SKIP, &file);
298 			break;
299 		}
300 		case O_WRONLY:
301 		case O_RDWR|O_CREAT:
302 		case O_RDWR|O_CREAT|O_TRUNC:
303 		{
304 			e = xosfind_openout(SKIP, name, SKIP, &file);
305 			break;
306 		}
307 		case O_RDWR:
308 		{
309 			e = xosfind_openup(SKIP, name, SKIP, &file);
310 			break;
311 		}
312 	}
313 	if (e)
314 	{
315 		file = (os_f) -1;
316 	}
317 	return (file);
318 }
319 
close(int fd)320 extern int close(int fd)
321 {
322 	return ((int) xosfind_close((os_f) fd));
323 }
324 
write(int fd,const char * buf,int nbytes)325 extern int write(int fd, const char *buf, int nbytes)
326 {
327 	/* Returns number of bytes written */
328 	return (nbytes - osgbpb_write((os_f) fd, (const byte*) buf, nbytes));
329 }
330 
read(int fd,char * buf,int nbytes)331 extern int read(int fd, char *buf, int nbytes)
332 {
333 	/* Returns number of bytes read */
334 	return (nbytes - osgbpb_read((os_f) fd, (byte*) buf, nbytes));
335 }
336 
lseek(int fd,off_t offset,int whence)337 extern off_t lseek(int fd, off_t offset, int whence)
338 {
339 	int absolute = 0;
340 
341 	switch (whence)
342 	{
343 		case SEEK_SET:
344 		{
345 			absolute = (int) offset;
346 			break;
347 		}
348 		case SEEK_CUR:
349 		{
350 			absolute = osargs_read_ptr((os_f) fd) + (int) offset;
351 			break;
352 		}
353 		case SEEK_END:
354 		{
355 			absolute = osargs_read_ext((os_f) fd) + (int) offset;
356 			break;
357 		}
358 	}
359 
360 	osargs_set_ptr((os_f) fd, absolute);
361 
362 	return ((off_t) osargs_read_ptr((os_f) fd));
363 }
364 #endif
365 
366 static tsize_t
_tiffReadProc(thandle_t fd,tdata_t buf,tsize_t size)367 _tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
368 {
369 	return ((tsize_t) read((int) fd, buf, (size_t) size));
370 }
371 
372 static tsize_t
_tiffWriteProc(thandle_t fd,tdata_t buf,tsize_t size)373 _tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
374 {
375 	return ((tsize_t) write((int) fd, buf, (size_t) size));
376 }
377 
378 static toff_t
_tiffSeekProc(thandle_t fd,toff_t off,int whence)379 _tiffSeekProc(thandle_t fd, toff_t off, int whence)
380 {
381 	return ((toff_t) lseek((int) fd, (off_t) off, whence));
382 }
383 
384 static int
_tiffCloseProc(thandle_t fd)385 _tiffCloseProc(thandle_t fd)
386 {
387 	return (close((int) fd));
388 }
389 
390 static toff_t
_tiffSizeProc(thandle_t fd)391 _tiffSizeProc(thandle_t fd)
392 {
393 	return (lseek((int) fd, SEEK_END, SEEK_SET));
394 }
395 
396 #ifdef HAVE_MMAP
397 #error "I didn't know Acorn had that!"
398 #endif
399 
400 /* !HAVE_MMAP */
401 static int
_tiffMapProc(thandle_t fd,tdata_t * pbase,toff_t * psize)402 _tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
403 {
404 	(void) fd; (void) pbase; (void) psize;
405 	return (0);
406 }
407 
408 static void
_tiffUnmapProc(thandle_t fd,tdata_t base,toff_t size)409 _tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
410 {
411 	(void) fd; (void) base; (void) size;
412 }
413 
414 /*
415  * Open a TIFF file descriptor for read/writing.
416  */
417 TIFF*
TIFFFdOpen(int fd,const char * name,const char * mode)418 TIFFFdOpen(int fd, const char* name, const char* mode)
419 {
420 	TIFF* tif;
421 
422 	tif = TIFFClientOpen(name, mode,
423 		(thandle_t) fd,
424 		_tiffReadProc, _tiffWriteProc,
425 		_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
426 		_tiffMapProc, _tiffUnmapProc);
427 	if (tif)
428 	{
429 		tif->tif_fd = fd;
430 	}
431 	return (tif);
432 }
433 
434 /*
435  * Open a TIFF file for read/writing.
436  */
437 TIFF*
TIFFOpen(const char * name,const char * mode)438 TIFFOpen(const char* name, const char* mode)
439 {
440 	static const char module[] = "TIFFOpen";
441 	int m, fd;
442 
443 	m = _TIFFgetMode(mode, module);
444 
445 	if (m == -1)
446 	{
447 		return ((TIFF*) 0);
448 	}
449 
450 	fd = open(name, 0, m);
451 
452 	if (fd < 0)
453 	{
454 		TIFFError(module, "%s: Cannot open", name);
455 		return ((TIFF *)0);
456 	}
457 	return (TIFFFdOpen(fd, name, mode));
458 }
459 
460 void*
_TIFFmalloc(tsize_t s)461 _TIFFmalloc(tsize_t s)
462 {
463 	return (malloc((size_t) s));
464 }
465 
466 void
_TIFFfree(tdata_t p)467 _TIFFfree(tdata_t p)
468 {
469 	free(p);
470 }
471 
472 void*
_TIFFrealloc(tdata_t p,tsize_t s)473 _TIFFrealloc(tdata_t p, tsize_t s)
474 {
475 	return (realloc(p, (size_t) s));
476 }
477 
478 void
_TIFFmemset(tdata_t p,int v,tsize_t c)479 _TIFFmemset(tdata_t p, int v, tsize_t c)
480 {
481 	memset(p, v, (size_t) c);
482 }
483 
484 void
_TIFFmemcpy(tdata_t d,const tdata_t s,tsize_t c)485 _TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
486 {
487 	memcpy(d, s, (size_t) c);
488 }
489 
490 int
_TIFFmemcmp(const tdata_t p1,const tdata_t p2,tsize_t c)491 _TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
492 {
493 	return (memcmp(p1, p2, (size_t) c));
494 }
495 
496 static void
acornWarningHandler(const char * module,const char * fmt,va_list ap)497 acornWarningHandler(const char* module, const char* fmt, va_list ap)
498 {
499 	if (module != NULL)
500 	{
501 		fprintf(stderr, "%s: ", module);
502 	}
503 	fprintf(stderr, "Warning, ");
504 	vfprintf(stderr, fmt, ap);
505 	fprintf(stderr, ".\n");
506 }
507 TIFFErrorHandler _TIFFwarningHandler = acornWarningHandler;
508 
509 static void
acornErrorHandler(const char * module,const char * fmt,va_list ap)510 acornErrorHandler(const char* module, const char* fmt, va_list ap)
511 {
512 	if (module != NULL)
513 	{
514 		fprintf(stderr, "%s: ", module);
515 	}
516 	vfprintf(stderr, fmt, ap);
517 	fprintf(stderr, ".\n");
518 }
519 TIFFErrorHandler _TIFFerrorHandler = acornErrorHandler;
520