Blame gawkapi.c

Packit Service f629e6
/*
Packit Service f629e6
 * gawkapi.c -- Implement the functions defined for gawkapi.h
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * Copyright (C) 2012-2018 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
#ifdef HAVE_MPFR
Packit Service f629e6
#define getmpfr(n)	getblock(n, BLOCK_MPFR, mpfr_ptr)
Packit Service f629e6
#define freempfr(n)	freeblock(n, BLOCK_MPFR)
Packit Service f629e6
Packit Service f629e6
#define getmpz(n)	getblock(n, BLOCK_MPZ, mpz_ptr)
Packit Service f629e6
#define freempz(n)	freeblock(n, BLOCK_MPZ)
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
/* Declare some globals used by api_get_file: */
Packit Service f629e6
extern IOBUF *curfile;
Packit Service f629e6
extern INSTRUCTION *main_beginfile;
Packit Service f629e6
extern int currule;
Packit Service f629e6
Packit Service f629e6
static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted);
Packit Service f629e6
static char *valtype2str(awk_valtype_t type);
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * api_get_argument --- get the count'th paramater, zero-based.
Packit Service f629e6
 *
Packit Service f629e6
 * Returns false if count is out of range, or if actual paramater
Packit Service f629e6
 * does not match what is specified in wanted. In the latter
Packit Service f629e6
 * case, fills in result->val_type with the actual type.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_get_argument(awk_ext_id_t id, size_t count,
Packit Service f629e6
			awk_valtype_t wanted, awk_value_t *result)
