/********************************************
da_bin.c
libmawk binary dump (C) 2012, Tibor 'Igor2' Palinkas;
losely based on mawk code coming with the below copyright:
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
#include "mawk.h"
#include "code.h"
#include "bi_funct.h"
#include "repl.h"
#include "field.h"
#include "num.h"
#include "fin.h"
#include "vars.h"
#include "f2d.h"
#include <string.h>
typedef long int da_word;
/* for load sanity checks declare large maximums; without these a malformed
binary may cause libmawk to allocate a lot of memory */
#define MEG (1024*1024)
#define BIN_CODE_MAXLEN 64*MEG
#define BIN_NAME_MAXLEN 1024
#define BIN_MAXVARS 1024*1024
#define BIN_MAXSTRS BIN_MAXVARS
#define BIN_FILEVER 1
/* SAVE:
- code
- constant nums
- constant str
- funtion names and pointers (including builtins!)
(->repl is not saved; regex's are recompiled since regex compiler needs
to be in the binary for runtime purposes anyway - save them as string)
*/
static int safe_strcmp(const char *s1, const char *s2)
{
if ((s1 == NULL) && (s2 == NULL))
return 0;
if ((s1 == NULL) || (s2 == NULL))
return 1;
return strcmp(s1, s2);
}
static int safe_strlen(const char *s)
{
if (s == NULL)
return 0;
return strlen(s);
}
static mawk_string_t *safe_new_STRING(mawk_state_t *MAWK, const char *s)
{
if (s == NULL)
s = "";
return mawk_new_STRING(MAWK, s);
}
/* link tables are slow linear lists for now; may replace with hashes later */
typedef struct {
int numsu, strsu, varsu;
int numsa, strsa, varsa;
mawk_num_t *nums;
const char **strs;
struct {
int vtype;
mawk_cell_t *cp;
} *vars;
} link_t;
static void link_free(link_t *l)
{
if (l->nums != NULL)
free(l->nums);
if (l->strs != NULL)
free(l->strs);
if (l->vars != NULL)
free(l->vars);
}
#define check_grow(l, arr, used, alloced) \
if (l->used >= l->alloced) { \
l->alloced += 256; \
l->arr = realloc(l->arr, sizeof(*l->arr) * l->alloced); \
}
static int save_num(link_t *l, mawk_num_t *num)
{
int n;
for(n = 0; n < l->numsu; n++)
if (l->nums[n] == *num)
return n;
check_grow(l, nums, numsu, numsa);
l->nums[l->numsu] = *num;
return l->numsu++;
}
static int save_str(link_t *l, const char *str)
{
int n;
for(n = 0; n < l->strsu; n++)
if (safe_strcmp(l->strs[n], str) == 0) {
return n;
}
check_grow(l, strs, strsu, strsa);
l->strs[l->strsu] = str; /* no need to copy, strings are constant during dumping */
return l->strsu++;
}
static int save_var(link_t *l, mawk_cell_t *v, int vtype)
{
int n;
for(n = 0; n < l->varsu; n++)
if ((l->vars[n].cp == v) && (l->vars[n].vtype == vtype))
return n;
check_grow(l, vars, varsu, varsa);
l->vars[l->varsu].vtype = vtype;
l->vars[l->varsu].cp = v;
return l->varsu++;
}
static mawk_num_t *load_num(mawk_state_t *MAWK, link_t *l, int id)
{
mawk_num_t *n;
if ((id < 0) || (id >= l->numsu))
return NULL;
n = mawk_zmalloc(MAWK, sizeof(mawk_num_t));
*n = l->nums[id];
return n;
}
static const char *invalid_str = "load_str invalid";
static const char *load_str(link_t *l, int id)
{
if ((id < 0) || (id >= l->strsu))
return invalid_str;
return l->strs[id];
}
static mawk_cell_t *load_var(link_t *l, int id)
{
if ((id < 0) || (id >= l->varsu))
return NULL;
return l->vars[id].cp;
}
static void *load_bifunc(link_t *l, int id)
{
const char *name;
name = load_str(l, id);
if (name == invalid_str)
return NULL;
return mawk_f2d(mawk_find_bi_ptr(name));
}
static FBLOCK *bin_new_funct(mawk_state_t *MAWK, const char *name, int add_to_list)
{
FBLOCK *fbp;
SYMTAB *s;
s = mawk_find(MAWK, name, 0);
if (s != NULL) {
if (s->type != ST_FUNCT)
return NULL;
if (add_to_list)
mawk_add_to_fdump_list(MAWK, s->stval.fbp);
return s->stval.fbp;
}
s = mawk_find(MAWK, name, 1);
s->type = ST_FUNCT ;
fbp = s->stval.fbp = (FBLOCK *) mawk_zmalloc(MAWK, sizeof(FBLOCK)) ;
fbp->name = mawk_zstrclone(MAWK, name);
fbp->code = (INST*) 0 ;
if (add_to_list)
mawk_add_to_fdump_list(MAWK, fbp);
return fbp;
}
static void *bin_load_func_ref(mawk_state_t *MAWK, link_t *l, int id)
{
const char *name;
name = load_str(l, id);
if (name == invalid_str)
return NULL;
return bin_new_funct(MAWK, name, 0);
}
#define pack_re(p, cp) p->op = DUMP_RE | save_str(l, mawk_re_uncompile(MAWK, cp->ptr))
#define pack_match(p) p->op = DUMP_RE | save_str(l, mawk_re_uncompile(MAWK, p->ptr))
#define pack_repl(p, r) p->op = DUMP_REPL | save_str(l, mawk_repl_uncompile(MAWK, r))
#define pack_numptr(p) p->op = DUMP_NUM | save_num(l, (mawk_num_t *)p->ptr)
#define pack_split_space(p) p->op = DUMP_SPLIT_SPACE
#define pack_split_null(p) p->op = DUMP_SPLIT_NULL
#define pack_str(p) \
do { \
mawk_string_t *sval = (mawk_string_t *) p->ptr; \
p->op = DUMP_STR | save_str(l, sval->str); \
} while(0)
#define pack_var_(p, cp, t) p->op = DUMP_VAR | save_var(l, p->ptr, t)
#define pack_var(p, cp) pack_var_(p, cp, ST_VAR)
#define pack_field(p, cp) pack_var_(p, cp, ST_FIELD)
#define pack_field_0(p) p->op = DUMP_SPECFIELD | 0
#define pack_field_shadow(p) p->op = DUMP_SPECFIELD | 1
#define pack_arr(p, cp) pack_var_(p, cp, ST_ARRAY)
#define pack_index(p, cp) p->op = DUMP_FIELDIDX | mawk_field_addr_to_index(MAWK, cp)
#define pack_bifunc(p, cp) p->op = DUMP_CALL | save_str(l, mawk_find_bi_name((PF_CP) mawk_d2f(p->ptr)))
#define pack_call(p) p->op = DUMP_CALL | save_str(l, ((FBLOCK *) p->ptr)->name)
/* check if op matches flag; return NULL if not or remove flag */
#define chk_mask(op, flag) do { if ((op & flag) != flag) return NULL; op &= ~(flag); } while(0)
#define unpack_re(p, cp) do { \
const char *s; \
chk_mask(p->op, DUMP_RE); \
s = load_str(l, p->op); \
if (s == invalid_str) \
return NULL; \
cp = mawk_zmalloc(MAWK, sizeof(mawk_cell_t)); \
p->ptr = cp; \
cp->type = C_RE; \
cp->ptr = mawk_re_compile(MAWK, mawk_new_STRING(MAWK, s)); \
} while(0)
#define unpack_match(p) do { \
const char *s; \
chk_mask(p->op, DUMP_RE); \
s = load_str(l, p->op); \
if (s == invalid_str) \
return NULL; \
p->ptr = mawk_re_compile(MAWK, mawk_new_STRING(MAWK, s)); \
} while(0)
#define unpack_repl(p, r) do { \
const char *s; \
chk_mask(p->op, DUMP_REPL); \
s = load_str(l, p->op); \
if (s == invalid_str) \
return NULL; \
cp = mawk_zmalloc(MAWK, sizeof(mawk_cell_t)); \
p->ptr = mawk_repl_compile(MAWK, safe_new_STRING(MAWK, s)); \
} while(0)
#define unpack_numptr(p) do { chk_mask(p->op, DUMP_NUM); p->ptr = load_num(MAWK, l, p->op); if (p->ptr == NULL) return NULL; } while(0)
#define unpack_split_space(p) do { mawk_cell_t *cp; chk_mask(p->op, DUMP_SPLIT_SPACE); cp = MAWK_ZMALLOC(MAWK, mawk_cell_t); p->ptr = cp; cp->type = C_SPACE; } while(0)
#define unpack_split_null(p) do { mawk_cell_t *cp; chk_mask(p->op, DUMP_SPLIT_NULL); cp = MAWK_ZMALLOC(MAWK, mawk_cell_t); p->ptr = cp; cp->type = C_SNULL; } while(0)
#define unpack_str(p) \
do { \
const char *s; \
chk_mask(p->op, DUMP_STR); \
s = load_str(l, p->op); \
if (s == invalid_str) \
return NULL; \
p->ptr = safe_new_STRING(MAWK, s); \
} while(0)
#define unpack_var_(p, cp, t) do { chk_mask(p->op, DUMP_VAR); p->ptr = load_var(l, p->op); if (p->ptr == NULL) return NULL; } while (0)
#define unpack_var(p, cp) unpack_var_(p, cp, ST_VAR)
#define unpack_field(p, cp) unpack_var_(p, cp, ST_FIELD)
#define unpack_field_0(p) do { chk_mask(p->op, DUMP_SPECFIELD); p->ptr = MAWK->field;} while (0)
#define unpack_field_shadow(p) do { chk_mask(p->op, DUMP_SPECFIELD); p->ptr = &MAWK->fs_shadow; } while (0)
#define unpack_arr(p, cp) unpack_var_(p, cp, ST_ARRAY)
#define unpack_index(p, cp) do { chk_mask(p->op, DUMP_FIELDIDX); p->ptr = field_ptr(p->op); } while (0)
#define unpack_bifunc(p, cp) do { chk_mask(p->op, DUMP_CALL); p->ptr = load_bifunc(l, p->op); if (p->ptr == NULL) return NULL; } while (0)
#define unpack_call(p) do { chk_mask(p->op, DUMP_CALL); p->ptr = bin_load_func_ref(MAWK, l, p->op); if (p->ptr == NULL) return NULL; } while (0)
/* evaluate macro pack_ or unpack_, depending on pack flag */
#define link_re(p, cp) do { if (pack) pack_re(p, cp); else unpack_re(p, cp); } while (0)
#define link_match(p) do { if (pack) pack_match(p); else unpack_match(p); } while (0)
#define link_repl(p, r) do { if (pack) pack_repl(p, r); else unpack_repl(p, r); } while (0)
#define link_numptr(p) do { if (pack) pack_numptr(p); else unpack_numptr(p); } while (0)
#define link_split_space(p) do { if (pack) pack_split_space(p); else unpack_split_space(p); } while (0)
#define link_split_null(p) do { if (pack) pack_split_null(p); else unpack_split_null(p); } while (0)
#define link_str(p) do { if (pack) pack_str(p); else unpack_str(p); } while (0)
#define link_var(p, cp) do { if (pack) pack_var(p, cp); else unpack_var(p, cp); } while (0)
#define link_field(p, cp) do { if (pack) pack_field(p, cp); else unpack_field(p, cp); } while (0)
#define link_field_0(p) do { if (pack) pack_field_0(p); else unpack_field_0(p); } while (0)
#define link_field_shadow(p) do { if (pack) pack_field_shadow(p); else unpack_field_shadow(p); } while (0)
#define link_arr(p, cp) do { if (pack) pack_arr(p, cp); else unpack_arr(p, cp); } while (0)
#define link_index(p, cp) do { if (pack) pack_index(p, cp); else unpack_index(p, cp); } while (0)
#define link_bifunc(p, cp) do { if (pack) pack_bifunc(p, cp); else unpack_bifunc(p, cp); } while (0)
#define link_call(p) do { if (pack) pack_call(p); else unpack_call(p); } while (0)
INST *mawk_da_bin(mawk_state_t *MAWK, INST *start, link_t *l, int pack)
{
mawk_cell_t *cp;
register INST *p = start;
/* fprintf(stderr, "-\n"); */
do {
/* fprintf(stderr, "%d: %d\n", p-start, p->op);*/
switch (p++->op) {
case _PUSHC:
cp = (mawk_cell_t *) p->ptr;
if (pack) {
switch (cp->type) {
case C_RE:
link_re(p, cp);
break;
case C_REPL:
case C_REPLV:
link_repl(p, cp);
break;
case C_SPACE:
link_split_space(p);
break;
case C_SNULL:
link_split_null(p);
break;
default:
/* nothing else to save */
break;
}
}
else {
if (p->op == DUMP_SPLIT_SPACE)
link_split_space(p);
else if (p->op == DUMP_SPLIT_NULL)
link_split_null(p);
else if ((p->op & DUMP_RE) == DUMP_RE)
link_re(p, cp);
else if ((p->op & DUMP_REPL) == DUMP_REPL)
link_repl(p, cp);
}
p++;
break;
case _PUSHD:
link_numptr(p);
p++;
break;
case _PUSHS:
link_str(p);
p++;
break;
case _MATCH0:
case _MATCH1:
link_match(p);
p++;
break;
case _PUSHA:
cp = (mawk_cell_t *) p->ptr;
link_var(p, cp);
p++;
break;
case _PUSHI:
cp = (mawk_cell_t *) p->ptr;
if (pack) {
if (cp == MAWK->field)
link_field_0(p);
else if (cp == &MAWK->fs_shadow)
link_field_shadow(p);
else {
if (cp > MAWK_NF && cp <= LAST_PFIELD)
link_field(p, cp);
else
link_var(p, cp);
}
}
else {
if (p->op == (DUMP_SPECFIELD | 0))
link_field_0(p);
else if (p->op == (DUMP_SPECFIELD | 1))
link_field_shadow(p);
else
link_var(p, cp); /* fields are just variables */
}
p++;
break;
case L_PUSHA:
case L_PUSHI:
case LAE_PUSHI:
case LAE_PUSHA:
case LAE_PUSHA_WRARR:
case LA_PUSHA:
/* address is (p+1)->op */
p++;
break;
case F_PUSHI:
/* address is (p+1)->op */
p++;
p++;
break;
case F_PUSHA:
cp = (mawk_cell_t *) p->ptr;
if (pack) {
if (cp >= MAWK_NF && cp <= LAST_PFIELD)
link_field(p, cp);
else
link_index(p, cp);
}
else {
if ((p->op & DUMP_FIELDIDX) == DUMP_FIELDIDX)
link_index(p, cp);
else
link_field(p, cp);
}
p++;
break;
case AE_PUSHA:
case AE_PUSHA_WRARR:
case AE_PUSHI:
case A_PUSHA:
cp = (mawk_cell_t *) p->ptr;
link_arr(p, cp);
p++;
break;
case _PUSHINT:
/* integer operand is (p+1)->op */
p++;
break;
case _BUILTIN:
case _PRINT:
cp = (mawk_cell_t *) p->ptr;
link_bifunc(p, cp);
p++;
break;
case _JMP:
case _JNZ:
case _JZ:
case _LJZ:
case _LJNZ:
case SET_ALOOP:
case ALOOP:
case A_CAT:
/* address is (p+1)->op */
p++;
break;
case _CALL:
link_call(p);
p += 2;
break;
case _HALT:
break;
case _RANGE_CHK:
p += 4;
break;
case LOCATION:
p++;
break;
default:
/* simple code */
break;
}
} while (p->op != _HALT);
p++;
return p;
}
void mawk_fdump_bin(mawk_state_t * MAWK, link_t *l)
{
register struct mawk_fdump *p, *q = MAWK->fdump_list;
while (q) {
p = q;
q = p->link;
/* fprintf(stdout, "function %s\n", p->fbp->name); */
mawk_da_bin(MAWK, p->fbp->code, l, 1);
}
}
static const char *f_id = "libmawk\n";
typedef struct header_s {
char f_id[8];
char numeric; /* see mawk_num_id in num_*.c */
char filever; /* should be BIN_FILEVER */
union {
short int s;
unsigned char c;
} byteorder;
char inst_size;
char num_size;
char pad[50]; /* reserved for future use - header size should be 64 bytes long */
} header_t;
#define chk_hdr_size(h) \
if (sizeof(h) != 64) { \
mawk_errmsg(MAWK, 0, "Internal libmawk error: da_bin: header struct size is not 64 bytes but %d bytes", sizeof(h)); \
abort(); \
}
#ifndef MAWK_NO_COMP
static int link_bin_sect(mawk_state_t * MAWK, INST *b, link_t *l)
{
INST *p;
if (b != NULL) {
p = mawk_da_bin(MAWK, b, l, 1);
return p - b;
}
return 0;
}
static int save_bin_sect(mawk_state_t * MAWK, void *fd, int (*write)(void *fd, const void *buff, size_t len), INST *b, da_word len)
{
if (write(fd, &len, sizeof(da_word)) != sizeof(da_word))
return -1;
if (b != NULL) {
int l;
l = len * sizeof(INST);
if (write(fd, b, l) != l)
return -1;
}
return 0;
}
int mawk_save_code_bin_(mawk_state_t * MAWK, void *fd, int (*write)(void *fd, const void *buff, size_t len))
{
header_t h;
link_t l;
int n;
long int begin_len, end_len, main_len;
da_word num_func, len;
long int *flen;
struct mawk_fdump **fps;
struct mawk_fdump *fp;
/* create header */
chk_hdr_size(h);
memcpy(h.f_id, f_id, sizeof(h.f_id));
h.numeric = mawk_num_id;
h.byteorder.s = 0x626F; /* bo in MSB */
h.filever = BIN_FILEVER;
h.inst_size = sizeof(INST);
h.num_size = sizeof(mawk_num_t);
memset(h.pad, 0, sizeof(h.pad));
write(fd, &h, sizeof(h));
/* prepare for linking */
memset(&l, 0, sizeof(l));
/* count functions */
num_func = 0;
for(fp = MAWK->fdump_list; fp != NULL; fp = fp->link)
num_func++;
if (num_func > 0) {
flen = malloc(sizeof(long int) * num_func);
fps = malloc(sizeof(struct mawk_fdump *) * num_func);
}
for(n = 0, fp = MAWK->fdump_list; fp != NULL; n++, fp = fp->link) {
fps[n] = fp;
}
/* fprintf(stderr, "Funcs: %d\n", num_func); */
begin_len = link_bin_sect(MAWK, MAWK->begin_start, &l);
/* fprintf(stderr, "BEGIN: total %d instructions\n", begin_len); */
end_len = link_bin_sect(MAWK, MAWK->end_start, &l);
/* fprintf(stderr, "END: total %d instructions\n", end_len); */
main_len = link_bin_sect(MAWK, MAWK->main_start, &l);
/* fprintf(stderr, "MAIN: total %d instructions\n", main_len); */
for(n = 0, fp = MAWK->fdump_list; fp != NULL; n++, fp = fp->link)
flen[n] = link_bin_sect(MAWK, fp->fbp->code, &l);
/* L1: save nums */
len = l.numsu;
write(fd, &len, sizeof(da_word));
write(fd, l.nums, sizeof(mawk_num_t) * l.numsu);
write(fd, &num_func, sizeof(da_word));
/* L2: save strings */
len = l.strsu;
write(fd, &len, sizeof(da_word));
for(n = 0; n < l.strsu; n++) {
len = safe_strlen(l.strs[n]);
write(fd, &len, sizeof(da_word));
if (len > 0)
write(fd, l.strs[n], len);
}
/* L3: save vars */
len = l.varsu;
write(fd, &len, sizeof(da_word));
for(n = 0; n < l.varsu; n++) {
const char *name;
SYMTAB *stp;
name = mawk_reverse_find(MAWK, l.vars[n].vtype, &(l.vars[n].cp));
if (name == mawk_reverse_uk) {
mawk_errmsg(MAWK, 0, "da_bin: Variable name lookup error");
return -1;
}
stp = mawk_find(MAWK, name, 0);
/* save types */
write(fd, &(l.vars[n].vtype), 2);
write(fd, &(stp->type), 1);
/* save name len and name*/
len = strlen(name);
write(fd, &len, sizeof(da_word));
write(fd, name, len);
/* save value len and content - empty for now */
len = 0;
write(fd, &len, sizeof(da_word));
}
/* L4: save begin/end/main sections */
save_bin_sect(MAWK, fd, write, MAWK->begin_start, begin_len);
save_bin_sect(MAWK, fd, write, MAWK->end_start, end_len);
save_bin_sect(MAWK, fd, write, MAWK->main_start, main_len);
/* L5: save user functions */
for(n = num_func-1; n >= 0; n--) {
int len;
fp = fps[n];
len = strlen(fp->fbp->name);
/* fprintf(stderr, "da_bin function %s/%d len=%d\n", fp->fbp->name, len,flen[n]); */
write(fd, &len, sizeof(da_word));
write(fd, fp->fbp->name, len);
/* fprintf(stderr, "NARGS=%d %d\n", fp->fbp->nargs, fp->fbp->typev[0]); */
write(fd, &fp->fbp->nargs, 2);
if (fp->fbp->nargs > 0)
write(fd, fp->fbp->typev, fp->fbp->nargs);
save_bin_sect(MAWK, fd, write, fp->fbp->code, flen[n]);
}
if (num_func > 0) {
free(flen);
free(fps);
}
link_free(&l);
return 0;
}
#endif
#ifndef MAWK_NO_EXEC
static int bin_load_func(mawk_state_t *MAWK, void *fd, int (*read)(void *fd, void *buff, size_t len), FBLOCK *fbp)
{
da_word len;
read(fd, &len, sizeof(da_word));
if (len > 0) {
if (len > BIN_CODE_MAXLEN)
return -1;
fbp->code = mawk_zmalloc(MAWK, len * sizeof(INST));
read(fd, fbp->code, len * sizeof(INST));
}
return 0;
}
static int bin_load_sect(mawk_state_t *MAWK, void *fd, int (*read)(void *fd, void *buff, size_t len), int scope)
{
da_word len;
read(fd, &len, sizeof(da_word));
if (len > 0) {
MAWK->scope = scope;
if ((scope == SCOPE_BEGIN) || (scope == SCOPE_END))
mawk_be_setup(MAWK, MAWK->scope);
mawk_code_reset_size(MAWK, len * sizeof(INST));
read(fd, MAWK->active_code.base, len * sizeof(INST));
MAWK->active_code.ptr = MAWK->active_code.base + len;
switch(scope) {
case SCOPE_BEGIN: *MAWK->begin_code_p = MAWK->active_code; break;
case SCOPE_END: *MAWK->end_code_p = MAWK->active_code; break;
case SCOPE_MAIN: *MAWK->main_code_p = MAWK->active_code; break;
/* avoid using default so later when scope is enum compiler can give warnings on missing scopes */
}
MAWK->active_code = *MAWK->main_code_p;
}
return 0;
}
static int bin_link_sect(mawk_state_t *MAWK, link_t *l, INST *blk, const char *sectname)
{
if (blk == NULL)
return 0;
if (mawk_da_bin(MAWK, blk, l, 0) == NULL) {
mawk_errmsg(MAWK, 0, "da_bin: Error: failed to link binary in section %s", sectname);
return 1;
}
return 0;
}
int mawk_load_code_bin_(mawk_state_t *MAWK, void *fd, int (*read)(void *fd, void *buff, size_t len))
{
SYMTAB *stp;
header_t h;
link_t l;
int n;
da_word num_func, len;
int ret;
memset(&l, 0, sizeof(l));
/* read header */
chk_hdr_size(h);
read(fd, &h, sizeof(h));
ret = 0;
if (memcmp(h.f_id, f_id, sizeof(h.f_id)) != 0) {
mawk_errmsg(MAWK, 0, "da_bin: header ID mismatch");
ret = MAWK_EHDRSIZE;
goto err;
}
if (h.numeric != mawk_num_id) {
mawk_errmsg(MAWK, 0, "da_bin: magic mismatch");
ret = MAWK_EFILEMAGIC;
goto err;
}
if (h.byteorder.s != 0x626F) { /* bo in MSB */
mawk_errmsg(MAWK, 0, "da_bin: byte order mismatch");
ret = MAWK_EBYTEORDER;
goto err;
}
if (h.filever != BIN_FILEVER) {
mawk_errmsg(MAWK, 0, "da_bin: file version mismatch: produced by %d, can load %d", h.filever, BIN_FILEVER);
ret = MAWK_EVERSION;
goto err;
}
if (h.inst_size != sizeof(INST)) {
mawk_errmsg(MAWK, 0, "da_bin: instruction size mismatch: expected %d, got %d", sizeof(INST), h.inst_size);
ret = MAWK_EINSTSIZE;
goto err;
}
if (h.num_size != sizeof(mawk_num_t)) {
mawk_errmsg(MAWK, 0, "da_bin: numeric size mismatch: expected %d, got %d", sizeof(mawk_num_t), h.num_size);
ret = MAWK_ENUMSIZE;
goto err;
}
/* prepare for linking */
memset(&l, 0, sizeof(l));
/* L1: load nums */
len = 0;
read(fd, &len, sizeof(da_word));
l.numsa = l.numsu = len;
len = sizeof(*l.nums) * l.numsa;
if (len > BIN_MAXVARS)
goto err;
l.nums = malloc(len);
read(fd, l.nums, len);
read(fd, &num_func, sizeof(da_word));
/* L2: load strings */
read(fd, &len, sizeof(da_word));
l.strsa = l.strsu = len;
len = sizeof(*l.strs) * l.strsa;
if (len > BIN_MAXSTRS)
goto err;
l.strs = malloc(len);
for(n = 0; n < l.strsu; n++) {
char *name;
read(fd, &len, sizeof(da_word));
if (len > BIN_NAME_MAXLEN)
goto err;
if (len > 0) {
l.strs[n] = mawk_zmalloc(MAWK, len+1);
if (l.strs[n] == NULL) {
ret = MAWK_EALLOC;
goto err;
}
read(fd, (char *)l.strs[n], len);
name = (char *)l.strs[n];
name[len] = '\0';
}
else
l.strs[n] = NULL;
/* fprintf(stderr, "LOAD str: [%d] '%s'\n", n, l.strs[n]); */
}
/* L3: load vars */
read(fd, &len, sizeof(da_word));
l.varsa = l.varsu = len;
len = sizeof(*l.vars) * l.varsa;
if (l.varsa > BIN_MAXVARS)
goto err;
l.vars = malloc(len);
/* fprintf(stderr, "numvars: %d allocated=%d\n", l.varsu, len); */
for(n = 0; n < l.varsu; n++) {
char *name;
short type;
char stype;
/* load type */
read(fd, &type, 2);
read(fd, &stype, 1);
/* load name len and name*/
read(fd, &len, sizeof(da_word));
if (len > BIN_NAME_MAXLEN)
goto err;
name = mawk_zmalloc(MAWK, len+1);
read(fd, name, len);
name[len] = '\0';
/* go for existing vars first (because ARGV and builtins) */
l.vars[n].cp = mawk_get_var(MAWK, name);
if (l.vars[n].cp == NULL) {
if (type == ST_ARRAY) {
SYMTAB *stp;
stp = mawk_insert(MAWK, name);
stp->stval.array = mawk_array_new(MAWK, NULL);
stp->type = ST_ARRAY;
l.vars[n].cp = (mawk_cell_t *)stp->stval.array;
}
else {
l.vars[n].cp = mawk_create_var(MAWK, name, NULL);
if (l.vars[n].cp == NULL) {
mawk_errmsg(MAWK, 0, "da_bin: load error: can not create variable %s", name);
goto err;
}
}
}
l.vars[n].vtype = type;
stp = mawk_find(MAWK, name, 0);
if (stp->type != stype) {
mawk_errmsg(MAWK, 0, "da_bin warning: type of variable %s changed from %d to %d", name, stp->type, stype);
}
stp->type = stype;
/* fprintf(stderr, "LOAD var name='%s' type=%d len=%d: %d -> %p\n", name, type, len, n, l.vars[n].cp); */
/* load value len and content - empty for now */
read(fd, &len, sizeof(da_word));
if (len != 0) {
ret = MAWK_EWRONGVAL;
goto err2;
}
}
/* L4: load begin/end/main sections */
mawk_code_init(MAWK);
/* printf("D1: %p %p %p\n", MAWK->main_code_p, MAWK->begin_code_p, MAWK->end_code_p); */
if (bin_load_sect(MAWK, fd, read, SCOPE_BEGIN))
goto err;
if (bin_load_sect(MAWK, fd, read, SCOPE_END))
goto err;
if (bin_load_sect(MAWK, fd, read, SCOPE_MAIN))
goto err;
/* L5: load functions */
for(n = 0; n < num_func; n++) {
int len;
char *name;
FBLOCK *fbp;
read(fd, &len, sizeof(da_word));
/* fprintf(stderr, "LOAD function len=%d\n", len); */
if (len > BIN_NAME_MAXLEN)
goto err;
name = mawk_zmalloc(MAWK, len+1);
read(fd, name, len);
name[len] = '\0';
/* fprintf(stderr, "LOAD function name=%s\n", name); */
fbp = bin_new_funct(MAWK, name, 1);
read(fd, &fbp->nargs, 2);
/* fprintf(stderr, "LOAD nargs=%d\n", fbp->nargs); */
if (fbp->nargs > 0) {
fbp->typev = mawk_zmalloc(MAWK, fbp->nargs);
read(fd, fbp->typev, fbp->nargs);
}
else
fbp->typev = NULL;
bin_load_func(MAWK, fd, read, fbp);
if (mawk_da_bin(MAWK, fbp->code, &l, 0) == NULL) {
mawk_errmsg(MAWK, 0, "Can't link function %s", name);
goto err2;
}
}
mawk_set_code(MAWK);
if (bin_link_sect(MAWK, &l, MAWK->begin_start, "BEGIN"))
goto err;
if (bin_link_sect(MAWK, &l, MAWK->end_start, "END"))
goto err;
if (bin_link_sect(MAWK, &l, MAWK->main_start, "main"))
goto err;
goto out;
err2:;
err:;
out:;
link_free(&l);
return ret;
}
#endif