/* Note that .setdevice clears the current pagedevice. */ int zsetdevice(i_ctx_t *i_ctx_p) { gx_device *dev = gs_currentdevice(igs); os_ptr op = osp; int code = 0; check_write_type(*op, t_device); if (dev->LockSafetyParams) { /* do additional checking if locked */ if(op->value.pdevice != dev) /* don't allow a different device */ return_error(e_invalidaccess); } #ifndef PSI_INCLUDED /* the language switching build shouldn't install a new device here. The language switching machinery installs a shared device. */ code = gs_setdevice_no_erase(igs, op->value.pdevice); #endif if (code < 0) return code; make_bool(op, code != 0); /* erase page if 1 */ clear_pagedevice(istate); return code; }
static int type1crypt(i_ctx_t *i_ctx_p, int (*proc)(byte *, const byte *, uint, ushort *)) { os_ptr op = osp; crypt_state state; uint ssize; check_type(op[-2], t_integer); state = op[-2].value.intval; if (op[-2].value.intval != state) return_error(e_rangecheck); /* state value was truncated */ check_read_type(op[-1], t_string); check_write_type(*op, t_string); ssize = r_size(op - 1); if (r_size(op) < ssize) return_error(e_rangecheck); discard((*proc)(op->value.bytes, op[-1].value.const_bytes, ssize, &state)); /* can't fail */ op[-2].value.intval = state; op[-1] = *op; r_set_size(op - 1, ssize); pop(1); return 0; }
static int zreadstring_at(i_ctx_t *i_ctx_p, os_ptr op, uint start) { stream *s; uint len, rlen; int status; check_write_type(*op, t_string); check_read_file(s, op - 1); len = r_size(op); status = sgets(s, op->value.bytes + start, len - start, &rlen); rlen += start; switch (status) { case EOFC: case 0: break; default: return handle_read_status(i_ctx_p, status, op - 1, &rlen, zreadstring_continue); } /* * The most recent Adobe specification says that readstring * must signal a rangecheck if the string length is zero. * I can't imagine the motivation for this, but we emulate it. * It's safe to check it here, rather than earlier, because if * len is zero, sgets will return 0 immediately with rlen = 0. */ if (len == 0) return_error(e_rangecheck); r_set_size(op, rlen); op[-1] = *op; make_bool(op, (rlen == len ? 1 : 0)); return 0; }
/* Get some double arguments, and check for a double result. */ static int double_params_result(os_ptr op, int count, double *pval) { check_write_type(*op, t_string); if (r_size(op) != sizeof(double)) return_error(e_typecheck); return double_params(op - 1, count, pval); }
static int zreadhexstring(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_write_type(*op, t_string); return zreadhexstring_at(i_ctx_p, op, 0, -1); }
/* the dictionary parameter for the BoundedHuffman filters. */ static int zcomputecodes(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; uint asize; hc_definition def; ushort *data; long *freqs; int code = 0; check_type(*op, t_integer); check_write_type(*op1, t_array); asize = r_size(op1); if (op->value.intval < 1 || op->value.intval > max_hc_length) return_error(e_rangecheck); def.num_counts = op->value.intval; if (asize < def.num_counts + 2) return_error(e_rangecheck); def.num_values = asize - (def.num_counts + 1); data = (ushort *) gs_alloc_byte_array(imemory, asize, sizeof(ushort), "zcomputecodes"); freqs = (long *)gs_alloc_byte_array(imemory, def.num_values, sizeof(long), "zcomputecodes(freqs)"); if (data == 0 || freqs == 0) code = gs_note_error(e_VMerror); else { uint i; def.counts = data; def.values = data + (def.num_counts + 1); for (i = 0; i < def.num_values; i++) { const ref *pf = op1->value.const_refs + i + def.num_counts + 1; if (!r_has_type(pf, t_integer)) { code = gs_note_error(e_typecheck); break; } freqs[i] = pf->value.intval; } if (!code) { code = hc_compute(&def, freqs, imemory); if (code >= 0) { /* Copy back results. */ for (i = 0; i < asize; i++) make_int(op1->value.refs + i, data[i]); } } } gs_free_object(imemory, freqs, "zcomputecodes(freqs)"); gs_free_object(imemory, data, "zcomputecodes"); if (code < 0) return code; pop(1); return code; }
/* <any> <string> cvs <substring> */ static int zcvs(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; check_write_type(*op, t_string); check_op(2); code = convert_to_string(imemory, op - 1, op); if (code >= 0) pop(1); return code; }
/* <dnum> <string> .dcvs <substring> */ static int zdcvs(i_ctx_t *i_ctx_p) { os_ptr op = osp; double num; int code = double_params(op - 1, 1, &num); char dot, str[MAX_CHARS + 1]; int len; if (code < 0) return code; check_write_type(*op, t_string); sprintf(str, "%f", 1.5); dot = str[1]; /* locale-dependent */ /* * To get fully accurate output results for IEEE double- * precision floats (53 bits of mantissa), the ANSI * %g default of 6 digits is not enough; 16 are needed. * Unfortunately, using %.16g produces unfortunate artifacts such as * 1.2 printing as 1.200000000000005. Therefore, we print using %g, * and if the result isn't accurate enough, print again * using %.16g. */ { double scanned; sprintf(str, "%g", num); sscanf(str, "%lf", &scanned); if (scanned != num) sprintf(str, "%.16g", num); } len = strlen(str); if (len > r_size(op)) return_error(e_rangecheck); /* Juggling locales isn't thread-safe. Posix me harder. */ if (dot != '.') { char *pdot = strchr(str, dot); if (pdot) *pdot = '.'; } memcpy(op->value.bytes, str, len); op[-1] = *op; r_set_size(op - 1, len); pop(1); return 0; }
/* *op contains the index within the string and the odd flag. */ static int zreadhexstring_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code, length, odd; check_type(*op, t_integer); length = op->value.intval & 0xFFFFFF; odd = op->value.intval >> 24; if (length > r_size(op - 1) || odd < -1 || odd > 0xF) return_error(e_rangecheck); check_write_type(op[-1], t_string); code = zreadhexstring_at(i_ctx_p, op - 1, (uint)length, odd); if (code >= 0) pop(1); return code; }
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); }
static int zbosobject(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; check_type(op[-3], t_integer); check_type(op[-2], t_integer); check_write_type(*op, t_string); if (r_size(op) < 8) return_error(gs_error_rangecheck); code = encode_binary_token(i_ctx_p, op - 1, &op[-3].value.intval, &op[-2].value.intval, op->value.bytes); if (code < 0) return code; op[-1] = *op; r_set_size(op - 1, 8); pop(1); return 0; }
/* <file> <string> .peekstring <substring> <filled_bool> */ static int zpeekstring(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream *s; uint len, rlen; check_read_file(s, op - 1); check_write_type(*op, t_string); len = r_size(op); while ((rlen = sbufavailable(s)) < len) { int status = s->end_status; switch (status) { case EOFC: break; case 0: /* * The following is a HACK. It should reallocate the buffer to hold * at least len bytes. However, this raises messy problems about * which allocator to use and how it should interact with restore. */ if (len >= s->bsize) return_error(e_rangecheck); s_process_read_buf(s); continue; default: return handle_read_status(i_ctx_p, status, op - 1, NULL, zpeekstring); } break; } if (rlen > len) rlen = len; /* Don't remove the data from the buffer. */ memcpy(op->value.bytes, sbufptr(s), rlen); r_set_size(op, rlen); op[-1] = *op; make_bool(op, (rlen == len ? 1 : 0)); return 0; }
/* Return 0 if OK, error code if not. */ int write_matrix_in(ref * op, const gs_matrix * pmat, gs_dual_memory_t *idmemory, gs_ref_memory_t *imem) { ref *aptr; const float *pel; int i; check_write_type(*op, t_array); if (r_size(op) != 6) return_error(e_rangecheck); aptr = op->value.refs; pel = (const float *)pmat; for (i = 5; i >= 0; i--, aptr++, pel++) { if (idmemory) { ref_save(op, aptr, "write_matrix"); make_real_new(aptr, *pel); } else { make_tav(aptr, t_real, imemory_new_mask(imem), realval, *pel); } } return 0; }
/* * We could handle readline the same way as readstring, * except for the anomalous situation where we get interrupted * between the CR and the LF of an end-of-line marker. * We hack around this in the following way: if we get interrupted * before we've read any characters, we just restart the readline; * if we get interrupted at any other time, we use readline_continue; * we use start=0 (which we have just ruled out as a possible start value * for readline_continue) to indicate interruption after the CR. */ static int zreadline_at(i_ctx_t *i_ctx_p, os_ptr op, uint count, bool in_eol) { stream *s; int status; gs_string str; check_write_type(*op, t_string); check_read_file(s, op - 1); str.data = op->value.bytes; str.size = r_size(op); status = zreadline_from(s, &str, NULL, &count, &in_eol); switch (status) { case 0: case EOFC: break; case 1: return_error(e_rangecheck); default: if (count == 0 && !in_eol) return handle_read_status(i_ctx_p, status, op - 1, NULL, zreadline); else { if (in_eol) { r_set_size(op, count); count = 0; } return handle_read_status(i_ctx_p, status, op - 1, &count, zreadline_continue); } } r_set_size(op, count); op[-1] = *op; make_bool(op, status == 0); return 0; }
/* .getbitsrect <height> <substring> */ static int zgetbitsrect(i_ctx_t *i_ctx_p) { /* * alpha? is 0 for no alpha, -1 for alpha first, 1 for alpha last. * std_depth is null for native pixels, depth/component for * standard color space. */ os_ptr op = osp; gx_device *dev; gs_int_rect rect; gs_get_bits_params_t params; int w, h; gs_get_bits_options_t options = GB_ALIGN_ANY | GB_RETURN_COPY | GB_OFFSET_0 | GB_RASTER_STANDARD | GB_PACKING_CHUNKY; int depth; uint raster; int num_rows; int code; check_read_type(op[-7], t_device); dev = op[-7].value.pdevice; check_int_leu(op[-6], dev->width); rect.p.x = op[-6].value.intval; check_int_leu(op[-5], dev->height); rect.p.y = op[-5].value.intval; check_int_leu(op[-4], dev->width); w = op[-4].value.intval; check_int_leu(op[-3], dev->height); h = op[-3].value.intval; check_type(op[-2], t_integer); /* * We use if/else rather than switch because the value is long, * which is not supported as a switch value in pre-ANSI C. */ if (op[-2].value.intval == -1) options |= GB_ALPHA_FIRST; else if (op[-2].value.intval == 0) options |= GB_ALPHA_NONE; else if (op[-2].value.intval == 1) options |= GB_ALPHA_LAST; else return_error(e_rangecheck); if (r_has_type(op - 1, t_null)) { options |= GB_COLORS_NATIVE; depth = dev->color_info.depth; } else { static const gs_get_bits_options_t depths[17] = { 0, GB_DEPTH_1, GB_DEPTH_2, 0, GB_DEPTH_4, 0, 0, 0, GB_DEPTH_8, 0, 0, 0, GB_DEPTH_12, 0, 0, 0, GB_DEPTH_16 }; gs_get_bits_options_t depth_option; int std_depth; check_int_leu(op[-1], 16); std_depth = (int)op[-1].value.intval; depth_option = depths[std_depth]; if (depth_option == 0) return_error(e_rangecheck); options |= depth_option | GB_COLORS_NATIVE; depth = (dev->color_info.num_components + (options & GB_ALPHA_NONE ? 0 : 1)) * std_depth; } if (w == 0) return_error(e_rangecheck); raster = (w * depth + 7) >> 3; check_write_type(*op, t_string); num_rows = r_size(op) / raster; h = min(h, num_rows); if (h == 0) return_error(e_rangecheck); rect.q.x = rect.p.x + w; rect.q.y = rect.p.y + h; params.options = options; params.data[0] = op->value.bytes; code = (*dev_proc(dev, get_bits_rectangle))(dev, &rect, ¶ms, NULL); if (code < 0) return code; make_int(op - 7, h); op[-6] = *op; r_set_size(op - 6, h * raster); pop(6); return 0; }
/* <bitmap> <cid> <type32font> <str22> .makeglyph32 <<same with substr>> */ static int zmakeglyph32(i_ctx_t *i_ctx_p) { os_ptr op = osp; bool long_form; uint msize; double metrics[10]; int wx, llx, lly, urx, ury; int width, height, raster; gs_font *pfont; int code; byte *str; check_array(op[-4]); msize = r_size(op - 4); switch (msize) { case 10: long_form = true; break; case 6: long_form = false; break; default: return_error(gs_error_rangecheck); } code = num_params(op[-4].value.refs + msize - 1, msize, metrics); if (code < 0) return code; if (~code & 0x3c) /* check llx .. ury for integers */ return_error(gs_error_typecheck); check_read_type(op[-3], t_string); llx = (int)metrics[2]; lly = (int)metrics[3]; urx = (int)metrics[4]; ury = (int)metrics[5]; width = urx - llx; height = ury - lly; raster = (width + 7) >> 3; if (width < 0 || height < 0 || r_size(op - 3) != raster * height) return_error(gs_error_rangecheck); check_int_leu(op[-2], 65535); code = font_param(op - 1, &pfont); if (code < 0) return code; if (pfont->FontType != ft_CID_bitmap) return_error(gs_error_invalidfont); check_write_type(*op, t_string); if (r_size(op) < 22) return_error(gs_error_rangecheck); str = op->value.bytes; if (long_form || metrics[0] != (wx = (int)metrics[0]) || metrics[1] != 0 || height == 0 || ((wx | width | height | (llx + 128) | (lly + 128)) & ~255) != 0 ) { /* Use the long form. */ int i, n = (long_form ? 10 : 6); str[0] = 0; str[1] = long_form; for (i = 0; i < n; ++i) { int v = (int)metrics[i]; /* no floating point widths yet */ str[2 + 2 * i] = (byte)(v >> 8); str[2 + 2 * i + 1] = (byte)v; } r_set_size(op, 2 + n * 2); } else {
/* <num> <radix_int> <string> cvrs <substring> */ static int zcvrs(i_ctx_t *i_ctx_p) { os_ptr op = osp; int radix; check_type(op[-1], t_integer); if (op[-1].value.intval < 2 || op[-1].value.intval > 36) return_error(e_rangecheck); radix = op[-1].value.intval; check_write_type(*op, t_string); if (radix == 10) { switch (r_type(op - 2)) { case t_integer: case t_real: { int code = convert_to_string(imemory, op - 2, op); if (code < 0) return code; pop(2); return 0; } case t__invalid: return_error(e_stackunderflow); default: return_error(e_rangecheck); /* CET 24-05 wants rangecheck */ } } else { uint ival; byte digits[sizeof(ulong) * 8]; byte *endp = &digits[countof(digits)]; byte *dp = endp; switch (r_type(op - 2)) { case t_integer: ival = (uint) op[-2].value.intval; break; case t_real: { float fval = op[-2].value.realval; if (!REAL_CAN_BE_INT(fval)) return_error(e_rangecheck); ival = (ulong) (long)fval; } break; case t__invalid: return_error(e_stackunderflow); default: return_error(e_rangecheck); /* CET 24-05 wants rangecheck */ } do { int dit = ival % radix; *--dp = dit + (dit < 10 ? '0' : ('A' - 10)); ival /= radix; } while (ival); if (endp - dp > r_size(op)) return_error(e_rangecheck); memcpy(op->value.bytes, dp, (uint) (endp - dp)); r_set_size(op, endp - dp); } op[-2] = *op; pop(2); return 0; }