/********************************************
code.c
libmawk changes (C) 2009-2010, Tibor 'Igor2' Palinkas;
based on mawk code coming with the below copyright:
copyright 1991-93, 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 "init.h"
#include "jmp.h"
#include "field.h"
static CODEBLOCK *new_code(mawk_state_t *);
/* grow the active code */
void mawk_code_grow(mawk_state_t * MAWK)
{
unsigned oldsize = mawk_code_limit - mawk_code_base;
unsigned newsize = PAGESZ + oldsize;
unsigned delta = mawk_code_ptr - mawk_code_base;
if (mawk_code_ptr > mawk_code_limit)
mawk_bozo(MAWK, "CODEWARN is too small");
mawk_code_base = (INST *)
mawk_zrealloc(MAWK, mawk_code_base, INST_BYTES(oldsize), INST_BYTES(newsize));
mawk_code_limit = mawk_code_base + newsize;
mawk_code_warn = mawk_code_limit - CODEWARN;
mawk_code_ptr = mawk_code_base + delta;
}
void mawk_code_reset_size(mawk_state_t *MAWK, int newsize)
{
unsigned oldsize = mawk_code_limit - mawk_code_base;
mawk_bfree(MAWK, mawk_code_base, oldsize);
mawk_code_base = (INST *)mawk_zmalloc(MAWK, INST_BYTES(newsize));
mawk_code_limit = mawk_code_base + newsize;
mawk_code_warn = mawk_code_limit - CODEWARN;
mawk_code_ptr = mawk_code_base;
}
/* shrinks executable code that's done to its final size */
INST *mawk_code_shrink(mawk_state_t *MAWK, CODEBLOCK *p, unsigned *sizep)
{
unsigned oldsize = INST_BYTES(p->limit - p->base);
unsigned newsize = INST_BYTES(p->ptr - p->base);
INST *retval;
*sizep = newsize;
retval = (INST *) mawk_zrealloc(MAWK, p->base, oldsize, newsize);
/* free CODEBLOCK: only INST will be used as this block won't grow anymore */
MAWK_ZFREE(MAWK, p);
return retval;
}
/* code an op and a pointer in the active_code */
void mawk_xcode2(mawk_state_t *MAWK, int op, PTR ptr)
{
register INST *p = mawk_code_ptr + 2;
if (p >= mawk_code_warn) {
mawk_code_grow(MAWK);
p = mawk_code_ptr + 2;
}
p[-2].op = op;
p[-1].ptr = ptr;
mawk_code_ptr = p;
}
/* code two ops in the active_code */
void mawk_code2op(mawk_state_t *MAWK, int x, int y)
{
register INST *p = mawk_code_ptr + 2;
if (p >= mawk_code_warn) {
mawk_code_grow(MAWK);
p = mawk_code_ptr + 2;
}
p[-2].op = x;
p[-1].op = y;
mawk_code_ptr = p;
}
void mawk_code_init(mawk_state_t *MAWK)
{
MAWK->main_code_p = new_code(MAWK);
if (MAWK->main_code_p->ptr == NULL)
return;
MAWK->active_code = *MAWK->main_code_p;
code1(_OMAIN);
}
/* final code relocation
set_code() as in set concrete */
void mawk_set_code(mawk_state_t * MAWK)
{
/* set the main code which is active_code */
if (MAWK->end_code_p || mawk_code_offset > 1) {
int gl_offset = mawk_code_offset;
if (MAWK->NR_flag)
mawk_code2op(MAWK, OL_GL_NR, _HALT);
else
mawk_code2op(MAWK, OL_GL, _HALT);
*MAWK->main_code_p = MAWK->active_code;
MAWK->main_start = mawk_code_shrink(MAWK, MAWK->main_code_p, &MAWK->main_size);
MAWK->next_label = MAWK->main_start + gl_offset;
MAWK->execution_start = MAWK->main_start;
}
else { /* only BEGIN */
mawk_zfree(MAWK, mawk_code_base, INST_BYTES(PAGESZ));
MAWK_ZFREE(MAWK, MAWK->main_code_p);
MAWK->main_code_p = NULL;
}
/* set the END code */
if (MAWK->end_code_p) {
MAWK->active_code = *MAWK->end_code_p;
mawk_code2op(MAWK, _EXIT0, _HALT);
*MAWK->end_code_p = MAWK->active_code;
MAWK->end_start = mawk_code_shrink(MAWK, MAWK->end_code_p, &MAWK->end_size);
MAWK->end_start_orig = MAWK->end_start;
}
/* set the BEGIN code */
if (MAWK->begin_code_p) {
MAWK->active_code = *MAWK->begin_code_p;
if (MAWK->main_start)
mawk_code2op(MAWK, _JMAIN, _HALT);
else
mawk_code2op(MAWK, _EXIT0, _HALT);
*MAWK->begin_code_p = MAWK->active_code;
MAWK->begin_start = mawk_code_shrink(MAWK, MAWK->begin_code_p, &MAWK->begin_size);
MAWK->execution_start = MAWK->begin_start;
}
if (!MAWK->execution_start) {
/* program had functions but no pattern-action bodies */
MAWK->execution_start = MAWK->begin_start = (INST *) mawk_zmalloc(MAWK, 2 * sizeof(INST));
MAWK->execution_start[0].op = _EXIT0;
MAWK->execution_start[1].op = _HALT;
}
}
static CODEBLOCK *new_code(mawk_state_t *MAWK)
{
CODEBLOCK *p = MAWK_ZMALLOC(MAWK, CODEBLOCK);
p->base = (INST *) mawk_zmalloc(MAWK, INST_BYTES(PAGESZ));
p->limit = p->base + PAGESZ;
p->warn = p->limit - CODEWARN;
p->ptr = p->base;
return p;
}
/* mawk_begin/end_setup: switches the active_code from MAIN to a
BEGIN or END */
void mawk_be_setup(mawk_state_t *MAWK, int scope)
{
*MAWK->main_code_p = MAWK->active_code;
if (scope == SCOPE_BEGIN) {
if (!MAWK->begin_code_p)
MAWK->begin_code_p = new_code(MAWK);
MAWK->active_code = *MAWK->begin_code_p;
}
else {
if (!MAWK->end_code_p)
MAWK->end_code_p = new_code(MAWK);
MAWK->active_code = *MAWK->end_code_p;
}
}