static int _event_handler (Xpost_Context *ctx, Xpost_Object devdic) { Xpost_Object privatestr; PrivateData private; xcb_generic_event_t *event; /* load private data struct from string */ privatestr = xpost_dict_get(ctx, devdic, namePrivate); if (xpost_object_get_type(privatestr) == invalidtype) return undefined; xpost_memory_get(xpost_context_select_memory(ctx, privatestr), xpost_object_get_ent(privatestr), 0, sizeof private, &private); event = xcb_poll_for_event(private.c); if (event) { switch(event->response_type & ~0x80) { case XCB_EXPOSE: _flush(ctx, devdic); break; default: break; } free(event); } else if (xcb_connection_has_error(private.c)) return unregistered; return 0; }
/* copy userdict names to systemdict Problem: This is clearly an invalidaccess, and yet is required by the PLRM. Discussion: https://groups.google.com/d/msg/comp.lang.postscript/VjCI0qxkGY4/y0urjqRA1IoJ The ignoreinvalidaccess exception has been isolated to this one case. */ static int copyudtosd(Xpost_Context *ctx, Xpost_Object ud, Xpost_Object sd) { Xpost_Object ed, de; ctx->ignoreinvalidaccess = 1; xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "userdict"), ud); ed = xpost_dict_get(ctx, ud, xpost_name_cons(ctx, "errordict")); if (xpost_object_get_type(ed) == invalidtype) return undefined; xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "errordict"), ed); de = xpost_dict_get(ctx, ud, xpost_name_cons(ctx, "$error")); if (xpost_object_get_type(de) == invalidtype) return undefined; xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "$error"), de); ctx->ignoreinvalidaccess = 0; return 0; }
/* create an instance of the device using the class .copydict procedure */ static int _create (Xpost_Context *ctx, Xpost_Object width, Xpost_Object height, Xpost_Object classdic) { xpost_stack_push(ctx->lo, ctx->os, width); xpost_stack_push(ctx->lo, ctx->os, height); xpost_stack_push(ctx->lo, ctx->os, classdic); xpost_dict_put(ctx, classdic, namewidth, width); xpost_dict_put(ctx, classdic, nameheight, height); /* call device class's ps-level .copydict procedure, then call _create_cont, by continuation. */ if (!xpost_stack_push(ctx->lo, ctx->es, xpost_operator_cons_opcode(_create_cont_opcode))) return execstackoverflow; if (!xpost_stack_push(ctx->lo, ctx->es, xpost_dict_get(ctx, classdic, //xpost_name_cons(ctx, ".copydict") namedotcopydict ))) return execstackoverflow; return 0; }
/* called by mainloop() after propagated error codes. pushes postscript-level error procedures and resumes normal execution. */ static void _onerror(Xpost_Context *ctx, unsigned int err) { Xpost_Object sd; Xpost_Object ed; Xpost_Object dollarerror; if (err > unknownerror) err = unknownerror; if (!validate_context(ctx)) XPOST_LOG_ERR("context not valid"); if (itpdata->in_onerror > 5) { fprintf(stderr, "LOOP in error handler\nabort\n"); ++ctx->quit; /*exit(undefinedresult); */ } ++itpdata->in_onerror; #ifdef EMITONERROR fprintf(stderr, "err: %s\n", errorname[err]); #endif /* reset stack */ if ((xpost_object_get_type(ctx->currentobject) == operatortype) && (ctx->currentobject.tag & XPOST_OBJECT_TAG_DATA_FLAG_OPARGSINHOLD)) { int n = ctx->currentobject.mark_.pad0; int i; for (i = 0; i < n; i++) { xpost_stack_push(ctx->lo, ctx->os, xpost_stack_bottomup_fetch(ctx->lo, ctx->hold, i)); } } /* printf("1\n"); */ sd = xpost_stack_bottomup_fetch(ctx->lo, ctx->ds, 0); /* printf("2\n"); */ dollarerror = xpost_dict_get(ctx, sd, namedollarerror); if (xpost_object_get_type(dollarerror) == invalidtype) { XPOST_LOG_ERR("cannot load $error dict for error: %s", errorname[err]); xpost_stack_push(ctx->lo, ctx->es, xpost_object_cvx(xpost_name_cons(ctx, "stop"))); /*itpdata->in_onerror = 0; */ return; } /* printf("3\n"); */ /* printf("4\n"); */ /* printf("5\n"); */ xpost_stack_push(ctx->lo, ctx->os, ctx->currentobject); #if 0 /* printf("6\n"); */ xpost_stack_push(ctx->lo, ctx->os, xpost_object_cvlit(xpost_name_cons(ctx, errorname[err]))); /* printf("7\n"); */ xpost_stack_push(ctx->lo, ctx->es, xpost_object_cvx(xpost_name_cons(ctx, "signalerror"))); #endif ed = xpost_dict_get(ctx, sd, nameerrordict); xpost_stack_push(ctx->lo, ctx->es, xpost_dict_get(ctx, ed, xpost_name_cons(ctx, errorname[err]))); /* printf("8\n"); */ itpdata->in_onerror = 0; }
/* execute ps program until quit, fall-through to quit, SHOWPAGE_RETURN semantic, or error (default action: message, purge and quit). */ XPAPI int xpost_run(Xpost_Context *ctx, Xpost_Input_Type input_type, const void *inputptr, size_t set_size) { Xpost_Object lsav = null; int llev = 0; unsigned int vs; const char *ps_str = NULL; const char *ps_file = NULL; const FILE *ps_file_ptr = NULL; int ret; Xpost_Object device; Xpost_Object semantic; switch(input_type) { case XPOST_INPUT_FILENAME: ps_file = inputptr; break; case XPOST_INPUT_STRING: ps_str = inputptr; ps_file_ptr = tmpfile(); if (set_size) fwrite(ps_str, 1, set_size, (FILE*)ps_file_ptr); else fwrite(ps_str, 1, strlen(ps_str), (FILE*)ps_file_ptr); rewind((FILE*)ps_file_ptr); break; case XPOST_INPUT_FILEPTR: ps_file_ptr = inputptr; break; case XPOST_INPUT_RESUME: /* resuming a returned session, skip startup */ goto run; } /* prime the exec stack so it starts with a 'start*' procedure, and if it ever gets to the bottom, it quits. These procedures are all defined in data/init.ps */ xpost_stack_push(ctx->lo, ctx->es, xpost_operator_cons(ctx, "quit", NULL,0,0)); /* if ps_file is NULL: if stdin is a tty `start` proc defined in init.ps runs `executive` which prompts for user input else 'startstdin' executes stdin but does not prompt if ps_file is not NULL: 'startfile' executes a named file wrapped in a stopped context with handleerror */ if (ps_file) { /*printf("ps_file\n"); */ xpost_stack_push(ctx->lo, ctx->os, xpost_object_cvlit(xpost_string_cons(ctx, strlen(ps_file), ps_file))); xpost_stack_push(ctx->lo, ctx->es, xpost_object_cvx(xpost_name_cons(ctx, "startfilename"))); } else if (ps_file_ptr) { xpost_stack_push(ctx->lo, ctx->os, xpost_object_cvlit(xpost_file_cons(ctx->lo, ps_file_ptr))); xpost_stack_push(ctx->lo, ctx->es, xpost_object_cvx(xpost_name_cons(ctx, "startfile"))); } else { if (xpost_isatty(fileno(stdin))) xpost_stack_push(ctx->lo, ctx->es, xpost_object_cvx(xpost_name_cons(ctx, "start"))); else xpost_stack_push(ctx->lo, ctx->es, xpost_object_cvx(xpost_name_cons(ctx, "startstdin"))); } (void) xpost_save_create_snapshot_object(ctx->gl); lsav = xpost_save_create_snapshot_object(ctx->lo); /* Run! */ run: ctx->quit = 0; ctx->state = C_RUN; ret = mainloop(ctx); semantic = xpost_dict_get(ctx, xpost_stack_bottomup_fetch(ctx->lo, ctx->ds, 0), xpost_name_cons(ctx, "ShowpageSemantics")); if (semantic.int_.val == XPOST_SHOWPAGE_RETURN) return ret == 1 ? yieldtocaller : 0; XPOST_LOG_INFO("destroying device"); device = xpost_dict_get(ctx, xpost_stack_bottomup_fetch(ctx->lo, ctx->ds, 2), xpost_name_cons(ctx, "DEVICE")); XPOST_LOG_INFO("device type=%s", xpost_object_type_names[xpost_object_get_type(device)]); /*xpost_operator_dump(ctx, 1); // is this pointer value constant? */ if (xpost_object_get_type(device) == arraytype){ XPOST_LOG_INFO("running proc"); xpost_stack_push(ctx->lo, ctx->es, xpost_operator_cons(ctx, "quit", NULL,0,0)); xpost_stack_push(ctx->lo, ctx->es, device); ctx->quit = 0; mainloop(ctx); device = xpost_stack_pop(ctx->lo, ctx->os); } if (xpost_object_get_type(device) == dicttype) { Xpost_Object Destroy; XPOST_LOG_INFO("destroying device dict"); Destroy = xpost_dict_get(ctx, device, xpost_name_cons(ctx, "Destroy")); if (xpost_object_get_type(Destroy) == operatortype) { int res; xpost_stack_push(ctx->lo, ctx->os, device); res = xpost_operator_exec(ctx, Destroy.mark_.padw); if (res) XPOST_LOG_ERR("%s error destroying device", errorname[res]); else XPOST_LOG_INFO("destroyed device"); } } xpost_save_restore_snapshot(ctx->gl); xpost_memory_table_get_addr(ctx->lo, XPOST_MEMORY_TABLE_SPECIAL_SAVE_STACK, &vs); if (xpost_object_get_type(lsav) == savetype) { for ( llev = xpost_stack_count(ctx->lo, vs); llev > lsav.save_.lev; llev-- ) { xpost_save_restore_snapshot(ctx->lo); } } return noerror; }