static int zpathforall(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_path_enum *penum; int code; check_proc(op[-3]); check_proc(op[-2]); check_proc(op[-1]); check_proc(*op); check_estack(8); if ((penum = gs_path_enum_alloc(imemory, "pathforall")) == 0) return_error(e_VMerror); code = gs_path_enum_init(penum, igs); if (code < 0) { ifree_object(penum, "path_cleanup"); return code; } /* Push a mark, the four procedures, and the path enumerator. */ push_mark_estack(es_for, path_cleanup); /* iterator */ memcpy(esp + 1, op - 3, 4 * sizeof(ref)); /* 4 procs */ esp += 5; make_istruct(esp, 0, penum); push_op_estack(path_continue); pop(4); op -= 4; return o_push_estack; }
/* <executable_file> .execfile - */ static int zexecfile(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_type_access(*op, t_file, a_executable | a_read | a_execute); check_estack(4); /* cleanup, file, finish, file */ push_mark_estack(es_other, execfile_cleanup); *++esp = *op; push_op_estack(execfile_finish); return zexec(i_ctx_p); }
static int zloop(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_proc(*op); check_estack(4); /* Push a mark and the procedure, and invoke */ /* the continuation operator. */ push_mark_estack(es_for, no_cleanup); *++esp = *op; make_op_estack(esp + 1, loop_continue); pop(1); return loop_continue(i_ctx_p); }
/* <obj> <result> <mask> .stopped <result> */ static int zzstopped(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_type(*op, t_integer); check_op(3); /* Mark the execution stack, and push the default result */ /* in case control returns normally. */ check_estack(5); push_mark_estack(es_stopped, no_cleanup); *++esp = op[-1]; /* save the result */ *++esp = *op; /* save the signal mask */ push_op_estack(stopped_push); push_op_estack(zexec); /* execute the operand */ pop(2); return o_push_estack; }
/* the stacks would get restored in case of an error. */ static int zstopped(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_op(1); /* Mark the execution stack, and push the default result */ /* in case control returns normally. */ check_estack(5); push_mark_estack(es_stopped, no_cleanup); ++esp; make_false(esp); /* save the result */ ++esp; make_int(esp, 1); /* save the signal mask */ push_op_estack(stopped_push); push_op_estack(zexec); /* execute the operand */ return o_push_estack; }
int zrepeat(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_proc(*op); check_type(op[-1], t_integer); if (op[-1].value.intval < 0) return_error(e_rangecheck); check_estack(5); /* Push a mark, the count, and the procedure, and invoke */ /* the continuation operator. */ push_mark_estack(es_for, no_cleanup); *++esp = op[-1]; *++esp = *op; make_op_estack(esp + 1, repeat_continue); pop(2); return repeat_continue(i_ctx_p); }
static int zfilenameforall(i_ctx_t *i_ctx_p) { os_ptr op = osp; file_enum *pfen; gx_io_device *iodev = NULL; gs_parsed_file_name_t pname; int code = 0; check_write_type(*op, t_string); check_proc(op[-1]); check_read_type(op[-2], t_string); /* Push a mark, the iodev, devicenamelen, the scratch string, the enumerator, */ /* and the procedure, and invoke the continuation. */ check_estack(7); /* Get the iodevice */ code = parse_file_name(op - 2, &pname, i_ctx_p->LockFilePermissions); if (code < 0) return code; iodev = (pname.iodev == NULL) ? iodev_default : pname.iodev; /* Check for several conditions that just cause us to return success */ if (pname.len == 0 || iodev->procs.enumerate_files == iodev_no_enumerate_files) { pop(3); return 0; /* no pattern, or device not found -- just return */ } pfen = iodev->procs.enumerate_files(iodev, (const char *)pname.fname, pname.len, imemory); if (pfen == 0) return_error(e_VMerror); push_mark_estack(es_for, file_cleanup); ++esp; make_istruct(esp, 0, iodev); ++esp; make_int(esp, r_size(op-2) - pname.len); *++esp = *op; ++esp; make_istruct(esp, 0, pfen); *++esp = op[-1]; pop(3); code = file_continue(i_ctx_p); return (code == o_pop_estack ? o_push_estack : code); }
/* * Do a callout to an OtherSubr implemented in PostScript. * The caller must have done a check_estack(4 + num_args). */ static int type1_call_OtherSubr(i_ctx_t *i_ctx_p, const gs_type1exec_state * pcxs, int (*cont) (i_ctx_t *), const ref * pos) { /* Move the Type 1 interpreter state to the heap. */ gs_type1exec_state *hpcxs = ialloc_struct(gs_type1exec_state, &st_gs_type1exec_state, "type1_call_OtherSubr"); if (hpcxs == 0) return_error(e_VMerror); *hpcxs = *pcxs; gs_type1_set_callback_data(&hpcxs->cis, hpcxs); push_mark_estack(es_show, op_type1_cleanup); ++esp; make_istruct(esp, 0, hpcxs); return type1_push_OtherSubr(i_ctx_p, pcxs, cont, pos); }
static int zimage_data_setup(i_ctx_t *i_ctx_p, const gs_pixel_image_t * pim, gx_image_enum_common_t * pie, const ref * sources, int npop) { int num_sources = pie->num_planes; int inumpush = NUM_PUSH(num_sources); int code; gs_image_enum *penum; int px; const ref *pp; bool string_sources = true; check_estack(inumpush + 2); /* stuff above, + continuation + proc */ make_int(EBOT_NUM_SOURCES(esp), num_sources); /* * Note that the data sources may be procedures, strings, or (Level * 2 only) files. (The Level 1 reference manual says that Level 1 * requires procedures, but Adobe Level 1 interpreters also accept * strings.) The sources must all be of the same type. * * The Adobe documentation explicitly says that if two or more of the * data sources are the same or inter-dependent files, the result is not * defined. We don't have a problem with the bookkeeping for * inter-dependent files, since each one has its own buffer, but we do * have to be careful if two or more sources are actually the same file. * That is the reason for the aliasing information described above. */ for (px = 0, pp = sources; px < num_sources; px++, pp++) { es_ptr ep = EBOT_SOURCE(esp, px); make_int(ep + 1, 1); /* default is no aliasing */ switch (r_type(pp)) { case t_file: if (!level2_enabled) return_error(e_typecheck); /* Check for aliasing. */ { int pi; for (pi = 0; pi < px; ++pi) if (sources[pi].value.pfile == pp->value.pfile) { /* Record aliasing */ make_int(ep + 1, -pi); EBOT_SOURCE(esp, pi)[1].value.intval++; break; } } string_sources = false; /* falls through */ case t_string: if (r_type(pp) != r_type(sources)) { if (pie != NULL) gx_image_end(pie, false); /* Clean up pie */ return_error(e_typecheck); } check_read(*pp); break; default: if (!r_is_proc(sources)) { static const char ds[] = "DataSource"; if (pie != NULL) gx_image_end(pie, false); /* Clean up pie */ gs_errorinfo_put_pair(i_ctx_p, ds, sizeof(ds) - 1, pp); return_error(e_typecheck); } check_proc(*pp); string_sources = false; } *ep = *pp; } /* Always place the image enumerator into local memory, because pie may have local objects inherited from igs, which may be local when the current allocation mode is global. Bug 688140. */ if ((penum = gs_image_enum_alloc(imemory_local, "image_setup")) == 0) return_error(e_VMerror); code = gs_image_enum_init(penum, pie, (const gs_data_image_t *)pim, igs); if (code != 0 || (pie->skipping && string_sources)) { /* error, or empty image */ int code1 = gs_image_cleanup_and_free_enum(penum, igs); if (code >= 0) /* empty image */ pop(npop); if (code >= 0 && code1 < 0) code = code1; return code; } push_mark_estack(es_other, image_cleanup); esp += inumpush - 1; make_int(ETOP_PLANE_INDEX(esp), 0); make_int(ETOP_NUM_SOURCES(esp), num_sources); make_struct(esp, avm_local, penum); switch (r_type(sources)) { case t_file: push_op_estack(image_file_continue); break; case t_string: push_op_estack(image_string_continue); break; default: /* procedure */ push_op_estack(image_proc_process); break; } pop(npop); return o_push_estack; }