
/********************************************
types.h

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.
********************************************/

#ifndef  MAWK_TYPES_H
#define  MAWK_TYPES_H

#include  <libmawk/sizes.h>
#include  <libmawk/num.h>

/*  mawk_cell_t  types  */

typedef enum {
	C_NOINIT   = 0,
#ifdef CELLDEBUG
/* catch invalid access */
	C_FREED    = 1,
#endif

	C_NUM      = 2,
	C_ARR_REF  = 3, /* array reference when using with WRARR: two adjacent cells represend index and array (on the stack, normally) */
	C_ARR_REF_BT=4, /* array reference for bifunct_target references it is a single cell with ptr pointing to the array and d.idx_str containing the index string */

	C_EXE_STTYPE=5,
	C_EXE_STATE=6,
	C_REQ_NOMORE=7,
	C_REQ_CALL=8,

/* #### WARNING #### anything that is >= C_STRING is treated as a string:
   refco, free(), etc. */
	C_STRING   = 16,
	C_STRNUM   = 17,
	C_MBSTRN   = 18, /*could be STRNUM, has not been checked */
	C_RE       = 19,
	C_SPACE    = 20, /* split on space */
	C_SNULL    = 21, /* split on the empty string  */
	C_REPL     = 22, /* a replacement string   '\&' changed to &  */
	C_REPLV    = 23, /* a vector replacement -- broken on &  */
	NUM_CELL_TYPES
} mawk_celltype_t;

/* these defines are used to check types for two
   CELLs which are adjacent in memory */
#define  TWO_NOINITS  (2*(1<<C_NOINIT))
#define  TWO_NUMS     (2*(1<<C_NUM))
#define  TWO_STRINGS  (2*(1<<C_STRING))
#define  TWO_STRNUMS  (2*(1<<C_STRNUM))
#define  TWO_MBSTRNS  (2*(1<<C_MBSTRN))
#define  NOINIT_AND_NUM     ((1<<C_NOINIT)+(1<<C_NUM))
#define  NOINIT_AND_STRING  ((1<<C_NOINIT)+(1<<C_STRING))
#define  NOINIT_AND_STRNUM  ((1<<C_NOINIT)+(1<<C_STRNUM))
#define  NUM_AND_STRING     ((1<<C_NUM)+(1<<C_STRING))
#define  NUM_AND_STRNUM     ((1<<C_STRNUM)+(1<<C_NUM))
#define  STRING_AND_STRNUM  ((1<<C_STRING)+(1<<C_STRNUM))
#define  NOINIT_AND_MBSTRN  ((1<<C_NOINIT)+(1<<C_MBSTRN))
#define  NUM_AND_MBSTRN     ((1<<C_NUM)+(1<<C_MBSTRN))
#define  STRING_AND_MBSTRN  ((1<<C_STRING)+(1<<C_MBSTRN))
#define  STRNUM_AND_MBSTRN  ((1<<C_STRNUM)+(1<<C_MBSTRN))

typedef struct {
	unsigned len;
	unsigned short ref_cnt;
	char str[2];
} mawk_string_t;

/* number of bytes more than the characters to store a
   string */
#define  STRING_OH   (sizeof(mawk_string_t)-1)

/* macro to get at the string part of a mawk_cell_t */
#define string(cp) ((mawk_string_t *)(cp)->ptr)

typedef struct mawk_cell_s mawk_cell_t;

struct mawk_cell_s {
	mawk_celltype_t type;
	PTR ptr;              /* payload 1 - can not be in payload 2 because of STRNUMs that use both ptr for string and d.dval for num in the same time */
	union {               /* payload 2 */
		mawk_num_t dval;    /* number */
		int vcnt;           /* regex lib: only used if type == C_REPLV   */
		mawk_cell_t *idx_cell;     /* zmalloc'd index for bifunct_target array refs */
	} d;
};


/* all builtins are passed the evaluation stack pointer and
   return its new value, here is the type */

#include "mawk.h"
typedef mawk_cell_t *(*PF_CP) (mawk_state_t *, mawk_cell_t *);

/* an element of code (instruction) */
typedef union {
	unsigned long op; /* must be unsigned and at least 32 bits for da_bin */
	PTR ptr;
} INST;

#endif /* MAWK_TYPES_H */
