예제 #1
0
csi_status_t
_csi_stack_grow (csi_t *ctx, csi_stack_t *stack, csi_integer_t cnt)
{
    csi_integer_t newsize;
    csi_object_t *newstack;

    if (_csi_likely (cnt <= stack->size))
	return CSI_STATUS_SUCCESS;
    if (_csi_unlikely ((unsigned) cnt >= INT_MAX / sizeof (csi_object_t)))
	return _csi_error (CSI_STATUS_NO_MEMORY);

    newsize = stack->size;
    do {
	newsize *= 2;
    } while (newsize <= cnt);

    newstack = _csi_realloc (ctx,
			     stack->objects,
			     newsize * sizeof (csi_object_t));
    if (_csi_unlikely (newstack == NULL))
	return _csi_error (CSI_STATUS_NO_MEMORY);

    stack->objects = newstack;
    stack->size  = newsize;

    return CSI_STATUS_SUCCESS;
}
void *
_csi_perm_alloc (csi_t *ctx, int size)
{
    csi_chunk_t *chunk;
    void *ptr;

    size = (size + sizeof (void *)-1) & -sizeof (void *);

    chunk = ctx->perm_chunk;
    if (chunk == NULL || chunk->rem < size) {
	int chunk_size = (size + 8191) & -8192;
	chunk = _csi_alloc (ctx, sizeof (csi_chunk_t) + chunk_size);
	if (_csi_unlikely (chunk == NULL))
	    return NULL;

	chunk->rem = chunk_size;
	chunk->ptr = (char *) (chunk + 1);
	chunk->next = ctx->perm_chunk;
	ctx->perm_chunk = chunk;
    }

    ptr = chunk->ptr;
    chunk->ptr += size;
    chunk->rem -= size;

    return ptr;
}
csi_status_t
_csi_intern_string (csi_t *ctx, const char **str_inout, int len)
{
    char *str = (char *) *str_inout;
    csi_intern_string_t tmpl, *istring;
    csi_status_t status = CSI_STATUS_SUCCESS;

    tmpl.hash_entry.hash = _intern_string_hash (str, len);
    tmpl.len = len;
    tmpl.string = (char *) str;

    istring = _csi_hash_table_lookup (&ctx->strings, &tmpl.hash_entry);
    if (istring == NULL) {
	istring = _csi_perm_alloc (ctx,
				   sizeof (csi_intern_string_t) + len + 1);
	if (istring != NULL) {
	    istring->hash_entry.hash = tmpl.hash_entry.hash;
	    istring->len = tmpl.len;
	    istring->string = (char *) (istring + 1);
	    memcpy (istring->string, str, len);
	    istring->string[len] = '\0';

	    status = _csi_hash_table_insert (&ctx->strings,
					     &istring->hash_entry);
	    if (_csi_unlikely (status)) {
		_csi_free (ctx, istring);
		return status;
	    }
	} else
	    return _csi_error (CSI_STATUS_NO_MEMORY);
    }

    *str_inout = istring->string;
    return CSI_STATUS_SUCCESS;
}
예제 #4
0
csi_object_t *
_csi_stack_peek (csi_stack_t *stack, csi_integer_t i)
{
    if (_csi_unlikely (stack->len < i))
	return NULL;

    return &stack->objects[stack->len - i -1];
}
void
_csi_free (csi_t *ctx, void *ptr)
{
    if (_csi_unlikely (ptr == NULL))
	return;

    free (ptr);
}
예제 #6
0
void
_csi_stack_pop (csi_t *ctx, csi_stack_t *stack, csi_integer_t count)
{
    if (_csi_unlikely (stack->len < count))
	count = stack->len;

    while (count--)
	csi_object_free (ctx, &stack->objects[--stack->len]);
}
예제 #7
0
csi_status_t
_csi_stack_roll (csi_t *ctx,
		 csi_stack_t *stack,
		 csi_integer_t mod, csi_integer_t n)
{
    csi_object_t stack_copy[128];
    csi_object_t *copy;
    csi_integer_t last, i, len;

    switch (mod) { /* special cases */
    case 1:
	last = stack->len - 1;
	stack_copy[0] = stack->objects[last];
	for (i = last; --n; i--)
	    stack->objects[i] = stack->objects[i-1];
	stack->objects[i] = stack_copy[0];
	return CSI_STATUS_SUCCESS;
    case -1:
	last = stack->len - 1;
	stack_copy[0] = stack->objects[i = last - n + 1];
	for (; --n; i++)
	    stack->objects[i] = stack->objects[i+1];
	stack->objects[i] = stack_copy[0];
	return CSI_STATUS_SUCCESS;
    }

    /* fall back to a copy */
    if (n > ARRAY_LENGTH (stack_copy)) {
	if (_csi_unlikely ((unsigned) n > INT_MAX / sizeof (csi_object_t)))
	    return _csi_error (CSI_STATUS_NO_MEMORY);
	copy = _csi_alloc (ctx, n * sizeof (csi_object_t));
	if (copy == NULL)
	    return _csi_error (CSI_STATUS_NO_MEMORY);
    } else
	copy = stack_copy;

    i = stack->len - n;
    memcpy (copy, stack->objects + i, n * sizeof (csi_object_t));
    mod = -mod;
    if (mod < 0)
	mod += n;
    last = mod;
    for (len = n; n--; i++) {
	stack->objects[i] = copy[last];
	if (++last == len)
	    last = 0;
    }

    if (copy != stack_copy)
	_csi_free (ctx, copy);

    return CSI_STATUS_SUCCESS;
}
예제 #8
0
csi_status_t
_csi_stack_push_internal (csi_t *ctx, csi_stack_t *stack,
			  const csi_object_t *obj)
{
    csi_status_t status;

    status = _csi_stack_grow (ctx, stack, stack->size + 1);
    if (_csi_unlikely (status))
	return status;

    stack->objects[stack->len++] = *obj;
    return CSI_STATUS_SUCCESS;
}
예제 #9
0
csi_status_t
_csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size)
{
    csi_status_t status = CSI_STATUS_SUCCESS;

    stack->len = 0;
    stack->size = size;
    /* assert ((unsigned) size < INT_MAX / sizeof (csi_object_t)); */
    stack->objects = _csi_alloc (ctx, size * sizeof (csi_object_t));
    if (_csi_unlikely (stack->objects == NULL))
	status = _csi_error (CSI_STATUS_NO_MEMORY);

    return status;
}
예제 #10
0
void
_csi_slab_free (csi_t *ctx, void *ptr, int size)
{
    int chunk_size;
    void **free_list;

    if (_csi_unlikely (ptr == NULL))
	return;

    chunk_size = 2 * sizeof (void *);
    chunk_size = (size + chunk_size - 1) / chunk_size;

    free_list = ptr;
    *free_list = ctx->slabs[chunk_size].free_list;
    ctx->slabs[chunk_size].free_list = ptr;
}
예제 #11
0
csi_status_t
_csi_stack_exch (csi_stack_t *stack)
{
    csi_object_t tmp;
    csi_integer_t n;

    if (_csi_unlikely (stack->len < 2))
	return _csi_error (CSI_STATUS_INVALID_SCRIPT);

    n = stack->len - 1;
    tmp = stack->objects[n];
    stack->objects[n] = stack->objects[n - 1];
    stack->objects[n - 1] = tmp;

    return CSI_STATUS_SUCCESS;
}
void *
_csi_slab_alloc (csi_t *ctx, int size)
{
#if CSI_DEBUG_MALLOC
    return malloc (size);
#else
    int chunk_size;
    csi_chunk_t *chunk;
    void *ptr;

    chunk_size = 2 * sizeof (void *);
    chunk_size = (size + chunk_size - 1) / chunk_size;

    if (ctx->slabs[chunk_size].free_list) {
	ptr = ctx->slabs[chunk_size].free_list;
	ctx->slabs[chunk_size].free_list = *(void **) ptr;
	return ptr;
    }

    chunk = ctx->slabs[chunk_size].chunk;
    if (chunk == NULL || ! chunk->rem) {
	int cnt = MAX (128, 8192 / (chunk_size * 2 * sizeof (void *)));

	chunk = _csi_alloc (ctx,
			    sizeof (csi_chunk_t) +
			    cnt * chunk_size * 2 * sizeof (void *));
	if (_csi_unlikely (chunk == NULL))
	    return NULL;

	chunk->rem = cnt;
	chunk->ptr = (char *) (chunk + 1);
	chunk->next = ctx->slabs[chunk_size].chunk;
	ctx->slabs[chunk_size].chunk = chunk;
    }

    ptr = chunk->ptr;
    chunk->ptr += chunk_size * 2 * sizeof (void *);
    chunk->rem--;

    return ptr;
#endif
}
void
_csi_slab_free (csi_t *ctx, void *ptr, int size)
{
    int chunk_size;
    void **free_list;

    if (_csi_unlikely (ptr == NULL))
	return;

#if CSI_DEBUG_MALLOC
    free (ptr);
#else
    chunk_size = 2 * sizeof (void *);
    chunk_size = (size + chunk_size - 1) / chunk_size;

    free_list = ptr;
    *free_list = ctx->slabs[chunk_size].free_list;
    ctx->slabs[chunk_size].free_list = ptr;
#endif
}
예제 #14
0
/**
 * _csi_hash_table_insert:
 * @hash_table: a hash table
 * @key_and_value: an entry to be inserted
 *
 * Insert the entry #key_and_value into the hash table.
 *
 * WARNING: There must not be an existing entry in the hash table
 * with a matching key.
 *
 * WARNING: It is a fatal error to insert an element while
 * an iterator is running
 *
 * Instead of using insert to replace an entry, consider just editing
 * the entry obtained with _csi_hash_table_lookup. Or if absolutely
 * necessary, use _csi_hash_table_remove first.
 *
 * Return value: %CAIRO_STATUS_SUCCESS if successful or
 * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
 **/
