#ifndef lint static char sccsid[] = "@(#)copy.c 7.1 87/05/09 Copyr 1985 Sun Micro"; #endif /* * Copyright (c) 1987 by Sun Microsystems, Inc. */ /* Miscellaneous PostScript copy primitives copy.c, Tue May 6 15:44:33 PDT 1986 To do: -fix copy to work with dict_table[]. -#def for taking objptr & returning proper value re dict_table[] -change dicts to use the size & used fields in bodies, then retrofit objects.c & primitives.h. -do only bounds checking in (ee) procs, have copy_foo do rest. [more shairable] Owen Densmore, Sun Microsystems */ #ifdef REF #include #include #endif #include "PostScript.h" #include "input.h" /* A[i,] <- B */ static enum error_type array_copy(A, i, B) register struct object *A; register int i; register struct object *B; { struct body *a = body_of(A); struct body *b = body_of(B); if (i < 0 || (i + B->value.substring.length) > A->value.substring.length) { return rangecheck_error_code; } /* if (a->readonly || b->readonly) { return invalidaccess_error_code; } */ if (A->type == array_type) { struct object *ai = &a->body.array.objects[A->value.substring.start+i]; struct object *bi = &b->body.array.objects[B->value.substring.start]; /* * In order to handle copying of overlapping intervals on the * same array, incref all of b first, then decref all of a. */ i = B->value.substring.length; /* REDEF of i */ while (--i >= 0) object_incref(&bi[i]); i = B->value.substring.length; /* Reset i */ while (--i >= 0) object_decref(&ai[i]); /* Now move the objects */ bcopy(bi, ai, B->value.substring.length * sizeof (struct object)); } else { /* string type */ bcopy(&b->body.string.chars[B->value.substring.start], &a->body.string.chars[A->value.substring.start + i], B->value.substring.length); } return no_error_code; } /* A <- B */ static enum error_type dict_copy(A, B) /* XXX does no bounds checking!! */ struct object *A; struct object *B; { register struct body *a = body_of(A); register struct body *b = body_of(B); register struct object *bi; register int n; register enum error_type error = no_error_code; /* * if (a->readonly || b->readonly) { error = invalidaccess_error_code; * } else */ if (a->body.array.used != 0) /* XXX Is this the semantics we want? */ error = rangecheck_error_code; else if (a->body.array.max_size < b->body.array.used) error = dictfull_error_code; else { if (a->body.array.size == b->body.array.size) { bcopy(b->body.array.objects, a->body.array.objects, a->body.array.size * sizeof(struct object)); bi = a->body.array.objects; n = a->body.array.size; while (--n >= 0) { object_incref(bi); bi++; } a->body.array.used = b->body.array.used; } else { bi = b->body.array.objects; n = b->body.array.size >> 1; while (--n >= 0) { if (bi->type != null_type) { object_incref(bi + 1); error = define_object_in_dictionary(bi[0], bi[1], a, 0); if (error != no_error_code) { object_decref(bi + 1); break; } } bi += 2; } } } return error; } /* E1 E2 -> E2 */ static enum error_type event_copy(dst, src) struct object *src; struct object *dst; { register struct body *e1 = body_of(src); register struct body *e2 = body_of(dst); register int t; if (e2->body.event.is_interest || e2->body.event.is_queued) return invalidaccess_error_code; t = e2->refcnt; event_dec_refs(e2); bcopy(e1, e2, body_size(event)); e2->refcnt = t; e2->body.event.next = 0; e2->body.event.next_int = 0; e2->body.event.is_interest = 0; e2->body.event.is_queued = 0; event_inc_refs(e2); return no_error_code; } /* A i B PUTINTERVAL - (A modified by B starting at A[i]) */ static putinterval(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; register struct object *A = optop - 3; register struct object *B = optop - 1; if (!(optop[-2].type == fixed_type && A->type == B->type && (A->type == array_type || A->type == string_type) )) { ee->error_code = typecheck_error_code; return; } if (body_of(A)->readonly || body_of(B)->readonly) { ee->error_code = invalidaccess_error_code; return; } if(ee->error_code = array_copy (A, roundfr(optop[-2].value.fixed), B)) return; object_decref(A); object_decref(B); ee->optop -= 3; } /* * a1 .. an n COPY a1 .. an a1 .. an * array1 array2 COPY subarray2 * string1 string2 COPY substring2 * dict1 dict2 COPY dict2 * event1 event2 COPY event2 */ /*void (but define_operator complains!) */ copy(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; switch (optop[-1].type) { case fixed_type:{ register struct object *A = optop - 1; int n = roundfr(A->value.fixed); register struct object *B = A - n; if (n < 0) { ee->error_code = rangecheck_error_code; return; } if (optop + n - 2 >= ee->overflow) { ee->error_code = stackoverflow_error_code; return; } if (B < ee->underflow) { ee->error_code = stackunderflow_error_code; return; } while (n--) { object_incref(B); *A++ = *B++; } ee->optop = A; break; } case array_type: case canvas_type: case dictionary_type: case event_type: case string_type:{ register struct object *A = optop - 2; register struct object *B = optop - 1; if (A < ee->underflow) { ee->error_code = stackunderflow_error_code; return; } if (A->type != B->type) { ee->error_code = typecheck_error_code; return; } if (body_of(B)->readonly) { ee->error_code = invalidaccess_error_code; return; } if (!equal_object(A, B)) { switch (A->type) { case array_type: case string_type: if (!(ee->error_code = array_copy(B, 0, A))) B->value.substring.length = A->value.substring.length; break; case dictionary_type: ee->error_code = dict_copy(B, A); break; case event_type: if ((ee->error_code = event_copy(B, A)) == no_error_code) break; return; case canvas_type: default: ee->error_code = typecheck_error_code; return; } if (ee->error_code) return; } object_decref(A); *A = *B; /* harmless in the equal-object case */ ee->optop--; break; } default: ee->error_code = typecheck_error_code; return; } } initialize_copy() { define_operator("putinterval", putinterval, 0, 3, 0); define_operator("copy", copy, 0, 1, 0); } /* /icopy {dup {dup index exch} repeat pop} def /acopy { % A B acopy B' dup % A B B 0 3 index % A B B 0 A putinterval % A B exch length % B lA 0 exch % B 0 lA getinterval % B' } def /dcopy { % D E dcopy E' % Deviation: this does not require length (E) == 0 dup 3 -1 roll % E E D { % E E ki vi put % E' dup % E' E' } forall pop % E' } def /copy { dup type [ /integertype {pop icopy} /stringtype /arraytype {pop acopy} /dicttype {pop dcopy} ] case } def */ /* /putinterval { % A i B putinterval - (A modified) { % A i bj 2 index 2 index % A i bj A i 3 -1 roll % A i A i bj put % A' i 1 add % A' i' } forall pop pop % - } def */