#ifndef lint static char sccsid[] = "@(#)moremisc.c 9.6 88/01/19 Copyright 1987 Sun Micro"; #endif /* * Copyright (c) 1987 by Sun Microsystems, Inc. */ /*- More miscellaneous routines for the PostScript interpreter moremisc.c, Wed Jan 22 12:52:43 1986 Sun Microsystems */ #ifdef REF #include #include #endif #include "PostScript.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif static struct object ParentDictArray; extern struct object *typed_result_matrix(); static atan_primitive(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; switch (object_type_pair(optop[-2], optop[-1])) { case tp(fixed, fixed): optop[-2].value.fixed = fratan2(optop[-2].value.fixed, optop[-1].value.fixed); break; case tp(fixed, real): optop[-2].value.real = floatfr(optop[-2].value.fixed); goto real_case; case tp(real, fixed): optop[-1].value.real = floatfr(optop[-1].value.fixed); case tp(real, real): real_case: optop[-2].value.fixed = fracti(atan2(optop[-2].value.real, optop[-1].value.real)); optop[-2].type = fixed_type; break; default: ee->error_code = typecheck_error_code; return; } ee->optop--; } static arctan(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; fract v; switch (optop[-1].type) { case fixed_type: optop[-1].value.fixed = fratan2(optop[-1].value.fixed, fracti(1)); break; case real_type: optop[-1].value.fixed = fractf((180 / M_PI) * atan(optop[-1].value.real)); optop[-1].type = fixed_type; break; default: ee->error_code = typecheck_error_code; break; } } static closefile(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; if (optop[-1].type == file_type) { register struct body *b = body_of(optop - 1); if (b->body.file.inbuf) { register fd = psio_fileno(b->body.file.inbuf); if (selectable_file(fd, 1)) remove_selectable_file(fd, 1); if (process_readers[fd + 1]) { enqueue_process(process_readers[fd + 1]); process_readers[fd + 1] = 0; } psio_close(b->body.file.inbuf); b->body.file.inbuf = 0; } if (b->body.file.outbuf) { psio_close(b->body.file.outbuf); b->body.file.outbuf = 0; } decref(b); ee->optop--; } else ee->error_code = typecheck_error_code; } static send(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; register struct execution_stack *es = ee->pos; register struct execution_stack *prevsend = ee->pos; register struct dictstack_ent *dp; struct object parent_dict_array; if (optop[-1].type != dictionary_type) { ee->error_code = typecheck_error_code; return; } if (es + 1 >= ee->limit) { ee->error_code = stackoverflow_error_code; return; } while (prevsend >= ee->execution_stack && prevsend->type != send_execution) prevsend--; { register struct object *o = find_object_in_dictionary(ParentDictArray, body_of(optop - 1)); if (o == 0 || o->type != array_type) { clear_object(&parent_dict_array); } else parent_dict_array = *o; } es++; clear_object(&es->executed); if (prevsend >= ee->execution_stack && (dp = &ee->dictionary_stack[prevsend->env.send.topdict]) < ee->dict_top) { if (dp + 1 == ee->dict_top) { /* No dicts above top class dict */ if (dp->body == body_of(optop - 1)) { object_decref(optop - 1); goto do_exec; /* sending to self */ } set_typed_bodied_object(&es->executed, dictionary_type, dp->body); incref(dp->body); } else { /* Stuff above the top class dict, need to * save them too */ register struct object *op; es->executed = make_array(ee->dict_top - dp); op = body_of(&es->executed)->body.array.objects; while (dp < ee->dict_top) { register struct body *target; if ((target = dp->obj) == 0) target = dp->body; set_typed_bodied_object(op, target->type, target); incref(target); dp++; op++; } } { register struct dictstack_ent *newtop; dp = &ee->dictionary_stack[prevsend->env.send.bottomdict]; newtop = dp; assert(dp<=ee->dict_top); while (dp < ee->dict_top) { if (dp->obj) { decref(dp->obj); } else decref(dp->body); dp++; } ee->dict_top = newtop; assert(ee->dict_topdict_limit); } } es->env.send.bottomdict = ee->dict_top - ee->dictionary_stack; es->env.send.topdict = es->env.send.bottomdict; if (!have_dict_space(ee, parent_dict_array.value.substring.length+1)) return; if (parent_dict_array.value.substring.length > 0) { register struct object *o = body_of(&parent_dict_array)->body.array.objects + parent_dict_array.value.substring.start; while (parent_dict_array.value.substring.length > 0) { if (o->type == dictionary_type) { register struct body *b = body_of(o); ee->dict_top->body = b; ee->dict_top->obj = 0; incref(b); ee->dict_top++; es->env.send.topdict++; assert(ee->dict_top<=ee->dict_limit); } o++; parent_dict_array.value.substring.length--; } } ee->dict_top->body = body_of(optop - 1); ee->dict_top->obj = 0; ee->dict_top++; assert(ee->dict_top<=ee->dict_limit); es->type = send_execution; ee->pos++; es++; do_exec: es->type = undetermined_execution; es->executed = optop[-2]; es->executed.executable = 1; ee->optop -= 2; ee->pos++; } complete_send(ee) register struct execution_environment *ee; { register struct execution_stack *es = ee->pos; register struct dictstack_ent *dp; assert(es->type == send_execution); { register struct dictstack_ent *newtop; dp = &ee->dictionary_stack[es->env.send.bottomdict]; newtop = dp; while (dp < ee->dict_top) { if (dp->obj) { decref(dp->obj); } else decref(dp->body); dp++; } ee->dict_top = newtop; } assert(ee->dict_top<=ee->dict_limit); if (es->executed.type != null_type) { register struct object *obj; register struct body *old; if (es->executed.type == dictionary_type) old = body_of(&es->executed); else { assert(es->executed.type == array_type); assert(es->executed.value.substring.length > 1); assert(es->executed.value.substring.start == 0); obj = body_of(&es->executed)->body.array.objects; assert(obj->type == dictionary_type); old = body_of(obj); } { register struct object *o; o = find_object_in_dictionary(ParentDictArray, old); if (o != 0 && o->type == array_type) { register left = o->value.substring.length; o = body_of(o)->body.array.objects; if (have_dict_space(ee, left)) while (--left >= 0) { if (o->type == dictionary_type) { register struct body *b = body_of(o); ee->dict_top->body = b; ee->dict_top->obj = 0; incref(b); ee->dict_top++; assert(ee->dict_top<=ee->dict_limit); } o++; } } if (have_dict_space(ee, 1)) { ee->dict_top->body = old; incref(old); ee->dict_top->obj = 0; ee->dict_top++; } assert(ee->dict_top<=ee->dict_limit); } if (es->executed.type == array_type) { register n = es->executed.value.substring.length; obj = body_of(&es->executed)->body.array.objects; if (have_dict_space(ee, n)) while (--n > 0) { register struct body *b; obj++; if (obj->type == dictionary_type) { b = body_of(obj); incref(b); ee->dict_top->obj = 0; } else { ee->dict_top->obj = body_of(obj); incref(body_of(obj)); b = dict_table[(int) obj->type]; } ee->dict_top->body = b; ee->dict_top++; assert(ee->dict_top<=ee->dict_limit); } } } } static status(ee) register struct execution_environment *ee; { register ret = 0; register struct object *optop = ee->optop; if (optop[-1].type == file_type) { register struct body *b = body_of(optop - 1); if (b && (b->body.file.inbuf == 0 || (!psio_eof(b->body.file.inbuf) && !psio_error(b->body.file.inbuf))) && (b->body.file.outbuf == 0 || !psio_error(b->body.file.outbuf)) && (b->body.file.outbuf != 0 || b->body.file.inbuf != 0)) ret = 1; object_decref(optop - 1); set_boolean_object(optop - 1, fracti(ret)); } else ee->error_code = typecheck_error_code; } static wcheck(ee) register struct execution_environment *ee; { register ret = 0; register struct object *optop = ee->optop; if (object_has_refcnt(optop - 1)) { register struct body *wbody = body_of(optop - 1); if (optop[-1].type == file_type ? wbody->body.file.outbuf && !psio_error(wbody->body.file.outbuf) : !wbody->readonly) ret = 1; } else ret = 1; object_decref(optop - 1); set_boolean_object(optop - 1, fracti(ret)); } static rcheck(ee) register struct execution_environment *ee; { register ret = 0; register struct object *optop = ee->optop; if (optop[-1].type == file_type) { register struct body *wbody = body_of(optop - 1); if (wbody->body.file.inbuf && !psio_error(wbody->body.file.inbuf) && !psio_eof(wbody->body.file.inbuf)) ret = 1; } else ret = 1; object_decref(optop - 1); set_boolean_object(optop - 1, fracti(ret)); } static xcheck(ee) struct execution_environment *ee; { register struct object *optop = ee->optop; register executable = optop[-1].executable; object_decref(optop - 1); set_boolean_object(optop - 1, fracti(executable)); } static concat(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; { fract matrix[6]; /* [3][2] */ register struct object *p; register struct body *b; register int i = 6; if (optop[-1].type != array_type || optop[-1].value.subarray.length < 6) { ee->error_code = typecheck_error_code; return; } b = body_of(optop - 1); p = &b->body.array.objects[optop[-1].value.subarray.start]; while (i-- > 0) switch (p[i].type) { case fixed_type: matrix[i] = p[i].value.fixed; break; case real_type: matrix[i] = fractf(p[i].value.real); default: { ee->error_code = typecheck_error_code; return; } } sh_matrix_mult(&ee->gontext, &matrix[0], &matrix[2], &matrix[4], &matrix[1], &matrix[3], &matrix[5]); decref(b); ee->optop--; } } static concatmatrix(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; { float matrix1[6], matrix2[6] /* [3][2] */ ; register struct object *p; register int i = 6; register FLMATRIX tr; if (optop[-2].type != array_type || optop[-1].value.subarray.length < 6) { ee->error_code = typecheck_error_code; return; } if (optop[-3].type != array_type || optop[-1].value.subarray.length < 6) { ee->error_code = typecheck_error_code; return; } p = &body_of(&optop[-3])->body.array.objects[optop[-3].value.subarray.start]; while (i-- > 0) switch (p[i].type) { case fixed_type: matrix1[i] = floatfr( p[i].value.fixed ); break; case real_type: matrix1[i] = p[i].value.real; break; default: ee->error_code = typecheck_error_code; return; } p = &body_of(&optop[-2])->body.array.objects[optop[-2].value.subarray.start]; i = 6; while (i-- > 0) switch (p[i].type) { case fixed_type: matrix2[i] = floatfr( p[i].value.fixed ); break; case real_type: matrix2[i] = p[i].value.real; break; default: ee->error_code = typecheck_error_code; return; } p = typed_result_matrix(optop[-1], real_type); if (p == 0) { ee->error_code = typecheck_error_code; return; } fl_matrix_concat(matrix1, matrix2, tr); p[0].value.real = (tr)[0][0]; p[1].value.real = (tr)[0][1]; p[2].value.real = (tr)[1][0]; p[3].value.real = (tr)[1][1]; p[4].value.real = (tr)[2][0]; p[5].value.real = (tr)[2][1]; decref(body_of(optop - 3)); decref(body_of(optop - 2)); optop[-3] = optop[-1]; ee->optop -= 2; } } /* end concatmatrix */ static cvs(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; struct psiobuf string_file; char *s; register len; if (optop[-1].type != string_type) { ee->error_code = typecheck_error_code; return; } switch (optop[-2].type) { default: /* Construct a FILE that points to string_buffer */ string_file.cnt = optop[-1].value.substring.length; string_file.ptr = string_file.base = (unsigned char *) body_of(&optop[-1])->body.string.chars + optop[-1].value.substring.start; string_file.flag = PSWRITE | PSSTRG; string_file.file = (char) -1; /* bogus fd */ decode_object(&string_file, optop[-2], 0); optop[-1].value.substring.length = string_file.ptr - string_file.base; break; case string_type: s = body_of(optop - 2)->body.string.chars + optop[-2].value.substring.start; len = optop[-2].value.substring.length; copy_string: if (len < optop[-1].value.substring.length) optop[-1].value.substring.length = len; bcopy(s, body_of(optop - 1)->body.string.chars + optop[-1].value.substring.start, optop[-1].value.substring.length); break; case keyword_type: s = body_of(optop - 2)->body.keyword.name; len = body_of(optop - 2)->body.keyword.namelen; goto copy_string; } object_decref(optop - 2); optop[-2] = optop[-1]; ee->optop--; } static where(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; register struct dictstack_ent *stackent = ee->dict_top; register hash; if (optop[-1].type == string_type) convert_string_to_name(optop - 1); hash_object(hash, &optop[-1]); while (--stackent >= ee->dictionary_stack) { register struct object *ret = &stackent->body->body.array.objects[ hash_index(hash, stackent->body->body.array.size >> 1)]; while (ret->type != null_type) { if (equal_object(ret, &optop[-1])) { object_decref(&optop[-1]); if (stackent->obj) set_typed_bodied_object(&optop[-1], stackent->obj->type, stackent->obj); else { set_typed_bodied_object(&optop[-1], dictionary_type, stackent->body); } object_incref(&optop[-1]); set_typed_object(optop, boolean_type); optop->value.fixed = fracti(1); ee->optop++; return; } ret -= 2; if (ret < stackent->body->body.array.objects) ret = &stackent->body->body.array.objects[stackent->body->body.array.size - 2]; } } object_decref(&optop[-1]); set_typed_object(optop - 1, boolean_type); optop[-1].value.fixed = 0; } static writehexstring(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; if (optop[-2].type != file_type || optop[-1].type != string_type) { ee->error_code = typecheck_error_code; return; } { register PSFILE *f = body_of(optop - 2)->body.file.outbuf; register char *s = body_of(optop - 1)->body.string.chars + optop[-1].value.substring.start; register n = optop[-1].value.substring.length; static char hex[] = "0123456789abcdef"; if (f == 0 || psio_error(f)) { ee->error_code = ioerror_error_code; return; } while (--n >= 0) { psio_putc(hex[(*s >> 4) & 0xF], f); psio_putc(hex[*s++ & 0xF], f); } } decref(body_of(optop - 1)); decref(body_of(optop - 2)); ee->optop -= 2; } static writestring(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; if (optop[-2].type != file_type || optop[-1].type != string_type) { ee->error_code = typecheck_error_code; return; } { register PSFILE *f = body_of(optop - 2)->body.file.outbuf; register char *s = body_of(optop - 1)->body.string.chars + optop[-1].value.substring.start; register n = optop[-1].value.substring.length; if (f == 0 || psio_error(f)) { ee->error_code = ioerror_error_code; return; } while (--n >= 0) psio_putc(*s++, f); } decref(body_of(optop - 1)); decref(body_of(optop - 2)); ee->optop -= 2; } static token(ee) register struct execution_environment *ee; { register struct object *optop = ee->optop; register struct execution_stack *es = ee->pos; if (optop[-1].type != string_type && optop[-1].type != file_type) { ee->error_code = typecheck_error_code; return; } if (es + 1 >= ee->limit) { ee->error_code = stackoverflow_error_code; return; } ee->seeking_token = 1; es++; es->type = token_execution; es->executed = optop[-1]; object_incref(optop - 1); es++; es->type = undetermined_execution; es->executed = optop[-1]; es->executed.executable = 1; /*- object_incref(optop - 1); object_decref(optop - 1); */ ee->optop--; ee->pos += 2; ee->fill = 1; } initialize_moremisc() { set_typed_bodied_object(&ParentDictArray, keyword_type, get_name("ParentDictArray", -1)); define_operator("arctan", arctan, 0, 1, 1); define_operator("atan", atan_primitive, 0, 2, 1); define_operator("closefile", closefile, 0, 1, 0); define_operator("concat", concat, 0, 1, 0); define_operator("concatmatrix", concatmatrix, 0, 3, 1); define_operator("cvs", cvs, 0, 2, 1); define_operator("rcheck", rcheck, 0, 1, 1); define_operator("send", send, 0, 2, 0); define_operator("status", status, 0, 1, 1); define_operator("token", token, 0, 1, 3); define_operator("wcheck", wcheck, 0, 1, 1); define_operator("where", where, 0, 1, 2); define_operator("writehexstring", writehexstring, 0, 2, 0); define_operator("writestring", writestring, 0, 2, 0); define_operator("xcheck", xcheck, 0, 1, 1); }