blob: 3da400c8635740054fa3e31f9cbaa1cf5d5d63ce [file] [log] [blame]
/*
* *****************************************************************************
*
* Copyright 2018 Gavin D. Howard
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* *****************************************************************************
*
* Code to manipulate data structures in programs.
*
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <lang.h>
BcStatus bc_func_insert(BcFunc *f, char *name, bool var) {
BcAuto a;
size_t i;
assert(f && name);
for (i = 0; i < f->autos.len; ++i) {
if (!strcmp(name, ((BcAuto*) bc_vec_item(&f->autos, i))->name))
return BC_STATUS_PARSE_DUPLICATE_LOCAL;
}
a.var = var;
a.name = name;
return bc_vec_push(&f->autos, 1, &a);
}
BcStatus bc_func_init(BcFunc *f) {
BcStatus status;
assert(f);
if ((status = bc_vec_init(&f->code, sizeof(uint8_t), NULL))) return status;
if ((status = bc_vec_init(&f->autos, sizeof(BcAuto), bc_auto_free))) goto err;
if ((status = bc_vec_init(&f->labels, sizeof(size_t), NULL))) goto label_err;
f->nparams = 0;
return BC_STATUS_SUCCESS;
label_err:
bc_vec_free(&f->autos);
err:
bc_vec_free(&f->code);
return status;
}
void bc_func_free(void *func) {
BcFunc *f = (BcFunc*) func;
assert(f);
bc_vec_free(&f->code);
bc_vec_free(&f->autos);
bc_vec_free(&f->labels);
}
BcStatus bc_array_copy(BcVec *d, BcVec *s) {
BcStatus status;
size_t i;
assert(d && s && d != s && d->size == s->size && d->dtor == s->dtor);
bc_vec_npop(d, d->len);
if ((status = bc_vec_expand(d, s->cap))) return status;
d->len = s->len;
for (i = 0; !status && i < s->len; ++i) {
BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
if ((status = bc_num_init(dnum, snum->len))) return status;
if ((status = bc_num_copy(dnum, snum))) bc_num_free(dnum);
}
return status;
}
BcStatus bc_array_expand(BcVec *a, size_t len) {
BcStatus status = BC_STATUS_SUCCESS;
BcNum num;
while (!status && len > a->len) {
if ((status = bc_num_init(&num, BC_NUM_DEF_SIZE))) return status;
bc_num_zero(&num);
if ((status = bc_vec_push(a, 1, &num))) bc_num_free(&num);
}
return status;
}
void bc_string_free(void *string) {
char **s = string;
assert(s && *s);
free(*s);
}
int bc_entry_cmp(const void *e1, const void *e2) {
return strcmp(((const BcEntry*) e1)->name, ((const BcEntry*) e2)->name);
}
void bc_entry_free(void *entry) {
BcEntry *e = entry;
assert(e && e->name);
free(e->name);
}
void bc_auto_free(void *auto1) {
BcAuto *a = (BcAuto*) auto1;
assert(a && a->name);
free(a->name);
}
void bc_result_free(void *result) {
BcResult *r = (BcResult*) result;
assert(r);
switch (r->type) {
case BC_RESULT_TEMP:
case BC_RESULT_SCALE:
case BC_RESULT_VAR_AUTO:
{
bc_num_free(&r->data.num);
break;
}
case BC_RESULT_ARRAY_AUTO:
{
bc_vec_free(&r->data.array);
break;
}
case BC_RESULT_VAR:
case BC_RESULT_ARRAY:
case BC_RESULT_ARRAY_ELEM:
{
assert(r->data.id.name);
free(r->data.id.name);
break;
}
default:
{
// Do nothing.
break;
}
}
}