diff options
author | Henry Stiles <henry.stiles@artifex.com> | 1998-09-04 15:53:41 +0000 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 1998-09-04 15:53:41 +0000 |
commit | 6382283b6f812883c171bb654cc1b10c58d53051 (patch) | |
tree | 10256af38a35d3ddeb37cd598b850bb5647ac350 /gs | |
parent | 35bf5548df5eed229be44891c4e8b940f37d8d8a (diff) |
gs5.38
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@396 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs')
-rw-r--r-- | gs/current.txt | 4 | ||||
-rw-r--r-- | gs/lib/gs_init.ps | 2 | ||||
-rw-r--r-- | gs/news | 59 | ||||
-rw-r--r-- | gs/src/gdevpdfi.c | 15 | ||||
-rw-r--r-- | gs/src/gdevpsdp.c | 40 | ||||
-rw-r--r-- | gs/src/gsalloc.c | 150 | ||||
-rw-r--r-- | gs/src/gsalloc.h | 13 | ||||
-rw-r--r-- | gs/src/gscolor2.c | 5 | ||||
-rw-r--r-- | gs/src/gscsepr.c | 5 | ||||
-rw-r--r-- | gs/src/gscspace.c | 32 | ||||
-rw-r--r-- | gs/src/gsmalloc.c | 1 | ||||
-rw-r--r-- | gs/src/gsmemlok.c | 9 | ||||
-rw-r--r-- | gs/src/gsmemory.c | 6 | ||||
-rw-r--r-- | gs/src/gsmemory.h | 5 | ||||
-rw-r--r-- | gs/src/gsmemraw.h | 17 | ||||
-rw-r--r-- | gs/src/gsnogc.c | 94 | ||||
-rw-r--r-- | gs/src/gsparam.c | 17 | ||||
-rw-r--r-- | gs/src/gspcolor.c | 5 | ||||
-rw-r--r-- | gs/src/gsstate.c | 34 | ||||
-rw-r--r-- | gs/src/gxalloc.h | 28 | ||||
-rw-r--r-- | gs/src/gxclip2.c | 3 | ||||
-rw-r--r-- | gs/src/gxcspace.h | 20 | ||||
-rw-r--r-- | gs/src/gxp1fill.c | 22 | ||||
-rw-r--r-- | gs/src/iparam.c | 6 | ||||
-rw-r--r-- | gs/src/version.mak | 6 | ||||
-rw-r--r-- | gs/src/zfileio.c | 6 |
26 files changed, 415 insertions, 189 deletions
diff --git a/gs/current.txt b/gs/current.txt index 3e8a9c461..62435efa2 100644 --- a/gs/current.txt +++ b/gs/current.txt @@ -30,8 +30,8 @@ New features (since release 5.10) (This is not a complete list of new features: see NEWS for details.) A number of PostScript LanguageLevel 3 features are implemented: ImageType 4 -images, CIEBasedDEF[G] color spaces, idiom recognition, shfill (partial -support), CloseSource/CloseTarget. +images, Type 32 fonts / CIDFontType 4 fonts, CIEBasedDEF[G] color spaces, +idiom recognition, shfill (partial support), CloseSource/CloseTarget. More of Display PostScript is implemented: view clipping, DevicePixel color space, context creation with private local VM, ImageType 2 images, diff --git a/gs/lib/gs_init.ps b/gs/lib/gs_init.ps index c5ee5662f..b92b668a6 100644 --- a/gs/lib/gs_init.ps +++ b/gs/lib/gs_init.ps @@ -31,7 +31,7 @@ % Check the interpreter revision. NOTE: the interpreter code requires % that the first non-comment token in this file be an integer. -537 +538 dup revision ne { (gs: Interpreter revision \() print revision 10 string cvs print (\) does not match gs_init.ps revision \() print 10 string cvs print @@ -29,6 +29,65 @@ Procedures, Utilities, Drivers, Platforms, Fonts, Interpreter, Streams (included under Interpreter through release 2.9.9), Library. Changes marked with a * were made available as patches to a previous release. +Version 5.38(beta) (9/3/98) +=========================== + +The sole purpose of this release was to fix some obscure bugs detected by +the Genoa tests and by another Aladdin project. + +Documentation +------------- + +Updates the list of implemented PostScript LanguageLevel 3 features. +(current.txt) + +Drivers +------- + +Fixes problems: + - The PDF writer did the wrong thing for multi-source images with +more than 180 bytes of data (total) per scan line. (gdevpdfi.c) + - If one used setdistillerparams, [g]restore caused a rangecheck in +.setpagedevice. ****** DISABLED FOR DCT DICTS, SINCE THIS CAUSES A SEGV +****** (gdevpsdp.c) + +Interpreter +----------- + +Fixes problems: + - 0-length parameter arrays were given an arbitrary type, confusing +clients. (iparam.c) + - EOD on a write stream caused an error. (zfileio.c) + +Library +------- + +Fixes problems: + - 0-length parameter arrays confused clients that wanted arrays of a +particular type. (gsparam.c) + - Patterns with XStep or YStep smaller than the bounding box didn't +work properly. (gxp1fill.c) + - Resizing an object sometimes copied it unnecessarily. (gsalloc.c) + - Freeing the shared part of a graphics state didn't free its +sub-objects. (gsstate.c) + - The standard allocator didn't free its initial (self-containing) +chunk when asked to free itself. (gsalloc.c) + - The standard allocator didn't attempt to merge free blocks before +giving up. We implemented this by adding another virtual procedure to +allocators, consolidate_free. (gsmemory.h, gsmemraw.h, gsalloc.c, +gsmalloc.c, gsmemlok.c, gsmemory.c) + - The free object merging algorithm thought there were free objects +even when there weren't. (Small performance bug only.) (gsalloc.c) + +Adds some more tracing to pattern filling. (gxclip2.c, gxp1fill.c) + +Replaces the cs_alloc, cs_copy, and cs_undo_alloc macros with procedures. +(gxcspace.h, gscolor2.c, gscsepr.c, gscspace.c, gspcolor.c) + +Moves the free-object merging code from gsnogc.c to gsalloc.c, so it can be +used even in systems that have a garbage collector. (gsalloc.h, gxalloc.h, +gsalloc.c, gsnogc.c) + Version 5.37(beta) (8/31/98) ============================ diff --git a/gs/src/gdevpdfi.c b/gs/src/gdevpdfi.c index cb8d377e5..56dc307cc 100644 --- a/gs/src/gdevpdfi.c +++ b/gs/src/gdevpdfi.c @@ -979,7 +979,6 @@ gdev_pdf_begin_image(gx_device * dev, if (pim->ImageMask) pdf_set_color(pdev, gx_dc_pure_color(pdcolor), &pdev->fill_color, "rg"); -/****** DOESN'T DO COMPRESSION YET ******/ { gs_matrix mat; gs_matrix bmat; @@ -1041,19 +1040,21 @@ pdf_image_plane_data(gx_device * dev, gx_image_enum_common_t * info, for (y = 0; y < h; ++y) { if (nplanes > 1) { /* Flip the data in blocks before writing. */ + int pi; uint count = bcount; + uint offset = 0; + const byte *bit_planes[gs_image_max_components]; + for (pi = 0; pi < nplanes; ++pi) + bit_planes[pi] = planes[pi].data + planes[pi].raster * y; while (count) { uint flip_count = min(count, row_bytes / nplanes); - const byte *bit_planes[gs_image_max_components]; - int pi; - for (pi = 0; pi < nplanes; ++pi) - bit_planes[pi] = planes[pi].data + planes[pi].raster * y; - image_flip_planes(row, bit_planes, 0, flip_count, nplanes, - pie->plane_depths[0]); + image_flip_planes(row, bit_planes, offset, flip_count, + nplanes, pie->plane_depths[0]); sputs(pie->writer.binary.strm, row, flip_count * nplanes, &ignore); + offset += flip_count; count -= flip_count; } } else { diff --git a/gs/src/gdevpsdp.c b/gs/src/gdevpsdp.c index f35f7c589..74c882754 100644 --- a/gs/src/gdevpsdp.c +++ b/gs/src/gdevpsdp.c @@ -124,17 +124,32 @@ typedef stream_state_proc_get_params((*ss_get_params_t), stream_state); private int psdf_CF_get_params(gs_param_list * plist, const stream_state * ss, bool all) { - return s_CF_get_params(plist, (const stream_CF_state *)ss, all); + return (ss == 0 ? 0 : + s_CF_get_params(plist, (const stream_CF_state *)ss, all)); } private int psdf_DCT_get_params(gs_param_list * plist, const stream_state * ss, bool all) { - return s_DCTE_get_params(plist, (const stream_DCT_state *)ss, all); + int code = (ss == 0 ? 0 : + s_DCTE_get_params(plist, (const stream_DCT_state *)ss, all)); + /* + * Add dummy Columns, Rows, and Colors parameters so that put_params + * won't complain. + */ + int dummy_size = 8, dummy_colors = 3; + + if (code < 0 || + (code = param_write_int(plist, "Columns", &dummy_size)) < 0 || + (code = param_write_int(plist, "Rows", &dummy_size)) < 0 || + (code = param_write_int(plist, "Colors", &dummy_colors)) < 0 + ) + return code; + return 0; } /* - * Get an image Dict parameter. Note that we return an empty dictionary if - * the parameter has never been set. + * Get an image Dict parameter. Note that we return a default (usually + * empty) dictionary if the parameter has never been set. */ private int psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname, @@ -148,8 +163,7 @@ psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname, dict.size = 12; /* enough for all param dicts we know about */ if ((code = param_begin_write_dict(plist, pname, &dict, false)) < 0) return code; - if (ss != 0) - code = (*get_params) (dict.list, ss, false); + code = (*get_params)(dict.list, ss, false); param_end_write_dict(plist, pname, &dict); return code; } @@ -410,13 +424,20 @@ psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname, ss = 0; break; case 0:{ + /****** + ****** THIS CAUSES A SEGV FOR DCT FILTERS, BECAUSE + ****** THEY DON'T INTIALIZE PROPERLY. + ******/ + if (template != &s_DCTE_template) { stream_state *ss_new = - s_alloc_state(mem, template->stype, pname); + s_alloc_state(mem, template->stype, pname); if (ss_new == 0) return_error(gs_error_VMerror); ss_new->template = template; - code = (*put_params) (dict.list, ss_new); + if (template->set_defaults) + (*template->set_defaults)(ss_new); + code = (*put_params)(dict.list, ss_new); if (code < 0) { param_signal_error(plist, pname, code); /* Make sure we free the new state. */ @@ -424,11 +445,12 @@ psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname, } else ss = ss_new; } + } param_end_read_dict(plist, pname, &dict); } if (*pss != ss) { if (ss) { -/****** FREE SUBSIDIARY OBJECTS -- HOW? ******/ + /****** FREE SUBSIDIARY OBJECTS -- HOW? ******/ gs_free_object(mem, *pss, pname); } *pss = ss; diff --git a/gs/src/gsalloc.c b/gs/src/gsalloc.c index c28803bfb..6658bb2d8 100644 --- a/gs/src/gsalloc.c +++ b/gs/src/gsalloc.c @@ -104,6 +104,7 @@ private gs_memory_proc_resize_object(i_resize_object); private gs_memory_proc_free_object(i_free_object); private gs_memory_proc_status(i_status); private gs_memory_proc_free_all(i_free_all); +private gs_memory_proc_consolidate_free(i_consolidate_free); /* Object memory procedures */ private gs_memory_proc_alloc_bytes(i_alloc_bytes); @@ -132,6 +133,7 @@ const gs_memory_procs_t gs_ref_memory_procs = i_free_object, i_status, i_free_all, + i_consolidate_free, /* Object memory procedures */ i_alloc_bytes, i_alloc_struct, @@ -169,6 +171,7 @@ ialloc_alloc_state(gs_raw_memory_t * parent, uint chunk_size) iimem->parent = parent; iimem->chunk_size = chunk_size; iimem->large_size = ((chunk_size / 4) & -obj_align_mod) + 1; + iimem->is_controlled = false; iimem->gc_status.vm_threshold = chunk_size * 3L; iimem->gc_status.max_vm = max_long; iimem->gc_status.psignal = NULL; @@ -230,6 +233,7 @@ ialloc_add_chunk(gs_ref_memory_t *imem, ulong space, client_name_t cname) chunk_t *cp; /* Allow acquisition of this chunk. */ + imem->is_controlled = false; imem->large_size = imem->chunk_size; imem->limit = max_long; imem->gc_status.max_vm = max_long; @@ -250,6 +254,7 @@ ialloc_add_chunk(gs_ref_memory_t *imem, ulong space, client_name_t cname) imem->procs.alloc_string_immovable = imem->procs.alloc_string; /* Disable acquisition of additional chunks. */ + imem->is_controlled = true; imem->limit = 0; return (cp ? 0 : gs_note_error(gs_error_VMerror)); @@ -305,12 +310,12 @@ ialloc_reset_free(gs_ref_memory_t * mem) /* vm_threshold, max_vm, or enabled, or after a GC. */ void ialloc_set_limit(register gs_ref_memory_t * mem) -{ /* - * The following code is intended to set the limit so that - * we stop allocating when allocated + previous_status.allocated - * exceeds the lesser of max_vm or (if GC is enabled) - * gc_allocated + vm_threshold. - */ +{ /* + * The following code is intended to set the limit so that + * we stop allocating when allocated + previous_status.allocated + * exceeds the lesser of max_vm or (if GC is enabled) + * gc_allocated + vm_threshold. + */ ulong max_allocated = (mem->gc_status.max_vm > mem->previous_status.allocated ? mem->gc_status.max_vm - mem->previous_status.allocated : @@ -359,16 +364,14 @@ i_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname) alloc_free_chunk(cp, imem); } } - if (free_mask & FREE_ALL_STRUCTURES) { - /* Note that the allocator is unusable after doing this. */ + if (free_mask & FREE_ALL_ALLOCATOR) { + /* Free the chunk holding the allocator itself. */ for (cp = imem->clast; cp != 0; cp = cp->cprev) if (cp->cbase + sizeof(obj_header_t) == (byte *)mem) { - gs_free_object(imem->parent, cp, cname); + alloc_free_chunk(cp, imem); break; } } - if (free_mask & FREE_ALL_ALLOCATOR) - gs_free_object(imem->parent, imem, cname); } /* ================ Accessors ================ */ @@ -577,12 +580,14 @@ i_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements, gs_memory_type_ptr_t pstype = pp->o_type; ulong old_size = pre_obj_contents_size(pp); ulong new_size = (ulong) pstype->ssize * new_num_elements; + ulong new_size_rounded; void *new_obj; - if ((byte *) obj + obj_align_round(old_size) == imem->cc.cbot && - imem->cc.ctop - imem->cc.cbot > new_size + obj_align_mod + if ((byte *)obj + obj_align_round(old_size) == imem->cc.cbot && + imem->cc.ctop - (byte *)obj >= + (new_size_rounded = obj_align_round(new_size)) ) { - imem->cc.cbot = (byte *) obj + obj_align_round(new_size); + imem->cc.cbot = (byte *)obj + new_size_rounded; pp->o_size = new_size; if_debug8('A', "[a%d:%c%c ]%s %s(%lu=>%lu) 0x%lx\n", imem->space, @@ -691,7 +696,8 @@ i_free_object(gs_memory_t * mem, void *ptr, client_name_t cname) cl.memory = imem; cl.cp = 0; if (chunk_locate_ptr(ptr, &cl)) { - alloc_free_chunk(cl.cp, imem); + if (!imem->is_controlled) + alloc_free_chunk(cl.cp, imem); return; } /* Don't overwrite even if gs_alloc_debug is set. */ @@ -899,10 +905,13 @@ alloc_obj(gs_ref_memory_t * mem, ulong lsize, gs_memory_type_ptr_t pstype, obj_header_t *ptr; if (lsize >= mem->large_size || immovable) { + /* + * Give the object a chunk all its own. Note that this case does + * not occur if is_controlled is true. + */ ulong asize = ((lsize + obj_align_mask) & -obj_align_mod) + sizeof(obj_header_t); - /* Give it a chunk all its own. */ chunk_t *cp = alloc_acquire_chunk(mem, asize + sizeof(chunk_head_t), false, "large object chunk"); @@ -915,16 +924,24 @@ alloc_obj(gs_ref_memory_t * mem, ulong lsize, gs_memory_type_ptr_t pstype, pre_obj_set_large_size(ptr, lsize); } else { uint asize = obj_size_round((uint) lsize); + bool consolidate = mem->is_controlled; while (mem->cc.ctop - (byte *) (ptr = (obj_header_t *) mem->cc.cbot) <= asize + sizeof(obj_header_t)) { - /* Add another chunk. */ - chunk_t *cp = - alloc_add_chunk(mem, (ulong)mem->chunk_size, "chunk"); - - if (cp == 0) - return 0; + if (consolidate) { + /* Try consolidating free space. */ + gs_consolidate_free((gs_memory_t *)mem); + consolidate = false; + continue; + } else { + /* Add another chunk. */ + chunk_t *cp = + alloc_add_chunk(mem, (ulong)mem->chunk_size, "chunk"); + + if (cp == 0) + return 0; + } } mem->cc.cbot = (byte *) ptr + asize; ptr->o_large = 0; @@ -936,6 +953,86 @@ alloc_obj(gs_ref_memory_t * mem, ulong lsize, gs_memory_type_ptr_t pstype, return ptr; } +/* Consolidate free objects. */ +void +ialloc_consolidate_free(gs_ref_memory_t *mem) +{ + chunk_t *cp; + chunk_t *cprev; + /* + * We're going to recompute lost.objects, by subtracting the + * amount of space reclaimed minus the amount of that space that + * was on free lists. + */ + ulong found = 0; + + alloc_close_chunk(mem); + + /* Visit chunks in reverse order to encourage LIFO behavior. */ + for (cp = mem->clast; cp != 0; cp = cprev) { + obj_header_t *begin_free = 0; + + cprev = cp->cprev; + SCAN_CHUNK_OBJECTS(cp) + DO_ALL + if (pre->o_type == &st_free) { + if (begin_free == 0) + begin_free = pre; + } else + begin_free = 0; + END_OBJECTS_SCAN + if (begin_free) { + /* We found free objects at the top of the object area. */ + int i; + + found += (byte *)cp->cbot - (byte *)begin_free; + /* Remove the free objects from the freelists. */ + for (i = 0; i < num_freelists; i++) { + obj_header_t *pfree; + obj_header_t **ppfprev = &mem->freelists[i]; + uint free_size = + (i << log2_obj_align_mod) + sizeof(obj_header_t); + + while ((pfree = *ppfprev) != 0) + if (ptr_ge(pfree, begin_free) && + ptr_lt(pfree, cp->cbot) + ) { /* We're removing an object. */ + *ppfprev = *(obj_header_t **) pfree; + found -= free_size; + } else + ppfprev = (obj_header_t **) pfree; + } + } else + begin_free = (obj_header_t *)cp->cbot; + if (begin_free == (obj_header_t *) cp->cbase && + cp->ctop == cp->climit + ) { /* The entire chunk is free. */ + chunk_t *cnext = cp->cnext; + + if (!mem->is_controlled) + alloc_free_chunk(cp, mem); + if (mem->pcc == cp) + mem->pcc = + (cnext == 0 ? cprev : cprev == 0 ? cnext : + cprev->cbot - cprev->ctop > + cnext->cbot - cnext->ctop ? cprev : + cnext); + } else if (begin_free != (obj_header_t *)cp->cbot) { + if_debug4('a', "[a]resetting chunk 0x%lx cbot from 0x%lx to 0x%lx (%lu free)\n", + (ulong) cp, (ulong) cp->cbot, (ulong) begin_free, + (ulong) ((byte *) cp->cbot - (byte *) begin_free)); + cp->cbot = (byte *) begin_free; + } + } + mem->lost.objects -= found; + alloc_open_chunk(mem); +} +private void +i_consolidate_free(gs_memory_t *mem) +{ + ialloc_consolidate_free((gs_ref_memory_t *)mem); +} + /* ================ Roots ================ */ /* Register a root. */ @@ -1192,13 +1289,19 @@ alloc_unlink_chunk(chunk_t * cp, gs_ref_memory_t * mem) } } -/* Free a chunk. This is exported for the GC. */ +/* + * Free a chunk. This is exported for the GC. Since we eventually use + * this to free the chunk containing the allocator itself, we must be + * careful not to reference anything in the allocator after freeing the + * chunk data. + */ void alloc_free_chunk(chunk_t * cp, gs_ref_memory_t * mem) { gs_raw_memory_t *parent = mem->parent; alloc_unlink_chunk(cp, mem); + mem->allocated -= st_chunk.ssize; if (mem->cfreed.cp == cp) mem->cfreed.cp = 0; if (cp->outer == 0) { @@ -1208,7 +1311,6 @@ alloc_free_chunk(chunk_t * cp, gs_ref_memory_t * mem) gs_free_object(parent, cdata, "alloc_free_chunk(data)"); } else cp->outer->inner_count--; - mem->allocated -= st_chunk.ssize; gs_free_object(parent, cp, "alloc_free_chunk(chunk struct)"); } diff --git a/gs/src/gsalloc.h b/gs/src/gsalloc.h index 3670e427c..910821ffb 100644 --- a/gs/src/gsalloc.h +++ b/gs/src/gsalloc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1995 Aladdin Enterprises. All rights reserved. +/* Copyright (C) 1995, 1998 Aladdin Enterprises. All rights reserved. This file is part of Aladdin Ghostscript. @@ -33,14 +33,14 @@ typedef struct gs_ref_memory_s gs_ref_memory_t; * Define a structure and interface for GC-related allocator state. */ typedef struct gs_memory_gc_status_s { - /* Set by client */ + /* Set by client */ long vm_threshold; /* GC interval */ long max_vm; /* maximum allowed allocation */ int *psignal; /* if not NULL, store signal_value */ - /* here if we go over the vm_threshold */ + /* here if we go over the vm_threshold */ int signal_value; /* value to store in *psignal */ bool enabled; /* auto GC enabled if true */ - /* Set by allocator */ + /* Set by allocator */ long requested; /* amount of last failing request */ } gs_memory_gc_status_t; void gs_memory_gc_status(P2(const gs_ref_memory_t *, gs_memory_gc_status_t *)); @@ -57,7 +57,7 @@ gs_ref_memory_t *ialloc_alloc_state(P2(gs_raw_memory_t *, uint)); /* * Add a chunk to an externally controlled allocator. Such allocators * allocate all objects as immovable, are not garbage-collected, and - * don't attempt to acquire additional memory on their own. + * don't attempt to acquire additional memory (or free chunks) on their own. */ int ialloc_add_chunk(P3(gs_ref_memory_t *, ulong, client_name_t)); @@ -75,4 +75,7 @@ void ialloc_reset_free(P1(gs_ref_memory_t *)); /* Set the cached allocation limit of an alloctor from its GC parameters. */ void ialloc_set_limit(P1(gs_ref_memory_t *)); +/* Consolidate free objects. */ +void ialloc_consolidate_free(P1(gs_ref_memory_t *)); + #endif /* gsalloc_INCLUDED */ diff --git a/gs/src/gscolor2.c b/gs/src/gscolor2.c index b56c6447c..c737efa3c 100644 --- a/gs/src/gscolor2.c +++ b/gs/src/gscolor2.c @@ -308,11 +308,14 @@ gs_cspace_build_Indexed( { gs_color_space *pcspace = 0; gs_indexed_params *pindexed = 0; + int code; if ((pbase_cspace == 0) || !pbase_cspace->type->can_be_base_space) return_error(gs_error_rangecheck); - cs_alloc(pcspace, &gs_color_space_type_Indexed, pmem); + code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Indexed, pmem); + if (code < 0) + return code; pindexed = &(pcspace->params.indexed); if (ptbl == 0) { pindexed->lookup.map = diff --git a/gs/src/gscsepr.c b/gs/src/gscsepr.c index f75220012..44cdeeed9 100644 --- a/gs/src/gscsepr.c +++ b/gs/src/gscsepr.c @@ -207,11 +207,14 @@ gs_cspace_build_Separation( { gs_color_space *pcspace = 0; gs_separation_params *pcssepr = 0; + int code; if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space) return_error(gs_error_rangecheck); - cs_alloc(pcspace, &gs_color_space_type_Separation, pmem); + code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Separation, pmem); + if (code < 0) + return code; pcssepr = &pcspace->params.separation; pcssepr->map = alloc_separation_map(palt_cspace, cache_size, pmem); if (pcssepr->map == 0) { diff --git a/gs/src/gscspace.c b/gs/src/gscspace.c index b445953fe..d36e3b83c 100644 --- a/gs/src/gscspace.c +++ b/gs/src/gscspace.c @@ -77,28 +77,37 @@ gs_cspace_DeviceCMYK(const gs_imager_state * pis) /* ------ Create/copy/destroy ------ */ -private int -cspace_build(gs_color_space ** ppcspace, const gs_color_space_type * pcstype, - gs_memory_t * pmem) -{ - cs_alloc(*ppcspace, pcstype, pmem); +int +gs_cspace_alloc(gs_color_space ** ppcspace, + const gs_color_space_type * pcstype, + gs_memory_t * mem) +{ + gs_color_space *pcspace = + gs_alloc_struct(mem, gs_color_space, &st_color_space, + "gs_cspace_alloc"); + + if (pcspace == 0) + return_error(gs_error_VMerror); + pcspace->pmem = mem; + pcspace->type = pcstype; + *ppcspace = pcspace; return 0; } int gs_cspace_build_DeviceGray(gs_color_space ** ppcspace, gs_memory_t * pmem) { - return cspace_build(ppcspace, &gs_color_space_type_DeviceGray, pmem); + return gs_cspace_alloc(ppcspace, &gs_color_space_type_DeviceGray, pmem); } int gs_cspace_build_DeviceRGB(gs_color_space ** ppcspace, gs_memory_t * pmem) { - return cspace_build(ppcspace, &gs_color_space_type_DeviceRGB, pmem); + return gs_cspace_alloc(ppcspace, &gs_color_space_type_DeviceRGB, pmem); } int gs_cspace_build_DeviceCMYK(gs_color_space ** ppcspace, gs_memory_t * pmem) { - return cspace_build(ppcspace, &gs_color_space_type_DeviceCMYK, pmem); + return gs_cspace_alloc(ppcspace, &gs_color_space_type_DeviceCMYK, pmem); } /* @@ -107,8 +116,11 @@ gs_cspace_build_DeviceCMYK(gs_color_space ** ppcspace, gs_memory_t * pmem) * compound color space when legal, but it can't check that the operation is * actually legal. */ -#define cs_copy(pcsto, pcsfrom)\ - memcpy(pcsto, pcsfrom, (pcsfrom)->type->stype->ssize) +inline private void +cs_copy(gs_color_space *pcsto, const gs_color_space *pcsfrom) +{ + memcpy(pcsto, pcsfrom, pcsfrom->type->stype->ssize); +} /* Copy a color space into one newly allocated by the caller. */ void diff --git a/gs/src/gsmalloc.c b/gs/src/gsmalloc.c index 0bc2394a1..1f9127412 100644 --- a/gs/src/gsmalloc.c +++ b/gs/src/gsmalloc.c @@ -60,6 +60,7 @@ private const gs_memory_procs_t gs_malloc_memory_procs = gs_heap_free_object, gs_heap_status, gs_heap_free_all, + gs_ignore_consolidate_free, /* Object memory procedures */ gs_heap_alloc_bytes, gs_heap_alloc_struct, diff --git a/gs/src/gsmemlok.c b/gs/src/gsmemlok.c index 21cf9c629..e70c1df22 100644 --- a/gs/src/gsmemlok.c +++ b/gs/src/gsmemlok.c @@ -33,6 +33,7 @@ private gs_memory_proc_resize_object(gs_locked_resize_object); private gs_memory_proc_free_object(gs_locked_free_object); private gs_memory_proc_status(gs_locked_status); private gs_memory_proc_free_all(gs_locked_free_all); +private gs_memory_proc_consolidate_free(gs_locked_consolidate_free); /* Object memory procedures */ private gs_memory_proc_alloc_bytes(gs_locked_alloc_bytes); @@ -59,6 +60,7 @@ private gs_memory_procs_t locked_procs = gs_locked_free_object, gs_locked_status, gs_locked_free_all, + gs_locked_consolidate_free, /* Object memory procedures */ gs_locked_alloc_bytes, gs_locked_alloc_struct, @@ -149,6 +151,13 @@ gs_locked_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname) if (free_mask & FREE_ALL_ALLOCATOR) gs_free_object(target, lmem, cname); } +private void +gs_locked_consolidate_free(gs_memory_t * mem) +{ + DO_MONITORED( + (*lmem->target->procs.consolidate_free)(lmem->target) + ); +} private byte * gs_locked_alloc_bytes(gs_memory_t * mem, uint size, client_name_t cname) { diff --git a/gs/src/gsmemory.c b/gs/src/gsmemory.c index 01c133d1d..6d5186931 100644 --- a/gs/src/gsmemory.c +++ b/gs/src/gsmemory.c @@ -80,6 +80,12 @@ gs_ignore_free_string(gs_memory_t * mem, byte * data, uint nbytes, { } +/* No-op consolidation procedure */ +void +gs_ignore_consolidate_free(gs_memory_t *mem) +{ +} + /* No-op pointer enumeration procedure */ ENUM_PTRS_BEGIN_PROC(gs_no_struct_enum_ptrs) { diff --git a/gs/src/gsmemory.h b/gs/src/gsmemory.h index 5e8036ef7..de0ed9813 100644 --- a/gs/src/gsmemory.h +++ b/gs/src/gsmemory.h @@ -84,6 +84,8 @@ typedef struct gs_memory_procs_s { gs_memory_t_proc_status(proc, gs_memory_t) #define gs_memory_proc_free_all(proc)\ gs_memory_t_proc_free_all(proc, gs_memory_t) +#define gs_memory_proc_consolidate_free(proc)\ + gs_memory_t_proc_consolidate_free(proc, gs_memory_t) /* * Allocate possibly movable bytes. (We inherit allocating immovable @@ -243,6 +245,9 @@ int gs_register_struct_root(P4(gs_memory_t *mem, gs_gc_root_t *root, gs_memory_proc_free_object(gs_ignore_free_object); gs_memory_proc_free_string(gs_ignore_free_string); +/* Define a no-op consolidation procedure. */ +gs_memory_proc_consolidate_free(gs_ignore_consolidate_free); + /* * Allocate a structure using a "raw memory" allocator. Note that this does * not retain the identity of the structure. Note also that it returns a diff --git a/gs/src/gsmemraw.h b/gs/src/gsmemraw.h index 26eacfded..fc57133a6 100644 --- a/gs/src/gsmemraw.h +++ b/gs/src/gsmemraw.h @@ -133,18 +133,31 @@ typedef struct gs_raw_memory_s gs_raw_memory_t; void proc(P3(mem_t *mem, uint free_mask, client_name_t cname)) #define gs_memory_free_all(mem, free_mask, cname)\ - (*(mem)->procs.free_all)(mem, free_mask, cname) + ((mem)->procs.free_all(mem, free_mask, cname)) /* Backward compatibility */ #define gs_free_all(mem)\ gs_memory_free_all(mem, FREE_ALL_DATA, "(free_all)") + /* + * Consolidate free space. This may be used as part of (or + * as an alternative to) garbage collection, or before + * giving up on an attempt to allocate. + */ + +#define gs_memory_t_proc_consolidate_free(proc, mem_t)\ + void proc(P1(mem_t *mem)) + +#define gs_consolidate_free(mem)\ + ((mem)->procs.consolidate_free(mem)) + /* Define the members of the procedure structure. */ #define gs_raw_memory_procs(mem_t)\ gs_memory_t_proc_alloc_bytes((*alloc_bytes_immovable), mem_t);\ gs_memory_t_proc_resize_object((*resize_object), mem_t);\ gs_memory_t_proc_free_object((*free_object), mem_t);\ gs_memory_t_proc_status((*status), mem_t);\ - gs_memory_t_proc_free_all((*free_all), mem_t) + gs_memory_t_proc_free_all((*free_all), mem_t);\ + gs_memory_t_proc_consolidate_free((*consolidate_free), mem_t) /* Define the procedure vector for a raw memory allocator. */ typedef struct gs_raw_memory_procs_s { diff --git a/gs/src/gsnogc.c b/gs/src/gsnogc.c index 029717c19..7ff6b4ddd 100644 --- a/gs/src/gsnogc.c +++ b/gs/src/gsnogc.c @@ -228,6 +228,24 @@ sf_merge_strings(chunk_t * cp) } } +/* Consolidate free space. */ +private void +sf_consolidate_free(gs_memory_t *mem) +{ + gs_ref_memory_t *imem = (gs_ref_memory_t *)mem; + chunk_t *cp; + + for (cp = imem->clast; cp != 0; cp = cp->cprev) { + byte *top = cp->ctop; + + sf_merge_strings(cp); + imem->lost.strings -= cp->ctop - top; + } + + /* Merge free objects, detecting entirely free chunks. */ + ialloc_consolidate_free(imem); +} + /* * This procedure has the same API as the garbage collector used by the * PostScript interpreter, but it is designed to be used in environments @@ -245,20 +263,10 @@ gs_reclaim(vm_spaces * pspaces, bool global) for (space = 0; space < countof(pspaces->indexed); ++space) { gs_ref_memory_t *mem = pspaces->indexed[space]; - chunk_t *cp; - chunk_t *cprev; - - /* - * We're going to recompute lost.objects, by subtracting the - * amount of space reclaimed minus the amount of that space that - * was on free lists. - */ - ulong found = 0; if (mem == 0 || mem == mem_prev) continue; mem_prev = mem; - alloc_close_chunk(mem); /* * Change the allocator to use string freelists in the future. @@ -267,69 +275,9 @@ gs_reclaim(vm_spaces * pspaces, bool global) if (mem->procs.free_string != gs_ignore_free_string) mem->procs.free_string = sf_free_string; mem->procs.enable_free = sf_enable_free; + mem->procs.consolidate_free = sf_consolidate_free; - /* Visit chunks in reverse order to encourage LIFO behavior. */ - for (cp = mem->clast; cp != 0; cp = cprev) { - obj_header_t *begin_free = (obj_header_t *) cp->cbase; - - cprev = cp->cprev; - SCAN_CHUNK_OBJECTS(cp) - DO_ALL - if (pre->o_type == &st_free) { - if (begin_free == 0) - begin_free = pre; - } else - begin_free = 0; - END_OBJECTS_SCAN - if (!begin_free) - continue; - /* We found free objects at the top of the object area. */ - found += (byte *) cp->cbot - (byte *) begin_free; - /* Remove the free objects from the freelists. */ - { - int i; - - for (i = 0; i < num_freelists; i++) { - obj_header_t *pfree; - obj_header_t **ppfprev = &mem->freelists[i]; - uint free_size = - (i << log2_obj_align_mod) + sizeof(obj_header_t); - - while ((pfree = *ppfprev) != 0) - if (ptr_ge(pfree, begin_free) && - ptr_lt(pfree, cp->cbot) - ) { /* We're removing an object. */ - *ppfprev = *(obj_header_t **) pfree; - found -= free_size; - } else - ppfprev = (obj_header_t **) pfree; - } - } - { - byte *top = cp->ctop; - - sf_merge_strings(cp); - mem->lost.strings -= cp->ctop - top; - } - if (begin_free == (obj_header_t *) cp->cbase && - cp->ctop == cp->climit - ) { /* The entire chunk is free. */ - chunk_t *cnext = cp->cnext; - - alloc_free_chunk(cp, mem); - if (mem->pcc == cp) - mem->pcc = - (cnext == 0 ? cprev : cprev == 0 ? cnext : - cprev->cbot - cprev->ctop > cnext->cbot - cnext->ctop ? - cprev : cnext); - } else { - if_debug4('a', "[a]resetting chunk 0x%lx cbot from 0x%lx to 0x%lx (%lu free)\n", - (ulong) cp, (ulong) cp->cbot, (ulong) begin_free, - (ulong) ((byte *) cp->cbot - (byte *) begin_free)); - cp->cbot = (byte *) begin_free; - } - } - mem->lost.objects -= found; - alloc_open_chunk(mem); + /* Merge free objects, detecting entirely free chunks. */ + gs_consolidate_free((gs_memory_t *)mem); } } diff --git a/gs/src/gsparam.c b/gs/src/gsparam.c index f03d1673a..6a99700ee 100644 --- a/gs/src/gsparam.c +++ b/gs/src/gsparam.c @@ -33,8 +33,9 @@ param_init_enumerator(gs_param_enumerator_t * enumerator) } /* Transfer a collection of parameters. */ -private const byte xfer_item_sizes[] = -{GS_PARAM_TYPE_SIZES(0)}; +private const byte xfer_item_sizes[] = { + GS_PARAM_TYPE_SIZES(0) +}; int gs_param_read_items(gs_param_list * plist, void *obj, const gs_param_item_t * items) @@ -103,7 +104,8 @@ param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type, /* * Look for coercion opportunities. It would be wonderful if we * could convert int/float arrays and name/string arrays, but - * right now we can't. + * right now we can't. However, a 0-length heterogenous array + * will satisfy a request for any specific type. */ switch (pvalue->type /* actual type */ ) { case gs_param_type_int: @@ -174,6 +176,15 @@ param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type, if (req_type == gs_param_type_string_array) goto ok; break; + case gs_param_type_array: + if (pvalue->value.d.size == 0 && + (req_type == gs_param_type_int_array || + req_type == gs_param_type_float_array || + req_type == gs_param_type_string_array || + req_type == gs_param_type_name_array) + ) + goto ok; + break; default: break; } diff --git a/gs/src/gspcolor.c b/gs/src/gspcolor.c index 68b9f32af..137d9970f 100644 --- a/gs/src/gspcolor.c +++ b/gs/src/gspcolor.c @@ -80,12 +80,15 @@ gs_cspace_build_Pattern1(gs_color_space ** ppcspace, const gs_color_space * pbase_cspace, gs_memory_t * pmem) { gs_color_space *pcspace = 0; + int code; if (pbase_cspace != 0) { if (gs_color_space_num_components(pcspace) < 0) /* Pattern space */ return_error(gs_error_rangecheck); } - cs_alloc(pcspace, &gs_color_space_type_Pattern, pmem); + code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Pattern, pmem); + if (code < 0) + return code; if (pbase_cspace != 0) { pcspace->params.pattern.has_base_space = true; gs_cspace_init_from((gs_color_space *) & (pcspace->params.pattern.base_space), diff --git a/gs/src/gsstate.c b/gs/src/gsstate.c index 79b342c70..00c709f7b 100644 --- a/gs/src/gsstate.c +++ b/gs/src/gsstate.c @@ -237,6 +237,27 @@ null_transfer(floatp gray, const gx_transfer_map * pmap) { return gray; } +private void +rc_free_imager_shared(gs_memory_t * mem, void *data, client_name_t cname) +{ + gs_imager_state_shared_t * const shared = + ((gs_imager_state *)data)->shared; + + if (shared->cs_DeviceCMYK) { + gs_cspace_release(shared->cs_DeviceCMYK); + gs_free_object(mem, shared->cs_DeviceCMYK, "shared DeviceCMYK"); + } + if (shared->cs_DeviceRGB) { + gs_cspace_release(shared->cs_DeviceRGB); + gs_free_object(mem, shared->cs_DeviceRGB, "shared DeviceRGB"); + } + if (shared->cs_DeviceGray) { + gs_cspace_release(shared->cs_DeviceGray); + gs_free_object(mem, shared->cs_DeviceGray, "shared DeviceGray"); + } + rc_free_struct_only(mem, data, cname); +} + int gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem) { @@ -250,12 +271,17 @@ gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem) &st_imager_state_shared, mem, return_error(gs_error_VMerror), "gs_imager_state_init(shared)"); - pis->shared = shared; + shared->cs_DeviceGray = shared->cs_DeviceRGB = + shared->cs_DeviceCMYK = 0; /* in case we bail out */ + shared->rc.free = rc_free_imager_shared; if ((code = gs_cspace_build_DeviceGray(&shared->cs_DeviceGray, mem)) < 0 || - (code = gs_cspace_build_DeviceRGB(&shared->cs_DeviceRGB, mem)) < 0 || - (code = gs_cspace_build_DeviceCMYK(&shared->cs_DeviceCMYK, mem)) < 0 - ) + (code = gs_cspace_build_DeviceRGB(&shared->cs_DeviceRGB, mem)) < 0 || + (code = gs_cspace_build_DeviceCMYK(&shared->cs_DeviceCMYK, mem)) < 0 + ) { + rc_free_imager_shared(mem, shared, "gs_imager_state_init(shared)"); return code; + } + pis->shared = shared; } /* Skip halftone */ { diff --git a/gs/src/gxalloc.h b/gs/src/gxalloc.h index e076eb814..ae0c2a056 100644 --- a/gs/src/gxalloc.h +++ b/gs/src/gxalloc.h @@ -317,31 +317,33 @@ struct gs_ref_memory_s { gs_raw_memory_t *parent; /* for allocating chunks */ uint chunk_size; uint large_size; /* min size to give large object */ - /* its own chunk: must be */ - /* 1 mod obj_align_mod */ + /* its own chunk: must be */ + /* 1 mod obj_align_mod */ gs_ref_memory_t *global; /* global VM for this allocator */ - /* (may point to itself) */ + /* (may point to itself) */ uint space; /* a_local, a_global, a_system */ /* Callers can change the following dynamically */ /* (through a procedural interface). */ gs_memory_gc_status_t gc_status; /* The following are updated dynamically. */ + bool is_controlled; /* if true, this allocator doesn't manage */ + /* its own chunks */ ulong limit; /* signal a VMerror when total */ - /* allocated exceeds this */ + /* allocated exceeds this */ chunk_t *cfirst; /* head of chunk list */ chunk_t *clast; /* tail of chunk list */ chunk_t cc; /* current chunk */ chunk_t *pcc; /* where to store cc */ chunk_locator_t cfreed; /* chunk where last object freed */ ulong allocated; /* total size of all chunks */ - /* allocated at this save level */ + /* allocated at this save level */ long inherited; /* chunks allocated at outer save */ - /* levels that should be counted */ - /* towards the GC threshold */ - /* (may be negative, but allocated + */ - /* inherited >= 0 always) */ + /* levels that should be counted */ + /* towards the GC threshold */ + /* (may be negative, but allocated + */ + /* inherited >= 0 always) */ ulong gc_allocated; /* value of (allocated + */ - /* previous_status.allocated) after last GC */ + /* previous_status.allocated) after last GC */ struct lost_ { /* space freed and 'lost' */ ulong objects; ulong refs; @@ -360,9 +362,9 @@ struct gs_ref_memory_s { struct alloc_save_s *saved; struct alloc_save_s *reloc_saved; /* for GC */ gs_memory_status_t previous_status; /* total allocated & used */ - /* in outer save levels */ - /* We put the freelists last to keep the scalar */ - /* offsets small. */ + /* in outer save levels */ + /* We put the freelists last to keep the */ + /* scalar offsets small. */ obj_header_t *freelists[num_freelists]; }; diff --git a/gs/src/gxclip2.c b/gs/src/gxclip2.c index 8897ee4d4..6b4274a29 100644 --- a/gs/src/gxclip2.c +++ b/gs/src/gxclip2.c @@ -221,7 +221,8 @@ tile_clip_copy_mono(gx_device * dev, tx1 = tx;\ do {\ t_next(tx);\ - } while ( tx < x + w && (*tp & tbit) != 0 ); + } while ( tx < x + w && (*tp & tbit) != 0 );\ + if_debug3('T', "[T]run x=(%d,%d), y=%d\n", tx1, tx, ty); /* (body goes here) */ #define END_FOR_RUNS()\ }\ diff --git a/gs/src/gxcspace.h b/gs/src/gxcspace.h index ddf43403e..3f32b7d8d 100644 --- a/gs/src/gxcspace.h +++ b/gs/src/gxcspace.h @@ -228,22 +228,12 @@ extern const gs_color_space_type extern_st(st_color_space); /* - * Macros for allocating, initializing, and freeing color spaces. - * These are only used by color space implementations. + * Allocate a color space and initialize its type and memory fields. + * This is only used by color space implementations. */ -#define cs_alloc(pcspace, pcstype, pmemory)\ - BEGIN\ - (pcspace) = gs_alloc_struct(pmemory, gs_color_space, &st_color_space,\ - "cs_alloc");\ - if ((pcspace) == 0)\ - return_error(gs_error_VMerror);\ - (pcspace)->pmem = (pmemory);\ - (pcspace)->type = (pcstype);\ - END - -#define cs_undo_alloc(pcspace)\ - (gs_free_object((pcspace)->pmem, pcspace, "cs_undo_alloc"),\ - gs_note_error(gs_error_VMerror)) +int gs_cspace_alloc(P3(gs_color_space **ppcspace, + const gs_color_space_type *pcstype, + gs_memory_t *mem)); #endif /* gxcspace_INCLUDED */ diff --git a/gs/src/gxp1fill.c b/gs/src/gxp1fill.c index 08645dcdd..5cce33624 100644 --- a/gs/src/gxp1fill.c +++ b/gs/src/gxp1fill.c @@ -102,6 +102,8 @@ tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0, { gs_rect bbox; /* bounding box in device space */ gs_rect ibbox; /* bounding box in stepping space */ + double bbw = ptile->bbox.q.x - ptile->bbox.p.x; + double bbh = ptile->bbox.q.y - ptile->bbox.p.y; bbox.p.x = x0, bbox.p.y = y0; bbox.q.x = x1, bbox.q.y = y1; @@ -111,14 +113,14 @@ tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0, x0, y0, w0, h0, ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y, step_matrix.tx, step_matrix.ty); - i0 = (int)floor(ibbox.p.x - ptile->bbox.q.x + 0.000001); - i1 = (int)ceil(ibbox.q.x - ptile->bbox.p.x - 0.000001); - j0 = (int)floor(ibbox.p.y - ptile->bbox.q.y + 0.000001); - j1 = (int)ceil(ibbox.q.y - ptile->bbox.p.y - 0.000001); + i0 = (int)ceil(ibbox.p.x - bbw - 0.000001); + i1 = (int)floor(ibbox.q.x + 0.000001); + j0 = (int)ceil(ibbox.p.y - bbh - 0.000001); + j1 = (int)floor(ibbox.q.y + 0.000001); } if_debug4('T', "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1); - for (i = i0; i < i1; i++) - for (j = j0; j < j1; j++) { + for (i = i0; i <= i1; i++) + for (j = j0; j <= j1; j++) { int x = (int)(step_matrix.xx * i + step_matrix.yx * j + step_matrix.tx); int y = (int)(step_matrix.xy * i + @@ -140,13 +142,13 @@ tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0, w = x1 - x; if (y + h > y1) h = y1 - y; - if_debug4('T', "=>(%d,%d) w,h=(%d,%d)\n", - x, y, w, h); + if_debug6('T', "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n", + x, y, w, h, xoff, yoff); if (w > 0 && h > 0) { if (ptfs->pcdev == (gx_device *) & ptfs->cdev) tile_clip_set_phase(&ptfs->cdev, - imod(xoff - x, ptfs->tmask->rep_width), - imod(yoff - y, ptfs->tmask->rep_height)); + imod(xoff - x, ptfs->tmask->rep_width), + imod(yoff - y, ptfs->tmask->rep_height)); /* Set the offsets for colored pattern fills */ ptfs->xoff = xoff; ptfs->yoff = yoff; diff --git a/gs/src/iparam.c b/gs/src/iparam.c index f9e76722a..2cd23498b 100644 --- a/gs/src/iparam.c +++ b/gs/src/iparam.c @@ -688,8 +688,10 @@ ref_param_read_typed(gs_param_list * plist, gs_param_name pkey, iparam_check_read(loc); if (r_size(loc.pvalue) <= 0) { /* 0-length array; can't get type info */ - pvalue->type = gs_param_type_int_array; - return ref_param_read_int_array(plist, pkey, &pvalue->value.ia); + pvalue->type = gs_param_type_array; + pvalue->value.d.list = 0; + pvalue->value.d.size = 0; + return 0; } /* Get array type based on type of 1st element of array */ array_get(loc.pvalue, 0, &elt); diff --git a/gs/src/version.mak b/gs/src/version.mak index 6e16f346b..00b66bf0e 100644 --- a/gs/src/version.mak +++ b/gs/src/version.mak @@ -24,10 +24,10 @@ VERSION_MAK=$(GLSRC)version.mak # Major and minor version numbers. # MINOR0 is different from MINOR only if MINOR is a single digit. GS_VERSION_MAJOR=5 -GS_VERSION_MINOR=37 -GS_VERSION_MINOR0=37 +GS_VERSION_MINOR=38 +GS_VERSION_MINOR0=38 # Revision date: year x 10000 + month x 100 + day. -GS_REVISIONDATE=19980831 +GS_REVISIONDATE=19980903 # Derived values GS_VERSION=$(GS_VERSION_MAJOR)$(GS_VERSION_MINOR0) diff --git a/gs/src/zfileio.c b/gs/src/zfileio.c index 951b6b1f2..ac51265bd 100644 --- a/gs/src/zfileio.c +++ b/gs/src/zfileio.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises. All rights reserved. +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. This file is part of Aladdin Ghostscript. @@ -813,7 +813,7 @@ handle_read_status(int ch, const ref * fop, const uint * pindex, /* Handle an exceptional status return from a write stream. */ /* fop points to the ref for the stream. */ /* ch may be any stream exceptional value. */ -/* Return 0, o_push_estack, or an error. */ +/* Return 0, 1 (EOF), o_push_estack, or an error. */ private int handle_write_status(int ch, const ref * fop, const uint * pindex, int (*cont) (P1(os_ptr))) @@ -821,6 +821,8 @@ handle_write_status(int ch, const ref * fop, const uint * pindex, switch (ch) { default: /* error */ return_error(e_ioerror); + case EOFC: + return 1; case INTC: case CALLC: if (pindex) { |