csi_status_t
_csi_hash_table_insert (csi_hash_table_t *hash_table,
			  csi_hash_entry_t *key_and_value)
{
    csi_status_t status;
    csi_hash_entry_t **entry;

    hash_table->live_entries++;
    status = _csi_hash_table_manage (hash_table);
    if (_csi_unlikely (status)) {
	/* abort the insert... */
	hash_table->live_entries--;
	return status;
    }

    entry = _csi_hash_table_lookup_unique_key (hash_table,
					       key_and_value);
    if (ENTRY_IS_FREE (*entry))
	hash_table->used_entries++;

    *entry = key_and_value;
    return CAIRO_STATUS_SUCCESS;
}
예제 #15
0
static csi_status_t
_init_dictionaries (csi_t *ctx)
{
    csi_status_t status;
    csi_stack_t *stack;
    csi_object_t obj;
    csi_dictionary_t *dict;
    const csi_operator_def_t *odef;
    const csi_integer_constant_def_t *idef;
    const csi_real_constant_def_t *rdef;

    stack = &ctx->dstack;

    status = _csi_stack_init (ctx, stack, 4);
    if (_csi_unlikely (status))
	return status;

    /* systemdict */
    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;

    status = _csi_stack_push (ctx, stack, &obj);
    if (_csi_unlikely (status))
	return status;

    dict = obj.datum.dictionary;

    /* fill systemdict with operators */
    for (odef = _csi_operators (); odef->name != NULL; odef++) {
	status = _add_operator (ctx, dict, odef);
	if (_csi_unlikely (status))
	    return status;
    }

    /* add constants */
    for (idef = _csi_integer_constants (); idef->name != NULL; idef++) {
	status = _add_integer_constant (ctx, dict, idef);
	if (_csi_unlikely (status))
	    return status;
    }
    for (rdef = _csi_real_constants (); rdef->name != NULL; rdef++) {
	status = _add_real_constant (ctx, dict, rdef);
	if (_csi_unlikely (status))
	    return status;
    }

    /* and seal */
    //dict.type &= ~CSI_OBJECT_ATTR_WRITABLE;


    /* globaldict */
    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;
    status = _csi_stack_push (ctx, stack, &obj);
    if (_csi_unlikely (status))
	return status;

    /* userdict */
    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;
    status = _csi_stack_push (ctx, stack, &obj);
    if (_csi_unlikely (status))
	return status;

    return CSI_STATUS_SUCCESS;
}
예제 #16
0
csi_status_t
csi_file_new_from_string (csi_t *ctx,
			  csi_object_t *obj,
			  csi_string_t *src)
{
    csi_file_t *file;

    file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
    if (_csi_unlikely (file == NULL))
	return _csi_error (CAIRO_STATUS_NO_MEMORY);

    file->base.type = CSI_OBJECT_TYPE_FILE;
    file->base.ref = 1;

    if (src->deflate) {
	uLongf len = src->deflate;
	csi_object_t tmp_obj;
	csi_string_t *tmp_str;
	csi_status_t status;

	status = csi_string_new (ctx, &tmp_obj,  NULL, src->deflate);
	if (_csi_unlikely (status))
	    return status;

	tmp_str = tmp_obj.datum.string;
	switch (src->method) {
	case NONE:
	default:
	    status = _csi_error (CAIRO_STATUS_NO_MEMORY);
	    break;

	case ZLIB:
#if HAVE_ZLIB
	    if (uncompress ((Bytef *) tmp_str->string, &len,
			    (Bytef *) src->string, src->len) != Z_OK)
#endif
		status = _csi_error (CAIRO_STATUS_NO_MEMORY);
	    break;
	case LZO:
#if HAVE_LZO
	    if (lzo2a_decompress ((lzo_bytep) src->string, src->len,
				  (lzo_bytep) tmp_str->string, &len,
				  NULL))
#endif
		status = _csi_error (CAIRO_STATUS_NO_MEMORY);
	    break;
	}
	if (_csi_unlikely (status)) {
	    csi_string_free (ctx, tmp_str);
	    _csi_slab_free (ctx, file, sizeof (csi_file_t));
	    return status;
	}

	file->src  = tmp_str;
	file->data = tmp_str->string;
	file->rem  = tmp_str->len;
    } else {
	file->src  = src; src->base.ref++;
	file->data = src->string;
	file->rem  = src->len;
    }
    file->type = BYTES;
    file->bp   = file->data;

    obj->type = CSI_OBJECT_TYPE_FILE;
    obj->datum.file = file;
    return CAIRO_STATUS_SUCCESS;
}
static csi_status_t
_init_dictionaries (csi_t *ctx)
{
    csi_status_t status;
    csi_stack_t *stack;
    csi_object_t obj;
    csi_dictionary_t *dict, *opcodes;
    const csi_operator_def_t *odef;
    const csi_integer_constant_def_t *idef;
    const csi_real_constant_def_t *rdef;
    unsigned n;

    stack = &ctx->dstack;

    status = _csi_stack_init (ctx, stack, 4);
    if (_csi_unlikely (status))
	return status;

    /* systemdict */
    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;

    status = _csi_stack_push (ctx, stack, &obj);
    if (_csi_unlikely (status))
	return status;

    dict = obj.datum.dictionary;

    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;

    opcodes = obj.datum.dictionary;

    n = 0;
    csi_integer_new (&obj, n);
    status = csi_dictionary_put (ctx, opcodes, 0, &obj);
    if (_csi_unlikely (status))
	return status;
    ctx->opcode[n++] = NULL;

    /* fill systemdict with operators */
    for (odef = _csi_operators (); odef->name != NULL; odef++) {
	status = _add_operator (ctx, dict, odef);
	if (_csi_unlikely (status))
	    return status;

	if (! csi_dictionary_has (opcodes, (csi_name_t) odef->op)) {
	    csi_integer_new (&obj, n);
	    status = csi_dictionary_put (ctx,
		                         opcodes, (csi_name_t) odef->op, &obj);
	    if (_csi_unlikely (status))
		return status;

	    assert (n < sizeof (ctx->opcode) / sizeof (ctx->opcode[0]));
	    ctx->opcode[n++] = odef->op;
	}
    }
    csi_dictionary_free (ctx, opcodes);

    /* add constants */
    for (idef = _csi_integer_constants (); idef->name != NULL; idef++) {
	status = _add_integer_constant (ctx, dict, idef);
	if (_csi_unlikely (status))
	    return status;
    }
    for (rdef = _csi_real_constants (); rdef->name != NULL; rdef++) {
	status = _add_real_constant (ctx, dict, rdef);
	if (_csi_unlikely (status))
	    return status;
    }

    /* and seal */
    //dict.type &= ~CSI_OBJECT_ATTR_WRITABLE;


    /* globaldict */
    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;
    status = _csi_stack_push (ctx, stack, &obj);
    if (_csi_unlikely (status))
	return status;

    /* userdict */
    status = csi_dictionary_new (ctx, &obj);
    if (_csi_unlikely (status))
	return status;
    status = _csi_stack_push (ctx, stack, &obj);
    if (_csi_unlikely (status))
	return status;

    return CSI_STATUS_SUCCESS;
}