blob: 47880e968660a0c3ca7588bc7c10a7fcaedc29e1 [file] [log] [blame]
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001
Guy Schalnat0f716451995-11-28 11:22:13 -06002/* pngmem.c - stub functions for memory allocation
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05004 * libpng 1.0.1d
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06008 * Copyright (c) 1998, Glenn Randers-Pehrson
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05009 * May 21, 1998
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060010 *
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -050011 * This file provides a location for all memory allocation. Users who
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060012 * need special memory handling are expected to modify the code in this file
13 * to meet their needs. See the instructions at each function.
14 */
Guy Schalnat0d580581995-07-20 02:43:20 -050015
16#define PNG_INTERNAL
17#include "png.h"
18
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -060019/* The following "hides" PNG_MALLOC and PNG_FREE thus allowing the pngtest
20 application to put a wrapper on top of them. */
21#ifdef PNGTEST_MEMORY_DEBUG
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -060022#define PNG_MALLOC png_debug_malloc
23#define PNG_FREE png_debug_free
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -060024#else
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -060025#define PNG_MALLOC png_malloc
26#define PNG_FREE png_free
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -060027#endif
28
Guy Schalnat4ee97b01996-01-16 01:51:56 -060029/* Borland DOS special memory handler */
30#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
31/* if you change this, be sure to change the one in png.h also */
32
Guy Schalnate5a37791996-06-05 15:50:50 -050033/* Allocate memory for a png_struct. The malloc and memset can be replaced
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060034 by a single call to calloc() if this is thought to improve performance. */
Guy Schalnate5a37791996-06-05 15:50:50 -050035png_voidp
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060036png_create_struct(int type)
Guy Schalnate5a37791996-06-05 15:50:50 -050037{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060038 png_size_t size;
Guy Schalnate5a37791996-06-05 15:50:50 -050039 png_voidp struct_ptr;
40
41 if (type == PNG_STRUCT_INFO)
42 size = sizeof(png_info);
43 else if (type == PNG_STRUCT_PNG)
44 size = sizeof(png_struct);
45 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060046 return ((png_voidp)NULL);
Guy Schalnate5a37791996-06-05 15:50:50 -050047
48 if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
49 {
50 png_memset(struct_ptr, 0, size);
51 }
52
53 return (struct_ptr);
54}
55
56
57/* Free memory allocated by a png_create_struct() call */
58void
59png_destroy_struct(png_voidp struct_ptr)
60{
Andreas Dilger47a0c421997-05-16 02:46:07 -050061 if (struct_ptr != NULL)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -060062 {
Guy Schalnate5a37791996-06-05 15:50:50 -050063 farfree (struct_ptr);
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -060064 struct_ptr = NULL;
65 }
Guy Schalnate5a37791996-06-05 15:50:50 -050066}
67
Guy Schalnat0d580581995-07-20 02:43:20 -050068/* Allocate memory. For reasonable files, size should never exceed
Andreas Dilger47a0c421997-05-16 02:46:07 -050069 * 64K. However, zlib may allocate more then 64K if you don't tell
70 * it not to. See zconf.h and png.h for more information. zlib does
71 * need to allocate exactly 64K, so whatever you call here must
72 * have the ability to do that.
73 *
74 * Borland seems to have a problem in DOS mode for exactly 64K.
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050075 * It gives you a segment with an offset of 8 (perhaps to store its
Andreas Dilger47a0c421997-05-16 02:46:07 -050076 * memory stuff). zlib doesn't like this at all, so we have to
77 * detect and deal with it. This code should not be needed in
78 * Windows or OS/2 modes, and only in 16 bit mode. This code has
79 * been updated by Alexander Lehmann for version 0.89 to waste less
80 * memory.
81 *
82 * Note that we can't use png_size_t for the "size" declaration,
83 * since on some systems a png_size_t is a 16-bit quantity, and as a
84 * result, we would be truncating potentially larger memory requests
85 * (which should cause a fatal error) and introducing major problems.
86 */
Guy Schalnat4ee97b01996-01-16 01:51:56 -060087png_voidp
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -060088PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
Guy Schalnat4ee97b01996-01-16 01:51:56 -060089{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060090 png_voidp ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -050091 if (png_ptr == NULL || size == 0)
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060092 return ((png_voidp)NULL);
Guy Schalnat4ee97b01996-01-16 01:51:56 -060093
94#ifdef PNG_MAX_MALLOC_64K
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060095 if (size > (png_uint_32)65536L)
96 png_error(png_ptr, "Cannot Allocate > 64K");
Guy Schalnat4ee97b01996-01-16 01:51:56 -060097#endif
98
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060099 if (size == (png_uint_32)65536L)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600100 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500101 if (png_ptr->offset_table == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600102 {
103 /* try to see if we need to do any of this fancy stuff */
104 ret = farmalloc(size);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500105 if (ret == NULL || ((png_size_t)ret & 0xffff))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600106 {
107 int num_blocks;
108 png_uint_32 total_size;
109 png_bytep table;
110 int i;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600111 png_byte huge * hptr;
112
Andreas Dilger47a0c421997-05-16 02:46:07 -0500113 if (ret != NULL)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600114 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600115 farfree(ret);
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600116 ret = NULL;
117 }
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600118
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600119 num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
120 if (num_blocks < 1)
121 num_blocks = 1;
122 if (png_ptr->zlib_mem_level >= 7)
123 num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
124 else
125 num_blocks++;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600126
Guy Schalnate5a37791996-06-05 15:50:50 -0500127 total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600128
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600129 table = farmalloc(total_size);
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600130
Andreas Dilger47a0c421997-05-16 02:46:07 -0500131 if (table == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600132 {
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600133 png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600134 }
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600135
Andreas Dilger47a0c421997-05-16 02:46:07 -0500136 if ((png_size_t)table & 0xfff0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600137 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500138 png_error(png_ptr, "Farmalloc didn't return normalized pointer");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600139 }
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600140
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600141 png_ptr->offset_table = table;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500142 png_ptr->offset_table_ptr = farmalloc(num_blocks *
143 sizeof (png_bytep));
Guy Schalnate5a37791996-06-05 15:50:50 -0500144
Andreas Dilger47a0c421997-05-16 02:46:07 -0500145 if (png_ptr->offset_table_ptr == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600146 {
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600147 png_error(png_ptr, "Out Of memory.");
Guy Schalnate5a37791996-06-05 15:50:50 -0500148 }
149
150 hptr = (png_byte huge *)table;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500151 if ((png_size_t)hptr & 0xf)
Guy Schalnate5a37791996-06-05 15:50:50 -0500152 {
153 hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
154 hptr += 16L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600155 }
156 for (i = 0; i < num_blocks; i++)
157 {
158 png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600159 hptr += (png_uint_32)65536L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600160 }
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600161
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600162 png_ptr->offset_table_number = num_blocks;
163 png_ptr->offset_table_count = 0;
164 png_ptr->offset_table_count_free = 0;
165 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600166 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500167
168 if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600169 png_error(png_ptr, "Out of Memory.");
Guy Schalnate5a37791996-06-05 15:50:50 -0500170
171 ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600172 }
173 else
174 ret = farmalloc(size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500175
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500176 if (ret == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500177 {
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600178 png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
Guy Schalnat0d580581995-07-20 02:43:20 -0500179 }
180
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600181 return (ret);
Guy Schalnat0d580581995-07-20 02:43:20 -0500182}
183
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600184/* free a pointer allocated by PNG_MALLOC(). In the default
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600185 configuration, png_ptr is not used, but is passed in case it
186 is needed. If ptr is NULL, return without taking any action. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500187void
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600188PNG_FREE(png_structp png_ptr, png_voidp ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500189{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500190 if (png_ptr == NULL || ptr == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600191 return;
192
Andreas Dilger47a0c421997-05-16 02:46:07 -0500193 if (png_ptr->offset_table != NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600194 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500195 int i;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600196
Andreas Dilger47a0c421997-05-16 02:46:07 -0500197 for (i = 0; i < png_ptr->offset_table_count; i++)
198 {
199 if (ptr == png_ptr->offset_table_ptr[i])
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600200 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500201 ptr = NULL;
202 png_ptr->offset_table_count_free++;
203 break;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600204 }
205 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500206 if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
207 {
208 farfree(png_ptr->offset_table);
209 farfree(png_ptr->offset_table_ptr);
210 png_ptr->offset_table = NULL;
211 png_ptr->offset_table_ptr = NULL;
212 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600213 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500214
215 if (ptr != NULL)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600216 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500217 farfree(ptr);
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600218 ptr = NULL;
219 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600220}
221
222#else /* Not the Borland DOS special memory handler */
223
Guy Schalnate5a37791996-06-05 15:50:50 -0500224/* Allocate memory for a png_struct or a png_info. The malloc and
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600225 memset can be replaced by a single call to calloc() if this is thought
226 to improve performance noticably.*/
Guy Schalnate5a37791996-06-05 15:50:50 -0500227png_voidp
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600228png_create_struct(int type)
Guy Schalnate5a37791996-06-05 15:50:50 -0500229{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500230 png_size_t size;
Guy Schalnate5a37791996-06-05 15:50:50 -0500231 png_voidp struct_ptr;
232
233 if (type == PNG_STRUCT_INFO)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500234 size = sizeof(png_info);
Guy Schalnate5a37791996-06-05 15:50:50 -0500235 else if (type == PNG_STRUCT_PNG)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500236 size = sizeof(png_struct);
Guy Schalnate5a37791996-06-05 15:50:50 -0500237 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600238 return ((png_voidp)NULL);
Guy Schalnate5a37791996-06-05 15:50:50 -0500239
240#if defined(__TURBOC__) && !defined(__FLAT__)
241 if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
242#else
243# if defined(_MSC_VER) && defined(MAXSEG_64K)
Guy Schalnatc21f90c1996-06-17 16:24:45 -0500244 if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500245# else
246 if ((struct_ptr = (png_voidp)malloc(size)) != NULL)
247# endif
248#endif
249 {
250 png_memset(struct_ptr, 0, size);
251 }
252
253 return (struct_ptr);
254}
255
256
257/* Free memory allocated by a png_create_struct() call */
258void
259png_destroy_struct(png_voidp struct_ptr)
260{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500261 if (struct_ptr != NULL)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600262 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500263#if defined(__TURBOC__) && !defined(__FLAT__)
264 farfree(struct_ptr);
265#else
266# if defined(_MSC_VER) && defined(MAXSEG_64K)
267 hfree(struct_ptr);
268# else
269 free(struct_ptr);
270# endif
271#endif
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600272 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500273}
274
275
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600276/* Allocate memory. For reasonable files, size should never exceed
277 64K. However, zlib may allocate more then 64K if you don't tell
Andreas Dilger47a0c421997-05-16 02:46:07 -0500278 it not to. See zconf.h and png.h for more information. zlib does
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600279 need to allocate exactly 64K, so whatever you call here must
280 have the ability to do that. */
281
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600282png_voidp
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600283PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600284{
285 png_voidp ret;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600286
Andreas Dilger47a0c421997-05-16 02:46:07 -0500287 if (png_ptr == NULL || size == 0)
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600288 return ((png_voidp)NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600289
290#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600291 if (size > (png_uint_32)65536L)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600292 png_error(png_ptr, "Cannot Allocate > 64K");
293#endif
294
295#if defined(__TURBOC__) && !defined(__FLAT__)
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600296 ret = farmalloc(size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600297#else
298# if defined(_MSC_VER) && defined(MAXSEG_64K)
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600299 ret = halloc(size, 1);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600300# else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600301 ret = malloc((size_t)size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600302# endif
303#endif
304
305 if (ret == NULL)
306 {
307 png_error(png_ptr, "Out of Memory");
308 }
309
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600310 return (ret);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600311}
312
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600313/* Free a pointer allocated by PNG_MALLOC(). In the default
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600314 configuration, png_ptr is not used, but is passed in case it
315 is needed. If ptr is NULL, return without taking any action. */
316void
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600317PNG_FREE(png_structp png_ptr, png_voidp ptr)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600318{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500319 if (png_ptr == NULL || ptr == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600320 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500321
Guy Schalnat6d764711995-12-19 03:22:19 -0600322#if defined(__TURBOC__) && !defined(__FLAT__)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500323 farfree(ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -0500324#else
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600325# if defined(_MSC_VER) && defined(MAXSEG_64K)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500326 hfree(ptr);
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600327# else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500328 free(ptr);
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600329# endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500330#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500331}
332
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600333#endif /* Not Borland DOS special memory handler */
Guy Schalnat6d764711995-12-19 03:22:19 -0600334
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600335png_voidp
336png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600337 png_uint_32 length)
338{
339 png_size_t size;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600340
341 size = (png_size_t)length;
342 if ((png_uint_32)size != length)
343 png_error(png_ptr,"Overflow in png_memcpy_check.");
344
345 return(png_memcpy (s1, s2, size));
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600346}
347
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600348png_voidp
349png_memset_check (png_structp png_ptr, png_voidp s1, int value,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600350 png_uint_32 length)
351{
352 png_size_t size;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600353
354 size = (png_size_t)length;
355 if ((png_uint_32)size != length)
356 png_error(png_ptr,"Overflow in png_memset_check.");
357
358 return (png_memset (s1, value, size));
359
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600360}