/********************************************
da.c
libmawk changes (C) 2009-2010, Tibor 'Igor2' Palinkas;
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.
********************************************/
/* disassemble code */
#include "mawk.h"
#include <stdio.h>
#include "code.h"
#include "bi_funct.h"
#include "repl.h"
#include "field.h"
#include "num.h"
#include "f2d.h"
static const struct sc {
char op;
char *name;
} simple_code[] = { /* read-only */
{_RANGE_STOP,"range_stop"},
{FE_PUSHA, "fe_pusha"},
{FE_PUSHI, "fe_pushi"},
{A_TEST, "a_test"},
{A_DEL, "a_del"},
{DEL_A, "del_a"},
{POP_AL, "pop_al"},
{_POP, "pop"},
{_ADD, "add"},
{_SUB, "sub"},
{_MUL, "mul"},
{_DIV, "div"},
{_MOD, "mod"},
{_POW, "pow"},
{_NOT, "not"},
{_UMINUS, "uminus"},
{_UPLUS, "uplus"},
{_TEST, "mawk_test"},
{_CAT, "cat"},
{_ASSIGN, "assign"},
{_ADD_ASG, "add_asg"},
{_SUB_ASG, "sub_asg"},
{_MUL_ASG, "mul_asg"},
{_DIV_ASG, "div_asg"},
{_MOD_ASG, "mod_asg"},
{_POW_ASG, "pow_asg"},
{NF_PUSHI, "nf_pushi"},
{F_ASSIGN, "f_assign"},
{F_ADD_ASG, "f_add_asg"},
{F_SUB_ASG, "f_sub_asg"},
{F_MUL_ASG, "f_mul_asg"},
{F_DIV_ASG, "f_div_asg"},
{F_MOD_ASG, "f_mod_asg"},
{F_POW_ASG, "f_pow_asg"},
{_POST_INC, "post_inc"},
{_POST_DEC, "post_dec"},
{_PRE_INC, "pre_inc"},
{_PRE_DEC, "pre_dec"},
{F_POST_INC, "f_post_inc"},
{F_POST_DEC, "f_post_dec"},
{F_PRE_INC, "f_pre_inc"},
{F_PRE_DEC, "f_pre_dec"},
{_EQ, "eq"},
{_NEQ, "neq"},
{_LT, "lt"},
{_LTE, "lte"},
{_GT, "gt"},
{_GTE, "gte"},
{_MATCH2, "match2"},
{_EXIT, "exit"},
{_EXIT0, "exit0"},
{_NEXT, "next"},
{_RET, "ret"},
{_RET0, "ret0"},
{_OMAIN, "omain"},
{_JMAIN, "jmain"},
{OL_GL, "ol_gl"},
{OL_GL_NR, "ol_gl_nr"},
{_ASSIGN_ARR, "assign_arr"},
{_ADD_ASG_ARR, "add_asg_arr"},
{_SUB_ASG_ARR, "sub_asg_arr"},
{_MUL_ASG_ARR, "mul_asg_arr"},
{_DIV_ASG_ARR, "div_asg_arr"},
{_MOD_ASG_ARR, "mod_asg_arr"},
{_POW_ASG_ARR, "pow_asg_arr"},
{_POST_INC_ARR, "post_inc_arr"},
{_POST_DEC_ARR, "post_dec_arr"},
{_PRE_INC_ARR, "pre_inc_arr"},
{_PRE_DEC_ARR, "pre_dec_arr"},
{_HALT, NULL}
};
static const char *jfmt = "%s%s%03d\n"; /* read-only */
/* format to print jumps */
static const char *tab2 = "\t\t"; /* read-only */
void mawk_da(mawk_state_t *MAWK, INST *start, void *fp_)
{
mawk_cell_t *cp;
FILE *fp = fp_;
register INST *p = start;
const char *name;
while (p->op != _HALT) {
/* print the relative code address (label) */
fprintf(fp, "%03d ", p - start);
switch (p++->op) {
case _PUSHC:
cp = (mawk_cell_t *) p++->ptr;
switch (cp->type) {
case C_RE:
fprintf(fp, "pushc\t<<%p>>\t/%s/\n", cp->ptr, mawk_re_uncompile(MAWK, cp->ptr));
break;
case C_SPACE:
fprintf(fp, "pushc\tspace split\n");
break;
case C_SNULL:
fprintf(fp, "pushc\tnull split\n");
break;
case C_REPL:
fprintf(fp, "pushc\trepl\t%s\n", mawk_repl_uncompile(MAWK, cp));
break;
case C_REPLV:
fprintf(fp, "pushc\treplv\t%s\n", mawk_repl_uncompile(MAWK, cp));
break;
default:
fprintf(fp, "pushc\tWEIRD\n");;
break;
}
break;
case _PUSHD:
fprintf(fp, "pushd\t" NUM_FMT_DA "\n", *(mawk_num_t *) p++->ptr);
break;
case _PUSHS:
{
mawk_string_t *sval = (mawk_string_t *) p++->ptr;
fprintf(fp, "pushs\t\"%s\"\n", sval->str);
break;
}
case _MATCH0:
case _MATCH1:
fprintf(fp, "match%d\t<<%p>>\t/%s/\n", p[-1].op == _MATCH1, p->ptr, mawk_re_uncompile(MAWK, p->ptr));
p++;
break;
case _PUSHA:
fprintf(fp, "pusha\t%s\n", mawk_reverse_find(MAWK, ST_VAR, &p++->ptr));
break;
case _PUSHI:
cp = (mawk_cell_t *) p++->ptr;
if (cp == MAWK->field)
fprintf(fp, "pushi\t$0\n");
else if (cp == &MAWK->fs_shadow)
fprintf(fp, "pushi\t@fs_shadow\n");
else {
if (cp > MAWK_NF && cp <= LAST_PFIELD)
name = mawk_reverse_find(MAWK, ST_FIELD, &cp);
else
name = mawk_reverse_find(MAWK, ST_VAR, &cp);
fprintf(fp, "pushi\t%s\n", name);
}
break;
case L_PUSHA:
fprintf(fp, "l_pusha\t%ld\n", (long)p++->op);
break;
case L_PUSHI:
fprintf(fp, "l_pushi\t%ld\n", (long)p++->op);
break;
case LAE_PUSHI:
fprintf(fp, "lae_pushi\t%ld\n", (long)p++->op);
break;
case LAE_PUSHA:
fprintf(fp, "lae_pusha\t%ld\n", (long)p++->op);
break;
case LAE_PUSHA_WRARR:
fprintf(fp, "lae_pusha_wr\t%ld\n", (long)p++->op);
break;
case LA_PUSHA:
fprintf(fp, "la_pusha\t%ld\n", (long)p++->op);
break;
case F_PUSHA:
cp = (mawk_cell_t *) p++->ptr;
if (cp >= MAWK_NF && cp <= LAST_PFIELD)
fprintf(fp, "f_pusha\t%s\n", mawk_reverse_find(MAWK, ST_FIELD, &cp));
else
fprintf(fp, "f_pusha\t$%d\n", mawk_field_addr_to_index(MAWK, cp));
break;
case F_PUSHI:
p++;
fprintf(fp, "f_pushi\t$%ld\n", (long)p++->op);
break;
case AE_PUSHA:
fprintf(fp, "ae_pusha\t%s\n", mawk_reverse_find(MAWK, ST_ARRAY, &p++->ptr));
break;
case AE_PUSHA_WRARR:
fprintf(fp, "ae_pusha_wr\t%s\n", mawk_reverse_find(MAWK, ST_ARRAY, &p++->ptr));
break;
case AE_PUSHI:
fprintf(fp, "ae_pushi\t%s\n", mawk_reverse_find(MAWK, ST_ARRAY, &p++->ptr));
break;
case A_PUSHA:
fprintf(fp, "a_pusha\t%s\n", mawk_reverse_find(MAWK, ST_ARRAY, &p++->ptr));
break;
case _PUSHINT:
fprintf(fp, "pushint\t%ld\n", (long)p++->op);
break;
case _BUILTIN:
fprintf(fp, "%s\n", mawk_find_bi_name((PF_CP) mawk_d2f(p++->ptr)));
break;
case _PRINT:
fprintf(fp, "%s\n", (PF_CP) mawk_d2f(p++->ptr) == mawk_bi_printf ? "printf" : "print");
break;
case _JMP:
fprintf(fp, jfmt, "jmp", tab2, (p - start) + p->op);
p++;
break;
case _JNZ:
fprintf(fp, jfmt, "jnz", tab2, (p - start) + p->op);
p++;
break;
case _JZ:
fprintf(fp, jfmt, "jz", tab2, (p - start) + p->op);
p++;
break;
case _LJZ:
fprintf(fp, jfmt, "ljz", tab2, (p - start) + p->op);
p++;
break;
case _LJNZ:
fprintf(fp, jfmt, "ljnz", tab2 + 1, (p - start) + p->op);
p++;
break;
case SET_ALOOP:
fprintf(fp, "set_al\t%03d\n", p + p->op - start);
p++;
break;
case ALOOP:
fprintf(fp, "aloop\t%03ld\n", (long)(p - start + p->op));
p++;
break;
case A_CAT:
fprintf(fp, "a_cat\t%ld\n", (long)p++->op);
break;
case _CALL:
fprintf(fp, "call\t%s\t%ld\n", ((FBLOCK *) p->ptr)->name, (long)p[1].op);
p += 2;
break;
case _RANGE_CHK:
fprintf(fp, "range\t%03ld %03ld %03ld\n",
/* label for pat2, action, follow */
(long)(p - start + p[1].op), (long)(p - start + p[2].op), (long)(p - start + p[3].op));
p += 4;
break;
case LOCATION:
fprintf(fp, "(location)\t%ld\n", (long)p[0].op);
p++;
break;
default:
{
const struct sc *q = simple_code;
int k = (p - 1)->op;
while (q->op != _HALT && q->op != k)
q++;
if (q->op != _HALT)
fprintf(fp, "%s\n", q->name);
else
fprintf(fp, "bad instruction %d\n", k);
}
break;
}
}
fflush(fp);
}
int mawk_fdump(mawk_state_t * MAWK)
{
register struct mawk_fdump *p, *q = MAWK->fdump_list;
int dumped = 0;
while (q) {
p = q;
q = p->link;
if (dumped)
fprintf(stdout, "\n");
fprintf(stdout, "function %s\n", p->fbp->name);
mawk_da(MAWK, p->fbp->code, stdout);
dumped++;
}
return dumped;
}
static void mawk_symdump(mawk_state_t * MAWK, int verbose)
{
HASHNODE *p;
int i;
for (i = 0; i < HASH_PRIME; i++) {
p = MAWK->hash_table[i];
while (p) {
switch (p->symtab.type) {
case ST_NONE:
break;
case ST_VAR: fprintf(stdout, "%s var\n", p->symtab.name); break;
case ST_KEYWORD: if (verbose) fprintf(stdout, "%s keyword\n", p->symtab.name); break;
case ST_BUILTIN: if (verbose) fprintf(stdout, "%s builtin\n", p->symtab.name); break;
case ST_ARRAY: fprintf(stdout, "%s array\n", p->symtab.name); break;
case ST_FIELD: if (verbose) fprintf(stdout, "%s field\n", p->symtab.name); break;
case ST_FUNCT: if (verbose) fprintf(stdout, "%s funct\n", p->symtab.name); break;
case ST_NR: if (verbose) fprintf(stdout, "%s <NR>\n", p->symtab.name); break;
case ST_LENGTH: if (verbose) fprintf(stdout, "%s <length>\n", p->symtab.name); break;
case ST_LOCAL_NONE:
case ST_LOCAL_VAR:
case ST_LOCAL_ARRAY:
fprintf(stdout, "%s ?local?\n", p->symtab.name); break;
case ST_C_FUNCTION: if (verbose) fprintf(stdout, "%s C-function\n", p->symtab.name); break;
}
p = p->link;
}
}
}
void mawk_dump_code_text(mawk_state_t * MAWK)
{
int fdmp;
/* dumps all user functions */
fdmp = mawk_fdump(MAWK);
if (MAWK->begin_start) {
if (fdmp)
fprintf(stdout, "\n");
fprintf(stdout, "BEGIN\n");
mawk_da(MAWK, MAWK->begin_start, stdout);
fdmp++;
}
if (MAWK->main_start) {
if (fdmp)
fprintf(stdout, "\n");
fprintf(stdout, "MAIN\n");
mawk_da(MAWK, MAWK->main_start, stdout);
fdmp++;
}
if (MAWK->end_start) {
if (fdmp)
fprintf(stdout, "\n");
fprintf(stdout, "END\n");
mawk_da(MAWK, MAWK->end_start, stdout);
fdmp++;
}
}
void mawk_dump_sym_text(mawk_state_t * MAWK)
{
fprintf(stdout, "SYMBOLS (global)\n");
mawk_symdump(MAWK, 0);
(void)mawk_f2d(NULL); /* suppress compiler warning on unused func */
}