Packit Service f629e6
{
Packit Service f629e6
#ifdef DYNAMIC
Packit Service f629e6
	NODE *arg;
Packit Service f629e6
Packit Service f629e6
	if (result == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	/* set up default result */
Packit Service f629e6
	memset(result, 0, sizeof(*result));
Packit Service f629e6
	result->val_type = AWK_UNDEFINED;
Packit Service f629e6
Packit Service f629e6
	/*
Packit Service f629e6
	 * Song and dance here.  get_array_argument() and get_scalar_argument()
Packit Service f629e6
	 * will force a change in type of a parameter that is Node_var_new.
Packit Service f629e6
	 *
Packit Service f629e6
	 * Start by looking at the unadulterated argument as it was passed.
Packit Service f629e6
	 */
Packit Service f629e6
	arg = get_argument(count);
Packit Service f629e6
	if (arg == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	/* if type is undefined */
Packit Service f629e6
	if (arg->type == Node_var_new) {
Packit Service f629e6
		if (wanted == AWK_UNDEFINED)
Packit Service f629e6
			return true;
Packit Service f629e6
		else if (wanted == AWK_ARRAY) {
Packit Service f629e6
			goto array;
Packit Service f629e6
		} else {
Packit Service f629e6
			goto scalar;
Packit Service f629e6
		}
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	/* at this point, we have real type */
Packit Service f629e6
	if (arg->type == Node_var_array || arg->type == Node_array_ref) {
Packit Service f629e6
		if (wanted != AWK_ARRAY && wanted != AWK_UNDEFINED)
Packit Service f629e6
			return false;
Packit Service f629e6
		goto array;
Packit Service f629e6
	} else
Packit Service f629e6
		goto scalar;
Packit Service f629e6
Packit Service f629e6
array:
Packit Service f629e6
	/* get the array here */
Packit Service f629e6
	arg = get_array_argument(arg, count);
Packit Service f629e6
	if (arg == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	return node_to_awk_value(arg, result, wanted);
Packit Service f629e6
Packit Service f629e6
scalar:
Packit Service f629e6
	/* at this point we have a real type that is not an array */
Packit Service f629e6
	arg = get_scalar_argument(arg, count);
Packit Service f629e6
	if (arg == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	return node_to_awk_value(arg, result, wanted);
Packit Service f629e6
#else
Packit Service f629e6
	return awk_false;
Packit Service f629e6
#endif
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_set_argument --- convert an argument to an array */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_set_argument(awk_ext_id_t id,
Packit Service f629e6
		size_t count,
Packit Service f629e6
		awk_array_t new_array)
Packit Service f629e6
{
Packit Service f629e6
#ifdef DYNAMIC
Packit Service f629e6
	NODE *arg;
Packit Service f629e6
	NODE *array = (NODE *) new_array;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	if (array == NULL || array->type != Node_var_array)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	if (   (arg = get_argument(count)) == NULL
Packit Service f629e6
	    || arg->type != Node_var_new)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	arg = get_array_argument(arg, count);
Packit Service f629e6
	if (arg == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	array->vname = arg->vname;
Packit Service f629e6
	*arg = *array;
Packit Service f629e6
	freenode(array);
Packit Service f629e6
Packit Service f629e6
	return awk_true;
Packit Service f629e6
#else
Packit Service f629e6
	return awk_false;
Packit Service f629e6
#endif
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* awk_value_to_node --- convert a value into a NODE */
Packit Service f629e6
Packit Service f629e6
NODE *
Packit Service f629e6
awk_value_to_node(const awk_value_t *retval)
Packit Service f629e6
{
Packit Service f629e6
	NODE *ext_ret_val = NULL;
Packit Service f629e6
	NODE *v;
Packit Service f629e6
Packit Service f629e6
	if (retval == NULL)
Packit Service f629e6
		fatal(_("awk_value_to_node: received null retval"));
Packit Service f629e6
Packit Service f629e6
	switch (retval->val_type) {
Packit Service f629e6
	case AWK_ARRAY:
Packit Service f629e6
		ext_ret_val = (NODE *) retval->array_cookie;
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_UNDEFINED:
Packit Service f629e6
		ext_ret_val = dupnode(Nnull_string);
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_NUMBER:
Packit Service f629e6
		switch (retval->num_type) {
Packit Service f629e6
		case AWK_NUMBER_TYPE_DOUBLE:
Packit Service f629e6
			ext_ret_val = make_number(retval->num_value);
Packit Service f629e6
			break;
Packit Service f629e6
		case AWK_NUMBER_TYPE_MPFR:
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
			if (! do_mpfr)
Packit Service f629e6
				fatal(_("awk_value_to_node: not in MPFR mode"));
Packit Service f629e6
			ext_ret_val = make_number_node(MPFN);
Packit Service f629e6
			memcpy(&ext_ret_val->mpg_numbr, retval->num_ptr, sizeof(ext_ret_val->mpg_numbr));
Packit Service f629e6
			freempfr(retval->num_ptr);
Packit Service f629e6
#else
Packit Service f629e6
			fatal(_("awk_value_to_node: MPFR not supported"));
Packit Service f629e6
#endif
Packit Service f629e6
			break;
Packit Service f629e6
		case AWK_NUMBER_TYPE_MPZ:
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
			if (! do_mpfr)
Packit Service f629e6
				fatal(_("awk_value_to_node: not in MPFR mode"));
Packit Service f629e6
			ext_ret_val = make_number_node(MPZN);
Packit Service f629e6
			memcpy(&ext_ret_val->mpg_i, retval->num_ptr, sizeof(ext_ret_val->mpg_i));
Packit Service f629e6
			freempz(retval->num_ptr);
Packit Service f629e6
#else
Packit Service f629e6
			fatal(_("awk_value_to_node: MPFR not supported"));
Packit Service f629e6
#endif
Packit Service f629e6
			break;
Packit Service f629e6
		default:
Packit Service f629e6
			fatal(_("awk_value_to_node: invalid number type `%d'"), retval->num_type);
Packit Service f629e6
			break;
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_STRING:
Packit Service f629e6
		ext_ret_val = make_str_node(retval->str_value.str,
Packit Service f629e6
				retval->str_value.len, ALREADY_MALLOCED);
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_STRNUM:
Packit Service f629e6
		ext_ret_val = make_str_node(retval->str_value.str,
Packit Service f629e6
				retval->str_value.len, ALREADY_MALLOCED);
Packit Service f629e6
		ext_ret_val->flags |= USER_INPUT;
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_REGEX:
Packit Service f629e6
		ext_ret_val = make_typed_regex(retval->str_value.str,
Packit Service f629e6
				retval->str_value.len);
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_SCALAR:
Packit Service f629e6
		v = (NODE *) retval->scalar_cookie;
Packit Service f629e6
		if (v->type != Node_var)
Packit Service f629e6
			ext_ret_val = NULL;
Packit Service f629e6
		else
Packit Service f629e6
			ext_ret_val = dupnode(v->var_value);
Packit Service f629e6
		break;
Packit Service f629e6
	case AWK_VALUE_COOKIE:
Packit Service f629e6
		ext_ret_val = dupnode((NODE *)(retval->value_cookie));
Packit Service f629e6
		break;
Packit Service f629e6
	default:	/* any invalid type */
Packit Service f629e6
		ext_ret_val = NULL;
Packit Service f629e6
		break;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	return ext_ret_val;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Functions to print messages */
Packit Service f629e6
Packit Service f629e6
/* api_fatal --- print a fatal message and exit */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_fatal(awk_ext_id_t id, const char *format, ...)
Packit Service f629e6
{
Packit Service f629e6
	va_list args;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	va_start(args, format);
Packit Service f629e6
	err(true, _("fatal: "), format, args);
Packit Service f629e6
	va_end(args);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_nonfatal --- print a non fatal error message */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_nonfatal(awk_ext_id_t id, const char *format, ...)
Packit Service f629e6
{
Packit Service f629e6
	va_list args;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	va_start(args, format);
Packit Service f629e6
	err(false, _("error: "), format, args);
Packit Service f629e6
	va_end(args);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_warning --- print a warning message */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_warning(awk_ext_id_t id, const char *format, ...)
Packit Service f629e6
{
Packit Service f629e6
	va_list args;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	va_start(args, format);
Packit Service f629e6
	err(false, _("warning: "), format, args);
Packit Service f629e6
	va_end(args);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_lintwarn --- print a lint warning message and exit if appropriate */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_lintwarn(awk_ext_id_t id, const char *format, ...)
Packit Service f629e6
{
Packit Service f629e6
	va_list args;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	va_start(args, format);
Packit Service f629e6
	if (lintwarn == r_fatal) {
Packit Service f629e6
		err(true, _("fatal: "), format, args);
Packit Service f629e6
	} else {
Packit Service f629e6
		err(false, _("warning: "), format, args);
Packit Service f629e6
	}
Packit Service f629e6
	va_end(args);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_register_input_parser --- register an input_parser; for opening files read-only */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_register_input_parser(awk_ext_id_t id, awk_input_parser_t *input_parser)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	if (input_parser == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	register_input_parser(input_parser);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_register_output_wrapper --- register an output wrapper, for writing files / two-way pipes */
Packit Service f629e6
Packit Service f629e6
static void api_register_output_wrapper(awk_ext_id_t id,
Packit Service f629e6
		awk_output_wrapper_t *output_wrapper)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	if (output_wrapper == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	register_output_wrapper(output_wrapper);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_register_two_way_processor --- register a processor for two way I/O */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_register_two_way_processor(awk_ext_id_t id,
Packit Service f629e6
		awk_two_way_processor_t *two_way_processor)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	if (two_way_processor == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	register_two_way_processor(two_way_processor);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Functions to update ERRNO */
Packit Service f629e6
Packit Service f629e6
/* api_update_ERRNO_int --- update ERRNO with an integer value */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_update_ERRNO_int(awk_ext_id_t id, int errno_val)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	update_ERRNO_int(errno_val);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_update_ERRNO_string --- update ERRNO with a string value */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_update_ERRNO_string(awk_ext_id_t id,
Packit Service f629e6
			const char *string)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	if (string == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	update_ERRNO_string(string);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_unset_ERRNO --- unset ERRNO */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_unset_ERRNO(awk_ext_id_t id)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	unset_ERRNO();
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
/* api_add_ext_func --- add a function to the interpreter, returns true upon success */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_add_ext_func(awk_ext_id_t id,
Packit Service f629e6
		const char *namespace,
Packit Service f629e6
		awk_ext_func_t *func)
Packit Service f629e6
{
Packit Service f629e6
	(void) id;
Packit Service f629e6
	(void) namespace;
Packit Service f629e6
Packit Service f629e6
	if (func == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
#ifdef DYNAMIC
Packit Service f629e6
	return make_builtin(func);
Packit Service f629e6
#else
Packit Service f629e6
	return awk_false;
Packit Service f629e6
#endif
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Stuff for exit handler - do it as linked list */
Packit Service f629e6
Packit Service f629e6
struct ext_exit_handler {
Packit Service f629e6
	struct ext_exit_handler *next;
Packit Service f629e6
	void (*funcp)(void *data, int exit_status);
Packit Service f629e6
	void *arg0;
Packit Service f629e6
};
Packit Service f629e6
static struct ext_exit_handler *list_head = NULL;
Packit Service f629e6
Packit Service f629e6
/* run_ext_exit_handlers --- run the extension exit handlers, LIFO order */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
run_ext_exit_handlers(int exitval)
Packit Service f629e6
{
Packit Service f629e6
	struct ext_exit_handler *p, *next;
Packit Service f629e6
Packit Service f629e6
	for (p = list_head; p != NULL; p = next) {
Packit Service f629e6
		next = p->next;
Packit Service f629e6
		p->funcp(p->arg0, exitval);
Packit Service f629e6
		free(p);
Packit Service f629e6
	}
Packit Service f629e6
	list_head = NULL;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_awk_atexit --- add an exit call back */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_awk_atexit(awk_ext_id_t id,
Packit Service f629e6
		void (*funcp)(void *data, int exit_status),
Packit Service f629e6
		void *arg0)
Packit Service f629e6
{
Packit Service f629e6
	struct ext_exit_handler *p;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	if (funcp == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	/* allocate memory */
Packit Service f629e6
	emalloc(p, struct ext_exit_handler *, sizeof(struct ext_exit_handler), "api_awk_atexit");
Packit Service f629e6
Packit Service f629e6
	/* fill it in */
Packit Service f629e6
	p->funcp = funcp;
Packit Service f629e6
	p->arg0 = arg0;
Packit Service f629e6
Packit Service f629e6
	/* add to linked list, LIFO order */
Packit Service f629e6
	p->next = list_head;
Packit Service f629e6
	list_head = p;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static struct {
Packit Service f629e6
	char **strings;
Packit Service f629e6
	size_t i, size;
Packit Service f629e6
} scopy;
Packit Service f629e6
Packit Service f629e6
/* free_api_string_copies --- release memory used by string copies */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
free_api_string_copies()
Packit Service f629e6
{
Packit Service f629e6
	size_t i;
Packit Service f629e6
Packit Service f629e6
	for (i = 0; i < scopy.i; i++)
Packit Service f629e6
		free(scopy.strings[i]);
Packit Service f629e6
	scopy.i = 0;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* assign_string --- return a string node with NUL termination */
Packit Service f629e6
Packit Service f629e6
static inline void
Packit Service f629e6
assign_string(NODE *node, awk_value_t *val, awk_valtype_t val_type)
Packit Service f629e6
{
Packit Service f629e6
	val->val_type = val_type;
Packit Service f629e6
	if (node->stptr[node->stlen] != '\0') {
Packit Service f629e6
		/*
Packit Service f629e6
		 * This is an unterminated field string, so make a copy.
Packit Service f629e6
		 * This should happen only for $n where n > 0 and n < NF.
Packit Service f629e6
		 */
Packit Service f629e6
		char *s;
Packit Service f629e6
Packit Service f629e6
		assert((node->flags & MALLOC) == 0);
Packit Service f629e6
		if (scopy.i == scopy.size) {
Packit Service f629e6
			/* expand list */
Packit Service f629e6
			if (scopy.size == 0)
Packit Service f629e6
				scopy.size = 8;	/* initial size */
Packit Service f629e6
			else
Packit Service f629e6
				scopy.size *= 2;
Packit Service f629e6
			erealloc(scopy.strings, char **, scopy.size * sizeof(char *), "assign_string");
Packit Service f629e6
		}
Packit Service f629e6
		emalloc(s, char *, node->stlen + 1, "assign_string");
Packit Service f629e6
		memcpy(s, node->stptr, node->stlen);
Packit Service f629e6
		s[node->stlen] = '\0';
Packit Service f629e6
		val->str_value.str = scopy.strings[scopy.i++] = s;
Packit Service f629e6
	}
Packit Service f629e6
	else
Packit Service f629e6
		val->str_value.str = node->stptr;
Packit Service f629e6
	val->str_value.len = node->stlen;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* assign_number -- return a number node */
Packit Service f629e6
Packit Service f629e6
#define assign_double(val) \
Packit Service f629e6
	val->num_value = node->numbr; \
Packit Service f629e6
	val->num_type = AWK_NUMBER_TYPE_DOUBLE; \
Packit Service f629e6
	val->num_ptr = NULL
Packit Service f629e6
Packit Service f629e6
static inline void
Packit Service f629e6
assign_number(NODE *node, awk_value_t *val)
Packit Service f629e6
{
Packit Service f629e6
	val->val_type = AWK_NUMBER;
Packit Service f629e6
Packit Service f629e6
#ifndef HAVE_MPFR
Packit Service f629e6
	assign_double(val);
Packit Service f629e6
#else
Packit Service f629e6
	switch (node->flags & (MPFN|MPZN)) {
Packit Service f629e6
	case 0:
Packit Service f629e6
		assign_double(val);
Packit Service f629e6
		break;
Packit Service f629e6
	case MPFN:
Packit Service f629e6
		val->num_value = mpfr_get_d(node->mpg_numbr, ROUND_MODE);
Packit Service f629e6
		val->num_type = AWK_NUMBER_TYPE_MPFR;
Packit Service f629e6
		val->num_ptr = &node->mpg_numbr;
Packit Service f629e6
		break;
Packit Service f629e6
	case MPZN:
Packit Service f629e6
		val->num_value = mpz_get_d(node->mpg_i);
Packit Service f629e6
		val->num_type = AWK_NUMBER_TYPE_MPZ;
Packit Service f629e6
		val->num_ptr = &node->mpg_i;
Packit Service f629e6
		break;
Packit Service f629e6
	default:
Packit Service f629e6
		fatal(_("node_to_awk_value: detected invalid numeric flags combination `%s'; please file a bug report."), flags2str(node->flags));
Packit Service f629e6
		break;
Packit Service f629e6
	}
Packit Service f629e6
#endif
Packit Service f629e6
}
Packit Service f629e6
#undef assign_double
Packit Service f629e6
Packit Service f629e6
/* assign_regex --- return a regex node */
Packit Service f629e6
Packit Service f629e6
static inline void
Packit Service f629e6
assign_regex(NODE *node, awk_value_t *val)
Packit Service f629e6
{
Packit Service f629e6
	/* a REGEX node cannot be an unterminated field string */
Packit Service f629e6
	assert((node->flags & MALLOC) != 0);
Packit Service f629e6
	assert(node->stptr[node->stlen] == '\0');
Packit Service f629e6
	val->str_value.str = node->stptr;
Packit Service f629e6
	val->str_value.len = node->stlen;
Packit Service f629e6
	val->val_type = AWK_REGEX;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* node_to_awk_value --- convert a node into a value for an extension */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted)
Packit Service f629e6
{
Packit Service f629e6
	awk_bool_t ret = awk_false;
Packit Service f629e6
Packit Service f629e6
	if (node == NULL)
Packit Service f629e6
		fatal(_("node_to_awk_value: received null node"));
Packit Service f629e6
Packit Service f629e6
	if (val == NULL)
Packit Service f629e6
		fatal(_("node_to_awk_value: received null val"));
Packit Service f629e6
Packit Service f629e6
	switch (node->type) {
Packit Service f629e6
	case Node_var_new:	/* undefined variable */
Packit Service f629e6
		val->val_type = AWK_UNDEFINED;
Packit Service f629e6
		if (wanted == AWK_UNDEFINED) {
Packit Service f629e6
			ret = awk_true;
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
	case Node_var:
Packit Service f629e6
		/* a scalar value */
Packit Service f629e6
		if (wanted == AWK_SCALAR) {
Packit Service f629e6
			val->val_type = AWK_SCALAR;
Packit Service f629e6
			val->scalar_cookie = (void *) node;
Packit Service f629e6
			ret = awk_true;
Packit Service f629e6
			break;
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
		node = node->var_value;
Packit Service f629e6
		/* FALL THROUGH */
Packit Service f629e6
	case Node_val:
Packit Service f629e6
		/* a scalar value */
Packit Service f629e6
		switch (wanted) {
Packit Service f629e6
		case AWK_NUMBER:
Packit Service f629e6
			if (node->flags & REGEX)
Packit Service f629e6
				val->val_type = AWK_REGEX;
Packit Service f629e6
			else {
Packit Service f629e6
				(void) force_number(node);
Packit Service f629e6
				assign_number(node, val);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case AWK_STRNUM:
Packit Service f629e6
			switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) {
Packit Service f629e6
			case STRING:
Packit Service f629e6
				val->val_type = AWK_STRING;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER:
Packit Service f629e6
				(void) force_string(node);
Packit Service f629e6
				/* fall through */
Packit Service f629e6
			case NUMBER|USER_INPUT:
Packit Service f629e6
				assign_string(node, val, AWK_STRNUM);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
				break;
Packit Service f629e6
			case REGEX:
Packit Service f629e6
				val->val_type = AWK_REGEX;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|STRING:
Packit Service f629e6
				if (node == Nnull_string) {
Packit Service f629e6
					val->val_type = AWK_UNDEFINED;
Packit Service f629e6
					break;
Packit Service f629e6
				}
Packit Service f629e6
				/* fall through */
Packit Service f629e6
			default:
Packit Service f629e6
				warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags));
Packit Service f629e6
				val->val_type = AWK_UNDEFINED;
Packit Service f629e6
				break;
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case AWK_STRING:
Packit Service f629e6
			(void) force_string(node);
Packit Service f629e6
			assign_string(node, val, AWK_STRING);
Packit Service f629e6
			ret = awk_true;
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case AWK_REGEX:
Packit Service f629e6
			switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) {
Packit Service f629e6
			case STRING:
Packit Service f629e6
				val->val_type = AWK_STRING;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER:
Packit Service f629e6
				val->val_type = AWK_NUMBER;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|USER_INPUT:
Packit Service f629e6
				val->val_type = AWK_STRNUM;
Packit Service f629e6
				break;
Packit Service f629e6
			case REGEX:
Packit Service f629e6
				assign_regex(node, val);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|STRING:
Packit Service f629e6
				if (node == Nnull_string) {
Packit Service f629e6
					val->val_type = AWK_UNDEFINED;
Packit Service f629e6
					break;
Packit Service f629e6
				}
Packit Service f629e6
				/* fall through */
Packit Service f629e6
			default:
Packit Service f629e6
				warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags));
Packit Service f629e6
				val->val_type = AWK_UNDEFINED;
Packit Service f629e6
				break;
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case AWK_SCALAR:
Packit Service f629e6
			switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) {
Packit Service f629e6
			case STRING:
Packit Service f629e6
				val->val_type = AWK_STRING;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER:
Packit Service f629e6
				val->val_type = AWK_NUMBER;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|USER_INPUT:
Packit Service f629e6
				val->val_type = AWK_STRNUM;
Packit Service f629e6
				break;
Packit Service f629e6
			case REGEX:
Packit Service f629e6
				val->val_type = AWK_REGEX;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|STRING:
Packit Service f629e6
				if (node == Nnull_string) {
Packit Service f629e6
					val->val_type = AWK_UNDEFINED;
Packit Service f629e6
					break;
Packit Service f629e6
				}
Packit Service f629e6
				/* fall through */
Packit Service f629e6
			default:
Packit Service f629e6
				warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags));
Packit Service f629e6
				val->val_type = AWK_UNDEFINED;
Packit Service f629e6
				break;
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case AWK_UNDEFINED:
Packit Service f629e6
			/* return true and actual type for request of undefined */
Packit Service f629e6
			switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) {
Packit Service f629e6
			case STRING:
Packit Service f629e6
				assign_string(node, val, AWK_STRING);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER:
Packit Service f629e6
				assign_number(node, val);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|USER_INPUT:
Packit Service f629e6
				assign_string(node, val, AWK_STRNUM);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
				break;
Packit Service f629e6
			case REGEX:
Packit Service f629e6
				assign_regex(node, val);
Packit Service f629e6
				ret = awk_true;
Packit Service f629e6
				break;
Packit Service f629e6
			case NUMBER|STRING:
Packit Service f629e6
				if (node == Nnull_string) {
Packit Service f629e6
					val->val_type = AWK_UNDEFINED;
Packit Service f629e6
					ret = awk_true;
Packit Service f629e6
					break;
Packit Service f629e6
				}
Packit Service f629e6
				/* fall through */
Packit Service f629e6
			default:
Packit Service f629e6
				warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags));
Packit Service f629e6
				val->val_type = AWK_UNDEFINED;
Packit Service f629e6
				break;
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case AWK_ARRAY:
Packit Service f629e6
		case AWK_VALUE_COOKIE:
Packit Service f629e6
			break;
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
	case Node_var_array:
Packit Service f629e6
		val->val_type = AWK_ARRAY;
Packit Service f629e6
		if (wanted == AWK_ARRAY || wanted == AWK_UNDEFINED) {
Packit Service f629e6
			val->array_cookie = node;
Packit Service f629e6
			ret = awk_true;
Packit Service f629e6
		} else
Packit Service f629e6
			ret = awk_false;
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
	default:
Packit Service f629e6
		val->val_type = AWK_UNDEFINED;
Packit Service f629e6
		ret = awk_false;
Packit Service f629e6
		break;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	return ret;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * Symbol table access:
Packit Service f629e6
 * 	- No access to special variables (NF, etc.)
Packit Service f629e6
 * 	- One special exception: PROCINFO.
Packit Service f629e6
 *	- Use sym_update() to change a value, including from UNDEFINED
Packit Service f629e6
 *	  to scalar or array.
Packit Service f629e6
 */
Packit Service f629e6
/*
Packit Service f629e6
 * Lookup a variable, fills in value. No messing with the value
Packit Service f629e6
 * returned. Returns false if the variable doesn't exist
Packit Service f629e6
 * or the wrong type was requested.
Packit Service f629e6
 * In the latter case, fills in vaule->val_type with the real type.
Packit Service f629e6
 * Built-in variables (except PROCINFO) may not be accessed by an extension.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
/* api_sym_lookup --- look up a symbol */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_sym_lookup(awk_ext_id_t id,
Packit Service f629e6
		const char *name,
Packit Service f629e6
		awk_valtype_t wanted,
Packit Service f629e6
		awk_value_t *result)
Packit Service f629e6
{
Packit Service f629e6
	NODE *node;
Packit Service f629e6
Packit Service f629e6
	update_global_values();		/* make sure stuff like NF, NR, are up to date */
Packit Service f629e6
Packit Service f629e6
	if (   name == NULL
Packit Service f629e6
	    || *name == '\0'
Packit Service f629e6
	    || result == NULL
Packit Service f629e6
	    || (node = lookup(name)) == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	if (is_off_limits_var(name))	/* a built-in variable */
Packit Service f629e6
		node->flags |= NO_EXT_SET;
Packit Service f629e6
Packit Service f629e6
	return node_to_awk_value(node, result, wanted);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_sym_lookup_scalar --- retrieve the current value of a scalar */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_sym_lookup_scalar(awk_ext_id_t id,
Packit Service f629e6
			awk_scalar_t cookie,
Packit Service f629e6
			awk_valtype_t wanted,
Packit Service f629e6
			awk_value_t *result)
Packit Service f629e6
{
Packit Service f629e6
	NODE *node = (NODE *) cookie;
Packit Service f629e6
Packit Service f629e6
	if (node == NULL
Packit Service f629e6
	    || result == NULL
Packit Service f629e6
	    || node->type != Node_var)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	update_global_values();	/* make sure stuff like NF, NR, are up to date */
Packit Service f629e6
Packit Service f629e6
	return node_to_awk_value(node, result, wanted);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_sym_update --- update a symbol's value, see gawkapi.h for semantics */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_sym_update(awk_ext_id_t id,
Packit Service f629e6
		const char *name,
Packit Service f629e6
		awk_value_t *value)
Packit Service f629e6
{
Packit Service f629e6
	NODE *node;
Packit Service f629e6
	NODE *array_node;
Packit Service f629e6
Packit Service f629e6
	if (   name == NULL
Packit Service f629e6
	    || *name == '\0'
Packit Service f629e6
	    || value == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	switch (value->val_type) {
Packit Service f629e6
	case AWK_NUMBER:
Packit Service f629e6
	case AWK_STRNUM:
Packit Service f629e6
	case AWK_STRING:
Packit Service f629e6
	case AWK_REGEX:
Packit Service f629e6
	case AWK_UNDEFINED:
Packit Service f629e6
	case AWK_ARRAY:
Packit Service f629e6
	case AWK_SCALAR:
Packit Service f629e6
	case AWK_VALUE_COOKIE:
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
	default:
Packit Service f629e6
		/* fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type); */
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	node = lookup(name);
Packit Service f629e6
Packit Service f629e6
	if (node == NULL) {
Packit Service f629e6
		/* new value to be installed */
Packit Service f629e6
		if (value->val_type == AWK_ARRAY) {
Packit Service f629e6
			array_node = awk_value_to_node(value);
Packit Service f629e6
			node = install_symbol(estrdup((char *) name, strlen(name)),
Packit Service f629e6
					Node_var_array);
Packit Service f629e6
			array_node->vname = node->vname;
Packit Service f629e6
			*node = *array_node;
Packit Service f629e6
			freenode(array_node);
Packit Service f629e6
			value->array_cookie = node;	/* pass new cookie back to extension */
Packit Service f629e6
		} else {
Packit Service f629e6
			/* regular variable */
Packit Service f629e6
			node = install_symbol(estrdup((char *) name, strlen(name)),
Packit Service f629e6
					Node_var);
Packit Service f629e6
			node->var_value = awk_value_to_node(value);
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
		return awk_true;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	/*
Packit Service f629e6
	 * If we get here, then it exists already.  Any valid type is
Packit Service f629e6
	 * OK except for AWK_ARRAY.
Packit Service f629e6
	 */
Packit Service f629e6
	if (   (node->flags & NO_EXT_SET) != 0
Packit Service f629e6
	    || is_off_limits_var(name)) {	/* most built-in vars not allowed */
Packit Service f629e6
		node->flags |= NO_EXT_SET;
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	if (    value->val_type != AWK_ARRAY
Packit Service f629e6
	    && (node->type == Node_var || node->type == Node_var_new)) {
Packit Service f629e6
		unref(node->var_value);
Packit Service f629e6
		node->var_value = awk_value_to_node(value);
Packit Service f629e6
		if (node->type == Node_var_new && value->val_type != AWK_UNDEFINED)
Packit Service f629e6
			node->type = Node_var;
Packit Service f629e6
Packit Service f629e6
		return awk_true;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	return awk_false;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_sym_update_scalar --- update a scalar cookie */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_sym_update_scalar(awk_ext_id_t id,
Packit Service f629e6
			awk_scalar_t cookie,
Packit Service f629e6
			awk_value_t *value)
Packit Service f629e6
{
Packit Service f629e6
	NODE *node = (NODE *) cookie;
Packit Service f629e6
Packit Service f629e6
	if (value == NULL
Packit Service f629e6
	    || node == NULL
Packit Service f629e6
	    || node->type != Node_var
Packit Service f629e6
	    || (node->flags & NO_EXT_SET) != 0)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	/*
Packit Service f629e6
	 * Optimization: if valref is 1, and the new value is a string or
Packit Service f629e6
	 * a number, we can avoid calling unref and then making a new node
Packit Service f629e6
	 * by simply installing the new value.  First, we follow the same
Packit Service f629e6
	 * recipe used by node.c:r_unref to wipe the current values, and then
Packit Service f629e6
	 * we copy the logic from r_make_number or make_str_node to install
Packit Service f629e6
	 * the new value.
Packit Service f629e6
	 */
Packit Service f629e6
	switch (value->val_type) {
Packit Service f629e6
	case AWK_NUMBER:
Packit Service f629e6
		if (node->var_value->valref == 1 && ! do_mpfr) {
Packit Service f629e6
			NODE *r = node->var_value;
Packit Service f629e6
Packit Service f629e6
			/* r_unref: */
Packit Service f629e6
			if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR))
Packit Service f629e6
				efree(r->stptr);
Packit Service f629e6
			free_wstr(r);
Packit Service f629e6
Packit Service f629e6
			/* r_make_number: */
Packit Service f629e6
			r->numbr = value->num_value;
Packit Service f629e6
			r->flags = MALLOC|NUMBER|NUMCUR;
Packit Service f629e6
			r->stptr = NULL;
Packit Service f629e6
			r->stlen = 0;
Packit Service f629e6
			return awk_true;
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
	case AWK_STRING:
Packit Service f629e6
	case AWK_STRNUM:
Packit Service f629e6
		if (node->var_value->valref == 1) {
Packit Service f629e6
			NODE *r = node->var_value;
Packit Service f629e6
Packit Service f629e6
			/* r_unref: */
Packit Service f629e6
			if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR))
Packit Service f629e6
				efree(r->stptr);
Packit Service f629e6
Packit Service f629e6
			mpfr_unset(r);
Packit Service f629e6
			free_wstr(r);
Packit Service f629e6
Packit Service f629e6
			/* make_str_node(s, l, ALREADY_MALLOCED): */
Packit Service f629e6
			r->numbr = 0;
Packit Service f629e6
			r->flags = (MALLOC|STRING|STRCUR);
Packit Service f629e6
			if (value->val_type == AWK_STRNUM)
Packit Service f629e6
				r->flags |= USER_INPUT;
Packit Service f629e6
			r->stfmt = STFMT_UNUSED;
Packit Service f629e6
			r->stptr = value->str_value.str;
Packit Service f629e6
			r->stlen = value->str_value.len;
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
			r->strndmode = MPFR_round_mode;
Packit Service f629e6
#endif
Packit Service f629e6
			return awk_true;
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
	case AWK_REGEX:
Packit Service f629e6
	case AWK_UNDEFINED:
Packit Service f629e6
	case AWK_SCALAR:
Packit Service f629e6
	case AWK_VALUE_COOKIE:
Packit Service f629e6
		break;
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
	default:	/* AWK_ARRAY or invalid type */
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	/* do it the hard (slow) way */
Packit Service f629e6
	unref(node->var_value);
Packit Service f629e6
	node->var_value = awk_value_to_node(value);
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * valid_subscript_type --- test if a type is allowed for an array subscript.
Packit Service f629e6
 *
Packit Service f629e6
 * Any scalar value is fine, so only AWK_ARRAY (or an invalid type) is illegal.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static inline bool
Packit Service f629e6
valid_subscript_type(awk_valtype_t valtype)
Packit Service f629e6
{
Packit Service f629e6
	switch (valtype) {
Packit Service f629e6
	case AWK_UNDEFINED:
Packit Service f629e6
	case AWK_NUMBER:
Packit Service f629e6
	case AWK_STRNUM:
Packit Service f629e6
	case AWK_STRING:
Packit Service f629e6
	case AWK_REGEX:
Packit Service f629e6
	case AWK_SCALAR:
Packit Service f629e6
	case AWK_VALUE_COOKIE:
Packit Service f629e6
		return true;
Packit Service f629e6
	default:	/* AWK_ARRAY or an invalid type */
Packit Service f629e6
		return false;
Packit Service f629e6
	}
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Array management */
Packit Service f629e6
/*
Packit Service f629e6
 * api_get_array_element --- teturn the value of an element - read only!
Packit Service f629e6
 *
Packit Service f629e6
 * Use set_array_element to change it.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_get_array_element(awk_ext_id_t id,
Packit Service f629e6
		awk_array_t a_cookie,
Packit Service f629e6
		const awk_value_t *const index,
Packit Service f629e6
		awk_valtype_t wanted,
Packit Service f629e6
		awk_value_t *result)
Packit Service f629e6
{
Packit Service f629e6
	NODE *array = (NODE *) a_cookie;
Packit Service f629e6
	NODE *subscript;
Packit Service f629e6
	NODE **aptr;
Packit Service f629e6
Packit Service f629e6
	/* don't check for index len zero, null str is ok as index */
Packit Service f629e6
	if (   array == NULL
Packit Service f629e6
	    || array->type != Node_var_array
Packit Service f629e6
	    || result == NULL
Packit Service f629e6
	    || index == NULL
Packit Service f629e6
	    || ! valid_subscript_type(index->val_type))
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	subscript = awk_value_to_node(index);
Packit Service f629e6
Packit Service f629e6
	/* if it doesn't exist, return false */
Packit Service f629e6
	if (in_array(array, subscript) == NULL) {
Packit Service f629e6
		unref(subscript);
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	aptr = assoc_lookup(array, subscript);
Packit Service f629e6
Packit Service f629e6
	if (aptr == NULL) {	/* can't happen */
Packit Service f629e6
		unref(subscript);
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	unref(subscript);
Packit Service f629e6
Packit Service f629e6
	return node_to_awk_value(*aptr, result, wanted);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * api_set_array_element --- change (or create) element in existing array
Packit Service f629e6
 *	with element->index and element->value.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
Packit Service f629e6
					const awk_value_t *const index,
Packit Service f629e6
					const awk_value_t *const value)
Packit Service f629e6
{
Packit Service f629e6
	NODE *array = (NODE *)a_cookie;
Packit Service f629e6
	NODE *tmp;
Packit Service f629e6
	NODE *elem;
Packit Service f629e6
	NODE **aptr;
Packit Service f629e6
Packit Service f629e6
	/* don't check for index len zero, null str is ok as index */
Packit Service f629e6
	if (   array == NULL
Packit Service f629e6
	    || array->type != Node_var_array
Packit Service f629e6
	    || (array->flags & NO_EXT_SET) != 0
Packit Service f629e6
	    || index == NULL
Packit Service f629e6
	    || value == NULL
Packit Service f629e6
	    || ! valid_subscript_type(index->val_type))
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	tmp = awk_value_to_node(index);
Packit Service f629e6
	aptr = assoc_lookup(array, tmp);
Packit Service f629e6
	unref(*aptr);
Packit Service f629e6
	elem = *aptr = awk_value_to_node(value);
Packit Service f629e6
	if (elem->type == Node_var_array) {
Packit Service f629e6
		elem->parent_array = array;
Packit Service f629e6
		elem->vname = estrdup(index->str_value.str,
Packit Service f629e6
					index->str_value.len);
Packit Service f629e6
	}
Packit Service f629e6
	if (array->astore != NULL)
Packit Service f629e6
		(*array->astore)(array, tmp);
Packit Service f629e6
	unref(tmp);
Packit Service f629e6
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * remove_element --- remove an array element
Packit Service f629e6
 *		common code used by multiple functions
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
remove_element(NODE *array, NODE *subscript)
Packit Service f629e6
{
Packit Service f629e6
	NODE *val;
Packit Service f629e6
Packit Service f629e6
	if (array == NULL)
Packit Service f629e6
		fatal(_("remove_element: received null array"));
Packit Service f629e6
Packit Service f629e6
	if (subscript == NULL)
Packit Service f629e6
		fatal(_("remove_element: received null subscript"));
Packit Service f629e6
Packit Service f629e6
	val = in_array(array, subscript);
Packit Service f629e6
Packit Service f629e6
	if (val == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	if (val->type == Node_var_array) {
Packit Service f629e6
		assoc_clear(val);
Packit Service f629e6
		/* cleared a sub-array, free Node_var_array */
Packit Service f629e6
		efree(val->vname);
Packit Service f629e6
		freenode(val);
Packit Service f629e6
	} else
Packit Service f629e6
		unref(val);
Packit Service f629e6
Packit Service f629e6
	(void) assoc_remove(array, subscript);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * api_del_array_element --- remove the element with the given index.
Packit Service f629e6
 *	Return success if removed or if element did not exist.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_del_array_element(awk_ext_id_t id,
Packit Service f629e6
		awk_array_t a_cookie, const awk_value_t* const index)
Packit Service f629e6
{
Packit Service f629e6
	NODE *array, *sub;
Packit Service f629e6
Packit Service f629e6
	array = (NODE *) a_cookie;
Packit Service f629e6
	if (   array == NULL
Packit Service f629e6
	    || array->type != Node_var_array
Packit Service f629e6
	    || (array->flags & NO_EXT_SET) != 0
Packit Service f629e6
	    || index == NULL
Packit Service f629e6
	    || ! valid_subscript_type(index->val_type))
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	sub = awk_value_to_node(index);
Packit Service f629e6
	remove_element(array, sub);
Packit Service f629e6
	unref(sub);
Packit Service f629e6
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * api_get_element_count --- retrieve total number of elements in array.
Packit Service f629e6
 *	Return false if some kind of error.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_get_element_count(awk_ext_id_t id,
Packit Service f629e6
		awk_array_t a_cookie, size_t *count)
Packit Service f629e6
{
Packit Service f629e6
	NODE *node = (NODE *) a_cookie;
Packit Service f629e6
Packit Service f629e6
	if (count == NULL || node == NULL || node->type != Node_var_array)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	*count = node->table_size;
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_create_array --- create a new array cookie to which elements may be added */
Packit Service f629e6
Packit Service f629e6
static awk_array_t
Packit Service f629e6
api_create_array(awk_ext_id_t id)
Packit Service f629e6
{
Packit Service f629e6
	NODE *n;
Packit Service f629e6
Packit Service f629e6
	getnode(n);
Packit Service f629e6
	memset(n, 0, sizeof(NODE));
Packit Service f629e6
	null_array(n);
Packit Service f629e6
Packit Service f629e6
	return (awk_array_t) n;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_clear_array --- clear out an array */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_clear_array(awk_ext_id_t id, awk_array_t a_cookie)
Packit Service f629e6
{
Packit Service f629e6
	NODE *node = (NODE *) a_cookie;
Packit Service f629e6
Packit Service f629e6
	if (   node == NULL
Packit Service f629e6
	    || node->type != Node_var_array
Packit Service f629e6
	    || (node->flags & NO_EXT_SET) != 0)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	assoc_clear(node);
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_flatten_array_typed --- flatten out an array so that it can be looped over easily. */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_flatten_array_typed(awk_ext_id_t id,
Packit Service f629e6
		awk_array_t a_cookie,
Packit Service f629e6
		awk_flat_array_t **data,
Packit Service f629e6
		awk_valtype_t index_type, awk_valtype_t value_type)
Packit Service f629e6
{
Packit Service f629e6
	NODE **list;
Packit Service f629e6
	size_t i, j;
Packit Service f629e6
	NODE *array = (NODE *) a_cookie;
Packit Service f629e6
	size_t alloc_size;
Packit Service f629e6
Packit Service f629e6
	if (   array == NULL
Packit Service f629e6
	    || array->type != Node_var_array
Packit Service f629e6
	    || array->table_size == 0
Packit Service f629e6
	    || data == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	alloc_size = sizeof(awk_flat_array_t) +
Packit Service f629e6
			(array->table_size - 1) * sizeof(awk_element_t);
Packit Service f629e6
Packit Service f629e6
	ezalloc(*data, awk_flat_array_t *, alloc_size,
Packit Service f629e6
			"api_flatten_array_typed");
Packit Service f629e6
Packit Service f629e6
	list = assoc_list(array, "@unsorted", ASORTI);
Packit Service f629e6
Packit Service f629e6
	(*data)->opaque1 = array;
Packit Service f629e6
	(*data)->opaque2 = list;
Packit Service f629e6
	(*data)->count = array->table_size;
Packit Service f629e6
Packit Service f629e6
	for (i = j = 0; i < 2 * array->table_size; i += 2, j++) {
Packit Service f629e6
		NODE *index, *value;
Packit Service f629e6
Packit Service f629e6
		index = list[i];
Packit Service f629e6
		value = list[i + 1]; /* number or string or subarray */
Packit Service f629e6
Packit Service f629e6
		/* Convert index and value to API types. */
Packit Service f629e6
		if (! node_to_awk_value(index,
Packit Service f629e6
				& (*data)->elements[j].index, index_type)) {
Packit Service f629e6
			fatal(_("api_flatten_array_typed: could not convert index %d to %s\n"),
Packit Service f629e6
						(int) i, valtype2str(index_type));
Packit Service f629e6
		}
Packit Service f629e6
		if (! node_to_awk_value(value,
Packit Service f629e6
				& (*data)->elements[j].value, value_type)) {
Packit Service f629e6
			fatal(_("api_flatten_array_typed: could not convert value %d to %s\n"),
Packit Service f629e6
						(int) i, valtype2str(value_type));
Packit Service f629e6
		}
Packit Service f629e6
	}
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * api_release_flattened_array --- release array memory,
Packit Service f629e6
 *	delete any marked elements. Count must match what
Packit Service f629e6
 *	gawk thinks the size is.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_release_flattened_array(awk_ext_id_t id,
Packit Service f629e6
		awk_array_t a_cookie,
Packit Service f629e6
		awk_flat_array_t *data)
Packit Service f629e6
{
Packit Service f629e6
	NODE *array = a_cookie;
Packit Service f629e6
	NODE **list;
Packit Service f629e6
	size_t i, j, k;
Packit Service f629e6
Packit Service f629e6
	if (   array == NULL
Packit Service f629e6
	    || array->type != Node_var_array
Packit Service f629e6
	    || data == NULL
Packit Service f629e6
	    || array != (NODE *) data->opaque1
Packit Service f629e6
	    || data->count != array->table_size
Packit Service f629e6
	    || data->opaque2 == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	list = (NODE **) data->opaque2;
Packit Service f629e6
Packit Service f629e6
	/* free index nodes */
Packit Service f629e6
	for (i = j = 0, k = 2 * array->table_size; i < k; i += 2, j++) {
Packit Service f629e6
		/* Delete items flagged for delete. */
Packit Service f629e6
		if (   (data->elements[j].flags & AWK_ELEMENT_DELETE) != 0
Packit Service f629e6
		    && (array->flags & NO_EXT_SET) == 0) {
Packit Service f629e6
			remove_element(array, list[i]);
Packit Service f629e6
		}
Packit Service f629e6
		unref(list[i]);
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	efree(list);
Packit Service f629e6
	efree(data);
Packit Service f629e6
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_create_value --- create a cached value */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_create_value(awk_ext_id_t id, awk_value_t *value,
Packit Service f629e6
		awk_value_cookie_t *result)
Packit Service f629e6
{
Packit Service f629e6
	if (value == NULL || result == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	switch (value->val_type) {
Packit Service f629e6
	case AWK_NUMBER:
Packit Service f629e6
	case AWK_STRNUM:
Packit Service f629e6
	case AWK_STRING:
Packit Service f629e6
	case AWK_REGEX:
Packit Service f629e6
		break;
Packit Service f629e6
	default:
Packit Service f629e6
		/* reject anything other than a simple scalar */
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	return (awk_bool_t) ((*result = awk_value_to_node(value)) != NULL);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_release_value --- release a cached value */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_release_value(awk_ext_id_t id, awk_value_cookie_t value)
Packit Service f629e6
{
Packit Service f629e6
	NODE *val = (NODE *) value;
Packit Service f629e6
Packit Service f629e6
	if (val == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	unref(val);
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_get_mpfr --- allocate an mpfr_ptr */
Packit Service f629e6
Packit Service f629e6
static void *
Packit Service f629e6
api_get_mpfr(awk_ext_id_t id)
Packit Service f629e6
{
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
	mpfr_ptr p;
Packit Service f629e6
	getmpfr(p);
Packit Service f629e6
	mpfr_init(p);
Packit Service f629e6
	return p;
Packit Service f629e6
#else
Packit Service f629e6
	fatal(_("api_get_mpfr: MPFR not supported"));
Packit Service f629e6
	return NULL;	// silence compiler warning
Packit Service f629e6
#endif
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_get_mpz --- allocate an mpz_ptr */
Packit Service f629e6
Packit Service f629e6
static void *
Packit Service f629e6
api_get_mpz(awk_ext_id_t id)
Packit Service f629e6
{
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
	mpz_ptr p;
Packit Service f629e6
	getmpz(p);
Packit Service f629e6
	mpz_init(p);
Packit Service f629e6
	return p;
Packit Service f629e6
#else
Packit Service f629e6
	fatal(_("api_get_mpfr: MPFR not supported"));
Packit Service f629e6
	return NULL;	// silence compiler warning
Packit Service f629e6
#endif
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* api_get_file --- return a handle to an existing or newly opened file */
Packit Service f629e6
Packit Service f629e6
static awk_bool_t
Packit Service f629e6
api_get_file(awk_ext_id_t id, const char *name, size_t namelen, const char *filetype,
Packit Service f629e6
		int fd, const awk_input_buf_t **ibufp, const awk_output_buf_t **obufp)
Packit Service f629e6
{
Packit Service f629e6
	const struct redirect *f;
Packit Service f629e6
	int flag;	/* not used, sigh */
Packit Service f629e6
	enum redirval redirtype;
Packit Service f629e6
Packit Service f629e6
	if (name == NULL || namelen == 0) {
Packit Service f629e6
		if (curfile == NULL) {
Packit Service f629e6
			INSTRUCTION *pc;
Packit Service f629e6
			int save_rule;
Packit Service f629e6
			char *save_source;
Packit Service f629e6
Packit Service f629e6
			if (nextfile(& curfile, false) <= 0)
Packit Service f629e6
				return awk_false;
Packit Service f629e6
Packit Service f629e6
			pc = main_beginfile;
Packit Service f629e6
			/* save execution state */
Packit Service f629e6
			save_rule = currule;
Packit Service f629e6
			save_source = source;
Packit Service f629e6
Packit Service f629e6
			for (;;) {
Packit Service f629e6
				if (pc == NULL)
Packit Service f629e6
					fatal(_("cannot find end of BEGINFILE rule"));
Packit Service f629e6
				if (pc->opcode == Op_after_beginfile)
Packit Service f629e6
					break;
Packit Service f629e6
				pc = pc->nexti;
Packit Service f629e6
			}
Packit Service f629e6
			pc->opcode = Op_stop;
Packit Service f629e6
		        (void) (*interpret)(main_beginfile);
Packit Service f629e6
			pc->opcode = Op_after_beginfile;
Packit Service f629e6
			after_beginfile(& curfile);
Packit Service f629e6
			/* restore execution state */
Packit Service f629e6
			currule = save_rule;
Packit Service f629e6
			source = save_source;
Packit Service f629e6
		}
Packit Service f629e6
		*ibufp = &curfile->public;
Packit Service f629e6
		*obufp = NULL;
Packit Service f629e6
Packit Service f629e6
		return awk_true;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	redirtype = redirect_none;
Packit Service f629e6
	switch (filetype[0]) {
Packit Service f629e6
	case '<':
Packit Service f629e6
		if (filetype[1] == '\0')
Packit Service f629e6
			redirtype = redirect_input;
Packit Service f629e6
		break;
Packit Service f629e6
	case '>':
Packit Service f629e6
		switch (filetype[1]) {
Packit Service f629e6
		case '\0':
Packit Service f629e6
			redirtype = redirect_output;
Packit Service f629e6
			break;
Packit Service f629e6
		case '>':
Packit Service f629e6
			if (filetype[2] == '\0')
Packit Service f629e6
				redirtype = redirect_append;
Packit Service f629e6
			break;
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
	case '|':
Packit Service f629e6
		if (filetype[2] == '\0') {
Packit Service f629e6
			switch (filetype[1]) {
Packit Service f629e6
			case '>':
Packit Service f629e6
				redirtype = redirect_pipe;
Packit Service f629e6
				break;
Packit Service f629e6
			case '<':
Packit Service f629e6
				redirtype = redirect_pipein;
Packit Service f629e6
				break;
Packit Service f629e6
			case '&':
Packit Service f629e6
				redirtype = redirect_twoway;
Packit Service f629e6
				break;
Packit Service f629e6
			}
Packit Service f629e6
		}
Packit Service f629e6
		break;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	if (redirtype == redirect_none) {
Packit Service f629e6
		warning(_("cannot open unrecognized file type `%s' for `%s'"),
Packit Service f629e6
			filetype, name);
Packit Service f629e6
		return awk_false;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
	if ((f = redirect_string(name, namelen, 0, redirtype, &flag, fd, false)) == NULL)
Packit Service f629e6
		return awk_false;
Packit Service f629e6
Packit Service f629e6
	*ibufp = f->iop ? & f->iop->public : NULL;
Packit Service f629e6
	*obufp = f->output.fp ? & f->output : NULL;
Packit Service f629e6
	return awk_true;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * Register a version string for this extension with gawk.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
struct version_info {
Packit Service f629e6
	const char *version;
Packit Service f629e6
	struct version_info *next;
Packit Service f629e6
};
Packit Service f629e6
Packit Service f629e6
static struct version_info *vi_head;
Packit Service f629e6
Packit Service f629e6
/* api_register_ext_version --- add an extension version string to the list */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
api_register_ext_version(awk_ext_id_t id, const char *version)
Packit Service f629e6
{
Packit Service f629e6
	struct version_info *info;
Packit Service f629e6
Packit Service f629e6
	if (version == NULL)
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	(void) id;
Packit Service f629e6
Packit Service f629e6
	emalloc(info, struct version_info *, sizeof(struct version_info), "register_ext_version");
Packit Service f629e6
	info->version = version;
Packit Service f629e6
	info->next = vi_head;
Packit Service f629e6
	vi_head = info;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* the struct api */
Packit Service f629e6
gawk_api_t api_impl = {
Packit Service f629e6
	/* data */
Packit Service f629e6
	GAWK_API_MAJOR_VERSION,	/* major and minor versions */
Packit Service f629e6
	GAWK_API_MINOR_VERSION,
Packit Service f629e6
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
	__GNU_MP_VERSION,
Packit Service f629e6
	__GNU_MP_VERSION_MINOR,
Packit Service f629e6
	MPFR_VERSION_MAJOR,
Packit Service f629e6
	MPFR_VERSION_MINOR,
Packit Service f629e6
#else
Packit Service f629e6
	0, 0, 0, 0,
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
	{ 0 },			/* do_flags */
Packit Service f629e6
Packit Service f629e6
	/* registration functions */
Packit Service f629e6
	api_add_ext_func,
Packit Service f629e6
	api_register_input_parser,
Packit Service f629e6
	api_register_output_wrapper,
Packit Service f629e6
	api_register_two_way_processor,
Packit Service f629e6
	api_awk_atexit,
Packit Service f629e6
	api_register_ext_version,
Packit Service f629e6
Packit Service f629e6
	/* message printing functions */
Packit Service f629e6
	api_fatal,
Packit Service f629e6
	api_warning,
Packit Service f629e6
	api_lintwarn,
Packit Service f629e6
	api_nonfatal,
Packit Service f629e6
Packit Service f629e6
	/* updating ERRNO */
Packit Service f629e6
	api_update_ERRNO_int,
Packit Service f629e6
	api_update_ERRNO_string,
Packit Service f629e6
	api_unset_ERRNO,
Packit Service f629e6
Packit Service f629e6
	/* Function arguments */
Packit Service f629e6
	api_get_argument,
Packit Service f629e6
	api_set_argument,
Packit Service f629e6
Packit Service f629e6
	/* Accessing and installing variables and constants */
Packit Service f629e6
	api_sym_lookup,
Packit Service f629e6
	api_sym_update,
Packit Service f629e6
Packit Service f629e6
	/* Accessing and modifying variables via scalar cookies */
Packit Service f629e6
	api_sym_lookup_scalar,
Packit Service f629e6
	api_sym_update_scalar,
Packit Service f629e6
Packit Service f629e6
	/* Cached values */
Packit Service f629e6
	api_create_value,
Packit Service f629e6
	api_release_value,
Packit Service f629e6
Packit Service f629e6
	/* Array management */
Packit Service f629e6
	api_get_element_count,
Packit Service f629e6
	api_get_array_element,
Packit Service f629e6
	api_set_array_element,
Packit Service f629e6
	api_del_array_element,
Packit Service f629e6
	api_create_array,
Packit Service f629e6
	api_clear_array,
Packit Service f629e6
	api_flatten_array_typed,
Packit Service f629e6
	api_release_flattened_array,
Packit Service f629e6
Packit Service f629e6
	/* Memory allocation */
Packit Service f629e6
	malloc,
Packit Service f629e6
	calloc,
Packit Service f629e6
	realloc,
Packit Service f629e6
	free,
Packit Service f629e6
	api_get_mpfr,
Packit Service f629e6
	api_get_mpz,
Packit Service f629e6
Packit Service f629e6
	/* Find/open a file */
Packit Service f629e6
	api_get_file,
Packit Service f629e6
};
Packit Service f629e6
Packit Service f629e6
/* init_ext_api --- init the extension API */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
init_ext_api()
Packit Service f629e6
{
Packit Service f629e6
	/* force values to 1 / 0 */
Packit Service f629e6
	api_impl.do_flags[0] = (do_lint ? 1 : 0);
Packit Service f629e6
	api_impl.do_flags[1] = (do_traditional ? 1 : 0);
Packit Service f629e6
	api_impl.do_flags[2] = (do_profile ? 1 : 0);
Packit Service f629e6
	api_impl.do_flags[3] = (do_sandbox ? 1 : 0);
Packit Service f629e6
	api_impl.do_flags[4] = (do_debug ? 1 : 0);
Packit Service f629e6
	api_impl.do_flags[5] = (do_mpfr ? 1 : 0);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* update_ext_api --- update the variables in the API that can change */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
update_ext_api()
Packit Service f629e6
{
Packit Service f629e6
	api_impl.do_flags[0] = (do_lint ? 1 : 0);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* print_ext_versions --- print the list */
Packit Service f629e6
Packit Service f629e6
extern void
Packit Service f629e6
print_ext_versions(void)
Packit Service f629e6
{
Packit Service f629e6
	struct version_info *p;
Packit Service f629e6
Packit Service f629e6
	for (p = vi_head; p != NULL; p = p->next)
Packit Service f629e6
		printf("%s\n", p->version);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* valtype2str --- return a printable representation of a value type */
Packit Service f629e6
Packit Service f629e6
static char *
Packit Service f629e6
valtype2str(awk_valtype_t type)
Packit Service f629e6
{
Packit Service f629e6
	static char buf[100];
Packit Service f629e6
Packit Service f629e6
	// Important: keep in same order as in gawkapi.h!
Packit Service f629e6
	static char *values[] = {
Packit Service f629e6
		"AWK_UNDEFINED",
Packit Service f629e6
		"AWK_NUMBER",
Packit Service f629e6
		"AWK_STRING",
Packit Service f629e6
		"AWK_REGEX",
Packit Service f629e6
		"AWK_STRNUM",
Packit Service f629e6
		"AWK_ARRAY",
Packit Service f629e6
		"AWK_SCALAR",
Packit Service f629e6
		"AWK_VALUE_COOKIE",
Packit Service f629e6
	};
Packit Service f629e6
Packit Service f629e6
	if (AWK_UNDEFINED <= type && type <= AWK_VALUE_COOKIE)
Packit Service f629e6
		return values[(int) type];
Packit Service f629e6
Packit Service f629e6
	sprintf(buf, "unknown type! (%d)", (int) type);
Packit Service f629e6
Packit Service f629e6
	return buf;
Packit Service f629e6
}