mawk/code.c
2010-02-01 01:18:08 -05:00

245 lines
5.0 KiB
C

/********************************************
code.c
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.
********************************************/
/*
* $MawkId: code.c,v 1.3 2010/01/31 22:17:18 tom Exp $
* @Log: code.c,v @
* Revision 1.6 1995/06/18 19:42:13 mike
* Remove some redundant declarations and add some prototypes
*
* Revision 1.5 1995/06/09 23:21:36 mike
* make sure there is an execution block in case user defines function,
* but no pattern-action pairs
*
* Revision 1.4 1995/03/08 00:06:22 mike
* add a pointer cast
*
* Revision 1.3 1994/10/08 19:15:29 mike
* remove SM_DOS
*
* Revision 1.2 1993/07/07 00:07:38 mike
* more work on 1.2
*
* Revision 1.1.1.1 1993/07/03 18:58:10 mike
* move source to cvs
*
* Revision 5.4 1993/01/14 13:11:11 mike
* code2() -> xcode2()
*
* Revision 5.3 1993/01/09 20:15:35 mike
* code_pop checks if the resolve_list needs relocation
*
* Revision 5.2 1993/01/07 02:50:33 mike
* relative vs absolute code
*
* Revision 5.1 1991/12/05 07:55:43 brennan
* 1.1 pre-release
*
*/
/* code.c */
#include "mawk.h"
#include "code.h"
#include "init.h"
#include "jmp.h"
#include "field.h"
static CODEBLOCK *new_code(void);
CODEBLOCK active_code;
CODEBLOCK *main_code_p, *begin_code_p, *end_code_p;
INST *begin_start, *main_start, *end_start;
unsigned begin_size, main_size;
INST *execution_start = 0;
/* grow the active code */
void
code_grow(void)
{
unsigned oldsize = (unsigned) (code_limit - code_base);
unsigned newsize = PAGESZ + oldsize;
unsigned delta = (unsigned) (code_ptr - code_base);
if (code_ptr > code_limit)
bozo("CODEWARN is too small");
code_base = (INST *)
zrealloc(code_base, INST_BYTES(oldsize),
INST_BYTES(newsize));
code_limit = code_base + newsize;
code_warn = code_limit - CODEWARN;
code_ptr = code_base + delta;
}
/* shrinks executable code that's done to its final size */
INST *
code_shrink(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 *) zrealloc(p->base, oldsize, newsize);
ZFREE(p);
return retval;
}
/* code an op and a pointer in the active_code */
void
xcode2(int op, PTR ptr)
{
register INST *p = code_ptr + 2;
if (p >= code_warn) {
code_grow();
p = code_ptr + 2;
}
p[-2].op = op;
p[-1].ptr = ptr;
code_ptr = p;
}
/* code two ops in the active_code */
void
code2op(int x, int y)
{
register INST *p = code_ptr + 2;
if (p >= code_warn) {
code_grow();
p = code_ptr + 2;
}
p[-2].op = x;
p[-1].op = y;
code_ptr = p;
}
void
code_init(void)
{
main_code_p = new_code();
active_code = *main_code_p;
code1(_OMAIN);
}
/* final code relocation
set_code() as in set concrete */
void
set_code(void)
{
/* set the main code which is active_code */
if (end_code_p || code_offset > 1) {
int gl_offset = code_offset;
if (NR_flag)
code2op(OL_GL_NR, _HALT);
else
code2op(OL_GL, _HALT);
*main_code_p = active_code;
main_start = code_shrink(main_code_p, &main_size);
next_label = main_start + gl_offset;
execution_start = main_start;
} else { /* only BEGIN */
zfree(code_base, INST_BYTES(PAGESZ));
ZFREE(main_code_p);
}
/* set the END code */
if (end_code_p) {
unsigned dummy;
active_code = *end_code_p;
code2op(_EXIT0, _HALT);
*end_code_p = active_code;
end_start = code_shrink(end_code_p, &dummy);
}
/* set the BEGIN code */
if (begin_code_p) {
active_code = *begin_code_p;
if (main_start)
code2op(_JMAIN, _HALT);
else
code2op(_EXIT0, _HALT);
*begin_code_p = active_code;
begin_start = code_shrink(begin_code_p, &begin_size);
execution_start = begin_start;
}
if (!execution_start) {
/* program had functions but no pattern-action bodies */
execution_start = begin_start = (INST *) zmalloc(2 * sizeof(INST));
execution_start[0].op = _EXIT0;
execution_start[1].op = _HALT;
}
}
void
dump_code(void)
{
fdump(); /* dumps all user functions */
if (begin_start) {
fprintf(stdout, "BEGIN\n");
da(begin_start, stdout);
}
if (end_start) {
fprintf(stdout, "END\n");
da(end_start, stdout);
}
if (main_start) {
fprintf(stdout, "MAIN\n");
da(main_start, stdout);
}
}
static CODEBLOCK *
new_code(void)
{
CODEBLOCK *p = ZMALLOC(CODEBLOCK);
p->base = (INST *) zmalloc(INST_BYTES(PAGESZ));
p->limit = p->base + PAGESZ;
p->warn = p->limit - CODEWARN;
p->ptr = p->base;
return p;
}
/* moves the active_code from MAIN to a BEGIN or END */
void
be_setup(int scope)
{
*main_code_p = active_code;
if (scope == SCOPE_BEGIN) {
if (!begin_code_p)
begin_code_p = new_code();
active_code = *begin_code_p;
} else {
if (!end_code_p)
end_code_p = new_code();
active_code = *end_code_p;
}
}