(root)/
gawk-5.2.2/
symbol.c
       1  /*
       2   * symbol.c - routines for symbol table management and code allocation
       3   */
       4  
       5  /*
       6   * Copyright (C) 1986, 1988, 1989, 1991-2015, 2017-2020, 2022, 2023,
       7   * the Free Software Foundation, Inc.
       8   *
       9   * This file is part of GAWK, the GNU implementation of the
      10   * AWK Programming Language.
      11   *
      12   * GAWK is free software; you can redistribute it and/or modify
      13   * it under the terms of the GNU General Public License as published by
      14   * the Free Software Foundation; either version 3 of the License, or
      15   * (at your option) any later version.
      16   *
      17   * GAWK is distributed in the hope that it will be useful,
      18   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20   * GNU General Public License for more details.
      21   *
      22   * You should have received a copy of the GNU General Public License
      23   * along with this program; if not, write to the Free Software
      24   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
      25   */
      26  
      27  #include "awk.h"
      28  
      29  extern SRCFILE *srcfiles;
      30  extern INSTRUCTION *rule_list;
      31  
      32  #define HASHSIZE	1021
      33  
      34  static NODE *symbol_list;
      35  static void (*install_func)(NODE *) = NULL;
      36  static NODE *make_symbol(const char *name, NODETYPE type);
      37  static NODE *install(const char *name, NODE *parm, NODETYPE type);
      38  static void free_bcpool(INSTRUCTION_POOL *pl);
      39  static NODE *get_name_from_awk_ns(const char *name);
      40  
      41  static AWK_CONTEXT *curr_ctxt = NULL;
      42  static int ctxt_level;
      43  
      44  static NODE *global_table, *param_table;
      45  NODE *symbol_table, *func_table;
      46  
      47  /* Use a flag to avoid a strcmp() call inside install() */
      48  static bool installing_specials = false;
      49  
      50  // Using persistent memory, manage the root pointer
      51  // which holds this struct:
      52  struct root_pointers {
      53  	NODE *global_table;
      54  	NODE *func_table;
      55  	NODE *symbol_table;
      56  	struct block_header nextfree[BLOCK_MAX];
      57  	int mpfr;
      58  	bool first;
      59  } *root_pointers = NULL;
      60  
      61  /* init_the_tables --- deal with the tables for in memory use */
      62  
      63  static void
      64  init_the_tables(void)
      65  {
      66  	getnode(global_table);
      67  	memset(global_table, '\0', sizeof(NODE));
      68  	null_array(global_table);
      69  
      70  	getnode(param_table);
      71  	memset(param_table, '\0', sizeof(NODE));
      72  	null_array(param_table);
      73  
      74  	installing_specials = true;
      75  	func_table = install_symbol(estrdup("FUNCTAB", 7), Node_var_array);
      76  	symbol_table = install_symbol(estrdup("SYMTAB", 6), Node_var_array);
      77  	installing_specials = false;
      78  }
      79  
      80  /* init_symbol_table --- make sure the symbol tables are initialized */
      81  
      82  void
      83  init_symbol_table()
      84  {
      85  	if (! using_persistent_malloc) {
      86  		// normal case, initialize regularly, return
      87  		init_the_tables();
      88  		return;
      89  	}
      90  
      91  	root_pointers = (struct root_pointers *) pma_get_root();
      92  
      93  	if (root_pointers == NULL) {
      94  		// very first time!
      95  
      96  		// set up the tables
      97  		init_the_tables();
      98  
      99  		// save the pointers for the next time.
     100  		emalloc(root_pointers, struct root_pointers *, sizeof(struct root_pointers), "init_symbol_table");
     101  		memset(root_pointers, 0, sizeof(struct root_pointers));
     102  		root_pointers->global_table = global_table;
     103  		root_pointers->func_table = func_table;
     104  		root_pointers->symbol_table = symbol_table;
     105  		root_pointers->first = true;
     106  		root_pointers->mpfr = 0;
     107  		pma_set_root(root_pointers);
     108  	} else {
     109  		// this is the next time, get the saved pointers and put them back in place
     110  		global_table = root_pointers->global_table;
     111  		func_table = root_pointers->func_table;
     112  		symbol_table = root_pointers->symbol_table;
     113  		memcpy(nextfree, root_pointers->nextfree, sizeof(nextfree));
     114  
     115  		// still need to set this one up as usual
     116  		getnode(param_table);
     117  		memset(param_table, '\0', sizeof(NODE));
     118  		null_array(param_table);
     119  	}
     120  }
     121  
     122  /* pma_mpfr_check --- check that -M is same between invocations */
     123  
     124  void
     125  pma_mpfr_check(void)
     126  {
     127  	if (! using_persistent_malloc)
     128  		return;
     129  
     130  	if (root_pointers->first) {
     131  		root_pointers->first = false;
     132  		root_pointers->mpfr = do_mpfr;
     133  		return;
     134  	}
     135  
     136  	if (root_pointers->mpfr != do_mpfr)
     137  		fatal(_("current setting of -M/--bignum does not match saved setting in PMA backing file"));
     138  }
     139  
     140  /* pma_save_free_lists --- save the free lists in the root pointer */
     141  
     142  void
     143  pma_save_free_lists(void)
     144  {
     145  	if (! using_persistent_malloc)
     146  		return;
     147  
     148  	assert(! root_pointers->first);
     149  
     150  	memcpy(root_pointers->nextfree, nextfree, sizeof(nextfree));
     151  }
     152  
     153  /*
     154   * install_symbol:
     155   * Install a global name in the symbol table, even if it is already there.
     156   * Caller must check against redefinition if that is desired.
     157   */
     158  
     159  NODE *
     160  install_symbol(const char *name, NODETYPE type)
     161  {
     162  	return install(name, NULL, type);
     163  }
     164  
     165  
     166  /*
     167   * lookup --- find the most recent global or param node for name
     168   *	installed by install_symbol
     169   */
     170  
     171  NODE *
     172  lookup(const char *name)
     173  {
     174  	NODE *n;
     175  	NODE *tmp;
     176  	NODE *tables[5];	/* manual init below, for z/OS */
     177  	int i;
     178  
     179  	/* ``It's turtles, all the way down.'' */
     180  	tables[0] = param_table;	/* parameters shadow everything */
     181  	tables[1] = global_table;	/* SYMTAB and FUNCTAB found first, can't be redefined */
     182  	tables[2] = func_table;		/* then functions */
     183  	tables[3] = symbol_table;	/* then globals */
     184  	tables[4] = NULL;
     185  
     186  	tmp = get_name_from_awk_ns(name);
     187  
     188  	n = NULL;
     189  	for (i = 0; tables[i] != NULL; i++) {
     190  		if (assoc_empty(tables[i]))
     191  			continue;
     192  
     193  		if ((do_posix || do_traditional) && tables[i] == global_table)
     194  			continue;
     195  
     196  		n = in_array(tables[i], tmp);
     197  		if (n != NULL)
     198  			break;
     199  	}
     200  
     201  	unref(tmp);
     202  	if (n == NULL || n->type == Node_val)	/* non-variable in SYMTAB */
     203  		return NULL;
     204  	return n;	/* new place */
     205  }
     206  
     207  /* make_params --- allocate function parameters for the symbol table */
     208  
     209  NODE *
     210  make_params(char **pnames, int pcount)
     211  {
     212  	NODE *p, *parms;
     213  	int i;
     214  
     215  	if (pcount <= 0 || pnames == NULL)
     216  		return NULL;
     217  
     218  	ezalloc(parms, NODE *, pcount * sizeof(NODE), "make_params");
     219  
     220  	for (i = 0, p = parms; i < pcount; i++, p++) {
     221  		p->type = Node_param_list;
     222  		p->param = pnames[i];	/* shadows pname and vname */
     223  		p->param_cnt = i;
     224  	}
     225  
     226  	return parms;
     227  }
     228  
     229  /* install_params --- install function parameters into the symbol table */
     230  
     231  void
     232  install_params(NODE *func)
     233  {
     234  	int i, pcount;
     235  	NODE *parms;
     236  
     237  	if (func == NULL)
     238  		return;
     239  
     240  	assert(func->type == Node_func);
     241  
     242  	if (   (pcount = func->param_cnt) <= 0
     243  	    || (parms = func->fparms) == NULL)
     244  		return;
     245  
     246  	for (i = 0; i < pcount; i++)
     247  		(void) install(parms[i].param, parms + i, Node_param_list);
     248  }
     249  
     250  
     251  /*
     252   * remove_params --- remove function parameters out of the symbol table.
     253   */
     254  
     255  void
     256  remove_params(NODE *func)
     257  {
     258  	NODE *parms, *p;
     259  	int i, pcount;
     260  
     261  	if (func == NULL)
     262  		return;
     263  
     264  	assert(func->type == Node_func);
     265  
     266  	if (   (pcount = func->param_cnt) <= 0
     267  	    || (parms = func->fparms) == NULL)
     268  		return;
     269  
     270  	for (i = pcount - 1; i >= 0; i--) {
     271  		NODE *tmp;
     272  		NODE *tmp2;
     273  
     274  		p = parms + i;
     275  		assert(p->type == Node_param_list);
     276  		tmp = make_string(p->vname, strlen(p->vname));
     277  		tmp2 = in_array(param_table, tmp);
     278  		if (tmp2 != NULL && tmp2->dup_ent != NULL)
     279  			tmp2->dup_ent = tmp2->dup_ent->dup_ent;
     280  		else
     281  			(void) assoc_remove(param_table, tmp);
     282  
     283  		unref(tmp);
     284  	}
     285  
     286  	assoc_clear(param_table);	/* shazzam! */
     287  }
     288  
     289  
     290  /* remove_symbol --- remove a symbol from the symbol table */
     291  
     292  NODE *
     293  remove_symbol(NODE *r)
     294  {
     295  	NODE *n = in_array(symbol_table, r);
     296  
     297  	if (n == NULL)
     298  		return n;
     299  
     300  	n = dupnode(n);
     301  
     302  	(void) assoc_remove(symbol_table, r);
     303  
     304  	return n;
     305  }
     306  
     307  
     308  /*
     309   * destroy_symbol --- remove a symbol from symbol table
     310   *	and free all associated memory.
     311   */
     312  
     313  void
     314  destroy_symbol(NODE *r)
     315  {
     316  	r = remove_symbol(r);
     317  	if (r == NULL)
     318  		return;
     319  
     320  	switch (r->type) {
     321  	case Node_func:
     322  		if (r->param_cnt > 0) {
     323  			NODE *n;
     324  			int i;
     325  			int pcount = r->param_cnt;
     326  
     327  			/* function parameters of type Node_param_list */
     328  			for (i = 0; i < pcount; i++) {
     329  				n = r->fparms + i;
     330  				efree(n->param);
     331  			}
     332  			efree(r->fparms);
     333  		}
     334  		break;
     335  
     336  	case Node_ext_func:
     337  		bcfree(r->code_ptr);
     338  		break;
     339  
     340  	case Node_var_array:
     341  		assoc_clear(r);
     342  		break;
     343  
     344  	case Node_var:
     345  		unref(r->var_value);
     346  		break;
     347  
     348  	default:
     349  		/* Node_param_list -- YYABORT */
     350  		break;	/* use break so that storage is freed */
     351  	}
     352  
     353  	efree(r->vname);
     354  	freenode(r);
     355  }
     356  
     357  
     358  /* make_symbol --- allocates a global symbol for the symbol table. */
     359  
     360  static NODE *
     361  make_symbol(const char *name, NODETYPE type)
     362  {
     363  	NODE *r;
     364  
     365  	getnode(r);
     366  	memset(r, '\0', sizeof(NODE));
     367  	if (type == Node_var_array)
     368  		null_array(r);
     369  	else if (type == Node_var)
     370  		r->var_value = dupnode(Nnull_string);
     371  	r->vname = (char *) name;
     372  	r->type = type;
     373  	r->valref = 1;
     374  
     375  	return r;
     376  }
     377  
     378  /* install --- install a global name or function parameter in the symbol table */
     379  
     380  static NODE *
     381  install(const char *name, NODE *parm, NODETYPE type)
     382  {
     383  	NODE *r;
     384  	NODE *table;
     385  	NODE *n_name;
     386  	NODE *prev;
     387  
     388  	n_name = get_name_from_awk_ns(name);
     389  
     390  	table = symbol_table;
     391  
     392  	if (type == Node_param_list) {
     393  		table = param_table;
     394  	} else if (   type == Node_func
     395  		   || type == Node_ext_func
     396  		   || type == Node_builtin_func) {
     397  		table = func_table;
     398  	} else if (installing_specials) {
     399  		table = global_table;
     400  	}
     401  
     402  	if (parm != NULL)
     403  		r = parm;
     404  	else {
     405  		/* global symbol */
     406  		r = make_symbol(name, type);
     407  	}
     408  
     409  	if (type == Node_param_list) {
     410  		prev = in_array(table, n_name);
     411  		if (prev == NULL)
     412  			goto simple;
     413  		r->dup_ent = prev->dup_ent;
     414  		prev->dup_ent = r;
     415  		unref(n_name);
     416  	} else {
     417  simple:
     418  		/* the simple case */
     419  		assoc_set(table, n_name, r);
     420  	}
     421  
     422  	if (install_func)
     423  		(*install_func)(r);
     424  
     425  	return r;
     426  }
     427  
     428  /* comp_symbol --- compare two (variable or function) names */
     429  
     430  static int
     431  comp_symbol(const void *v1, const void *v2)
     432  {
     433  	const NODE *const *npp1, *const *npp2;
     434  	const NODE *n1, *n2;
     435  
     436  	npp1 = (const NODE *const *) v1;
     437  	npp2 = (const NODE *const *) v2;
     438  	n1 = *npp1;
     439  	n2 = *npp2;
     440  
     441  	// names in awk namespace come out first
     442  	bool n1_is_in_ns = (strchr(n1->vname, ':') != NULL);
     443  	bool n2_is_in_ns = (strchr(n2->vname, ':') != NULL);
     444  
     445  	if (n1_is_in_ns && n2_is_in_ns)
     446  		return strcmp(n1->vname, n2->vname);
     447  	else if (n1_is_in_ns && ! n2_is_in_ns)
     448  		return 1;
     449  	else if (! n1_is_in_ns && n2_is_in_ns)
     450  		return -1;
     451  	else
     452  		return strcmp(n1->vname, n2->vname);
     453  }
     454  
     455  
     456  typedef enum { FUNCTION = 1, VARIABLE } SYMBOL_TYPE;
     457  
     458  /* get_symbols --- return a list of optionally sorted symbols */
     459  
     460  static NODE **
     461  get_symbols(SYMBOL_TYPE what, bool sort)
     462  {
     463  	int i;
     464  	NODE **table;
     465  	NODE **list;
     466  	NODE *r;
     467  	long count = 0;
     468  	long max;
     469  	NODE *the_table;
     470  
     471  	/*
     472  	 * assoc_list() returns an array with two elements per awk array
     473  	 * element. Elements i and i+1 in the C array represent the key
     474  	 * and value of element j in the awk array. Thus the loops use += 2
     475  	 * to go through the awk array.
     476  	 */
     477  
     478  	if (what == FUNCTION) {
     479  		the_table = func_table;
     480  		max = the_table->table_size * 2;
     481  
     482  		list = assoc_list(the_table, "@unsorted", ASORTI);
     483  		emalloc(table, NODE **, (the_table->table_size + 1) * sizeof(NODE *), "get_symbols");
     484  
     485  		for (i = count = 0; i < max; i += 2) {
     486  			r = list[i+1];
     487  			if (r->type == Node_ext_func || r->type == Node_builtin_func)
     488  				continue;
     489  			assert(r->type == Node_func);
     490  			table[count++] = r;
     491  		}
     492  	} else {	/* what == VARIABLE */
     493  		update_global_values();
     494  
     495  		the_table = symbol_table;
     496  		max = the_table->table_size * 2;
     497  
     498  		list = assoc_list(the_table, "@unsorted", ASORTI);
     499  		/* add three: one for FUNCTAB, one for SYMTAB, and one for a final NULL */
     500  		emalloc(table, NODE **, (the_table->table_size + 1 + 1 + 1) * sizeof(NODE *), "get_symbols");
     501  
     502  		for (i = count = 0; i < max; i += 2) {
     503  			r = list[i+1];
     504  			if (r->type == Node_val)	/* non-variable in SYMTAB */
     505  				continue;
     506  			table[count++] = r;
     507  		}
     508  
     509  		table[count++] = func_table;
     510  		table[count++] = symbol_table;
     511  	}
     512  
     513  	efree(list);
     514  
     515  	if (sort && count > 1)
     516  		qsort(table, count, sizeof(NODE *), comp_symbol);	/* Shazzam! */
     517  	table[count] = NULL; /* null terminate the list */
     518  	return table;
     519  }
     520  
     521  
     522  /* variable_list --- list of global variables */
     523  
     524  NODE **
     525  variable_list()
     526  {
     527  	return get_symbols(VARIABLE, true);
     528  }
     529  
     530  /* function_list --- list of functions */
     531  
     532  NODE **
     533  function_list(bool sort)
     534  {
     535  	return get_symbols(FUNCTION, sort);
     536  }
     537  
     538  /* print_vars --- print names and values of global variables */
     539  
     540  void
     541  print_vars(NODE **table, int (*print_func)(FILE *, const char *, ...), FILE *fp)
     542  {
     543  	int i;
     544  	NODE *r;
     545  
     546  	assert(table != NULL);
     547  
     548  	for (i = 0; (r = table[i]) != NULL; i++) {
     549  		if (r->type == Node_func || r->type == Node_ext_func)
     550  			continue;
     551  		print_func(fp, "%s: ", r->vname);
     552  		if (r->type == Node_var_array)
     553  			print_func(fp, "array, %ld elements\n", assoc_length(r));
     554  		else if (r->type == Node_var_new)
     555  			print_func(fp, "untyped variable\n");
     556  		else if (r->type == Node_var)
     557  			valinfo(r->var_value, print_func, fp);
     558  		else
     559  			cant_happen("unexpected node type: %s", nodetype2str(r->type));
     560  	}
     561  }
     562  
     563  
     564  /* foreach_func --- execute given function for each awk function in table. */
     565  
     566  int
     567  foreach_func(NODE **table, int (*pfunc)(INSTRUCTION *, void *), void *data)
     568  {
     569  	int i;
     570  	NODE *r;
     571  	int ret = 0;
     572  
     573  	assert(table != NULL);
     574  
     575  	for (i = 0; (r = table[i]) != NULL; i++) {
     576  		if ((ret = pfunc(r->code_ptr, data)) != 0)
     577  			break;
     578  	}
     579  	return ret;
     580  }
     581  
     582  /* release_all_vars --- free all variable memory */
     583  
     584  void
     585  release_all_vars()
     586  {
     587  	assoc_clear(symbol_table);
     588  	assoc_clear(func_table);
     589  	assoc_clear(global_table);
     590  }
     591  
     592  
     593  /* append_symbol --- append symbol to the list of symbols
     594   *	installed in the symbol table.
     595   */
     596  
     597  void
     598  append_symbol(NODE *r)
     599  {
     600  	NODE *p;
     601  
     602  	getnode(p);
     603  	p->lnode = r;
     604  	p->rnode = symbol_list->rnode;
     605  	symbol_list->rnode = p;
     606  }
     607  
     608  /* release_symbols --- free symbol list and optionally remove symbol from symbol table */
     609  
     610  void
     611  release_symbols(NODE *symlist, int keep_globals)
     612  {
     613  	NODE *p, *next;
     614  
     615  	for (p = symlist->rnode; p != NULL; p = next) {
     616  		if (! keep_globals) {
     617  			/*
     618  			 * destroys globals, function, and params
     619  			 * if still in symbol table
     620  			 */
     621  			destroy_symbol(p->lnode);
     622  		}
     623  		next = p->rnode;
     624  		freenode(p);
     625  	}
     626  	symlist->rnode = NULL;
     627  }
     628  
     629  /* load_symbols --- fill in symbols' information */
     630  
     631  void
     632  load_symbols()
     633  {
     634  	NODE *r;
     635  	NODE *tmp;
     636  	NODE *sym_array;
     637  	NODE **aptr;
     638  	long i, j, max;
     639  	NODE *user, *extension, *untyped, *scalar, *array, *built_in;
     640  	NODE **list;
     641  	NODE *tables[4];
     642  
     643  	if (PROCINFO_node == NULL)
     644  		return;
     645  
     646  	tables[0] = func_table;
     647  	tables[1] = symbol_table;
     648  	tables[2] = global_table;
     649  	tables[3] = NULL;
     650  
     651  	tmp = make_string("identifiers", 11);
     652  	aptr = assoc_lookup(PROCINFO_node, tmp);
     653  
     654  	getnode(sym_array);
     655  	memset(sym_array, '\0', sizeof(NODE));	/* PPC Mac OS X wants this */
     656  	null_array(sym_array);
     657  
     658  	unref(tmp);
     659  	unref(*aptr);
     660  	*aptr = sym_array;
     661  
     662  	sym_array->parent_array = PROCINFO_node;
     663  	sym_array->vname = estrdup("identifiers", 11);
     664  
     665  	user = make_string("user", 4);
     666  	extension = make_string("extension", 9);
     667  	scalar = make_string("scalar", 6);
     668  	untyped = make_string("untyped", 7);
     669  	array = make_string("array", 5);
     670  	built_in = make_string("builtin", 7);
     671  
     672  	for (i = 0; tables[i] != NULL; i++) {
     673  		list = assoc_list(tables[i], "@unsorted", ASORTI);
     674  		max = tables[i]->table_size * 2;
     675  		if (max == 0)
     676  			continue;
     677  		for (j = 0; j < max; j += 2) {
     678  			r = list[j+1];
     679  			if (   r->type == Node_ext_func
     680  			    || r->type == Node_func
     681  			    || r->type == Node_builtin_func
     682  			    || r->type == Node_var
     683  			    || r->type == Node_var_array
     684  			    || r->type == Node_var_new) {
     685  				if (strncmp(r->vname, "awk::", 5) == 0)
     686  					tmp = make_string(r->vname + 5, strlen(r->vname) - 5);
     687  				else
     688  					tmp = make_string(r->vname, strlen(r->vname));
     689  				aptr = assoc_lookup(sym_array, tmp);
     690  				unref(tmp);
     691  				unref(*aptr);
     692  				switch (r->type) {
     693  				case Node_ext_func:
     694  					*aptr = dupnode(extension);
     695  					break;
     696  				case Node_func:
     697  					*aptr = dupnode(user);
     698  					break;
     699  				case Node_builtin_func:
     700  					*aptr = dupnode(built_in);
     701  					break;
     702  				case Node_var:
     703  					*aptr = dupnode(scalar);
     704  					break;
     705  				case Node_var_array:
     706  					*aptr = dupnode(array);
     707  					break;
     708  				case Node_var_new:
     709  					*aptr = dupnode(untyped);
     710  					break;
     711  				default:
     712  					cant_happen("unexpected node type %s", nodetype2str(r->type));
     713  					break;
     714  				}
     715  			}
     716  		}
     717  		efree(list);
     718  	}
     719  
     720  	unref(user);
     721  	unref(extension);
     722  	unref(scalar);
     723  	unref(untyped);
     724  	unref(array);
     725  	unref(built_in);
     726  }
     727  
     728  /* check_param_names --- make sure no parameter is the name of a function */
     729  
     730  bool
     731  check_param_names(void)
     732  {
     733  	int i, j;
     734  	NODE **list;
     735  	NODE *f;
     736  	long max;
     737  	bool result = true;
     738  	NODE n;
     739  
     740  	if (assoc_empty(func_table))
     741  		return result;
     742  
     743  	max = func_table->table_size * 2;
     744  
     745  	memset(& n, 0, sizeof n);
     746  	n.type = Node_val;
     747  	n.flags = STRING|STRCUR;
     748  	n.stfmt = STFMT_UNUSED;
     749  #ifdef HAVE_MPFR
     750  	n.strndmode = MPFR_round_mode;
     751  #endif
     752  
     753  	/*
     754  	 * assoc_list() returns an array with two elements per awk array
     755  	 * element. Elements i and i+1 in the C array represent the key
     756  	 * and value of element j in the awk array. Thus the loops use += 2
     757  	 * to go through the awk array.
     758  	 *
     759  	 * In this case, the name is in list[i], and the function is
     760  	 * in list[i+1]. Just what we need.
     761  	 */
     762  
     763  	list = assoc_list(func_table, "@unsorted", ASORTI);
     764  
     765  	for (i = 0; i < max; i += 2) {
     766  		f = list[i+1];
     767  		if (f->type == Node_builtin_func || f->param_cnt == 0)
     768  			continue;
     769  
     770  		/* loop over each param in function i */
     771  		for (j = 0; j < f->param_cnt; j++) {
     772  			/* compare to function names */
     773  
     774  			/* use a fake node to avoid malloc/free of make_string */
     775  			n.stptr = f->fparms[j].param;
     776  			n.stlen = strlen(f->fparms[j].param);
     777  
     778  			if (in_array(func_table, & n)) {
     779  				error(
     780  			_("function `%s': cannot use function `%s' as a parameter name"),
     781  					list[i]->stptr,
     782  					f->fparms[j].param);
     783  				result = false;
     784  			}
     785  		}
     786  	}
     787  
     788  	efree(list);
     789  	return result;
     790  }
     791  
     792  static INSTRUCTION_POOL *pools;
     793  
     794  /*
     795   * For best performance, the INSTR_CHUNK value should be divisible by all
     796   * possible sizes, i.e. 1 through MAX_INSTRUCTION_ALLOC. Otherwise, there
     797   * will be wasted space at the end of the block.
     798   */
     799  #define INSTR_CHUNK (2*3*21)
     800  
     801  struct instruction_block {
     802  	struct instruction_block *next;
     803  	INSTRUCTION i[INSTR_CHUNK];
     804  };
     805  
     806  /* bcfree --- deallocate instruction */
     807  
     808  void
     809  bcfree(INSTRUCTION *cp)
     810  {
     811  	assert(cp->pool_size >= 1 && cp->pool_size <= MAX_INSTRUCTION_ALLOC);
     812  
     813  	cp->opcode = Op_illegal;
     814  	cp->nexti = pools->pool[cp->pool_size - 1].free_list;
     815  	pools->pool[cp->pool_size - 1].free_list = cp;
     816  }
     817  
     818  /* bcalloc --- allocate a new instruction */
     819  
     820  INSTRUCTION *
     821  bcalloc(OPCODE op, int size, int srcline)
     822  {
     823  	INSTRUCTION *cp;
     824  	struct instruction_mem_pool *pool;
     825  
     826  	assert(size >= 1 && size <= MAX_INSTRUCTION_ALLOC);
     827  	pool = &pools->pool[size - 1];
     828  
     829  	if (pool->free_list != NULL) {
     830  		cp = pool->free_list;
     831  		pool->free_list = cp->nexti;
     832  	} else if (pool->free_space && pool->free_space + size <= & pool->block_list->i[INSTR_CHUNK]) {
     833  		cp = pool->free_space;
     834  		pool->free_space += size;
     835  	} else {
     836  		struct instruction_block *block;
     837  		emalloc(block, struct instruction_block *, sizeof(struct instruction_block), "bcalloc");
     838  		block->next = pool->block_list;
     839  		pool->block_list = block;
     840  		cp = &block->i[0];
     841  		pool->free_space = &block->i[size];
     842  	}
     843  
     844  	memset(cp, 0, size * sizeof(INSTRUCTION));
     845  	cp->pool_size = size;
     846  	cp->opcode = op;
     847  	cp->source_line = srcline;
     848  	return cp;
     849  }
     850  
     851  /* new_context --- create a new execution context. */
     852  
     853  AWK_CONTEXT *
     854  new_context()
     855  {
     856  	AWK_CONTEXT *ctxt;
     857  
     858  	ezalloc(ctxt, AWK_CONTEXT *, sizeof(AWK_CONTEXT), "new_context");
     859  	ctxt->srcfiles.next = ctxt->srcfiles.prev = & ctxt->srcfiles;
     860  	ctxt->rule_list.opcode = Op_list;
     861  	ctxt->rule_list.lasti = & ctxt->rule_list;
     862  	return ctxt;
     863  }
     864  
     865  /* set_context --- change current execution context. */
     866  
     867  static void
     868  set_context(AWK_CONTEXT *ctxt)
     869  {
     870  	pools = & ctxt->pools;
     871  	symbol_list = & ctxt->symbols;
     872  	srcfiles = & ctxt->srcfiles;
     873  	rule_list = & ctxt->rule_list;
     874  	install_func = ctxt->install_func;
     875  	curr_ctxt = ctxt;
     876  }
     877  
     878  /*
     879   * push_context:
     880   *
     881   * Switch to the given context after saving the current one. The set
     882   * of active execution contexts forms a stack; the global or main context
     883   * is at the bottom of the stack.
     884   */
     885  
     886  void
     887  push_context(AWK_CONTEXT *ctxt)
     888  {
     889  	ctxt->prev = curr_ctxt;
     890  	/* save current source and sourceline */
     891  	if (curr_ctxt != NULL) {
     892  		curr_ctxt->sourceline = sourceline;
     893  		curr_ctxt->source = source;
     894  	}
     895  	sourceline = 0;
     896  	source = NULL;
     897  	set_context(ctxt);
     898  	ctxt_level++;
     899  }
     900  
     901  /* pop_context --- switch to previous execution context. */
     902  
     903  void
     904  pop_context()
     905  {
     906  	AWK_CONTEXT *ctxt;
     907  
     908  	assert(curr_ctxt != NULL);
     909  	if (curr_ctxt->prev == NULL)
     910  		fatal(_("cannot pop main context"));
     911  	ctxt = curr_ctxt->prev;
     912  	/* restore source and sourceline */
     913  	sourceline = ctxt->sourceline;
     914  	source = ctxt->source;
     915  	set_context(ctxt);
     916  	ctxt_level--;
     917  }
     918  
     919  /* in_main_context --- are we in the main context ? */
     920  
     921  int
     922  in_main_context()
     923  {
     924  	assert(ctxt_level > 0);
     925  	return (ctxt_level == 1);
     926  }
     927  
     928  /* free_context --- free context structure and related data. */
     929  
     930  void
     931  free_context(AWK_CONTEXT *ctxt, bool keep_globals)
     932  {
     933  	SRCFILE *s, *sn;
     934  
     935  	if (ctxt == NULL)
     936  		return;
     937  
     938  	assert(curr_ctxt != ctxt);
     939  
     940   	/* free all code including function codes */
     941  
     942  	free_bcpool(& ctxt->pools);
     943  
     944  	/* free symbols */
     945  
     946  	release_symbols(& ctxt->symbols, keep_globals);
     947  
     948  	/* free srcfiles */
     949  
     950  	for (s = & ctxt->srcfiles; s != & ctxt->srcfiles; s = sn) {
     951  		sn = s->next;
     952  		if (s->stype != SRC_CMDLINE && s->stype != SRC_STDIN)
     953  			efree(s->fullpath);
     954  		efree(s->src);
     955  		efree(s);
     956  	}
     957  
     958  	efree(ctxt);
     959  }
     960  
     961  /* free_bc_internal --- free internal memory of an instruction. */
     962  
     963  static void
     964  free_bc_internal(INSTRUCTION *cp)
     965  {
     966  	NODE *m;
     967  
     968  	switch(cp->opcode) {
     969  	case Op_func_call:
     970  		if (cp->func_name != NULL)
     971  			efree(cp->func_name);
     972  		break;
     973  	case Op_push_re:
     974  	case Op_match_rec:
     975  	case Op_match:
     976  	case Op_nomatch:
     977  		m = cp->memory;
     978  		if (m->re_reg[0] != NULL)
     979  			refree(m->re_reg[0]);
     980  		if (m->re_reg[1] != NULL)
     981  			refree(m->re_reg[1]);
     982  		if (m->re_exp != NULL)
     983  			unref(m->re_exp);
     984  		if (m->re_text != NULL)
     985  			unref(m->re_text);
     986  		freenode(m);
     987  		break;
     988  	case Op_token:
     989  		/* token lost during error recovery in yyparse */
     990  		if (cp->lextok != NULL)
     991  			efree(cp->lextok);
     992  		break;
     993  	case Op_push_i:
     994  		m = cp->memory;
     995  		unref(m);
     996  		break;
     997  	case Op_store_var:
     998  		m = cp->initval;
     999  		if (m != NULL)
    1000  			unref(m);
    1001  		break;
    1002  	case Op_illegal:
    1003  		cant_happen("unexpected opcode %s", opcode2str(cp->opcode));
    1004  	default:
    1005  		break;
    1006  	}
    1007  }
    1008  
    1009  /* free_bc_mempool --- free a single pool */
    1010  
    1011  static void
    1012  free_bc_mempool(struct instruction_mem_pool *pool, int size)
    1013  {
    1014  	bool first = true;
    1015  	struct instruction_block *block, *next;
    1016  
    1017  	for (block = pool->block_list; block; block = next) {
    1018  		INSTRUCTION *cp, *end;
    1019  
    1020  		end = (first ? pool->free_space : & block->i[INSTR_CHUNK]);
    1021  		for (cp = & block->i[0]; cp + size <= end; cp += size) {
    1022  			if (cp->opcode != Op_illegal)
    1023  				free_bc_internal(cp);
    1024  		}
    1025  		next = block->next;
    1026  		efree(block);
    1027  		first = false;
    1028  	}
    1029  }
    1030  
    1031  
    1032  /* free_bcpool --- free list of instruction memory pools */
    1033  
    1034  static void
    1035  free_bcpool(INSTRUCTION_POOL *pl)
    1036  {
    1037  	int i;
    1038  
    1039  	for (i = 0; i < MAX_INSTRUCTION_ALLOC; i++)
    1040  		free_bc_mempool(& pl->pool[i], i + 1);
    1041  }
    1042  
    1043  /* is_all_upper --- return true if name is all uppercase letters */
    1044  
    1045  /*
    1046   * DON'T use isupper(), it's locale aware!
    1047   */
    1048  
    1049  bool
    1050  is_all_upper(const char *name)
    1051  {
    1052  	for (; *name != '\0'; name++) {
    1053  		switch (*name) {
    1054  		case 'A': case 'B': case 'C': case 'D': case 'E':
    1055  		case 'F': case 'G': case 'H': case 'I': case 'J':
    1056  		case 'K': case 'L': case 'M': case 'N': case 'O':
    1057  		case 'P': case 'Q': case 'R': case 'S': case 'T':
    1058  		case 'U': case 'V': case 'W': case 'X': case 'Y':
    1059  		case 'Z':
    1060  			break;
    1061  		default:
    1062  			return false;
    1063  		}
    1064  	}
    1065  
    1066  	return true;
    1067  }
    1068  
    1069  /* get_name_from_awk_ns --- get the name after awk:: or the full name */
    1070  
    1071  static NODE *
    1072  get_name_from_awk_ns(const char *name)
    1073  {
    1074  	NODE *tmp;
    1075  
    1076  	if (strncmp(name, "awk::", 5) == 0)
    1077  		tmp = make_string(name + 5, strlen(name) - 5);
    1078  	else
    1079  		tmp = make_string(name, strlen(name));
    1080  
    1081  	return tmp;
    1082  }