/********************************************
field_common.c - $ field operation required in both compile and execute time

libmawk changes (C) 2009-2010, Tibor 'Igor2' Palinkas;
based on mawk code coming with the below copyright:

copyright 1991, Michael D. Brennan

This is a source file for mawk, an implementation of
the AWK programming language.

Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
#include "mawk.h"
#include "field.h"
#include "init.h"
#include "memory.h"
#include "scan.h"
#include "bi_vars.h"
#include "repl.h"
#include "regexp.h"

void mawk_load_pfield(mawk_state_t *MAWK, char *name, mawk_cell_t *cp)
{
	SYMTAB *stp;

	stp = mawk_insert(MAWK, name);
	stp->type = ST_FIELD;
	stp->stval.cp = cp;
}


int mawk_field_addr_to_index(mawk_state_t *MAWK, mawk_cell_t *cp)
{
	mawk_cell_t **p = MAWK->fbank;

	while (cp < *p || cp >= *p + FBANK_SZ)
		p++;

	return ((p - MAWK->fbank) << FB_SHIFT) + (cp - *p);
}

/*------- more than 1 fbank needed  ------------*/

/*
  compute the address of a field with index
  > MAX_SPLIT
*/
mawk_cell_t *mawk_slow_field_ptr(mawk_state_t *MAWK, register int i)
{

	if (i > MAWK->max_field) {
		int j;

		if (i > MAX_FIELD)
			mawk_rt_overflow(MAWK, "maximum number of fields", MAX_FIELD);

		j = 1;
		while (MAWK->fbank[j])
			j++;

		do {
			MAWK->fbank[j] = (mawk_cell_t *) mawk_zmalloc(MAWK, sizeof(mawk_cell_t) * FBANK_SZ);
			memset(MAWK->fbank[j], 0, sizeof(mawk_cell_t) * FBANK_SZ);
			j++;
			MAWK->max_field += FBANK_SZ;
		}
		while (i > MAWK->max_field);
	}

	return &MAWK->fbank[i >> FB_SHIFT][i & (FBANK_SZ - 1)];
}


/* mawk_initialize $0 and the pseudo fields */
void mawk_field_init(mawk_state_t * MAWK)
{
	MAWK->field[0].type = C_STRING;
	MAWK->field[0].ptr = (PTR) & MAWK->null_str;
	MAWK->null_str.ref_cnt++;

	mawk_load_pfield(MAWK, "NF", MAWK_NF);
	MAWK_NF->type = C_NUM;
	MAWK_NF->d.dval = MAWK_NUM_ZERO;

	mawk_load_pfield(MAWK, "RS", MAWK_RS);
	MAWK_RS->type = C_STRING;
	MAWK_RS->ptr = (PTR) mawk_new_STRING(MAWK, "\n");
	/* rs_shadow already set */

	mawk_load_pfield(MAWK, "FS", MAWK_FS);
	MAWK_FS->type = C_STRING;
	MAWK_FS->ptr = (PTR) mawk_new_STRING(MAWK, " ");
	/* fs_shadow is already set */

	mawk_load_pfield(MAWK, "OFMT", MAWK_OFMT);
	MAWK_OFMT->type = C_STRING;
	MAWK_OFMT->ptr = (PTR) mawk_new_STRING(MAWK, "%.6g");

	mawk_load_pfield(MAWK, "CONVFMT", MAWK_CONVFMT);
	MAWK_CONVFMT->type = C_STRING;
	MAWK_CONVFMT->ptr = MAWK_OFMT->ptr;
	string(MAWK_OFMT)->ref_cnt++;
}

#ifdef MAWK_MEM_PEDANTIC
void mawk_field_uninit(mawk_state_t * MAWK)
{
	mawk_delete(MAWK, "NF", 1);
	mawk_delete(MAWK, "RS", 1);
	mawk_delete(MAWK, "FS", 1);
	mawk_delete(MAWK, "OFMT", 1);
	mawk_delete(MAWK, "CONVFMT", 1);
}
#endif
