/*
array.h

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

copyright 1991-96, 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.
*/

/*
This file originally had been generated with the command

   notangle -R'"array.h"' array.w > array.h

but is maintained as .h in libmawk.

(Notangle is part of Norman Ramsey's noweb literate programming package
available from CTAN(ftp.shsu.edu)).
*/

#ifndef ARRAY_H
#define ARRAY_H 1

#define AY_NULL         0
#define AY_INT          1
#define AY_STR          2
#define AY_SPLIT        4

#define NO_MAWK_CREATE  0
#define MAWK_CREATE     1

#include "cell.h"
#include "array_orig.h"

/* create a new, empty array, copying implementation from imp; if imp is NULL,
   use the default (original) implementation. */
mawk_array_t mawk_array_new(mawk_state_t *MAWK, const array_imp_t *imp);

/* free all memory used by ARR */
void mawk_array_destroy(mawk_state_t *MAWK, mawk_array_t ARR);

/* concat multiple expressions separated by SUBSEP to be an array index */
mawk_cell_t *mawk_array_cat(mawk_state_t *MAWK, mawk_cell_t *sp, int cnt);

/* clear the common administrative part of the array, leaving imp alone;
   this must be used instead of memsetting the mawk_array_t */
void mawk_array_clear_common(mawk_state_t *MAWK, mawk_array_t A);


/* wrappers for accessing the implementations; a layer of macros is introduced
   here to guarantee future flexibility */
/* **** WARNING: these macros will ecaluate ARR_ at least twice!  **** */
#define mawk_array_find(MAWK_, ARR_, idx_, result_, create_)  (ARR_)->imp.find((MAWK_), (ARR_), (idx_), (result_), (create_))
#define mawk_array_set(MAWK_, ARR_, idx_, val_)      (ARR_)->imp.set((MAWK_), (ARR_), (idx_), (val_))
#define mawk_array_delete(MAWK_, ARR_, cell_)        (ARR_)->imp.delet((MAWK_), (ARR_), (cell_))
#define mawk_array_clear(MAWK_, ARR_)                (ARR_)->imp.clear((MAWK_), (ARR_))
#define mawk_array_loop_vector(MAWK_, ARR_, sizep_)  (ARR_)->imp.loop_vect((MAWK_), (ARR_), (sizep_))
#define mawk_array_load(MAWK_, ARR_, cnt_)           (ARR_)->imp.load((MAWK_), (ARR_), (cnt_))





/* The following macros are used in execute.c for fast and convenient access
   to cells on SP */

/* check whether an array is pure (no side effects, aka orig implementation) for
   read or read+write */
#define mawk_array_pure4wr(MAWK, ARR_) (ARR_)->imp.set == mawk_array_orig_imp.set
#define mawk_array_pure4del(MAWK, ARR_) (ARR_)->imp.delet == mawk_array_orig_imp.delet
#define mawk_array_pure4rd(MAWK, ARR_) (ARR_)->imp.find == mawk_array_orig_imp.find
#define mawk_array_pure4rdwr(MAWK, ARR_) ((mawk_array_pure4wr((MAWK), (ARR_))) && (mawk_array_pure4del((MAWK), (ARR_))) && (mawk_array_pure4rd((MAWK), (ARR_))))

#define mawk_array_pure(MAWK, ARR_REF_, for_write) ((for_write) ? (mawk_array_pure4rdwr((MAWK), (mawk_array_t)(ARR_REF_)->ptr)) : (mawk_array_pure4rd((MAWK), (mawk_array_t)(ARR_REF_)->ptr)))

/* change the value of an array pointed to by ARR_REF_ (typer C_ARR_REF).
   This wrapper is useful from execute.c where multiple assignments
   to array elemts will have to do the same:
    - look up the index in the array
    - modify the content of the array element
    - destroy the index and the rvalue
    - put the value of the expr in res_

   Note: mawk_cell_destroy(MAWK, (mawk_cell_t *)(ARR_REF_)) is not required: destroy of C_ARR_REF is a nop
*/
#define mawk_array_set_execute_(MAWK, res_, ARR_REF_, IDX_, rvalue_) \
do { \
	mawk_array_set(MAWK, (mawk_array_t)((ARR_REF_)->ptr), (IDX_), rvalue_); \
	mawk_cell_destroy(MAWK, (mawk_cell_t *)(IDX_)); \
	if (IDX_ != res_) \
		mawk_cell_destroy(MAWK, res_); \
	mawk_cellcpy(MAWK, res_, rvalue_); \
	mawk_cell_destroy(MAWK, rvalue_); \
} while(0)

/* look up an array element; place the resulting cell in res_

   Does not destroy IDX_.

   Note: mawk_cell_destroy(MAWK, (mawk_cell_t *)(ARR_REF_)) is not required: destroy of C_ARR_REF is a nop
*/
#define mawk_array_get_execute_(MAWK, res_, ARR_REF_, IDX_) \
do { \
	mawk_array_find(MAWK, (mawk_array_t)((ARR_REF_)->ptr), (IDX_), (res_), MAWK_CREATE); \
} while(0)


/* this must not be used on arrays with side effects */
mawk_cell_t *mawk_array_find_orig_(mawk_state_t *MAWK, mawk_array_t A, const mawk_cell_t *cp, int create_flag);
#define mawk_array_getptr_execute_(MAWK, res_, ARR_REF_, IDX_) \
do { \
	res_ = mawk_array_find_orig_(MAWK, (mawk_array_t)((ARR_REF_)->ptr), (IDX_), MAWK_CREATE); \
} while(0)


/* same as mawk_arra_get_execute plus cast the result to number if it is not
   a number already
   does not destroy IDX
    */
#define mawk_array_getnum_execute_(MAWK, res_, ARR_REF_, IDX_) \
do { \
	mawk_array_get_execute(MAWK, (res_), (ARR_REF_), (IDX_)); \
	if ((res_)->type != C_NUM) \
		mawk_cast1_to_num(MAWK, (res_)); \
} while(0)

#ifdef DEBUG
	/* in debug mode use static inlines for easier debugging */
	static inline void mawk_array_get_execute(mawk_state_t *MAWK, mawk_cell_t *res, mawk_cell_t *arr_ref, mawk_cell_t *idx)
	{
		mawk_array_get_execute_(MAWK, res, arr_ref, idx);
	}

	static inline void mawk_array_getptr_execute(mawk_state_t *MAWK, mawk_cell_t *res, mawk_cell_t *arr_ref, mawk_cell_t *idx)
	{
		mawk_array_getptr_execute_(MAWK, res, arr_ref, idx);
	}

	static inline void mawk_array_getnum_execute(mawk_state_t *MAWK, mawk_cell_t *res, mawk_cell_t *arr_ref, mawk_cell_t *idx)
	{
		mawk_array_getnum_execute_(MAWK, res, arr_ref, idx);
	}

	static inline void mawk_array_set_execute(mawk_state_t *MAWK, mawk_cell_t *res, mawk_cell_t *arr_ref, mawk_cell_t *idx, mawk_cell_t *rvalue)
	{
		mawk_array_set_execute_(MAWK, res, arr_ref, idx, rvalue);
	}
#else
#define mawk_array_getnum_execute mawk_array_getnum_execute_
#define mawk_array_getptr_execute mawk_array_getptr_execute_
#define mawk_array_get_execute mawk_array_get_execute_
#define mawk_array_set_execute mawk_array_set_execute_
#endif



#endif /* ARRAY_H */



