/*
 *  Insert a jump offset at 'offset' to complete an instruction
 *  (the jump offset is always the last component of an instruction).
 *  The 'skip' argument must be computed relative to 'offset',
 *  -without- taking into account the skip field being inserted.
 *
 *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
 *   =>  ... A B C ins SKIP X Y Z
 *
 *  Computing the final (adjusted) skip value, which is relative to the
 *  first byte of the next instruction, is a bit tricky because of the
 *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
 */
DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
    duk_small_int_t len;

    /* XXX: solve into closed form (smaller code) */

    if (skip < 0) {
        /* two encoding attempts suffices */
        len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
        len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
        DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
        skip -= (duk_int32_t) len;
    }
    return duk__insert_i32(re_ctx, offset, skip);
}
/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
 * maximum size.
 */
DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
    duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
    duk_small_int_t len;

    len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
    DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
    return (duk_uint32_t) len;
}

DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
    duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
    duk_small_int_t len;

    len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
    DUK_BW_WRITE_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, buf, len);
    return (duk_uint32_t) len;
}

DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
    return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
}

#if 0  /* unused */
DUK_LOCAL duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
    return duk__append_u32(re_ctx, duk__encode_i32(x));
}
示例#3
0
/*
 *  Insert a jump offset at 'offset' to complete an instruction
 *  (the jump offset is always the last component of an instruction).
 *  The 'skip' argument must be computed relative to 'offset',
 *  -without- taking into account the skip field being inserted.
 *
 *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
 *   =>  ... A B C ins SKIP X Y Z
 *
 *  Computing the final (adjusted) skip value, which is relative to the
 *  first byte of the next instruction, is a bit tricky because of the
 *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
 */
DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
#if 0
	/* Iterative solution. */
	if (skip < 0) {
		duk_small_int_t len;
		/* two encoding attempts suffices */
		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
		skip -= (duk_int32_t) len;
	}
#endif

#if defined(DUK_USE_PREFER_SIZE)
	/* Closed form solution, this produces smallest code.
	 * See re_neg_jump_offset (closed2).
	 */
	if (skip < 0) {
		skip--;
		if (skip < -0x3fL) {
			skip--;
		}
		if (skip < -0x3ffL) {
			skip--;
		}
		if (skip < -0x7fffL) {
			skip--;
		}
		if (skip < -0xfffffL) {
			skip--;
		}
		if (skip < -0x1ffffffL) {
			skip--;
		}
		if (skip < -0x3fffffffL) {
			skip--;
		}
	}
#else  /* DUK_USE_PREFER_SIZE */
	/* Closed form solution, this produces fastest code.
	 * See re_neg_jump_offset (closed1).
	 */
	if (skip < 0) {
		if (skip >= -0x3eL) {
			skip -= 1;
		} else if (skip >= -0x3fdL) {
			skip -= 2;
		} else if (skip >= -0x7ffcL) {
			skip -= 3;
		} else if (skip >= -0xffffbL) {
			skip -= 4;
		} else if (skip >= -0x1fffffaL) {
			skip -= 5;
		} else if (skip >= -0x3ffffff9L) {
			skip -= 6;
		} else {
			skip -= 7;
		}
	}
#endif  /* DUK_USE_PREFER_SIZE */

	return duk__insert_i32(re_ctx, offset, skip);
}
DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
    return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
}
示例#5
0
/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
 * maximum size.
 */
DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
	duk_small_int_t len;

	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
	return (duk_uint32_t) len;
}

DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
}

DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
#if defined(DUK_USE_PREFER_SIZE)
	duk__append_u32(re_ctx, x);
#else
	DUK_ASSERT(x <= 0x7fU);
	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
#endif
}

#if 0
DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
}
#endif

DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
}

DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
	DUK_ASSERT(reop <= 0x7fU);
	(void) duk__append_7bit(re_ctx, reop);
}

#if 0  /* unused */
DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
	duk__append_u32(re_ctx, duk__encode_i32(x));
}