#ifndef lint static char sccsid[] = "@(#)decode.c 7.7 87/09/19 Copyright 1987 Sun Micro"; #endif /* * Copyright (c) 1987 by Sun Microsystems, Inc. */ /*- Decoding and printing of PostScript objects decode.c, Mon Dec 31 09:40:18 1984 James Gosling, Sun Microsystems */ #ifdef REF #include #include #endif #include "PostScript.h" #ifndef cv_is_canvas #include "canvas.h" #endif #ifdef undef char * decode_body(p) register struct body *p; { static char buf[100]; if (p == 0) return "NIL"; switch (p->type) { case fixed_type: sprintf(buf, "fixed_type"); break; case real_type: sprintf(buf, "real_type"); break; case boolean_type: sprintf(buf, "boolean_type"); break; case null_type: sprintf(buf, "null_type"); break; case marker_type: sprintf(buf, "marker_type"); break; case font_id_type: sprintf(buf, "font(%s%p)", body->body.font->family->FamilyName, body->body.font->matrix[0][0]); break; case file_type: sprintf(buf, "file_type"); break; case operator_type: sprintf(buf, "operator_type"); break; case called_operator_type: sprintf(buf, "called_operator_type"); break; case magic_variable_type: sprintf(buf, "magic_variable_type"); break; case keyword_type: sprintf(buf, "keyword %.*s", p->body.keyword.namelen, p->body.keyword.name); break; case string_type: sprintf(buf, "string_type '%.*s'", p->body.string.used, p->body.string.chars); break; case array_type: sprintf(buf, "array_type[%d]", p->body.array.size); break; case dictionary_type: sprintf(buf, "dictionary_type[%d]", p->body.array.size); break; } return buf; } #endif char * process_event_name(body) register struct body *body; { if (body == 0 || body->body.process.env == 0) return "internal_error"; switch (body->body.process.env->event) { case runnable_process: return "runnable"; case dead_process: return "dead"; case zombie_process: return "zombie"; case input_event_wait: return "input_wait"; case suspended_process: return "breakpoint"; case process_activity_wait: return "proc_wait"; case monitor_wait: return "mon_wait"; default: return "IO_wait"; } } decode_object(f, obj, depth) register PSFILE *f; struct object obj; { register struct body *body; if (object_has_body(&obj)) { body = body_of(&obj); if (body->type != obj.type) { psio_fprintf(f, "**obj/body type mismatch**"); return; } } switch (obj.type) { case fixed_type: if (fractionalbits(obj.value.fixed)) { /* Its really a real */ psio_fprintf(f, "%p", obj.value.fixed); } else { /* Its an integer */ psio_fprintf(f, "%d", floorfr(obj.value.fixed)); } break; case real_type: psio_fprintf(f, "%g", obj.value.real); break; case boolean_type: psio_fprintf(f, obj.value.fixed ? "true" : "false"); break; case null_type: psio_fprintf(f, "null"); break; case color_type: psio_fprintf(f, "color(%.2f,%.2f,%.2f)", obj.value.color.red / 255., obj.value.color.green / 255., obj.value.color.blue / 255.); break; case marker_type: psio_fprintf(f, "marker"); break; case font_id_type: { register struct psfont *ft = body->body.font; psio_fprintf(f, "font(%s%p", ft->family->FamilyName, ft->matrix[0][0]); if (ft->matrix[0][1] != 0 || ft->matrix[1][0] != 0 || ft->matrix[1][1] != ft->matrix[0][0]) psio_fprintf(f, ",%p,%p,%p", ft->matrix[0][1], ft->matrix[1][0], ft->matrix[1][1]); if (ft->remap) psio_fprintf(f, ",remapped"); psio_fprintf(f, ")"); } break; case file_type: psio_fprintf(f, "file("); if (body->body.file.name) psio_fprintf(f, "'%.*s'", body->body.file.name->body.string.used, body->body.file.name->body.string.chars); else if (body->body.file.outbuf == psio_stdout) psio_fprintf(f, "%stdout"); else if (body->body.file.inbuf && psio_fileno(body->body.file.inbuf) == 0) psio_fprintf(f, "%stdin"); else psio_fprintf(f, "?"); if (body->body.file.inbuf == 0 && body->body.file.outbuf == 0) psio_fprintf(f, ",nil"); else { if (body->body.file.outbuf) psio_fprintf(f, ",W"); if (body->body.file.inbuf) { psio_fprintf(f, ",R"); if (psio_eof(body->body.file.inbuf)) psio_fprintf(f, ",EOF"); if (psio_error(body->body.file.inbuf)) psio_fprintf(f, ",ERR"); } } psio_fprintf(f, ")"); break; case operator_type: psio_fprintf(f, "'%s'", obj.value.def->pname); break; case called_operator_type: psio_fprintf(f, "`%s'", obj.value.def->pname); break; case magic_variable_type: psio_fprintf(f, "`%s!'", obj.value.def->pname); break; case keyword_type: if (!obj.executable) psio_putc('/', f); psio_fprintf(f, "%.*s", body->body.keyword.namelen, body->body.keyword.name); break; case string_type: { register unsigned char *s = (unsigned char *) body->body.string.chars + obj.value.substring.start; register n = obj.value.substring.length; if (psio_isstringfile(f)) psio_write(s, n, 1, f); else { psio_putc('(', f); while (--n >= 0) { switch (*s) { case '\n': psio_fprintf(f, "\\n"); break; case '\f': psio_fprintf(f, "\\f"); break; case '\b': psio_fprintf(f, "\\b"); break; case '\r': psio_fprintf(f, "\\r"); break; case BACKSLASH: case '(': case ')': psio_fprintf(f, "\\%c", *s); break; default: if (*s < 040 || *s >= 0177) { psio_fprintf(f, "\\%03o", *s); } else psio_putc(*s, f); } s++; } psio_putc(')', f); } } break; case array_type: if (depth > 0) { register i, n; psio_putc(obj.executable ? '{' : '[', f); i = obj.value.substring.start; for (n = obj.value.substring.length; --n >= 0;) { decode_object(f, body->body.array.objects[i], depth - 1); i++; if (n) psio_putc(' ', f); } psio_putc(obj.executable ? '}' : ']', f); } else psio_fprintf(f, obj.executable ? "array{%d}" : "array[%d]", obj.value.substring.length); break; case dictionary_type: if (depth > 1) { register n; register struct object *ob_array; register dumped = 0; psio_fprintf(f, "dict[\n "); ob_array = body->body.array.objects; for (n = body->body.array.size; (n -= 2) >= 0; ob_array += 2) { if (ob_array->type != null_type && ob_array[1].type != operator_type) { if (++dumped > 15) { psio_fprintf(f, "... "); break; } decode_object(f, ob_array[0], 1); psio_fprintf(f, ": "); decode_object(f, ob_array[1], 1); if (n) psio_fprintf(f, "\n "); } } psio_putc(']', f); } else psio_fprintf(f, "dictionary[%d]", body->body.array.size); break; case canvas_type: psio_fprintf(f, "canvas(%dx%d", obj.value.canvas->pr_size.x, obj.value.canvas->pr_size.y); if (!cv_is_canvas(obj.value.canvas)) psio_fprintf(f, ",pixrect"); else { if (!((struct canvas *) obj.value.canvas)->mapped) psio_fprintf(f, ",unmapped"); if (((struct canvas *) obj.value.canvas)->transparent) psio_fprintf(f, ",transparent"); if (((struct canvas *) obj.value.canvas)->parent == 0) psio_fprintf(f, ",root"); if (((struct canvas *) obj.value.canvas)->topchild != 0) psio_fprintf(f, ",parent"); if (((struct canvas *) obj.value.canvas)->complete) psio_fprintf(f, ",complete"); if (((struct canvas *) obj.value.canvas)->retained_part.pixrect != 0) psio_fprintf(f, ",retained"); } psio_putc(')', f); break; case process_type: psio_fprintf(f, "process(%o", body->body.process.env); if (body->body.process.env) psio_fprintf(f, ", %s", process_event_name(body)); if (depth > 0 && body->body.process.env) { psio_fprintf(f, ", "); decode_object(f, body->body.process.env->execee, depth - 1); } psio_fprintf(f, ")"); break; case event_type: if (depth > 0) { psio_fprintf(f, "event(0x%x, [%p,%p]", body, body->body.event.pos.x, body->body.event.pos.y); psio_fprintf(f, ", name("); decode_object(f, body->body.event.name, depth - 1); psio_fprintf(f, "), action("); decode_object(f, body->body.event.action, depth - 1); if (body->body.event.canvas) psio_fprintf(f, "), canvas(%dx%d@%d,%d", body->body.event.canvas->pixrect.pr_size.x, body->body.event.canvas->pixrect.pr_size.y, body->body.event.canvas->pos.x, body->body.event.canvas->pos.y); #ifdef NOTDEF if (body->body.event.shape) psio_fprintf(f, "), shape(%dx%d@%d,%d", body->body.event.shape->size.x, body->body.event.shape->size.y, body->body.event.shape->pos.x, body->body.event.shape->pos.y); #endif psio_fprintf(f, "))"); } else psio_fprintf(f, "event(0x%x)", body); break; case shape_type: { struct object *objp = &obj; register struct shape *sh = body->body.shape; if (obj.value.shape != sh) { psio_fprintf(f, "Pointer mis-match"); } if (sh) { psio_fprintf(f, "%s@(%d,%d)-(%d,%d)", (sh->is_rect ? "rect" : "curve"), sh->pos.x, sh->pos.y, sh->size.x, sh->size.y); } else { psio_fprintf(f, "shape(null)"); } } break; case monitor_type: psio_fprintf(f, "monitor("); if (body->body.monitor.holder) psio_fprintf(f, "held"); if (body->body.monitor.first) psio_fprintf(f, ", waiting"); psio_fprintf(f, ")"); break; case cursor_type: psio_fprintf(f, "cursor()"); break; case graphicsstate_type: psio_fprintf(f, "graphicsstate()"); break; default: psio_fprintf(f, "huh?(%d)", obj.type); break; } } #ifdef undef prfree(o) struct object o; { if (verbose) { psio_fprintf(psio_stdout, "Freed "); decode_object(psio_stdout, o, 1); psio_fprintf(psio_stdout, "\n"); } } #endif char *error_names[] = { "none", "accept", "dictfull", "dictstackoverflow", "dictstackunderflow", "execstackoverflow", "interrupt", "invalidaccess", "invalidexit", "invalidfileaccess", "invalidfont", "invalidrestore", "ioerr", "limitcheck", "nocurrentpoint", "rangecheck", "stackoverflow", "stackunderflow", "syntaxerror", "timeout", "typecheck", "undefined", "undefinedfilename", "undefinedresult", "unimplemented", "unmatchedmark", "unregistered", "VMerror", "killprocess", }; dump() { decode_process_state(0, 0); } decode_process_state(f, ee) register PSFILE *f; register struct execution_environment *ee; { if (f == 0) f = psio_stdout; /* To facilitate calling from dbx */ if (ee == 0) ee = current_process; if (ee == 0) { psio_fprintf(f, "decode_process: NULL process handle\n"); return; } if (!verbose && 0) { psio_fprintf(f, "ERROR: %s\n", error_names[(int) ee->error_code]); psio_fprintf(f, "OFFENDING COMMAND: "); decode_object(f, ee->last_executed, 1); psio_fprintf(f, "\nPROCESS: 0x%x\n", ee); psio_fprintf(f, "STACK: "); { register struct object *p = &ee->operand_stack->body.array.objects[0], *top = &ee->operand_stack->body.array.objects [ee->operand_stack->body.array.used]; while (p < top) { psio_putc(' ', f); decode_object(f, *p++, 0); } } psio_putc('\n', f); return; } psio_fprintf(f, "Process: 0x%x Error: %s\n", ee, error_names[(int) ee->error_code]); if (ee->error_detail) psio_fprintf(f, " %s\n", ee->error_detail); psio_fprintf(f, "Stack:"); { register struct object *p = ee->underflow; while (p < ee->optop) { psio_putc(' ', f); decode_object(f, *p++, 0); } } psio_fprintf(f, "\nExecuting: "); decode_object(f, ee->last_executed, 1); { char *prefix = "\nAt: "; register struct execution_stack *es = ee->pos; while (es >= ee->execution_stack) { switch (es->type) { default: break; case file_execution: psio_fprintf(f, "%sReading ", prefix); decode_object(f, es->executed, 1); es = ee->execution_stack; /* break out of outer loop */ break; case array_body_execution: if (es->executed.type == array_type && es->executed.offset > 0) { register struct object *ip = body_of(&es->executed)->body.array.objects + es->executed.value.substring.start; register left = es->executed.value.substring.length; psio_fprintf(f, "%s{", prefix); while (--left >= 0) { if (left == es->env.array.left) psio_fprintf(f, "*"); decode_object(f, *ip++, 0); psio_fprintf(f, left ? " " : "}"); } } prefix = "\nIn: "; break; } es--; } } psio_fprintf(f, "\n"); psio_flush(f); } dump_all() { struct object sys; set_typed_bodied_object(&sys, dictionary_type, system_dictionary); sys.value.substring.length = system_dictionary->body.array.size; decode_object(psio_stdout, sys, 999); psio_putc('\n', psio_stdout); psio_flush(psio_stdout); } pstack_primitive(ee) register struct execution_environment *ee; { register struct object *p = ee->underflow; register PSFILE *psf = ee->stdprnt->body.file.outbuf; if (psf == 0 || psio_error(psf)) { ee->error_code == ioerror_error_code; return; } if (ee->optop <= ee->underflow) psio_fprintf(psf, "Empty stack"); while (p < ee->optop) { decode_object(psf, *p, ee->execee.value.def->index); psio_putc(' ', psf); p++; } psio_putc('\n', psf); } writeobject(ee) register struct execution_environment *ee; { PSFILE *f; if (ee->optop[-2].type != file_type) { ee->error_code = typecheck_error_code; return; } if ((f = body_of(ee->optop - 2)->body.file.outbuf) == 0) { ee->error_code = invalidaccess_error_code; return; } if (psio_error(f)) { ee->error_code == ioerror_error_code; return; } decode_object(f, ee->optop[-1], 4); object_decref(ee->optop - 1); object_decref(ee->optop - 2); ee->optop -= 2; } initialize_decode() { define_operator("writeobject", writeobject, 0, 2, 0); define_operator("pstack", pstack_primitive, 4, 0, 0); define_operator("stack", pstack_primitive, 0, 0, 0); define_operator("dumpsys", dump_all, 0, 0, 0); }