|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* symbol.c - routines for symbol table management and code allocation
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Copyright (C) 1986, 1988, 1989, 1991-2015, 2017, 2018,
|
|
Packit Service |
f629e6 |
* the Free Software Foundation, Inc.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* This file is part of GAWK, the GNU implementation of the
|
|
Packit Service |
f629e6 |
* AWK Programming Language.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK is free software; you can redistribute it and/or modify
|
|
Packit Service |
f629e6 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
f629e6 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit Service |
f629e6 |
* (at your option) any later version.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK is distributed in the hope that it will be useful,
|
|
Packit Service |
f629e6 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f629e6 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
f629e6 |
* GNU General Public License for more details.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
f629e6 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
f629e6 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include "awk.h"
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
extern SRCFILE *srcfiles;
|
|
Packit Service |
f629e6 |
extern INSTRUCTION *rule_list;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#define HASHSIZE 1021
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static int func_count; /* total number of functions */
|
|
Packit Service |
f629e6 |
static int var_count; /* total number of global variables and functions */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static NODE *symbol_list;
|
|
Packit Service |
f629e6 |
static void (*install_func)(NODE *) = NULL;
|
|
Packit Service |
f629e6 |
static NODE *make_symbol(const char *name, NODETYPE type);
|
|
Packit Service |
f629e6 |
static NODE *install(const char *name, NODE *parm, NODETYPE type);
|
|
Packit Service |
f629e6 |
static void free_bcpool(INSTRUCTION_POOL *pl);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static AWK_CONTEXT *curr_ctxt = NULL;
|
|
Packit Service |
f629e6 |
static int ctxt_level;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static NODE *global_table, *param_table;
|
|
Packit Service |
f629e6 |
NODE *symbol_table, *func_table;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Use a flag to avoid a strcmp() call inside install() */
|
|
Packit Service |
f629e6 |
static bool installing_specials = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* init_symbol_table --- make sure the symbol tables are initialized */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
init_symbol_table()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
getnode(global_table);
|
|
Packit Service |
f629e6 |
memset(global_table, '\0', sizeof(NODE));
|
|
Packit Service |
f629e6 |
null_array(global_table);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
getnode(param_table);
|
|
Packit Service |
f629e6 |
memset(param_table, '\0', sizeof(NODE));
|
|
Packit Service |
f629e6 |
null_array(param_table);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
installing_specials = true;
|
|
Packit Service |
f629e6 |
func_table = install_symbol(estrdup("FUNCTAB", 7), Node_var_array);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
symbol_table = install_symbol(estrdup("SYMTAB", 6), Node_var_array);
|
|
Packit Service |
f629e6 |
installing_specials = false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* install_symbol:
|
|
Packit Service |
f629e6 |
* Install a global name in the symbol table, even if it is already there.
|
|
Packit Service |
f629e6 |
* Caller must check against redefinition if that is desired.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
NODE *
|
|
Packit Service |
f629e6 |
install_symbol(const char *name, NODETYPE type)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return install(name, NULL, type);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* lookup --- find the most recent global or param node for name
|
|
Packit Service |
f629e6 |
* installed by install_symbol
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
NODE *
|
|
Packit Service |
f629e6 |
lookup(const char *name)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *n;
|
|
Packit Service |
f629e6 |
NODE *tmp;
|
|
Packit Service |
f629e6 |
NODE *tables[5]; /* manual init below, for z/OS */
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* ``It's turtles, all the way down.'' */
|
|
Packit Service |
f629e6 |
tables[0] = param_table; /* parameters shadow everything */
|
|
Packit Service |
f629e6 |
tables[1] = global_table; /* SYMTAB and FUNCTAB found first, can't be redefined */
|
|
Packit Service |
f629e6 |
tables[2] = func_table; /* then functions */
|
|
Packit Service |
f629e6 |
tables[3] = symbol_table; /* then globals */
|
|
Packit Service |
f629e6 |
tables[4] = NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
tmp = make_string(name, strlen(name));
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
n = NULL;
|
|
Packit Service |
f629e6 |
for (i = 0; tables[i] != NULL; i++) {
|
|
Packit Service |
f629e6 |
if (tables[i]->table_size == 0)
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if ((do_posix || do_traditional) && tables[i] == global_table)
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
n = in_array(tables[i], tmp);
|
|
Packit Service |
f629e6 |
if (n != NULL)
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
unref(tmp);
|
|
Packit Service |
f629e6 |
if (n == NULL || n->type == Node_val) /* non-variable in SYMTAB */
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
return n; /* new place */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* make_params --- allocate function parameters for the symbol table */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
NODE *
|
|
Packit Service |
f629e6 |
make_params(char **pnames, int pcount)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *p, *parms;
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (pcount <= 0 || pnames == NULL)
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ezalloc(parms, NODE *, pcount * sizeof(NODE), "make_params");
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0, p = parms; i < pcount; i++, p++) {
|
|
Packit Service |
f629e6 |
p->type = Node_param_list;
|
|
Packit Service |
f629e6 |
p->param = pnames[i]; /* shadows pname and vname */
|
|
Packit Service |
f629e6 |
p->param_cnt = i;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return parms;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* install_params --- install function parameters into the symbol table */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
install_params(NODE *func)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i, pcount;
|
|
Packit Service |
f629e6 |
NODE *parms;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (func == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(func->type == Node_func);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if ( (pcount = func->param_cnt) <= 0
|
|
Packit Service |
f629e6 |
|| (parms = func->fparms) == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; i < pcount; i++)
|
|
Packit Service |
f629e6 |
(void) install(parms[i].param, parms + i, Node_param_list);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* remove_params --- remove function parameters out of the symbol table.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
remove_params(NODE *func)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *parms, *p;
|
|
Packit Service |
f629e6 |
int i, pcount;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (func == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(func->type == Node_func);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if ( (pcount = func->param_cnt) <= 0
|
|
Packit Service |
f629e6 |
|| (parms = func->fparms) == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = pcount - 1; i >= 0; i--) {
|
|
Packit Service |
f629e6 |
NODE *tmp;
|
|
Packit Service |
f629e6 |
NODE *tmp2;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
p = parms + i;
|
|
Packit Service |
f629e6 |
assert(p->type == Node_param_list);
|
|
Packit Service |
f629e6 |
tmp = make_string(p->vname, strlen(p->vname));
|
|
Packit Service |
f629e6 |
tmp2 = in_array(param_table, tmp);
|
|
Packit Service |
f629e6 |
if (tmp2 != NULL && tmp2->dup_ent != NULL)
|
|
Packit Service |
f629e6 |
tmp2->dup_ent = tmp2->dup_ent->dup_ent;
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
(void) assoc_remove(param_table, tmp);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
unref(tmp);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assoc_clear(param_table); /* shazzam! */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* remove_symbol --- remove a symbol from the symbol table */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
NODE *
|
|
Packit Service |
f629e6 |
remove_symbol(NODE *r)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *n = in_array(symbol_table, r);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (n == NULL)
|
|
Packit Service |
f629e6 |
return n;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
n = dupnode(n);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
(void) assoc_remove(symbol_table, r);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return n;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* destroy_symbol --- remove a symbol from symbol table
|
|
Packit Service |
f629e6 |
* and free all associated memory.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
destroy_symbol(NODE *r)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
r = remove_symbol(r);
|
|
Packit Service |
f629e6 |
if (r == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
switch (r->type) {
|
|
Packit Service |
f629e6 |
case Node_func:
|
|
Packit Service |
f629e6 |
if (r->param_cnt > 0) {
|
|
Packit Service |
f629e6 |
NODE *n;
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
int pcount = r->param_cnt;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* function parameters of type Node_param_list */
|
|
Packit Service |
f629e6 |
for (i = 0; i < pcount; i++) {
|
|
Packit Service |
f629e6 |
n = r->fparms + i;
|
|
Packit Service |
f629e6 |
efree(n->param);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
efree(r->fparms);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Node_ext_func:
|
|
Packit Service |
f629e6 |
bcfree(r->code_ptr);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Node_var_array:
|
|
Packit Service |
f629e6 |
assoc_clear(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Node_var:
|
|
Packit Service |
f629e6 |
unref(r->var_value);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
/* Node_param_list -- YYABORT */
|
|
Packit Service |
f629e6 |
break; /* use break so that storage is freed */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
efree(r->vname);
|
|
Packit Service |
f629e6 |
freenode(r);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* make_symbol --- allocates a global symbol for the symbol table. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static NODE *
|
|
Packit Service |
f629e6 |
make_symbol(const char *name, NODETYPE type)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *r;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
getnode(r);
|
|
Packit Service |
f629e6 |
memset(r, '\0', sizeof(NODE));
|
|
Packit Service |
f629e6 |
if (type == Node_var_array)
|
|
Packit Service |
f629e6 |
null_array(r);
|
|
Packit Service |
f629e6 |
else if (type == Node_var)
|
|
Packit Service |
f629e6 |
r->var_value = dupnode(Nnull_string);
|
|
Packit Service |
f629e6 |
r->vname = (char *) name;
|
|
Packit Service |
f629e6 |
r->type = type;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return r;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* install --- install a global name or function parameter in the symbol table */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static NODE *
|
|
Packit Service |
f629e6 |
install(const char *name, NODE *parm, NODETYPE type)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *r;
|
|
Packit Service |
f629e6 |
NODE **aptr;
|
|
Packit Service |
f629e6 |
NODE *table;
|
|
Packit Service |
f629e6 |
NODE *n_name;
|
|
Packit Service |
f629e6 |
NODE *prev;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
n_name = make_string(name, strlen(name));
|
|
Packit Service |
f629e6 |
table = symbol_table;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (type == Node_param_list) {
|
|
Packit Service |
f629e6 |
table = param_table;
|
|
Packit Service |
f629e6 |
} else if ( type == Node_func
|
|
Packit Service |
f629e6 |
|| type == Node_ext_func
|
|
Packit Service |
f629e6 |
|| type == Node_builtin_func) {
|
|
Packit Service |
f629e6 |
table = func_table;
|
|
Packit Service |
f629e6 |
} else if (installing_specials) {
|
|
Packit Service |
f629e6 |
table = global_table;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (parm != NULL)
|
|
Packit Service |
f629e6 |
r = parm;
|
|
Packit Service |
f629e6 |
else {
|
|
Packit Service |
f629e6 |
/* global symbol */
|
|
Packit Service |
f629e6 |
r = make_symbol(name, type);
|
|
Packit Service |
f629e6 |
if (type == Node_func)
|
|
Packit Service |
f629e6 |
func_count++;
|
|
Packit Service |
f629e6 |
if (type != Node_ext_func && type != Node_builtin_func && table != global_table)
|
|
Packit Service |
f629e6 |
var_count++; /* total, includes Node_func */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (type == Node_param_list) {
|
|
Packit Service |
f629e6 |
prev = in_array(table, n_name);
|
|
Packit Service |
f629e6 |
if (prev == NULL)
|
|
Packit Service |
f629e6 |
goto simple;
|
|
Packit Service |
f629e6 |
r->dup_ent = prev->dup_ent;
|
|
Packit Service |
f629e6 |
prev->dup_ent = r;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
simple:
|
|
Packit Service |
f629e6 |
/* the simple case */
|
|
Packit Service |
f629e6 |
aptr = assoc_lookup(table, n_name);
|
|
Packit Service |
f629e6 |
unref(*aptr);
|
|
Packit Service |
f629e6 |
*aptr = r;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
unref(n_name);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (install_func)
|
|
Packit Service |
f629e6 |
(*install_func)(r);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return r;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* comp_symbol --- compare two (variable or function) names */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static int
|
|
Packit Service |
f629e6 |
comp_symbol(const void *v1, const void *v2)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
const NODE *const *npp1, *const *npp2;
|
|
Packit Service |
f629e6 |
const NODE *n1, *n2;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
npp1 = (const NODE *const *) v1;
|
|
Packit Service |
f629e6 |
npp2 = (const NODE *const *) v2;
|
|
Packit Service |
f629e6 |
n1 = *npp1;
|
|
Packit Service |
f629e6 |
n2 = *npp2;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return strcmp(n1->vname, n2->vname);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
typedef enum { FUNCTION = 1, VARIABLE } SYMBOL_TYPE;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* get_symbols --- return a list of optionally sorted symbols */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static NODE **
|
|
Packit Service |
f629e6 |
get_symbols(SYMBOL_TYPE what, bool sort)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
NODE **table;
|
|
Packit Service |
f629e6 |
NODE **list;
|
|
Packit Service |
f629e6 |
NODE *r;
|
|
Packit Service |
f629e6 |
long count = 0;
|
|
Packit Service |
f629e6 |
long max;
|
|
Packit Service |
f629e6 |
NODE *the_table;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* assoc_list() returns an array with two elements per awk array
|
|
Packit Service |
f629e6 |
* element. Elements i and i+1 in the C array represent the key
|
|
Packit Service |
f629e6 |
* and value of element j in the awk array. Thus the loops use += 2
|
|
Packit Service |
f629e6 |
* to go through the awk array.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (what == FUNCTION) {
|
|
Packit Service |
f629e6 |
the_table = func_table;
|
|
Packit Service |
f629e6 |
max = the_table->table_size * 2;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
list = assoc_list(the_table, "@unsorted", ASORTI);
|
|
Packit Service |
f629e6 |
emalloc(table, NODE **, (func_count + 1) * sizeof(NODE *), "get_symbols");
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = count = 0; i < max; i += 2) {
|
|
Packit Service |
f629e6 |
r = list[i+1];
|
|
Packit Service |
f629e6 |
if (r->type == Node_ext_func || r->type == Node_builtin_func)
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
assert(r->type == Node_func);
|
|
Packit Service |
f629e6 |
table[count++] = r;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
} else { /* what == VARIABLE */
|
|
Packit Service |
f629e6 |
update_global_values();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
the_table = symbol_table;
|
|
Packit Service |
f629e6 |
max = the_table->table_size * 2;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
list = assoc_list(the_table, "@unsorted", ASORTI);
|
|
Packit Service |
f629e6 |
/* add three: one for FUNCTAB, one for SYMTAB, and one for a final NULL */
|
|
Packit Service |
f629e6 |
emalloc(table, NODE **, (var_count + 1 + 1 + 1) * sizeof(NODE *), "get_symbols");
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = count = 0; i < max; i += 2) {
|
|
Packit Service |
f629e6 |
r = list[i+1];
|
|
Packit Service |
f629e6 |
if (r->type == Node_val) /* non-variable in SYMTAB */
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
table[count++] = r;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
table[count++] = func_table;
|
|
Packit Service |
f629e6 |
table[count++] = symbol_table;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
efree(list);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (sort && count > 1)
|
|
Packit Service |
f629e6 |
qsort(table, count, sizeof(NODE *), comp_symbol); /* Shazzam! */
|
|
Packit Service |
f629e6 |
table[count] = NULL; /* null terminate the list */
|
|
Packit Service |
f629e6 |
return table;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* variable_list --- list of global variables */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
NODE **
|
|
Packit Service |
f629e6 |
variable_list()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return get_symbols(VARIABLE, true);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* function_list --- list of functions */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
NODE **
|
|
Packit Service |
f629e6 |
function_list(bool sort)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return get_symbols(FUNCTION, sort);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* print_vars --- print names and values of global variables */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
print_vars(NODE **table, int (*print_func)(FILE *, const char *, ...), FILE *fp)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
NODE *r;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(table != NULL);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; (r = table[i]) != NULL; i++) {
|
|
Packit Service |
f629e6 |
if (r->type == Node_func || r->type == Node_ext_func)
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
print_func(fp, "%s: ", r->vname);
|
|
Packit Service |
f629e6 |
if (r->type == Node_var_array)
|
|
Packit Service |
f629e6 |
print_func(fp, "array, %ld elements\n", assoc_length(r));
|
|
Packit Service |
f629e6 |
else if (r->type == Node_var_new)
|
|
Packit Service |
f629e6 |
print_func(fp, "untyped variable\n");
|
|
Packit Service |
f629e6 |
else if (r->type == Node_var)
|
|
Packit Service |
f629e6 |
valinfo(r->var_value, print_func, fp);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* foreach_func --- execute given function for each awk function in table. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
foreach_func(NODE **table, int (*pfunc)(INSTRUCTION *, void *), void *data)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
NODE *r;
|
|
Packit Service |
f629e6 |
int ret = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(table != NULL);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; (r = table[i]) != NULL; i++) {
|
|
Packit Service |
f629e6 |
if ((ret = pfunc(r->code_ptr, data)) != 0)
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return ret;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* release_all_vars --- free all variable memory */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
release_all_vars()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
assoc_clear(symbol_table);
|
|
Packit Service |
f629e6 |
assoc_clear(func_table);
|
|
Packit Service |
f629e6 |
assoc_clear(global_table);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* append_symbol --- append symbol to the list of symbols
|
|
Packit Service |
f629e6 |
* installed in the symbol table.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
append_symbol(NODE *r)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *p;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
getnode(p);
|
|
Packit Service |
f629e6 |
p->lnode = r;
|
|
Packit Service |
f629e6 |
p->rnode = symbol_list->rnode;
|
|
Packit Service |
f629e6 |
symbol_list->rnode = p;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* release_symbols --- free symbol list and optionally remove symbol from symbol table */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
release_symbols(NODE *symlist, int keep_globals)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *p, *next;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (p = symlist->rnode; p != NULL; p = next) {
|
|
Packit Service |
f629e6 |
if (! keep_globals) {
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* destroys globals, function, and params
|
|
Packit Service |
f629e6 |
* if still in symbol table
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
destroy_symbol(p->lnode);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
next = p->rnode;
|
|
Packit Service |
f629e6 |
freenode(p);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
symlist->rnode = NULL;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* load_symbols --- fill in symbols' information */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
load_symbols()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *r;
|
|
Packit Service |
f629e6 |
NODE *tmp;
|
|
Packit Service |
f629e6 |
NODE *sym_array;
|
|
Packit Service |
f629e6 |
NODE **aptr;
|
|
Packit Service |
f629e6 |
long i, j, max;
|
|
Packit Service |
f629e6 |
NODE *user, *extension, *untyped, *scalar, *array, *built_in;
|
|
Packit Service |
f629e6 |
NODE **list;
|
|
Packit Service |
f629e6 |
NODE *tables[4];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (PROCINFO_node == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
tables[0] = func_table;
|
|
Packit Service |
f629e6 |
tables[1] = symbol_table;
|
|
Packit Service |
f629e6 |
tables[2] = global_table;
|
|
Packit Service |
f629e6 |
tables[3] = NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
tmp = make_string("identifiers", 11);
|
|
Packit Service |
f629e6 |
aptr = assoc_lookup(PROCINFO_node, tmp);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
getnode(sym_array);
|
|
Packit Service |
f629e6 |
memset(sym_array, '\0', sizeof(NODE)); /* PPC Mac OS X wants this */
|
|
Packit Service |
f629e6 |
null_array(sym_array);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
unref(tmp);
|
|
Packit Service |
f629e6 |
unref(*aptr);
|
|
Packit Service |
f629e6 |
*aptr = sym_array;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
sym_array->parent_array = PROCINFO_node;
|
|
Packit Service |
f629e6 |
sym_array->vname = estrdup("identifiers", 11);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
user = make_string("user", 4);
|
|
Packit Service |
f629e6 |
extension = make_string("extension", 9);
|
|
Packit Service |
f629e6 |
scalar = make_string("scalar", 6);
|
|
Packit Service |
f629e6 |
untyped = make_string("untyped", 7);
|
|
Packit Service |
f629e6 |
array = make_string("array", 5);
|
|
Packit Service |
f629e6 |
built_in = make_string("builtin", 7);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; tables[i] != NULL; i++) {
|
|
Packit Service |
f629e6 |
list = assoc_list(tables[i], "@unsorted", ASORTI);
|
|
Packit Service |
f629e6 |
max = tables[i]->table_size * 2;
|
|
Packit Service |
f629e6 |
if (max == 0)
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
for (j = 0; j < max; j += 2) {
|
|
Packit Service |
f629e6 |
r = list[j+1];
|
|
Packit Service |
f629e6 |
if ( r->type == Node_ext_func
|
|
Packit Service |
f629e6 |
|| r->type == Node_func
|
|
Packit Service |
f629e6 |
|| r->type == Node_builtin_func
|
|
Packit Service |
f629e6 |
|| r->type == Node_var
|
|
Packit Service |
f629e6 |
|| r->type == Node_var_array
|
|
Packit Service |
f629e6 |
|| r->type == Node_var_new) {
|
|
Packit Service |
f629e6 |
tmp = make_string(r->vname, strlen(r->vname));
|
|
Packit Service |
f629e6 |
aptr = assoc_lookup(sym_array, tmp);
|
|
Packit Service |
f629e6 |
unref(tmp);
|
|
Packit Service |
f629e6 |
unref(*aptr);
|
|
Packit Service |
f629e6 |
switch (r->type) {
|
|
Packit Service |
f629e6 |
case Node_ext_func:
|
|
Packit Service |
f629e6 |
*aptr = dupnode(extension);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Node_func:
|
|
Packit Service |
f629e6 |
*aptr = dupnode(user);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Node_builtin_func:
|
|
Packit Service |
f629e6 |
*aptr = dupnode(built_in);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Node_var:
|
|
Packit Service |
f629e6 |
*aptr = dupnode(scalar);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Node_var_array:
|
|
Packit Service |
f629e6 |
*aptr = dupnode(array);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Node_var_new:
|
|
Packit Service |
f629e6 |
*aptr = dupnode(untyped);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
cant_happen();
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
efree(list);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
unref(user);
|
|
Packit Service |
f629e6 |
unref(extension);
|
|
Packit Service |
f629e6 |
unref(scalar);
|
|
Packit Service |
f629e6 |
unref(untyped);
|
|
Packit Service |
f629e6 |
unref(array);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* check_param_names --- make sure no parameter is the name of a function */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
bool
|
|
Packit Service |
f629e6 |
check_param_names(void)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i, j;
|
|
Packit Service |
f629e6 |
NODE **list;
|
|
Packit Service |
f629e6 |
NODE *f;
|
|
Packit Service |
f629e6 |
long max;
|
|
Packit Service |
f629e6 |
bool result = true;
|
|
Packit Service |
f629e6 |
NODE n;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (func_table->table_size == 0)
|
|
Packit Service |
f629e6 |
return result;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
max = func_table->table_size * 2;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
memset(& n, 0, sizeof n);
|
|
Packit Service |
f629e6 |
n.type = Node_val;
|
|
Packit Service |
f629e6 |
n.flags = STRING|STRCUR;
|
|
Packit Service |
f629e6 |
n.stfmt = STFMT_UNUSED;
|
|
Packit Service |
f629e6 |
#ifdef HAVE_MPFR
|
|
Packit Service |
f629e6 |
n.strndmode = MPFR_round_mode;
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* assoc_list() returns an array with two elements per awk array
|
|
Packit Service |
f629e6 |
* element. Elements i and i+1 in the C array represent the key
|
|
Packit Service |
f629e6 |
* and value of element j in the awk array. Thus the loops use += 2
|
|
Packit Service |
f629e6 |
* to go through the awk array.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* In this case, the name is in list[i], and the function is
|
|
Packit Service |
f629e6 |
* in list[i+1]. Just what we need.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
list = assoc_list(func_table, "@unsorted", ASORTI);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; i < max; i += 2) {
|
|
Packit Service |
f629e6 |
f = list[i+1];
|
|
Packit Service |
f629e6 |
if (f->type == Node_builtin_func || f->param_cnt == 0)
|
|
Packit Service |
f629e6 |
continue;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* loop over each param in function i */
|
|
Packit Service |
f629e6 |
for (j = 0; j < f->param_cnt; j++) {
|
|
Packit Service |
f629e6 |
/* compare to function names */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* use a fake node to avoid malloc/free of make_string */
|
|
Packit Service |
f629e6 |
n.stptr = f->fparms[j].param;
|
|
Packit Service |
f629e6 |
n.stlen = strlen(f->fparms[j].param);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (in_array(func_table, & n)) {
|
|
Packit Service |
f629e6 |
error(
|
|
Packit Service |
f629e6 |
_("function `%s': can't use function `%s' as a parameter name"),
|
|
Packit Service |
f629e6 |
list[i]->stptr,
|
|
Packit Service |
f629e6 |
f->fparms[j].param);
|
|
Packit Service |
f629e6 |
result = false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
efree(list);
|
|
Packit Service |
f629e6 |
return result;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static INSTRUCTION_POOL *pools;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* For best performance, the INSTR_CHUNK value should be divisible by all
|
|
Packit Service |
f629e6 |
* possible sizes, i.e. 1 through MAX_INSTRUCTION_ALLOC. Otherwise, there
|
|
Packit Service |
f629e6 |
* will be wasted space at the end of the block.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
#define INSTR_CHUNK (2*3*21)
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
struct instruction_block {
|
|
Packit Service |
f629e6 |
struct instruction_block *next;
|
|
Packit Service |
f629e6 |
INSTRUCTION i[INSTR_CHUNK];
|
|
Packit Service |
f629e6 |
};
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* bcfree --- deallocate instruction */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
bcfree(INSTRUCTION *cp)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
assert(cp->pool_size >= 1 && cp->pool_size <= MAX_INSTRUCTION_ALLOC);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
cp->opcode = Op_illegal;
|
|
Packit Service |
f629e6 |
cp->nexti = pools->pool[cp->pool_size - 1].free_list;
|
|
Packit Service |
f629e6 |
pools->pool[cp->pool_size - 1].free_list = cp;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* bcalloc --- allocate a new instruction */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
INSTRUCTION *
|
|
Packit Service |
f629e6 |
bcalloc(OPCODE op, int size, int srcline)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
INSTRUCTION *cp;
|
|
Packit Service |
f629e6 |
struct instruction_mem_pool *pool;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(size >= 1 && size <= MAX_INSTRUCTION_ALLOC);
|
|
Packit Service |
f629e6 |
pool = &pools->pool[size - 1];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (pool->free_list != NULL) {
|
|
Packit Service |
f629e6 |
cp = pool->free_list;
|
|
Packit Service |
f629e6 |
pool->free_list = cp->nexti;
|
|
Packit Service |
f629e6 |
} else if (pool->free_space && pool->free_space + size <= & pool->block_list->i[INSTR_CHUNK]) {
|
|
Packit Service |
f629e6 |
cp = pool->free_space;
|
|
Packit Service |
f629e6 |
pool->free_space += size;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
struct instruction_block *block;
|
|
Packit Service |
f629e6 |
emalloc(block, struct instruction_block *, sizeof(struct instruction_block), "bcalloc");
|
|
Packit Service |
f629e6 |
block->next = pool->block_list;
|
|
Packit Service |
f629e6 |
pool->block_list = block;
|
|
Packit Service |
f629e6 |
cp = &block->i[0];
|
|
Packit Service |
f629e6 |
pool->free_space = &block->i[size];
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
memset(cp, 0, size * sizeof(INSTRUCTION));
|
|
Packit Service |
f629e6 |
cp->pool_size = size;
|
|
Packit Service |
f629e6 |
cp->opcode = op;
|
|
Packit Service |
f629e6 |
cp->source_line = srcline;
|
|
Packit Service |
f629e6 |
return cp;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* new_context --- create a new execution context. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
AWK_CONTEXT *
|
|
Packit Service |
f629e6 |
new_context()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
AWK_CONTEXT *ctxt;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ezalloc(ctxt, AWK_CONTEXT *, sizeof(AWK_CONTEXT), "new_context");
|
|
Packit Service |
f629e6 |
ctxt->srcfiles.next = ctxt->srcfiles.prev = & ctxt->srcfiles;
|
|
Packit Service |
f629e6 |
ctxt->rule_list.opcode = Op_list;
|
|
Packit Service |
f629e6 |
ctxt->rule_list.lasti = & ctxt->rule_list;
|
|
Packit Service |
f629e6 |
return ctxt;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* set_context --- change current execution context. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
set_context(AWK_CONTEXT *ctxt)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
pools = & ctxt->pools;
|
|
Packit Service |
f629e6 |
symbol_list = & ctxt->symbols;
|
|
Packit Service |
f629e6 |
srcfiles = & ctxt->srcfiles;
|
|
Packit Service |
f629e6 |
rule_list = & ctxt->rule_list;
|
|
Packit Service |
f629e6 |
install_func = ctxt->install_func;
|
|
Packit Service |
f629e6 |
curr_ctxt = ctxt;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* push_context:
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* Switch to the given context after saving the current one. The set
|
|
Packit Service |
f629e6 |
* of active execution contexts forms a stack; the global or main context
|
|
Packit Service |
f629e6 |
* is at the bottom of the stack.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
push_context(AWK_CONTEXT *ctxt)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
ctxt->prev = curr_ctxt;
|
|
Packit Service |
f629e6 |
/* save current source and sourceline */
|
|
Packit Service |
f629e6 |
if (curr_ctxt != NULL) {
|
|
Packit Service |
f629e6 |
curr_ctxt->sourceline = sourceline;
|
|
Packit Service |
f629e6 |
curr_ctxt->source = source;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
sourceline = 0;
|
|
Packit Service |
f629e6 |
source = NULL;
|
|
Packit Service |
f629e6 |
set_context(ctxt);
|
|
Packit Service |
f629e6 |
ctxt_level++;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* pop_context --- switch to previous execution context. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
pop_context()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
AWK_CONTEXT *ctxt;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(curr_ctxt != NULL);
|
|
Packit Service |
f629e6 |
if (curr_ctxt->prev == NULL)
|
|
Packit Service |
f629e6 |
fatal(_("can not pop main context"));
|
|
Packit Service |
f629e6 |
ctxt = curr_ctxt->prev;
|
|
Packit Service |
f629e6 |
/* restore source and sourceline */
|
|
Packit Service |
f629e6 |
sourceline = ctxt->sourceline;
|
|
Packit Service |
f629e6 |
source = ctxt->source;
|
|
Packit Service |
f629e6 |
set_context(ctxt);
|
|
Packit Service |
f629e6 |
ctxt_level--;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* in_main_context --- are we in the main context ? */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
in_main_context()
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
assert(ctxt_level > 0);
|
|
Packit Service |
f629e6 |
return (ctxt_level == 1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free_context --- free context structure and related data. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
free_context(AWK_CONTEXT *ctxt, bool keep_globals)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SRCFILE *s, *sn;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (ctxt == NULL)
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(curr_ctxt != ctxt);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free all code including function codes */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
free_bcpool(& ctxt->pools);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free symbols */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
release_symbols(& ctxt->symbols, keep_globals);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free srcfiles */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (s = & ctxt->srcfiles; s != & ctxt->srcfiles; s = sn) {
|
|
Packit Service |
f629e6 |
sn = s->next;
|
|
Packit Service |
f629e6 |
if (s->stype != SRC_CMDLINE && s->stype != SRC_STDIN)
|
|
Packit Service |
f629e6 |
efree(s->fullpath);
|
|
Packit Service |
f629e6 |
efree(s->src);
|
|
Packit Service |
f629e6 |
efree(s);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
efree(ctxt);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free_bc_internal --- free internal memory of an instruction. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
free_bc_internal(INSTRUCTION *cp)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *m;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
switch(cp->opcode) {
|
|
Packit Service |
f629e6 |
case Op_func_call:
|
|
Packit Service |
f629e6 |
if (cp->func_name != NULL)
|
|
Packit Service |
f629e6 |
efree(cp->func_name);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Op_push_re:
|
|
Packit Service |
f629e6 |
case Op_match_rec:
|
|
Packit Service |
f629e6 |
case Op_match:
|
|
Packit Service |
f629e6 |
case Op_nomatch:
|
|
Packit Service |
f629e6 |
m = cp->memory;
|
|
Packit Service |
f629e6 |
if (m->re_reg[0] != NULL)
|
|
Packit Service |
f629e6 |
refree(m->re_reg[0]);
|
|
Packit Service |
f629e6 |
if (m->re_reg[1] != NULL)
|
|
Packit Service |
f629e6 |
refree(m->re_reg[1]);
|
|
Packit Service |
f629e6 |
if (m->re_exp != NULL)
|
|
Packit Service |
f629e6 |
unref(m->re_exp);
|
|
Packit Service |
f629e6 |
if (m->re_text != NULL)
|
|
Packit Service |
f629e6 |
unref(m->re_text);
|
|
Packit Service |
f629e6 |
freenode(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Op_token:
|
|
Packit Service |
f629e6 |
/* token lost during error recovery in yyparse */
|
|
Packit Service |
f629e6 |
if (cp->lextok != NULL)
|
|
Packit Service |
f629e6 |
efree(cp->lextok);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Op_push_i:
|
|
Packit Service |
f629e6 |
m = cp->memory;
|
|
Packit Service |
f629e6 |
unref(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Op_store_var:
|
|
Packit Service |
f629e6 |
m = cp->initval;
|
|
Packit Service |
f629e6 |
if (m != NULL)
|
|
Packit Service |
f629e6 |
unref(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case Op_illegal:
|
|
Packit Service |
f629e6 |
cant_happen();
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free_bc_mempool --- free a single pool */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
free_bc_mempool(struct instruction_mem_pool *pool, int size)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
bool first = true;
|
|
Packit Service |
f629e6 |
struct instruction_block *block, *next;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (block = pool->block_list; block; block = next) {
|
|
Packit Service |
f629e6 |
INSTRUCTION *cp, *end;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
end = (first ? pool->free_space : & block->i[INSTR_CHUNK]);
|
|
Packit Service |
f629e6 |
for (cp = & block->i[0]; cp + size <= end; cp += size) {
|
|
Packit Service |
f629e6 |
if (cp->opcode != Op_illegal)
|
|
Packit Service |
f629e6 |
free_bc_internal(cp);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
next = block->next;
|
|
Packit Service |
f629e6 |
efree(block);
|
|
Packit Service |
f629e6 |
first = false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* free_bcpool --- free list of instruction memory pools */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
free_bcpool(INSTRUCTION_POOL *pl)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; i < MAX_INSTRUCTION_ALLOC; i++)
|
|
Packit Service |
f629e6 |
free_bc_mempool(& pl->pool[i], i + 1);
|
|
Packit Service |
f629e6 |
}
|