Exemplo n.º 1
0
/* <array|dict|name|packedarray|string> length <int> */
static int
zlength(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    switch (r_type(op)) {
	case t_array:
	case t_string:
	case t_mixedarray:
	case t_shortarray:
	    check_read(*op);
	    make_int(op, r_size(op));
	    return 0;
	case t_dictionary:
	    check_dict_read(*op);
	    make_int(op, dict_length(op));
	    return 0;
	case t_name: {
	    ref str;

	    name_string_ref(imemory, op, &str);
	    make_int(op, r_size(&str));
	    return 0;
	}
	case t_astruct:
	    if (gs_object_type(imemory, op->value.pstruct) != &st_bytes)
		return_error(e_typecheck);
	    check_read(*op);
	    make_int(op, gs_object_size(imemory, op->value.pstruct));
	    return 0;
	default:
	    return_op_typecheck(op);
    }
}
Exemplo n.º 2
0
/*
 * Force the enumerator to be a gs_show_enum *, which the current
 * implementation code requires.
 */
static int
show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, gs_text_enum_t *pte)
{
    if (code < 0)
	return code;
    if (gs_object_type(pgs->memory, pte) != &st_gs_show_enum) {
	/* Use the default implementation. */
	gx_device *dev = pgs->device;
	gs_text_params_t text;
	gs_memory_t *mem = pte->memory;
	dev_proc_text_begin((*text_begin)) = dev_proc(dev, text_begin);

	text = pte->text;
	gs_text_release(pte, "show_n_begin");
	/* Temporarily reset the text_begin procedure to the default. */
	set_dev_proc(dev, text_begin, gx_default_text_begin);
	code = gs_text_begin(pgs, &text, mem, &pte);
	set_dev_proc(dev, text_begin, text_begin);
	if (code < 0)
	    return code;
    }
    /* Now we know pte points to a gs_show_enum. */
    *penum = *(gs_show_enum *)pte;
    gs_free_object(pgs->memory, pte, "show_n_begin");
    return code;
}
Exemplo n.º 3
0
/* <obj> <typenames> .type <name> */
static int
ztype(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    ref tnref;
    int code = array_get(imemory, op, (long)r_btype(op - 1), &tnref);

    if (code < 0)
	return code;
    if (!r_has_type(&tnref, t_name)) {
	/* Must be either a stack underflow or a t_[a]struct. */
	check_op(2);
	{			/* Get the type name from the structure. */
	    const char *sname =
		gs_struct_type_name_string(gs_object_type(imemory,
							  op[-1].value.pstruct));
	    int code = name_ref(imemory, (const byte *)sname, strlen(sname),
				(ref *) (op - 1), 0);

	    if (code < 0)
		return code;
	}
	r_set_attrs(op - 1, a_executable);
    } else {
	ref_assign(op - 1, &tnref);
    }
    pop(1);
    return 0;
}
Exemplo n.º 4
0
/*
 * Get graphics state pointer (from imager state pointer)
 */
const gs_state * gx_hld_get_gstate_ptr(const gs_imager_state * pis)
{
    extern_st(st_gs_state);		/* only for testing */

    /* Check to verify the structure type is really st_gs_state */
    if (pis == NULL || gs_object_type(pis->memory, pis) != &st_gs_state)
	return NULL;

    return (const gs_state *) pis;
}
Exemplo n.º 5
0
/* <string> <index> <int> put - */
static int
zput(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr op1 = op - 1;
    os_ptr op2 = op1 - 1;
    byte *sdata;
    uint ssize;

    switch (r_type(op2)) {
	case t_dictionary:
	    if (i_ctx_p->in_superexec == 0)
		check_dict_write(*op2);
	    {
		int code = idict_put(op2, op1, op);

		if (code < 0)
		    return code;	/* error */
	    }
	    break;
	case t_array:
	    check_write(*op2);
	    check_int_ltu(*op1, r_size(op2));
	    store_check_dest(op2, op);
	    {
		ref *eltp = op2->value.refs + (uint) op1->value.intval;

		ref_assign_old(op2, eltp, op, "put");
	    }
	    break;
	case t_mixedarray:	/* packed arrays are read-only */
	case t_shortarray:
	    return_error(e_invalidaccess);
	case t_string:
	    sdata = op2->value.bytes;
	    ssize = r_size(op2);
str:	    check_write(*op2);
	    check_int_ltu(*op1, ssize);
	    check_int_leu(*op, 0xff);
	    sdata[(uint)op1->value.intval] = (byte)op->value.intval;
	    break;
	case t_astruct:
	    if (gs_object_type(imemory, op2->value.pstruct) != &st_bytes)
		return_error(e_typecheck);
	    sdata = r_ptr(op2, byte);
	    ssize = gs_object_size(imemory, op2->value.pstruct);
	    goto str;
	default:
	    return_op_typecheck(op2);
    }
    pop(3);
    return 0;
}
Exemplo n.º 6
0
/* r_size(op1) was set just above. */
static int
do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1)
{
    os_ptr op = osp;
    ref *arefs = op1->value.refs;
    uint asize = r_size(op1);
    uint i;
    ref *rq;

    /*
     * Copy elements from the stack to the array,
     * optionally skipping executable nulls.
     * Clear the executable bit in any internal operators, and
     * convert t_structs and t_astructs (which can only appear
     * in connection with stack marks, which means that they will
     * probably be freed when unwinding) to something harmless.
     */
    for (i = 0, rq = arefs + asize; rq != arefs; ++i) {
        const ref *rp = ref_stack_index(&e_stack, (long)i);

        if (r_has_type_attrs(rp, t_null, a_executable) && !include_marks)
            continue;
        --rq;
        ref_assign_old(op1, rq, rp, "execstack");
        switch (r_type(rq)) {
            case t_operator: {
                uint opidx = op_index(rq);

                if (opidx == 0 || op_def_is_internal(op_index_def(opidx)))
                    r_clear_attrs(rq, a_executable);
                break;
            }
            case t_struct:
            case t_astruct: {
                const char *tname = rq->value.pstruct ?
                    gs_struct_type_name_string(
                                gs_object_type(imemory, rq->value.pstruct))
                    : "NULL";

                make_const_string(rq, a_readonly | avm_foreign,
                                  strlen(tname), (const byte *)tname);
                break;
            }
            default:
                ;
        }
    }
    pop(op - op1);
    return 0;
}
Exemplo n.º 7
0
/* BitsPerSample. */
static int
dict_threshold2_params(const ref * pdict, gs_threshold2_halftone * ptp,
		       ref * ptproc, gs_memory_t *mem)
{
    ref *tstring;
    int code =
	dict_threshold_common_params(pdict,
				     (gs_threshold_halftone_common *)ptp,
				     &tstring, ptproc);
    int bps;
    uint size;
    int cw2, ch2;

    if (code < 0 ||
	(code = cw2 = dict_int_param(pdict, "Width2", 0, 0x7fff, 0,
				     &ptp->width2)) < 0 ||
	(code = ch2 = dict_int_param(pdict, "Height2", 0, 0x7fff, 0,
				     &ptp->height2)) < 0 ||
	(code = dict_int_param(pdict, "BitsPerSample", 8, 16, -1, &bps)) < 0
	)
	return code;
    if ((bps != 8 && bps != 16) || cw2 != ch2 ||
	(!cw2 && (ptp->width2 == 0 || ptp->height2 == 0))
	)
	return_error(e_rangecheck);
    ptp->bytes_per_sample = bps / 8;
    switch (r_type(tstring)) {
    case t_string:
	size = r_size(tstring);
	gs_bytestring_from_string(&ptp->thresholds, tstring->value.const_bytes,
				  size);
	break;
    case t_astruct:
	if (gs_object_type(mem, tstring->value.pstruct) != &st_bytes)
	    return_error(e_typecheck);
	size = gs_object_size(mem, tstring->value.pstruct);
	gs_bytestring_from_bytes(&ptp->thresholds, r_ptr(tstring, byte),
				 0, size);
	break;
    default:
	return_error(e_typecheck);
    }
    check_read(*tstring);
    if (size != (ptp->width * ptp->height + ptp->width2 * ptp->height2) *
	ptp->bytes_per_sample)
	return_error(e_rangecheck);
    return 0;
}
Exemplo n.º 8
0
/* <bytestring1> <index> <string2> putinterval - */
static int
zputinterval(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr opindex = op - 1;
    os_ptr opto = opindex - 1;
    int code;

    switch (r_type(opto)) {
	default:
            return_error(e_typecheck);
        case t__invalid:
            if (r_type(op) != t_array && r_type(op) != t_string && r_type(op) != t__invalid)
                return_error(e_typecheck); /* to match Distiller */
            else
                return_error(e_stackunderflow);
	case t_mixedarray:
	case t_shortarray:
	    return_error(e_invalidaccess);
	case t_array:
	case t_string:
	    check_write(*opto);
	    check_int_leu(*opindex, r_size(opto));
	    code = copy_interval(i_ctx_p, opto, (uint)(opindex->value.intval),
				 op, "putinterval");
	    break;
	case t_astruct: {
	    uint dsize, ssize, index;

	    check_write(*opto);
	    if (gs_object_type(imemory, opto->value.pstruct) != &st_bytes)
		return_error(e_typecheck);
	    dsize = gs_object_size(imemory, opto->value.pstruct);
	    check_int_leu(*opindex, dsize);
	    index = (uint)opindex->value.intval;
	    check_read_type(*op, t_string);
	    ssize = r_size(op);
	    if (ssize > dsize - index)
		return_error(e_rangecheck);
	    memcpy(r_ptr(opto, byte) + index, op->value.const_bytes, ssize);
	    code = 0;
	    break;
	}
    }
    if (code >= 0)
	pop(3);
    return code;
}
Exemplo n.º 9
0
/* Read a string value. */
static int
ref_param_read_string_value(gs_memory_t *mem, const iparam_loc * ploc, gs_param_string * pvalue)
{
    const ref *pref = ploc->pvalue;

    switch (r_type(pref)) {
	case t_name: {
	    ref nref;

	    name_string_ref(mem, pref, &nref);
	    pvalue->data = nref.value.const_bytes;
	    pvalue->size = r_size(&nref);
	    pvalue->persistent = true;
	}
	    break;
	case t_string:
	    iparam_check_read(*ploc);
	    pvalue->data = pref->value.const_bytes;
	    pvalue->size = r_size(pref);
	    pvalue->persistent = false;
	    break;
	case t_astruct:
	    /* Note: technically, instead of the "mem" argument, we
	       should be using the plists's ref_memory. However, in a
	       simple call to .putdeviceparams, they are identical. */
	    iparam_check_read(*ploc);
	    if (gs_object_type(mem, pref->value.pstruct) != &st_bytes) 
		return iparam_note_error(*ploc, e_typecheck);
	    pvalue->data = r_ptr(pref, byte);
	    pvalue->size = gs_object_size(mem, pref->value.pstruct);
	    pvalue->persistent = false;
	    break;
	default:
	    return iparam_note_error(*ploc, e_typecheck);
    }
    return 0;
}
Exemplo n.º 10
0
static int
zreusablestream(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr source_op = op - 1;
    long length = max_long;
    bool close_source;
    int code;

    check_type(*op, t_boolean);
    close_source = op->value.boolval;
    if (r_has_type(source_op, t_string)) {
        uint size = r_size(source_op);

        check_read(*source_op);
        code = make_rss(i_ctx_p, source_op, source_op->value.const_bytes,
                        size, r_space(source_op), 0L, size, false);
    } else if (r_has_type(source_op, t_astruct)) {
        uint size = gs_object_size(imemory, source_op->value.pstruct);

        if (gs_object_type(imemory, source_op->value.pstruct) != &st_bytes)
            return_error(e_rangecheck);
        check_read(*source_op);
        code = make_rss(i_ctx_p, source_op,
                        (const byte *)source_op->value.pstruct, size,
                        r_space(source_op), 0L, size, true);
    } else if (r_has_type(source_op, t_array)) {  /* no packedarrays */
        int i, blk_cnt, blk_sz;
        ref *blk_ref;
        ulong filelen = 0;

        check_read(*source_op);
        blk_cnt = r_size(source_op);
        blk_ref = source_op->value.refs;
        if (blk_cnt > 0) {
            blk_sz = r_size(blk_ref);
            for (i = 0; i < blk_cnt; i++) {
                int len;

                check_read_type(blk_ref[i], t_string);
                len = r_size(&blk_ref[i]);
                if (len > blk_sz || (len < blk_sz && i < blk_cnt - 1))
                   return_error(e_rangecheck); /* last block can be smaller */
                filelen += len;
            }
        }
        if (filelen == 0) {
           code = make_rss(i_ctx_p, source_op, (unsigned char *)"", 0,
               r_space(source_op), 0, 0, false);
        } else {
           code = make_aos(i_ctx_p, source_op, blk_sz, r_size(&blk_ref[blk_cnt - 1]), filelen);
        }
    } else {
        long offset = 0;
        stream *source;
        stream *s;

        check_read_file(i_ctx_p, source, source_op);
        s = source;
rs:
        if (s->cbuf_string.data != 0) {	/* string stream */
            long pos = stell(s);
            long avail = sbufavailable(s) + pos;

            offset += pos;
            code = make_rss(i_ctx_p, source_op, s->cbuf_string.data,
                            s->cbuf_string.size,
                            imemory_space((const gs_ref_memory_t *)s->memory),
                            offset, min(avail, length), false);
        } else if (s->file != 0) { /* file stream */
            if (~s->modes & (s_mode_read | s_mode_seek))
                return_error(e_ioerror);
            code = make_rfs(i_ctx_p, source_op, s, offset + stell(s), length);
        } else if (s->state->templat == &s_SFD_template) {
            /* SubFileDecode filter */
            const stream_SFD_state *const sfd_state =
                (const stream_SFD_state *)s->state;

            if (sfd_state->eod.size != 0)
                return_error(e_rangecheck);
            offset += sfd_state->skip_count - sbufavailable(s);
            if (sfd_state->count != 0) {
                long left = max(sfd_state->count, 0) + sbufavailable(s);

                if (left < length)
                    length = left;
            }
            s = s->strm;
            goto rs;
        }
        else			/* some other kind of stream */
            return_error(e_rangecheck);
        if (close_source) {
            stream *rs = fptr(source_op);

            rs->strm = source;	/* only for close_source */
            rs->close_strm = true;
        }
    }
    if (code >= 0)
        pop(1);
    return code;
}
Exemplo n.º 11
0
int
obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
	int full_print, uint start_pos, const gs_memory_t *mem, bool restart)
{
    char buf[50];  /* big enough for any float, double, or struct name */
    const byte *data = (const byte *)buf;
    uint size;
    int code;
    ref nref;

    if (full_print) {
	static const char * const type_strings[] = { REF_TYPE_PRINT_STRINGS };

	switch (r_btype(op)) {
	case t_boolean:
	case t_integer:
	    break;
	case t_real: {
	    /*
	     * To get fully accurate output results for IEEE
	     * single-precision floats (24 bits of mantissa), the ANSI %g
	     * default of 6 digits is not enough; 9 are needed.
	     * Unfortunately, using %.9g for floats (as opposed to doubles)
	     * produces unfortunate artifacts such as 0.01 5 mul printing as
	     * 0.049999997.  Therefore, we print using %g, and if the result
	     * isn't accurate enough, print again using %.9g.
	     * Unfortunately, a few PostScript programs 'know' that the
	     * printed representation of floats fits into 6 digits (e.g.,
	     * with cvs).  We resolve this by letting cvs, cvrs, and = do
	     * what the Adobe interpreters appear to do (use %g), and only
	     * produce accurate output for ==, for which there is no
	     * analogue of cvs.  What a hack!
	     */
	    float value = op->value.realval;
	    float scanned;

	    sprintf(buf, "%g", value);
	    sscanf(buf, "%f", &scanned);
	    if (scanned != value)
		sprintf(buf, "%.9g", value);
	    ensure_dot(buf);
	    goto rs;
	}
	case t_operator:
	case t_oparray:  
	    code = obj_cvp(op, (byte *)buf + 2, sizeof(buf) - 4, &size, 0, 0, mem, restart);
	    if (code < 0) 
		return code;
	    buf[0] = buf[1] = buf[size + 2] = buf[size + 3] = '-';
	    size += 4;
	    goto nl;
	case t_name:	 
	    if (r_has_attr(op, a_executable)) {
		code = obj_string_data(mem, op, &data, &size);
		if (code < 0)
		    return code;
		goto nl;
	    }
	    if (start_pos > 0)
		return obj_cvp(op, str, len, prlen, 0, start_pos - 1, mem, restart);
	    if (len < 1)
		return_error(e_rangecheck);
	    code = obj_cvp(op, str + 1, len - 1, prlen, 0, 0, mem, restart);
	    if (code < 0)
		return code;
	    str[0] = '/';
	    ++*prlen;
	    return code;
	case t_null:
	    data = (const byte *)"null";
	    goto rs;
	case t_string:  
	    if (!r_has_attr(op, a_read))
		goto other;
	    size = r_size(op);
	    {
		bool truncate = (full_print == 1 && size > CVP_MAX_STRING);
		stream_cursor_read r;
		stream_cursor_write w;
		uint skip;
		byte *wstr;
		uint len1;
		int status = 1;

		if (start_pos == 0) {
		    if (len < 1)
			return_error(e_rangecheck);
		    str[0] = '(';
		    skip = 0;
		    wstr = str + 1;
		} else {
		    skip = start_pos - 1;
		    wstr = str;
		}
		len1 = len + (str - wstr);
		r.ptr = op->value.const_bytes - 1;
		r.limit = r.ptr + (truncate ? CVP_MAX_STRING : size);
		while (skip && status == 1) {
		    uint written;

		    w.ptr = (byte *)buf - 1;
		    w.limit = w.ptr + min(skip + len1, sizeof(buf));
		    status = s_PSSE_template.process(NULL, &r, &w, false);
		    written = w.ptr - ((byte *)buf - 1);
		    if (written > skip) {
			written -= skip;
			memcpy(wstr, buf + skip, written);
			wstr += written;
			skip = 0;
			break;
		    }
		    skip -= written;
		}
		/*
		 * We can reach here with status == 0 (and skip != 0) if
		 * start_pos lies within the trailing ")" or  "...)".
		 */
		if (status == 0) {
#ifdef DEBUG
		    if (skip > (truncate ? 4 : 1)) {
			return_error(e_Fatal);
		    }
#endif
		}
		w.ptr = wstr - 1;
		w.limit = str - 1 + len;
		if (status == 1)
		    status = s_PSSE_template.process(NULL, &r, &w, false);
		*prlen = w.ptr - (str - 1);
		if (status != 0)
		    return 1;
		if (truncate) {
		    if (len - *prlen < 4 - skip)
			return 1;
		    memcpy(w.ptr + 1, "...)" + skip, 4 - skip);
		    *prlen += 4 - skip;
		} else {
		    if (len - *prlen < 1 - skip)
			return 1;
		    memcpy(w.ptr + 1, ")" + skip, 1 - skip);
		    *prlen += 1 - skip;
		}
	    }
	    return 0;
	case t_astruct:
	case t_struct:    
	    if (r_is_foreign(op)) {
		/* gs_object_type may not work. */
		data = (const byte *)"-foreign-struct-";
		goto rs;
	    }
	    if (!mem) {
		data = (const byte *)"-(struct)-";
		goto rs;
	    }
	    data = (const byte *)
		gs_struct_type_name_string(
				gs_object_type(mem,
				    (const obj_header_t *)op->value.pstruct));
	    size = strlen((const char *)data);
	    if (size > 4 && !memcmp(data + size - 4, "type", 4))
		size -= 4;
	    if (size > sizeof(buf) - 2)
		return_error(e_rangecheck);
	    buf[0] = '-';
	    memcpy(buf + 1, data, size);
	    buf[size + 1] = '-';
	    size += 2;
	    data = (const byte *)buf;
	    goto nl;
	default:
other:
	    {
		int rtype = r_btype(op);

		if (rtype > countof(type_strings))
		    return_error(e_rangecheck);
		data = (const byte *)type_strings[rtype];
		if (data == 0)
		    return_error(e_rangecheck);
	    }
	    goto rs;
	}
    }	
    /* full_print = 0 */
    switch (r_btype(op)) {
    case t_boolean:
	data = (const byte *)(op->value.boolval ? "true" : "false");
	break;
    case t_integer:
	sprintf(buf, "%ld", op->value.intval);
	break;
    case t_string:
	check_read(*op);
	/* falls through */
    case t_name:
	code = obj_string_data(mem, op, &data, &size);
	if (code < 0)
	    return code;
	goto nl;
    case t_oparray: {
	uint index = op_index(op);
	const op_array_table *opt = op_index_op_array_table(index);

	name_index_ref(mem, opt->nx_table[index - opt->base_index], &nref);
	name_string_ref(mem, &nref, &nref);
	code = obj_string_data(mem, &nref, &data, &size);
	if (code < 0)
	    return code;
	goto nl;
    }
    case t_operator: {
	/* Recover the name from the initialization table. */
	uint index = op_index(op);

	/*
	 * Check the validity of the index.  (An out-of-bounds index
	 * is only possible when examining an invalid object using
	 * the debugger.)
	 */
	if (index > 0 && index < op_def_count) {
	    data = (const byte *)(op_index_def(index)->oname + 1);
	    break;
	}
	/* Internal operator, no name. */
	sprintf(buf, "@0x%lx", (ulong) op->value.opproc);
	break;
    }
    case t_real:
	/*
	 * The value 0.0001 is a boundary case that the Adobe interpreters
	 * print in f-format but at least some gs versions print in
	 * e-format, presumably because of differences in the underlying C
	 * library implementation.  Work around this here.
	 */
	if (op->value.realval == (float)0.0001) {
	    strcpy(buf, "0.0001");
	} else {
	    sprintf(buf, "%g", op->value.realval);
	}
	ensure_dot(buf);
	break;
    default:
	data = (const byte *)"--nostringval--";
    }
rs: size = strlen((const char *)data);
nl: if (size < start_pos)
	return_error(e_rangecheck);
    if (!restart && size > len)
	return_error(e_rangecheck);
    size -= start_pos;
    *prlen = min(size, len);
    memmove(str, data + start_pos, *prlen);
    return (size > len);
}