/*
* $Id$
*
Copyright 2006-2012 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see .
*/
#ifndef _QSE_AWK_AWK_H_
#define _QSE_AWK_AWK_H_
#include
#include
#include
#include
/** @file
* An embeddable AWK interpreter is defined in this header file.
*
* @todo
* - make enhancement to treat a function as a value
* - improve performance of qse_awk_rtx_readio() if RS is logner than 2 chars.
* - consider something like ${1:3,5} => $1, $2, $3, and $5 concatenated
*/
/**
* @example awk.c
* This program demonstrates how to build a complete awk interpreter.
*
* @example awk01.c
* This program demonstrates how to use qse_awk_rtx_loop().
*
* @example awk02.c
* The program deparses the source code and prints it before executing it.
*
* @example awk03.c
* This program demonstrates how to use qse_awk_rtx_call().
* It parses the program stored in the string src and calls the functions
* stated in the array fnc. If no errors occur, it should print 24.
*
* @example awk04.c
* This programs shows how to qse_awk_rtx_call().
*
* @example awk10.c
* This programs shows how to manipuate a map using qse_awk_rtx_makemapval()
* and qse_awk_rtx_setmapvalfld().
*
*/
/** @struct qse_awk_t
* The #qse_awk_t type defines an AWK interpreter. It provides an interface
* to parse an AWK script and run it to manipulate input and output data.
*
* In brief, you need to call APIs with user-defined handlers to run a typical
* AWK script as shown below:
*
* @code
* qse_awk_t* awk;
* qse_awk_rtx_t* rtx;
* qse_awk_sio_t sio; // need to initialize it with callback functions
* qse_awk_rio_t rio; // need to initialize it with callback functions
*
* awk = qse_awk_open (mmgr, 0, prm); // create an interpreter
* qse_awk_parse (awk, &sio); // parse a script
* rtx = qse_awk_rtx_open (awk, 0, &rio); // create a runtime context
* retv = qse_awk_rtx_loop (rtx); // run a standard AWK loop
* if (retv != QSE_NULL)
* qse_awk_rtx_refdownval (rtx, retv); // free return value
* qse_awk_rtx_close (rtx); // destroy the runtime context
* qse_awk_close (awk); // destroy the interpreter
* @endcode
*
* It provides an interface to change the conventional behavior of the
* interpreter; most notably, you can call a particular function with
* qse_awk_rtx_call() instead of entering the BEGIN, pattern-action blocks, END
* loop. By doing this, you may utilize a script in an event-driven way.
*
* @sa qse_awk_rtx_t qse_awk_open qse_awk_close
*/
typedef struct qse_awk_t qse_awk_t;
/** @struct qse_awk_rtx_t
* The #qse_awk_rtx_t type defines a runtime context. A runtime context
* maintains runtime state for a running script. You can create multiple
* runtime contexts out of a single AWK interpreter; in other words, you
* can run the same script with different input and output data by providing
* customized I/O handlers when creating a runtime context with
* qse_awk_rtx_open().
*
* I/O handlers are categoriezed into three kinds: console, file, pipe.
* The #qse_awk_rio_t type defines as a callback a set of I/O handlers
* to handle runtime I/O:
* - getline piped in from a command reads from a pipe.
* ("ls -l" | getline line)
* - print and printf piped out to a command write to a pipe.
* (print 2 | "sort")
* - getline redirected in reads from a file.
* (getline line < "file")
* - print and printf redirected out write to a file.
* (print num > "file")
* - The pattern-action loop and getline with no redirected input
* read from a console. (/susie/ { ... })
* - print and printf write to a console. (print "hello, world")
*
* @sa qse_awk_t qse_awk_rtx_open qse_awk_rio_t
*/
typedef struct qse_awk_rtx_t qse_awk_rtx_t;
/**
* The qse_awk_loc_t type defines a structure to hold location.
*/
struct qse_awk_loc_t
{
const qse_char_t* file; /**< file */
qse_size_t line; /**< line */
qse_size_t colm; /**< column */
};
typedef struct qse_awk_loc_t qse_awk_loc_t;
/**
* The QSE_AWK_VAL_HDR defines the common header for a value.
* Three common fields are:
* - type - type of a value from #qse_awk_val_type_t
* - ref - reference count
* - nstr - numeric string marker
*/
#if QSE_SIZEOF_INT == 2
# define QSE_AWK_VAL_HDR \
unsigned int type: 3; \
unsigned int ref: 10; \
unsigned int stat: 1; \
unsigned int nstr: 2
#else
# define QSE_AWK_VAL_HDR \
unsigned int type: 3; \
unsigned int ref: 26; \
unsigned int stat: 1; \
unsigned int nstr: 2
#endif
/**
* The qse_awk_val_t type is an abstract value type. A value commonly contains:
* - type of a value
* - reference count
* - indicator for a numeric string
*/
struct qse_awk_val_t
{
QSE_AWK_VAL_HDR;
};
typedef struct qse_awk_val_t qse_awk_val_t;
/**
* The qse_awk_val_nil_t type is a nil value type. The type field is
* #QSE_AWK_VAL_NIL.
*/
struct qse_awk_val_nil_t
{
QSE_AWK_VAL_HDR;
};
typedef struct qse_awk_val_nil_t qse_awk_val_nil_t;
/**
* The qse_awk_val_int_t type is an integer number type. The type field is
* #QSE_AWK_VAL_INT.
*/
struct qse_awk_val_int_t
{
QSE_AWK_VAL_HDR;
qse_long_t val;
void* nde;
};
typedef struct qse_awk_val_int_t qse_awk_val_int_t;
/**
* The qse_awk_val_flt_t type is a floating-point number type. The type field
* is #QSE_AWK_VAL_FLT.
*/
struct qse_awk_val_flt_t
{
QSE_AWK_VAL_HDR;
qse_flt_t val;
void* nde;
};
typedef struct qse_awk_val_flt_t qse_awk_val_flt_t;
/**
* The qse_awk_val_str_t type is a string type. The type field is
* #QSE_AWK_VAL_STR.
*/
struct qse_awk_val_str_t
{
QSE_AWK_VAL_HDR;
qse_xstr_t val;
};
typedef struct qse_awk_val_str_t qse_awk_val_str_t;
/**
* The qse_awk_val_rex_t type is a regular expression type. The type field
* is #QSE_AWK_VAL_REX.
*/
struct qse_awk_val_rex_t
{
QSE_AWK_VAL_HDR;
qse_xstr_t str;
void* code;
};
typedef struct qse_awk_val_rex_t qse_awk_val_rex_t;
/**
* The qse_awk_val_map_t type defines a map type. The type field is
* #QSE_AWK_VAL_MAP.
*/
struct qse_awk_val_map_t
{
QSE_AWK_VAL_HDR;
/* TODO: make val_map to array if the indices used are all
* integers switch to map dynamically once the
* non-integral index is seen.
*/
qse_htb_t* map;
};
typedef struct qse_awk_val_map_t qse_awk_val_map_t;
/**
* The qse_awk_val_ref_t type defines a reference type that is used
* internally only. The type field is #QSE_AWK_VAL_REF.
*/
struct qse_awk_val_ref_t
{
QSE_AWK_VAL_HDR;
enum
{
/* keep these items in the same order as corresponding items
* in qse_awk_nde_type_t. */
QSE_AWK_VAL_REF_NAMED, /**< plain named variable */
QSE_AWK_VAL_REF_GBL, /**< plain global variable */
QSE_AWK_VAL_REF_LCL, /**< plain local variable */
QSE_AWK_VAL_REF_ARG, /**< plain function argument */
QSE_AWK_VAL_REF_NAMEDIDX, /**< member of named map variable */
QSE_AWK_VAL_REF_GBLIDX, /**< member of global map variable */
QSE_AWK_VAL_REF_LCLIDX, /**< member of local map variable */
QSE_AWK_VAL_REF_ARGIDX, /**< member of map argument */
QSE_AWK_VAL_REF_POS /**< positional variable */
} id;
/* if id is QSE_AWK_VAL_REF_POS, adr holds an index of the
* positional variable. Otherwise, adr points to the value
* directly. */
qse_awk_val_t** adr;
};
typedef struct qse_awk_val_ref_t qse_awk_val_ref_t;
/**
* The qse_awk_val_map_itr_t type defines the iterator to map value fields.
*/
struct qse_awk_val_map_itr_t
{
qse_htb_pair_t* pair;
qse_size_t buckno;
};
typedef struct qse_awk_val_map_itr_t qse_awk_val_map_itr_t;
#define QSE_AWK_VAL_MAP_ITR_KEY(itr) \
((const qse_cstr_t*)QSE_HTB_KPTL((itr)->pair))
#define QSE_AWK_VAL_MAP_ITR_VAL(itr) \
((const qse_awk_val_t*)QSE_HTB_VPTR((itr)->pair))
enum qse_awk_val_map_data_type_t
{
QSE_AWK_VAL_MAP_DATA_INT = 0,
QSE_AWK_VAL_MAP_DATA_FLT,
QSE_AWK_VAL_MAP_DATA_STR,
QSE_AWK_VAL_MAP_DATA_MBS,
QSE_AWK_VAL_MAP_DATA_WCS,
QSE_AWK_VAL_MAP_DATA_CSTR,
QSE_AWK_VAL_MAP_DATA_XSTR,
QSE_AWK_VAL_MAP_DATA_MCSTR,
QSE_AWK_VAL_MAP_DATA_MXSTR,
QSE_AWK_VAL_MAP_DATA_WCSTR,
QSE_AWK_VAL_MAP_DATA_WXSTR
};
typedef enum qse_awk_val_map_data_type_t qse_awk_val_map_data_type_t;
struct qse_awk_val_map_data_t
{
qse_cstr_t key;
qse_awk_val_map_data_type_t type;
void* vptr;
};
typedef struct qse_awk_val_map_data_t qse_awk_val_map_data_t;
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_nde_type_t defines the node types.
*/
enum qse_awk_nde_type_t
{
QSE_AWK_NDE_NULL,
/* statement */
QSE_AWK_NDE_BLK,
QSE_AWK_NDE_IF,
QSE_AWK_NDE_WHILE,
QSE_AWK_NDE_DOWHILE,
QSE_AWK_NDE_FOR,
QSE_AWK_NDE_FOREACH,
QSE_AWK_NDE_BREAK,
QSE_AWK_NDE_CONTINUE,
QSE_AWK_NDE_RETURN,
QSE_AWK_NDE_EXIT,
QSE_AWK_NDE_NEXT,
QSE_AWK_NDE_NEXTFILE,
QSE_AWK_NDE_DELETE,
QSE_AWK_NDE_RESET,
/* expression */
/* if you change the following values including their order,
* you should change __eval_func of __eval_expression
* in run.c accordingly */
QSE_AWK_NDE_GRP,
QSE_AWK_NDE_ASS,
QSE_AWK_NDE_EXP_BIN,
QSE_AWK_NDE_EXP_UNR,
QSE_AWK_NDE_EXP_INCPRE,
QSE_AWK_NDE_EXP_INCPST,
QSE_AWK_NDE_CND,
QSE_AWK_NDE_FNC,
QSE_AWK_NDE_FUN,
QSE_AWK_NDE_INT,
QSE_AWK_NDE_FLT,
QSE_AWK_NDE_STR,
QSE_AWK_NDE_REX,
/* keep this order for the following items otherwise, you may have
* to change eval_incpre and eval_incpst in run.c as well as
* QSE_AWK_VAL_REF_XXX in qse_awk_val_ref_t */
QSE_AWK_NDE_NAMED,
QSE_AWK_NDE_GBL,
QSE_AWK_NDE_LCL,
QSE_AWK_NDE_ARG,
QSE_AWK_NDE_NAMEDIDX,
QSE_AWK_NDE_GBLIDX,
QSE_AWK_NDE_LCLIDX,
QSE_AWK_NDE_ARGIDX,
QSE_AWK_NDE_POS,
/* ---------------------------------- */
QSE_AWK_NDE_GETLINE,
QSE_AWK_NDE_PRINT,
QSE_AWK_NDE_PRINTF
};
typedef enum qse_awk_nde_type_t qse_awk_nde_type_t;
#define QSE_AWK_NDE_HDR \
qse_awk_nde_type_t type; \
qse_awk_loc_t loc; \
qse_awk_nde_t* next
/** @struct qse_awk_nde_t
* The qse_awk_nde_t type defines a common part of a node.
*/
typedef struct qse_awk_nde_t qse_awk_nde_t;
struct qse_awk_nde_t
{
QSE_AWK_NDE_HDR;
};
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_fun_t type defines a structure to maintain functions
* defined with the keyword 'function'.
*/
struct qse_awk_fun_t
{
qse_xstr_t name;
qse_size_t nargs;
qse_awk_nde_t* body;
};
typedef struct qse_awk_fun_t qse_awk_fun_t;
/* ------------------------------------------------------------------------ */
typedef int (*qse_awk_sprintf_t) (
qse_awk_t* awk,
qse_char_t* buf,
qse_size_t size,
const qse_char_t* fmt,
...
);
typedef qse_flt_t (*qse_awk_math1_t) (
qse_awk_t* awk,
qse_flt_t x
);
typedef qse_flt_t (*qse_awk_math2_t) (
qse_awk_t* awk,
qse_flt_t x,
qse_flt_t y
);
/* ------------------------------------------------------------------------ */
typedef struct qse_awk_mod_spec_t qse_awk_mod_spec_t;
struct qse_awk_mod_spec_t
{
const qse_char_t* prefix;
const qse_char_t* postfix;
const qse_char_t* name;
};
typedef void* (*qse_awk_modopen_t) (
qse_awk_t* awk,
const qse_awk_mod_spec_t* spec
);
typedef void* (*qse_awk_modsym_t) (
qse_awk_t* awk,
void* handle,
const qse_char_t* name
);
typedef void (*qse_awk_modclose_t) (
qse_awk_t* awk,
void* handle
);
/* ------------------------------------------------------------------------ */
#if 0
typedef void* (*qse_awk_buildrex_t) (
qse_awk_t* awk,
const qse_char_t* ptn,
qse_size_t len
);
typedef int (*qse_awk_matchrex_t) (
qse_awk_t* awk,
void* code,
int option,
const qse_char_t* str,
qse_size_t len,
const qse_char_t** mptr,
qse_size_t* mlen
);
typedef void (*qse_awk_freerex_t) (
qse_awk_t* awk,
void* code
);
typedef int (*qse_awk_isemptyrex_t) (
qse_awk_t* awk,
void* code
);
#endif
/**
* The qse_awk_sio_cmd_t type defines I/O commands for a script stream.
*/
enum qse_awk_sio_cmd_t
{
QSE_AWK_SIO_OPEN = 0, /**< open a script stream */
QSE_AWK_SIO_CLOSE = 1, /**< close a script stream */
QSE_AWK_SIO_READ = 2, /**< read text from an input script stream */
QSE_AWK_SIO_WRITE = 3 /**< write text to an output script stream */
};
typedef enum qse_awk_sio_cmd_t qse_awk_sio_cmd_t;
/**
* The qse_awk_sio_lxc_t type defines a structure to store a character
* with its location information.
*/
struct qse_awk_sio_lxc_t
{
qse_cint_t c; /**< character */
qse_size_t line; /**< line */
qse_size_t colm; /**< column */
const qse_char_t* file; /**< file */
};
typedef struct qse_awk_sio_lxc_t qse_awk_sio_lxc_t;
enum qse_awk_sio_arg_flag_t
{
QSE_AWK_SIO_INCLUDED = (1 << 0)
};
typedef struct qse_awk_sio_arg_t qse_awk_sio_arg_t;
struct qse_awk_sio_arg_t
{
/**
* [IN] bitwise-ORed of #qse_awk_sio_arg_flag_t.
* The field is set with #QSE_AWK_SIO_INCLUDED if an included file
* is handled.
*/
int flags;
/**
* [IN/OUT] name of I/O object.
* if #QSE_AWK_SIO_INCLUDED is not set, the name is set to #QSE_NULL.
* the source stream handler(#qse_awk_sio_impl_t) can change this field
* to give useful information back to the parser.
*
* if #QSE_AWK_SIO_INCLUDED is set in the flags field,
* the name field is set to the name of the included file.
*/
const qse_char_t* name;
/**
* [OUT] I/O handle set by a handler.
* The source stream handler can set this field when it opens a stream.
* All subsequent operations on the stream see this field as set
* during opening.
*/
void* handle;
/*-- from here down, internal use only --*/
struct
{
qse_char_t buf[1024];
qse_size_t pos;
qse_size_t len;
} b;
qse_size_t line;
qse_size_t colm;
qse_awk_sio_lxc_t last;
qse_awk_sio_arg_t* next;
};
/**
* The qse_awk_sio_impl_t type defines a source IO function
*/
typedef qse_ssize_t (*qse_awk_sio_impl_t) (
qse_awk_t* awk,
qse_awk_sio_cmd_t cmd,
qse_awk_sio_arg_t* arg,
qse_char_t* data,
qse_size_t count
);
/**
* The qse_awk_rio_cmd_t type defines runtime I/O request types.
*/
enum qse_awk_rio_cmd_t
{
QSE_AWK_RIO_OPEN = 0, /**< open a stream */
QSE_AWK_RIO_CLOSE = 1, /**< close a stream */
QSE_AWK_RIO_READ = 2, /**< read a stream */
QSE_AWK_RIO_WRITE = 3, /**< write to a stream */
QSE_AWK_RIO_FLUSH = 4, /**< flush buffered data to a stream */
QSE_AWK_RIO_NEXT = 5 /**< close the current stream and
open the next stream (only for console) */
};
typedef enum qse_awk_rio_cmd_t qse_awk_rio_cmd_t;
/**
* The qse_awk_rio_mode_t type defines the I/O modes used by I/O handlers.
* Each I/O handler should inspect the requested mode and open an I/O
* stream accordingly for subsequent operations.
*/
enum qse_awk_rio_mode_t
{
QSE_AWK_RIO_PIPE_READ = 0, /**< open a pipe for read */
QSE_AWK_RIO_PIPE_WRITE = 1, /**< open a pipe for write */
QSE_AWK_RIO_PIPE_RW = 2, /**< open a pipe for read and write */
QSE_AWK_RIO_FILE_READ = 0, /**< open a file for read */
QSE_AWK_RIO_FILE_WRITE = 1, /**< open a file for write */
QSE_AWK_RIO_FILE_APPEND = 2, /**< open a file for append */
QSE_AWK_RIO_CONSOLE_READ = 0, /**< open a console for read */
QSE_AWK_RIO_CONSOLE_WRITE = 1 /**< open a console for write */
};
typedef enum qse_awk_rio_mode_t qse_awk_rio_mode_t;
/*
* The qse_awk_rio_rwcmode_t type defines I/O closing modes, especially for
* a two-way pipe.
*/
enum qse_awk_rio_rwcmode_t
{
QSE_AWK_RIO_CLOSE_FULL = 0, /**< close both read and write end */
QSE_AWK_RIO_CLOSE_READ = 1, /**< close the read end */
QSE_AWK_RIO_CLOSE_WRITE = 2 /**< close the write end */
};
typedef enum qse_awk_rio_rwcmode_t qse_awk_rio_rwcmode_t;
/**
* The qse_awk_rio_arg_t defines the data structure passed to a runtime
* I/O handler. An I/O handler should inspect the @a mode field and the
* @a name field and store an open handle to the @a handle field when
* #QSE_AWK_RIO_OPEN is requested. For other request type, it can refer
* to the @a handle field set previously.
*/
struct qse_awk_rio_arg_t
{
/* read-only. a user handler shouldn't change any of these fields */
qse_awk_rio_mode_t mode; /**< opening mode */
qse_char_t* name; /**< name of I/O object */
qse_awk_rio_rwcmode_t rwcmode; /**< closing mode for rwpipe */
/* read-write. a user handler can do whatever it likes to do with these. */
void* handle; /**< I/O handle set by a handler */
int uflags; /**< flags set by a handler */
/*-- from here down, internal use only --*/
int type;
int rwcstate; /* closing state for rwpipe */
struct
{
qse_char_t buf[2048];
qse_size_t pos;
qse_size_t len;
int eof;
int eos;
} in;
struct
{
int eof;
int eos;
} out;
struct qse_awk_rio_arg_t* next;
};
typedef struct qse_awk_rio_arg_t qse_awk_rio_arg_t;
/**
* The qse_awk_rio_impl_t type defines a runtime I/O handler.
*/
typedef qse_ssize_t (*qse_awk_rio_impl_t) (
qse_awk_rtx_t* rtx,
qse_awk_rio_cmd_t cmd,
qse_awk_rio_arg_t* riod,
qse_char_t* data,
qse_size_t count
);
/**
* The qse_awk_prm_t type defines primitive functions required to perform
* a set of primitive operations.
*/
struct qse_awk_prm_t
{
qse_awk_sprintf_t sprintf;
struct
{
qse_awk_math2_t pow; /**< floating-point power function */
qse_awk_math2_t mod; /**< floating-point remainder function */
qse_awk_math1_t sin;
qse_awk_math1_t cos;
qse_awk_math1_t tan;
qse_awk_math1_t atan;
qse_awk_math2_t atan2;
qse_awk_math1_t log;
qse_awk_math1_t log10;
qse_awk_math1_t exp;
qse_awk_math1_t sqrt;
} math;
qse_awk_modopen_t modopen;
qse_awk_modclose_t modclose;
qse_awk_modsym_t modsym;
#if 0
struct
{
/* TODO: accept regular expression handling functions */
qse_awk_buildrex_t build;
qse_awk_matchrex_t match;
qse_awk_freerex_t free;
qse_awk_isemptyrex_t isempty;
} rex;
#endif
};
typedef struct qse_awk_prm_t qse_awk_prm_t;
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_sio_t type defines a script stream handler set.
* The qse_awk_parse() function calls the input and output handler to parse
* a script and optionally deparse it. Typical input and output handlers
* are shown below:
*
* @code
* qse_ssize_t in (
* qse_awk_t* awk, qse_awk_sio_cmd_t cmd,
* qse_char_t* buf, qse_size_t size)
* {
* if (cmd == QSE_AWK_SIO_OPEN) open input stream;
* else if (cmd == QSE_AWK_SIO_CLOSE) close input stream;
* else read input stream and fill buf up to size characters;
* }
*
* qse_ssize_t out (
* qse_awk_t* awk, qse_awk_sio_cmd_t cmd,
* qse_char_t* data, qse_size_t size)
* {
* if (cmd == QSE_AWK_SIO_OPEN) open_output_stream;
* else if (cmd == QSE_AWK_SIO_CLOSE) close_output_stream;
* else write data of size characters to output stream;
* }
* @endcode
*
* For #QSE_AWK_SIO_OPEN, a handler must return:
* - -1 if it failed to open a stream.
* - 0 if it has opened a stream but has reached the end.
* - 1 if it has successfully opened a stream.
*
* For #QSE_AWK_SIO_CLOSE, a handler must return:
* - -1 if it failed to close a stream.
* - 0 if it has closed a stream.
*
* For #QSE_AWK_SIO_READ and #QSE_AWK_SIO_WRITE, a handler must return:
* - -1 if there was an error occurred during operation.
* - 0 if it has reached the end.
* - the number of characters read or written on success.
*/
struct qse_awk_sio_t
{
qse_awk_sio_impl_t in; /**< input script stream handler */
qse_awk_sio_impl_t out; /**< output script stream handler */
};
typedef struct qse_awk_sio_t qse_awk_sio_t;
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_rio_t type defines a runtime I/O handler set.
* @sa qse_awk_rtx_t
*/
struct qse_awk_rio_t
{
qse_awk_rio_impl_t pipe; /**< pipe handler */
qse_awk_rio_impl_t file; /**< file handler */
qse_awk_rio_impl_t console; /**< console handler */
};
typedef struct qse_awk_rio_t qse_awk_rio_t;
/* ------------------------------------------------------------------------ */
typedef struct qse_awk_fnc_t qse_awk_fnc_t;
typedef struct qse_awk_fnc_spec_t qse_awk_fnc_spec_t;
typedef struct qse_awk_fnc_info_t qse_awk_fnc_info_t;
/**
* The qse_awk_fnc_impl_t type defines a intrinsic function handler.
*/
typedef int (*qse_awk_fnc_impl_t) (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_fnc_info_t* fi /**< function information */
);
/**
* The qse_awk_fnc_spec_t type defines a structure to hold the specification
* of an intrinsic function or a module function.
*/
struct qse_awk_fnc_spec_t
{
/** parameter specification */
struct
{
qse_size_t min; /**< min. numbers of argument for a function */
qse_size_t max; /**< max. numbers of argument for a function */
const qse_char_t* spec;
} arg;
/** pointer to the function implementing this function */
qse_awk_fnc_impl_t impl;
/**
* when this field is set to a non-zero value bitwise-ORed of
* #qse_awk_trait_t enumerators, the function is available if
* this field bitwise-ANDed the global trait option produces
* this field itself.
*
* this field doesn't take effect for a module function.
*/
int trait;
};
/* ------------------------------------------------------------------------ */
typedef struct qse_awk_mod_t qse_awk_mod_t;
typedef struct qse_awk_mod_sym_t qse_awk_mod_sym_t;
struct qse_awk_fnc_info_t
{
qse_xstr_t name;
/** #QSE_NULL if the function is not registered from module */
qse_awk_mod_t* mod;
};
typedef int (*qse_awk_mod_load_t) (
qse_awk_mod_t* mod,
qse_awk_t* awk
);
typedef int (*qse_awk_mod_query_t) (
qse_awk_mod_t* mod,
qse_awk_t* awk,
const qse_char_t* name,
qse_awk_mod_sym_t* sym
);
typedef void (*qse_awk_mod_unload_t) (
qse_awk_mod_t* mod,
qse_awk_t* awk
);
typedef int (*qse_awk_mod_init_t) (
qse_awk_mod_t* mod,
qse_awk_rtx_t* rtx
);
typedef void (*qse_awk_mod_fini_t) (
qse_awk_mod_t* mod,
qse_awk_rtx_t* rtx
);
struct qse_awk_mod_t
{
qse_awk_mod_query_t query;
qse_awk_mod_unload_t unload;
qse_awk_mod_init_t init;
qse_awk_mod_fini_t fini;
void* ctx;
};
enum qse_awk_mod_sym_type_t
{
QSE_AWK_MOD_FNC = 0,
QSE_AWK_MOD_INT, /* constant */
QSE_AWK_MOD_FLT /* constant */
/*QSE_AWK_MOD_STR,
QSE_AWK_MOD_VAR,
*/
};
typedef enum qse_awk_mod_sym_type_t qse_awk_mod_sym_type_t;
typedef qse_awk_fnc_spec_t qse_awk_mod_sym_fnc_t;
typedef struct qse_awk_mod_sym_int_t qse_awk_mod_sym_int_t;
typedef struct qse_awk_mod_sym_flt_t qse_awk_mod_sym_flt_t;
struct qse_awk_mod_sym_int_t
{
qse_long_t val;
};
struct qse_awk_mod_sym_flt_t
{
qse_flt_t val;
};
struct qse_awk_mod_sym_t
{
qse_awk_mod_sym_type_t type;
union
{
qse_awk_mod_sym_fnc_t fnc;
qse_awk_mod_sym_int_t in;
qse_awk_mod_sym_flt_t flt;
} u;
};
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_ecb_close_t type defines the callback function
* called when an awk object is closed.
*/
typedef void (*qse_awk_ecb_close_t) (
qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_ecb_clear_t type defines the callback function
* called when an awk object is cleared.
*/
typedef void (*qse_awk_ecb_clear_t) (
qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_ecb_t type defines an event callback set.
* You can register a callback function set with
* qse_awk_pushecb(). The callback functions in the registered
* set are called in the reverse order of registration.
*/
typedef struct qse_awk_ecb_t qse_awk_ecb_t;
struct qse_awk_ecb_t
{
/**
* called by qse_awk_close().
*/
qse_awk_ecb_close_t close;
/**
* called by qse_awk_clear().
*/
qse_awk_ecb_clear_t clear;
/* internal use only. don't touch this field */
qse_awk_ecb_t* next;
};
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_rtx_ecb_close_t type defines the callback function
* called when the runtime context is closed.
*/
typedef void (*qse_awk_rtx_ecb_close_t) (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_ecb_stmt_t type defines the callback function for each
* statement.
*/
typedef void (*qse_awk_rtx_ecb_stmt_t) (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_nde_t* nde /**< node */
);
/**
* The qse_awk_rtx_ecb_t type defines an event callback set for a
* runtime context. You can register a callback function set with
* qse_awk_rtx_pushecb(). The callback functions in the registered
* set are called in the reverse order of registration.
*/
typedef struct qse_awk_rtx_ecb_t qse_awk_rtx_ecb_t;
struct qse_awk_rtx_ecb_t
{
/**
* called by qse_awk_rtx_close().
*/
qse_awk_rtx_ecb_close_t close;
/**
* called by qse_awk_rtx_loop() and qse_awk_rtx_call() for
* each statement executed.
*/
qse_awk_rtx_ecb_stmt_t stmt;
/* internal use only. don't touch this field */
qse_awk_rtx_ecb_t* next;
};
/* ------------------------------------------------------------------------ */
enum qse_awk_opt_t
{
QSE_AWK_TRAIT = 0,
QSE_AWK_MODPREFIX,
QSE_AWK_MODPOSTFIX,
QSE_AWK_DEPTH_INCLUDE,
QSE_AWK_DEPTH_BLOCK_PARSE,
QSE_AWK_DEPTH_BLOCK_RUN,
QSE_AWK_DEPTH_EXPR_PARSE,
QSE_AWK_DEPTH_EXPR_RUN,
QSE_AWK_DEPTH_REX_BUILD,
QSE_AWK_DEPTH_REX_MATCH
};
typedef enum qse_awk_opt_t qse_awk_opt_t;
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_trait_t type defines various options to change the behavior
* of #qse_awk_t.
*/
enum qse_awk_trait_t
{
/**
* allows undeclared variables and implicit concatenation
**/
QSE_AWK_IMPLICIT = (1 << 0),
/**
* enable abort,reset,nextofile,OFILENAME,@include.
*/
QSE_AWK_EXTRAKWS = (1 << 2),
/** supports @b getline and @b print */
QSE_AWK_RIO = (1 << 3),
/** enables the two-way pipe if #QSE_AWK_RIO is on */
QSE_AWK_RWPIPE = (1 << 4),
/** a new line can terminate a statement */
QSE_AWK_NEWLINE = (1 << 5),
/**
* removes empty fields when splitting a record if FS is a regular
* expression and the match is all spaces.
*
* @code
* BEGIN { FS="[[:space:]]+"; }
* {
* print "NF=" NF;
* for (i = 0; i < NF; i++) print i " [" $(i+1) "]";
* }
* @endcode
* " a b c " is split to [a], [b], [c] if #QSE_AWK_STRIPRECSPC is on.
* Otherwise, it is split to [], [a], [b], [c], [].
*
* @code
* BEGIN {
* n=split(" oh my noodle ", x, /[ o]+/);
* for (i=1;i<=n;i++) print "[" x[i] "]";
* }
* @endcode
* This example splits the string to [], [h], [my], [n], [dle]
* if #QSE_AWK_STRIPRECSPC is on. Otherwise, it results in
* [], [h], [my], [n], [dle], []. Note that the first empty field is not
* removed as the field separator is not all spaces. (space + 'o').
*/
QSE_AWK_STRIPRECSPC = (1 << 6),
/**
* strips off leading spaces when converting a string to a number.
*/
QSE_AWK_STRIPSTRSPC = (1 << 7),
QSE_AWK_BLANKCONCAT = (1 << 8),
/** CR + LF by default */
QSE_AWK_CRLF = (1 << 10),
/** treats a map value more flexibly. a function can return
* a map. you can override a map with a scalar value without
* 'delete' or '@reset'.
*/
QSE_AWK_FLEXMAP = (1 << 11),
/** allows @b BEGIN, @b END, pattern-action blocks */
QSE_AWK_PABLOCK = (1 << 12),
/** allows {n,m} in a regular expression. */
QSE_AWK_REXBOUND = (1 << 13),
/**
* performs numeric comparison when a string convertable
* to a number is compared with a number or vice versa.
*
* For an expression (9 > "10.9"),
* - 9 is greater if #QSE_AWK_NCMPONSTR is off;
* - "10.9" is greater if #QSE_AWK_NCMPONSTR is on
*/
QSE_AWK_NCMPONSTR = (1 << 14),
/**
* enables the strict naming rule.
* - a parameter name can not be the same as the owning function name.
* - a local variable name can not be the same as the owning
* function name.
*/
QSE_AWK_STRICTNAMING = (1 << 15),
/**
* makes AWK more fault-tolerant.
* - prevents termination due to print and printf failure.
* - achieves this by handling print and printf as if
* they are functions like getline.
* - allows an expression group in a normal context
* without the 'in' operator. the evaluation result
* of the last expression is returned as that of
* the expression group.
* - e.g.) a = (1, 3 * 3, 4, 5 + 1); # a is assigned 6.
*/
QSE_AWK_TOLERANT = (1 << 17),
/**
* makes #qse_awk_t to behave compatibly with classical AWK
* implementations
*/
QSE_AWK_CLASSIC =
QSE_AWK_IMPLICIT | QSE_AWK_RIO |
QSE_AWK_NEWLINE | QSE_AWK_BLANKCONCAT | QSE_AWK_PABLOCK |
QSE_AWK_STRIPSTRSPC | QSE_AWK_STRICTNAMING,
QSE_AWK_MODERN =
QSE_AWK_CLASSIC | QSE_AWK_EXTRAKWS | QSE_AWK_FLEXMAP |
QSE_AWK_RWPIPE | QSE_AWK_TOLERANT
};
typedef enum qse_awk_trait_t qse_awk_trait_t;
/* ------------------------------------------------------------------------ */
/**
* The qse_awk_errnum_t type defines error codes.
*/
enum qse_awk_errnum_t
{
QSE_AWK_ENOERR, /**< no error */
QSE_AWK_EOTHER, /**< other error */
QSE_AWK_ENOIMPL, /**< not implemented */
QSE_AWK_ESYSERR, /**< subsystem error */
QSE_AWK_EINTERN, /**< internal error */
/* common errors */
QSE_AWK_ENOMEM, /**< insufficient memory */
QSE_AWK_EINVAL, /**< invalid parameter or data */
QSE_AWK_ENOSUP, /**< not supported */
QSE_AWK_ENOPER, /**< operation not allowed */
QSE_AWK_ENOENT, /**< '${0}' not found */
QSE_AWK_EEXIST, /**< '${0}' already exists */
QSE_AWK_EIOERR, /**< I/O error */
/* mostly parse errors */
QSE_AWK_EOPEN, /**< cannot open '${0}' */
QSE_AWK_EREAD, /**< cannot read '${0}' */
QSE_AWK_EWRITE, /**< cannot write '${0}' */
QSE_AWK_ECLOSE, /**< cannot close '${0}' */
QSE_AWK_EBLKNST, /**< block nested too deeply */
QSE_AWK_EEXPRNST,/**< expression nested too deeply */
QSE_AWK_ELXCHR, /**< invalid character '${0}' */
QSE_AWK_ELXDIG, /**< invalid digit '${0}' */
QSE_AWK_EEOF, /**< unexpected end of source */
QSE_AWK_ECMTNC, /**< comment not closed properly */
QSE_AWK_ESTRNC, /**< string or regular expression not closed */
QSE_AWK_ELBRACE, /**< left brace expected in place of '${0}' */
QSE_AWK_ELPAREN, /**< left parenthesis expected in place of '${0}' */
QSE_AWK_ERPAREN, /**< right parenthesis expected in place of '${0}' */
QSE_AWK_ERBRACK, /**< right bracket expected in place of '${0}' */
QSE_AWK_ECOMMA, /**< comma expected in place of '${0}' */
QSE_AWK_ESCOLON, /**< semicolon expected in place of '${0}' */
QSE_AWK_ECOLON, /**< colon expected in place of '${0}' */
QSE_AWK_ESTMEND, /**< statement not ending with a semicolon */
QSE_AWK_EKWIN, /**< keyword 'in' expected in place of '${0}' */
QSE_AWK_ENOTVAR, /**< right-hand side of 'in' not a variable */
QSE_AWK_EEXPRNR, /**< expression not recognized around '${0}' */
QSE_AWK_EKWFNC, /**< keyword 'function' expected in place of '${0}' */
QSE_AWK_EKWWHL, /**< keyword 'while' expected in place of '${0}' */
QSE_AWK_EASSIGN, /**< assignment statement expected */
QSE_AWK_EIDENT, /**< identifier expected in place of '${0}' */
QSE_AWK_EFUNNAM, /**< '${0}' not a valid function name */
QSE_AWK_EBLKBEG, /**< BEGIN not followed by left bracket on the same line */
QSE_AWK_EBLKEND, /**< END not followed by left bracket on the same line */
QSE_AWK_EKWRED, /**< keyword '${0}' redefined */
QSE_AWK_EFNCRED, /**< intrinsic function '${0}' redefined */
QSE_AWK_EFUNRED, /**< function '${0}' redefined */
QSE_AWK_EGBLRED, /**< global variable '${0}' redefined */
QSE_AWK_EPARRED, /**< parameter '${0}' redefined */
QSE_AWK_EVARRED, /**< variable '${0}' redefined */
QSE_AWK_EDUPPAR, /**< duplicate parameter name '${0}' */
QSE_AWK_EDUPGBL, /**< duplicate global variable name '${0}' */
QSE_AWK_EDUPLCL, /**< duplicate local variable name '${0}' */
QSE_AWK_EBADPAR, /**< '${0}' not a valid parameter name */
QSE_AWK_EBADVAR, /**< '${0}' not a valid variable name */
QSE_AWK_EVARMS, /**< variable name missing */
QSE_AWK_EUNDEF, /**< undefined identifier '${0}' */
QSE_AWK_ELVALUE, /**< l-value required */
QSE_AWK_EGBLTM, /**< too many global variables */
QSE_AWK_ELCLTM, /**< too many local variables */
QSE_AWK_EPARTM, /**< too many parameters */
QSE_AWK_ESEGTM, /**< too many identifier segments */
QSE_AWK_EBADARG, /**< bad argument */
QSE_AWK_ENOARG, /**< no argument */
QSE_AWK_EBREAK, /**< 'break' outside a loop */
QSE_AWK_ECONTINUE, /**< 'continue' outside a loop */
QSE_AWK_ENEXTBEG, /**< 'next' illegal in BEGIN block */
QSE_AWK_ENEXTEND, /**< 'next' illegal in END block */
QSE_AWK_ENEXTFBEG, /**< 'nextfile' illegal in BEGIN block */
QSE_AWK_ENEXTFEND, /**< 'nextfile' illegal in END block */
QSE_AWK_EPREPST, /**< both prefix and postfix incr/decr operator present */
QSE_AWK_EINCDECOPR,/**< illegal operand for incr/decr operator */
QSE_AWK_EINCLSTR, /**< 'include' not followed by a string */
QSE_AWK_EINCLTD, /**< include level too deep */
QSE_AWK_EXKWNR, /**< @word '${0}' not recognized */
QSE_AWK_EXKWEM, /**< @ not followed by a valid word */
/* run time error */
QSE_AWK_EDIVBY0, /**< divide by zero */
QSE_AWK_EOPERAND, /**< invalid operand */
QSE_AWK_EPOSIDX, /**< wrong position index */
QSE_AWK_EARGTF, /**< too few arguments */
QSE_AWK_EARGTM, /**< too many arguments */
QSE_AWK_EFUNNF, /**< function '${0}' not found */
QSE_AWK_ENOTIDX, /**< not indexable */
QSE_AWK_ENOTDEL, /**< '${0}' not deletable */
QSE_AWK_ENOTMAP, /**< value not a map */
QSE_AWK_ENOTMAPIN, /**< right-hand side of 'in' not a map */
QSE_AWK_ENOTMAPNILIN, /**< right-hand side of 'in' not a map nor nil */
QSE_AWK_ENOTREF, /**< value not referenceable */
QSE_AWK_EIDXVALMAP, /**< indexed value cannot be a map */
QSE_AWK_EPOSVALMAP, /**< positional cannot be a map */
QSE_AWK_EMAPNA, /**< map cannot be assigned to variable */
QSE_AWK_EMAPNRA, /**< map '${0}' cannot be reassigned */
QSE_AWK_EMAPUR, /**< map unreturnable */
QSE_AWK_EMAPPH, /**< map prohibited */
QSE_AWK_ESCALARTOMAP, /**< cannot change a scalar value to a map */
QSE_AWK_EVALTYPE, /**< invalid value type */
QSE_AWK_ERNEXTBEG, /**< 'next' called from BEGIN block */
QSE_AWK_ERNEXTEND, /**< 'next' called from END block */
QSE_AWK_ERNEXTFBEG, /**< 'nextfile' called from BEGIN block */
QSE_AWK_ERNEXTFEND, /**< 'nextfile' called from END block */
QSE_AWK_EFNCIMPL, /**< intrinsic function handler for '${0}' failed */
QSE_AWK_EIOUSER, /**< wrong user io handler implementation */
QSE_AWK_EIOIMPL, /**< I/O callback returned an error */
QSE_AWK_EIONMNF, /**< no such I/O name found */
QSE_AWK_EIONMEM, /**< I/O name empty */
QSE_AWK_EIONMNL, /**< I/O name '${0}' containing '\\0' */
QSE_AWK_EFMTARG, /**< not sufficient arguments to formatting sequence */
QSE_AWK_EFMTCNV, /**< recursion detected in format conversion */
QSE_AWK_ECONVFMTCHR, /**< invalid character in CONVFMT */
QSE_AWK_EOFMTCHR, /**< invalid character in OFMT */
/* regular expression error */
QSE_AWK_EREXNOCOMP, /**< no regular expression compiled */
QSE_AWK_EREXRECUR, /**< recursion too deep */
QSE_AWK_EREXRPAREN, /**< a right parenthesis is expected */
QSE_AWK_EREXRBRACK, /**< a right bracket is expected */
QSE_AWK_EREXRBRACE, /**< a right brace is expected */
QSE_AWK_EREXCOLON, /**< a colon is expected */
QSE_AWK_EREXCRANGE, /**< invalid character range */
QSE_AWK_EREXCCLASS, /**< invalid character class */
QSE_AWK_EREXBOUND, /**< invalid occurrence bound */
QSE_AWK_EREXSPCAWP, /**< special character at wrong position */
QSE_AWK_EREXPREEND, /**< premature end of regular expression */
/* the number of error numbers, internal use only */
QSE_AWK_NUMERRNUM
};
typedef enum qse_awk_errnum_t qse_awk_errnum_t;
/**
* The qse_awk_errinf_t type defines a placeholder for error information.
*/
struct qse_awk_errinf_t
{
qse_awk_errnum_t num; /**< error number */
qse_char_t msg[256]; /**< error message */
qse_awk_loc_t loc; /**< error location */
};
typedef struct qse_awk_errinf_t qse_awk_errinf_t;
/**
* The qse_awk_errstr_t type defines an error string getter. It should return
* an error formatting string for an error number requested. A new string
* should contain the same number of positional parameters (${X}) as in the
* default error formatting string. You can set a new getter into an awk
* object with the qse_awk_seterrstr() function to customize an error string.
*/
typedef const qse_char_t* (*qse_awk_errstr_t) (
const qse_awk_t* awk, /**< awk */
qse_awk_errnum_t num /**< error number */
);
/**
* The qse_awk_gbl_id_t type defines intrinsic globals variable IDs.
*/
enum qse_awk_gbl_id_t
{
/* this table should match gtab in parse.c.
* in addition, qse_awk_rtx_setgbl also counts
* on the order of these values.
*
* note that set_global() in run.c contains code
* preventing these global variables from being assigned
* with a map value. if you happen to add one that can
* be a map, don't forget to change code in set_global().
* but is this check really necessary???
*/
QSE_AWK_GBL_CONVFMT,
QSE_AWK_GBL_FILENAME,
QSE_AWK_GBL_FNR,
QSE_AWK_GBL_FS,
QSE_AWK_GBL_IGNORECASE,
QSE_AWK_GBL_NF,
QSE_AWK_GBL_NR,
QSE_AWK_GBL_OFILENAME,
QSE_AWK_GBL_OFMT,
QSE_AWK_GBL_OFS,
QSE_AWK_GBL_ORS,
QSE_AWK_GBL_RLENGTH,
QSE_AWK_GBL_RS,
QSE_AWK_GBL_RSTART,
QSE_AWK_GBL_SUBSEP,
/* these are not not the actual IDs and are used internally only
* Make sure you update these values properly if you add more
* ID definitions, however */
QSE_AWK_MIN_GBL_ID = QSE_AWK_GBL_CONVFMT,
QSE_AWK_MAX_GBL_ID = QSE_AWK_GBL_SUBSEP
};
typedef enum qse_awk_gbl_id_t qse_awk_gbl_id_t;
/**
* The qse_awk_val_type_t type defines types of AWK values. Each value
* allocated is tagged with a value type in the @a type field.
* @sa qse_awk_val_t QSE_AWK_VAL_HDR
*/
enum qse_awk_val_type_t
{
/* the values between QSE_AWK_VAL_NIL and QSE_AWK_VAL_STR inclusive
* must be synchronized with an internal table of the __cmp_val
* function in run.c */
QSE_AWK_VAL_NIL = 0, /**< nil */
QSE_AWK_VAL_INT = 1, /**< integer */
QSE_AWK_VAL_FLT = 2, /**< floating-pointer number */
QSE_AWK_VAL_STR = 3, /**< string */
QSE_AWK_VAL_REX = 4, /**< regular expression */
QSE_AWK_VAL_MAP = 5, /**< map */
QSE_AWK_VAL_REF = 6 /**< reference to other types */
};
/**
* The values defined are used to set the type field of the
* #qse_awk_rtx_valtostr_out_t structure. The field should be one of the
* following values:
*
* - #QSE_AWK_RTX_VALTOSTR_CPL
* - #QSE_AWK_RTX_VALTOSTR_CPLCPY
* - #QSE_AWK_RTX_VALTOSTR_CPLDUP
* - #QSE_AWK_RTX_VALTOSTR_STRP
* - #QSE_AWK_RTX_VALTOSTR_STRPCAT
*
* and it can optionally be ORed with #QSE_AWK_RTX_VALTOSTR_PRINT.
*/
enum qse_awk_rtx_valtostr_type_t
{
/** use u.cpl of #qse_awk_rtx_valtostr_out_t */
QSE_AWK_RTX_VALTOSTR_CPL = 0x00,
/** use u.cplcpy of #qse_awk_rtx_valtostr_out_t */
QSE_AWK_RTX_VALTOSTR_CPLCPY = 0x01,
/** use u.cpldup of #qse_awk_rtx_valtostr_out_t */
QSE_AWK_RTX_VALTOSTR_CPLDUP = 0x02,
/** use u.strp of #qse_awk_rtx_valtostr_out_t */
QSE_AWK_RTX_VALTOSTR_STRP = 0x03,
/** use u.strpcat of #qse_awk_rtx_valtostr_out_t */
QSE_AWK_RTX_VALTOSTR_STRPCAT = 0x04,
/** convert for print */
QSE_AWK_RTX_VALTOSTR_PRINT = 0x10
};
/**
* The qse_awk_rtx_valtostr() function converts a value to a string as
* indicated in a parameter of the qse_awk_rtx_valtostr_out_t type.
*/
struct qse_awk_rtx_valtostr_out_t
{
int type; /**< enum #qse_awk_rtx_valtostr_type_t */
union
{
qse_cstr_t cpl;
qse_xstr_t cplcpy;
qse_xstr_t cpldup; /* need to free cpldup.ptr */
qse_str_t* strp;
qse_str_t* strpcat;
} u;
};
typedef struct qse_awk_rtx_valtostr_out_t qse_awk_rtx_valtostr_out_t;
/* record filter using NR */
struct qse_awk_nrflt_t
{
qse_long_t limit;
qse_long_t size;
qse_long_t rank;
};
typedef struct qse_awk_nrflt_t qse_awk_nrflt_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* The qse_awk_open() function creates a new qse_awk_t object. The object
* created can be passed to other qse_awk_xxx() functions and is valid until
* it is destroyed with the qse_awk_close() function. The function saves the
* memory manager pointer while it copies the contents of the primitive
* function structures. Therefore, you should keep the memory manager valid
* during the whole life cycle of an qse_awk_t object.
*
* @code
* qse_awk_t* dummy()
* {
* qse_mmgr_t mmgr;
* qse_awk_prm_t prm;
* return qse_awk_open (
* &mmgr, // NOT OK because the contents of mmgr is
* // invalidated when dummy() returns.
* 0,
* &prm // OK
* );
* }
* @endcode
*
* @return a pointer to a qse_awk_t object on success, #QSE_NULL on failure.
*/
QSE_EXPORT qse_awk_t* qse_awk_open (
qse_mmgr_t* mmgr, /**< memory manager */
qse_size_t xtnsize, /**< extension size in bytes */
qse_awk_prm_t* prm /**< pointer to a primitive function structure */
);
/**
* The qse_awk_close() function destroys a qse_awk_t object.
* @return 0 on success, -1 on failure
*/
QSE_EXPORT int qse_awk_close (
qse_awk_t* awk /**< awk */
);
QSE_EXPORT qse_mmgr_t* qse_awk_getmmgr (
qse_awk_t* awk
);
QSE_EXPORT void* qse_awk_getxtn (
qse_awk_t* awk
);
/**
* The qse_awk_getprm() function gets primitive functions
*/
QSE_EXPORT qse_awk_prm_t* qse_awk_getprm (
qse_awk_t* awk
);
/**
* The qse_awk_clear() clears the internal state of @a awk. If you want to
* reuse a qse_awk_t instance that finished being used, you may call
* qse_awk_clear() instead of destroying and creating a new
* #qse_awk_t instance using qse_awk_close() and qse_awk_open().
*
* @return 0 on success, -1 on failure
*/
QSE_EXPORT int qse_awk_clear (
qse_awk_t* awk
);
/**
* The qse_awk_geterrstr() gets an error string getter.
*/
QSE_EXPORT qse_awk_errstr_t qse_awk_geterrstr (
const qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_seterrstr() sets an error string getter that is called to
* compose an error message when its retrieval is requested.
*
* Here is an example of changing the formatting string for the #QSE_SED_ECMDNR
* error.
* @code
* qse_awk_errstr_t orgerrstr;
*
* const qse_char_t* myerrstr (qse_awk_t* awk, qse_awk_errnum_t num)
* {
* if (num == QSE_SED_ECMDNR) return QSE_T("unrecognized command ${0}");
* return orgerrstr (awk, num);
* }
* int main ()
* {
* qse_awk_t* awk;
* ...
* orgerrstr = qse_awk_geterrstr (awk);
* qse_awk_seterrstr (awk, myerrstr);
* ...
* }
* @endcode
*/
QSE_EXPORT void qse_awk_seterrstr (
qse_awk_t* awk, /**< awk */
qse_awk_errstr_t errstr /**< error string getter */
);
/**
* The qse_awk_geterrnum() function returns the number of the last error
* occurred.
* @return error number
*/
QSE_EXPORT qse_awk_errnum_t qse_awk_geterrnum (
const qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_geterrloc() function returns the location where the
* last error has occurred.
*/
QSE_EXPORT const qse_awk_loc_t* qse_awk_geterrloc (
const qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_geterrmsg() function returns the error message describing
* the last error occurred. The @b fil field of the location returned is
* #QSE_NULL if the error occurred in the main script.
* @return error message
*/
QSE_EXPORT const qse_char_t* qse_awk_geterrmsg (
const qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_geterrinf() function copies error information into memory
* pointed to by @a errinf from @a awk.
*/
QSE_EXPORT void qse_awk_geterrinf (
const qse_awk_t* awk, /**< awk */
qse_awk_errinf_t* errinf /**< error information buffer */
);
/**
* The qse_awk_seterrnum() function sets the error information omitting
* error location. You must pass a non-NULL for @a errarg if the specified
* error number @a errnum requires one or more arguments to format an
* error message.
*/
QSE_EXPORT void qse_awk_seterrnum (
qse_awk_t* awk, /**< awk */
qse_awk_errnum_t errnum, /**< error number */
const qse_cstr_t* errarg /**< argument array for formatting
* an error message */
);
/**
* The qse_awk_seterrinf() function sets the error information. This function
* may be useful if you want to set a custom error message rather than letting
* it automatically formatted.
*/
QSE_EXPORT void qse_awk_seterrinf (
qse_awk_t* awk, /**< awk */
const qse_awk_errinf_t* errinf /**< error information */
);
/**
* The qse_awk_geterror() function gets error information via parameters.
*/
QSE_EXPORT void qse_awk_geterror (
const qse_awk_t* awk, /**< awk */
qse_awk_errnum_t* errnum, /**< error number */
const qse_char_t** errmsg, /**< error message */
qse_awk_loc_t* errloc /**< error location */
);
/**
* The qse_awk_seterror() function sets error information.
*/
QSE_EXPORT void qse_awk_seterror (
qse_awk_t* awk, /**< awk */
qse_awk_errnum_t errnum, /**< error number */
const qse_cstr_t* errarg, /**< argument array for formatting
* an error message */
const qse_awk_loc_t* errloc /**< error location */
);
QSE_EXPORT int qse_awk_getopt (
qse_awk_t* awk,
qse_awk_opt_t id,
void* value
);
QSE_EXPORT int qse_awk_setopt (
qse_awk_t* awk,
qse_awk_opt_t id,
const void* value
);
/**
* The qse_awk_popecb() function pops an awk event callback set
* and returns the pointer to it. If no callback set can be popped,
* it returns #QSE_NULL.
*/
QSE_EXPORT qse_awk_ecb_t* qse_awk_popecb (
qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_pushecb() function register a runtime callback set.
*/
QSE_EXPORT void qse_awk_pushecb (
qse_awk_t* awk, /**< awk */
qse_awk_ecb_t* ecb /**< callback set */
);
/**
* The qse_awk_addgbl() function adds an intrinsic global variable.
* @return the ID of the global variable added on success, -1 on failure.
*/
QSE_EXPORT int qse_awk_addgbl (
qse_awk_t* awk, /**< awk */
const qse_char_t* name /**< variable name */
);
/**
* The qse_awk_delgbl() function deletes an intrinsic global variable by name.
* @return 0 on success, -1 on failure
*/
QSE_EXPORT int qse_awk_delgbl (
qse_awk_t* awk, /**< awk */
const qse_char_t* name /**< variable name */
);
/**
* The qse_awk_findgbl() function returns the numeric ID of an intrinsic global
* variable.
* @return number >= 0 on success, -1 on failure
*/
QSE_EXPORT int qse_awk_findgbl (
qse_awk_t* awk, /**< awk */
const qse_char_t* name /**< variable name */
);
/**
* The qse_awk_addfnc() function adds an intrinsic function.
*/
QSE_EXPORT qse_awk_fnc_t* qse_awk_addfnc (
qse_awk_t* awk,
const qse_char_t* name,
const qse_awk_fnc_spec_t* spec
);
/**
* The qse_awk_delfnc() function deletes an intrinsic function by name.
* @return 0 on success, -1 on failure
*/
QSE_EXPORT int qse_awk_delfnc (
qse_awk_t* awk, /**< awk */
const qse_char_t* name /**< function name */
);
/**
* The qse_awk_clrfnc() function deletes all intrinsic functions
*/
QSE_EXPORT void qse_awk_clrfnc (
qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_parse() function parses a source script, and optionally
* deparses it back.
*
* It reads a source script by calling @a sio->in as shown in the pseudo code
* below:
*
* @code
* n = sio->in (awk, QSE_AWK_SIO_OPEN);
* if (n >= 0)
* {
* while (n > 0)
* n = sio->in (awk, QSE_AWK_SIO_READ, buf, buf_size);
* sio->in (awk, QSE_AWK_SIO_CLOSE);
* }
* @endcode
*
* A negative number returned causes qse_awk_parse() to return failure;
* 0 returned indicates the end of a stream; A positive number returned
* indicates successful opening of a stream or the length of the text read.
*
* If @a sio->out is not #QSE_NULL, it deparses the internal parse tree
* composed of a source script and writes back the deparsing result by
* calling @a sio->out as shown below:
*
* @code
* n = sio->out (awk, QSE_AWK_SIO_OPEN);
* if (n >= 0)
* {
* while (n > 0)
* n = sio->out (awk, QSE_AWK_SIO_WRITE, text, text_size);
* sio->out (awk, QSE_AWK_SIO_CLOSE);
* }
* @endcode
*
* Unlike @a sf->in, the return value of 0 from @a sf->out is treated as
* premature end of a stream; therefore, it causes qse_awk_parse() to return
* failure.
*
* @return 0 on success, -1 on failure.
*/
QSE_EXPORT int qse_awk_parse (
qse_awk_t* awk, /**< awk */
qse_awk_sio_t* sio /**< source script I/O handler */
);
/**
* The qse_awk_allocmem() function allocates dynamic memory.
* @return a pointer to a memory block on success, #QSE_NULL on failure
*/
QSE_EXPORT void* qse_awk_allocmem (
qse_awk_t* awk, /**< awk */
qse_size_t size /**< size of memory to allocate in bytes */
);
/**
* The qse_awk_reallocmem() function resizes a dynamic memory block.
* @return a pointer to a memory block on success, #QSE_NULL on failure
*/
QSE_EXPORT void* qse_awk_reallocmem (
qse_awk_t* awk, /**< awk */
void* ptr, /**< memory block */
qse_size_t size /**< new block size in bytes */
);
/**
* The qse_awk_callocmem() function allocates a memory block of
* the size of @a size bytes and initializes it with 0.
* @return a pointer to a memory block on success, #QSE_NULL on failure
*/
QSE_EXPORT void* qse_awk_callocmem (
qse_awk_t* awk, /**< awk */
qse_size_t size /**< size of memory to allocate in bytes */
);
/**
* The qse_awk_freemem() function frees dynamic memory allocated.
*/
QSE_EXPORT void qse_awk_freemem (
qse_awk_t* awk, /**< awk */
void* ptr /**< memory block to free */
);
/**
* The qse_awk_strdup() function is used to duplicate a string using
* the memory manager used by the associated qse_awk_t instance.
* The new string must be freed using the qse_awk_freemem() function when
* it's not needed any more.
*
* @return a pointer to a new string duplicated of @a s on success,
* #QSE_NULL on failure.
*/
QSE_EXPORT qse_char_t* qse_awk_strdup (
qse_awk_t* awk, /**< awk */
const qse_char_t* str /**< string pointer */
);
/**
* The qse_awk_strxdup() function is used to duplicate a string whose length
* is as long as len characters using the memory manager used by the
* qse_awk_t instance. The new string must be freed using the qse_awk_freemem()
* function it's not needed any more.
*
* @return a pointer to a new string duplicated of @a s on success,
* #QSE_NULL on failure.
*/
QSE_EXPORT qse_char_t* qse_awk_strxdup (
qse_awk_t* awk, /**< awk */
const qse_char_t* str, /**< string pointer */
qse_size_t len /**< string length */
);
/**
* The qse_awk_cstrdup() funcation duplicates @a str->len characters from a
* string pointed to by @str->ptr. The duplicated string must be freed with
* the qse_awk_freemem() function when it's not needed any more.
*
* @return pointer to a duplicated string on success,
* #QSE_NULL on failure.
*/
QSE_EXPORT qse_char_t* qse_awk_cstrdup (
qse_awk_t* awk, /**< awk */
const qse_cstr_t* str /**< string */
);
/**
* The qse_awk_strxtolong() function converts a string to an integer.
*/
QSE_EXPORT qse_long_t qse_awk_strxtolong (
qse_awk_t* awk,
const qse_char_t* str,
qse_size_t len,
int base,
const qse_char_t** endptr
);
/**
* The qse_awk_strxtoflt() function converts a string to a floating-point
* number.
*/
QSE_EXPORT qse_flt_t qse_awk_strxtoflt (
qse_awk_t* awk,
const qse_char_t* str,
qse_size_t len,
const qse_char_t** endptr
);
/**
* The qse_awk_longtostr() functon convers an integer to a string.
*/
QSE_EXPORT qse_size_t qse_awk_longtostr (
qse_awk_t* awk,
qse_long_t value,
int radix,
const qse_char_t* prefix,
qse_char_t* buf,
qse_size_t size
);
/**
* The qse_awk_rtx_open() creates a runtime context associated with @a awk.
* It also allocates an extra memory block as large as the @a xtn bytes.
* You can get the pointer to the beginning of the block with
* qse_awk_rtx_getxtn(). The block is destroyed when the runtime context is
* destroyed.
*
* @return new runtime context on success, #QSE_NULL on failure
*/
QSE_EXPORT qse_awk_rtx_t* qse_awk_rtx_open (
qse_awk_t* awk, /**< awk */
qse_size_t xtn, /**< size of extension in bytes */
qse_awk_rio_t* rio /**< runtime IO handlers */
);
/**
* The qse_awk_rtx_close() function destroys a runtime context.
*/
QSE_EXPORT void qse_awk_rtx_close (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_loop() function executes the BEGIN block, pattern-action
* blocks and the END blocks in an AWK program. It returns the global return
* value of which the reference count must be decremented when not necessary.
* Multiple invocations of the function for the lifetime of a runtime context
* is not desirable.
*
* The example shows typical usage of the function.
* @code
* rtx = qse_awk_rtx_open (awk, 0, rio, QSE_NULL);
* if (rtx != QSE_NULL)
* {
* retv = qse_awk_rtx_loop (rtx);
* if (retv != QSE_NULL) qse_awk_rtx_refdownval (rtx, retv);
* qse_awk_rtx_close (rtx);
* }
* @endcode
*
* @return return value on success, #QSE_NULL on failure.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_loop (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_findfun() function finds the function structure by name
* and returns the pointer to it if one is found. It returns #QSE_NULL if
* it fails to find a function by the @a name.
*/
QSE_EXPORT qse_awk_fun_t* qse_awk_rtx_findfun (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_char_t* name /**< function name */
);
/**
* The qse_awk_rtx_callfun() function invokdes an AWK function described by
* the structure pointed to by @a fun.
* @sa qse_awk_rtx_call
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_callfun (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_fun_t* fun, /**< function */
qse_awk_val_t* args[], /**< arguments to the function */
qse_size_t nargs /**< the number of arguments */
);
/**
* The qse_awk_rtx_call() function invokes an AWK function named @a name.
* However, it is not able to invoke an intrinsic function such as split().
* The #QSE_AWK_PABLOCK option can be turned off to make illegal the BEGIN
* block, the pattern-action blocks, and the END block.
*
* The example shows typical usage of the function.
* @code
* rtx = qse_awk_rtx_open (awk, 0, rio, QSE_NULL);
* if (rtx != QSE_NULL)
* {
* v = qse_awk_rtx_call (rtx, QSE_T("init"), QSE_NULL, 0);
* if (v != QSE_NULL) qse_awk_rtx_refdownval (rtx, v);
* qse_awk_rtx_call (rtx, QSE_T("fini"), QSE_NULL, 0);
* if (v != QSE_NULL) qse_awk_rtx_refdownval (rtx, v);
* qse_awk_rtx_close (rtx);
* }
* @endcode
*
* @return 0 on success, -1 on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_call (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_char_t* name, /**< function name */
qse_awk_val_t* args[], /**< arguments to the function */
qse_size_t nargs /**< the number of arguments */
);
/**
* The qse_awk_rtx_callwithstrs() function is the same as qse_awk_rtx_call()
* except that you pass pointers to null-terminated strings. It creates values
* from the null-terminated strings and calls qse_awk_rtx_call() with the
* values created.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_callwithstrs (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_char_t* name, /**< function name */
const qse_char_t* args[], /**< arguments to the function */
qse_size_t nargs /**< the number of arguments */
);
/**
* The qse_awk_stopall() function aborts all active runtime contexts
* associated with @a awk.
*/
QSE_EXPORT void qse_awk_stopall (
qse_awk_t* awk /**< awk */
);
/**
* The qse_awk_rtx_isstop() function tests if qse_awk_rtx_stop() has been
* called.
*/
QSE_EXPORT int qse_awk_rtx_isstop (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_stop() function causes an active runtime context @a rtx to
* be aborted.
*/
QSE_EXPORT void qse_awk_rtx_stop (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_getrio() function copies runtime I/O handlers
* to the memory buffer pointed to by @a rio.
*/
QSE_EXPORT void qse_awk_rtx_getrio (
qse_awk_rtx_t* rtx,
qse_awk_rio_t* rio
);
/**
* The qse_awk_rtx_getrio() function sets runtime I/O handlers
* with the functions pointed to by @a rio.
*/
QSE_EXPORT void qse_awk_rtx_setrio (
qse_awk_rtx_t* rtx,
const qse_awk_rio_t* rio
);
/**
* The qse_awk_rtx_popecb() function pops a runtime callback set
* and returns the pointer to it. If no callback set can be popped,
* it returns #QSE_NULL.
*/
QSE_EXPORT qse_awk_rtx_ecb_t* qse_awk_rtx_popecb (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_pushecb() function register a runtime callback set.
*/
QSE_EXPORT void qse_awk_rtx_pushecb (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_rtx_ecb_t* ecb /**< callback set */
);
/**
* The qse_awk_rtx_getnargs() gets the number of arguments passed to an
* intrinsic functon.
*/
QSE_EXPORT qse_size_t qse_awk_rtx_getnargs (
qse_awk_rtx_t* rtx
);
/**
* The qse_awk_rtx_getarg() function gets an argument passed to an intrinsic
* function. it doesn't touch the reference count of the value.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getarg (
qse_awk_rtx_t* rtx,
qse_size_t idx
);
/**
* The qse_awk_rtx_getsubsep() function returns the
* pointer to the internal value of SUBSEP. It's a specialized
* version of qse_awk_rtx_getgbl (rtx, QSE_AWK_GBL_SUBSEP).
*/
QSE_EXPORT const qse_xstr_t* qse_awk_rtx_getsubsep (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_getgbl() gets the value of a global variable.
* The global variable ID @a id is one of the predefined global
* variable IDs or a value returned by qse_awk_addgbl().
* This function never fails so long as the ID is valid. Otherwise,
* you may get into trouble.
*
* @return value pointer
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getgbl (
qse_awk_rtx_t* rtx, /**< runtime context */
int id /**< global variable ID */
);
/**
* The qse_awk_rtx_setgbl() sets the value of a global variable.
*/
QSE_EXPORT int qse_awk_rtx_setgbl (
qse_awk_rtx_t* rtx,
int id,
qse_awk_val_t* val
);
/**
* The qse_awk_rtx_setretval() sets the return value of a function
* when called from within a function handler. The caller doesn't
* have to invoke qse_awk_rtx_refupval() and qse_awk_rtx_refdownval()
* with the value to be passed to qse_awk_rtx_setretval().
* The qse_awk_rtx_setretval() will update its reference count properly
* once the return value is set.
*/
QSE_EXPORT void qse_awk_rtx_setretval (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_val_t* val /**< return value */
);
/**
* The qse_awk_rtx_setfilename() function sets FILENAME.
*/
QSE_EXPORT int qse_awk_rtx_setfilename (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_char_t* str, /**< name pointer */
qse_size_t len /**< name length */
);
/**
* The qse_awk_rtx_setofilename() function sets OFILENAME.
*/
QSE_EXPORT int qse_awk_rtx_setofilename (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_char_t* str, /**< name pointer */
qse_size_t len /**< name length */
);
/**
* The qse_awk_rtx_getawk() function gets the owner of a runtime context @a rtx.
* @return owner of a runtime context @a rtx.
*/
QSE_EXPORT qse_awk_t* qse_awk_rtx_getawk (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_getmmgr() function gets the memory manager of a runtime
* context.
*/
QSE_EXPORT qse_mmgr_t* qse_awk_rtx_getmmgr (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_getxtn() function gets the pointer to the extension block.
*/
QSE_EXPORT void* qse_awk_rtx_getxtn (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_getnvmap() gets the map of named variables
*/
QSE_EXPORT qse_htb_t* qse_awk_rtx_getnvmap (
qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_geterrnum() function gets the number of the last error
* occurred during runtime.
* @return error number
*/
QSE_EXPORT qse_awk_errnum_t qse_awk_rtx_geterrnum (
const qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_geterrloc() function gets the location of the last error
* occurred during runtime. The
* @return error location
*/
QSE_EXPORT const qse_awk_loc_t* qse_awk_rtx_geterrloc (
const qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_geterrmsg() function gets the string describing the last
* error occurred during runtime.
* @return error message
*/
QSE_EXPORT const qse_char_t* qse_awk_rtx_geterrmsg (
const qse_awk_rtx_t* rtx /**< runtime context */
);
/**
* The qse_awk_rtx_geterrinf() function copies error information into memory
* pointed to by @a errinf from a runtime context @a rtx.
*/
QSE_EXPORT void qse_awk_rtx_geterrinf (
const qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_errinf_t* errinf /**< error information */
);
/**
* The qse_awk_rtx_geterror() function retrieves error information from a
* runtime context @a rtx. The error number is stored into memory pointed
* to by @a errnum; the error message pointer into memory pointed to by
* @a errmsg; the error line into memory pointed to by @a errlin.
*/
QSE_EXPORT void qse_awk_rtx_geterror (
const qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_errnum_t* errnum, /**< error number */
const qse_char_t** errmsg, /**< error message */
qse_awk_loc_t* errloc /**< error location */
);
/**
* The qse_awk_rtx_seterrnum() function sets the error information omitting
* the error location.
*/
QSE_EXPORT void qse_awk_rtx_seterrnum (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_errnum_t errnum, /**< error number */
const qse_cstr_t* errarg /**< arguments to format error message */
);
/**
* The qse_awk_rtx_seterrinf() function sets error information.
*/
QSE_EXPORT void qse_awk_rtx_seterrinf (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_errinf_t* errinf /**< error information */
);
/**
* The qse_awk_rtx_seterror() function sets error information.
*/
QSE_EXPORT void qse_awk_rtx_seterror (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_errnum_t errnum, /**< error number */
const qse_cstr_t* errarg, /**< argument array for formatting
* an error message */
const qse_awk_loc_t* errloc /**< error line */
);
/**
* The qse_awk_rtx_clrrec() function clears the input record ($0)
* and fields ($1 to $N).
*/
QSE_EXPORT int qse_awk_rtx_clrrec (
qse_awk_rtx_t* rtx, /**< runtime context */
int skip_inrec_line
);
/**
* The qse_awk_rtx_setrec() function sets the input record ($0) or
* input fields ($1 to $N).
*/
QSE_EXPORT int qse_awk_rtx_setrec (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_size_t idx, /**< 0 for $0, N for $N */
const qse_cstr_t* str /**< string */
);
/**
* The qse_awk_rtx_isnilval(0 function determines if a value
* is a nil value.
*/
QSE_EXPORT int qse_awk_rtx_isnilval (
qse_awk_rtx_t* rtx,
qse_awk_val_t* val
);
/**
* The qse_awk_rtx_makenilval() function creates a nil value.
* It always returns the pointer to the statically allocated
* nil value. So it never fails.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makenilval (
qse_awk_rtx_t* rtx
);
/**
* The qse_awk_rtx_makeintval() function creates an integer value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makeintval (
qse_awk_rtx_t* rtx,
qse_long_t v
);
/**
* The qse_awk_rtx_makefltval() function creates a floating-point value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makefltval (
qse_awk_rtx_t* rtx,
qse_flt_t v
);
/**
* The qse_awk_rtx_makestrvalwithstr() function creates a string value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrvalwithstr (
qse_awk_rtx_t* rtx,
const qse_char_t* str
);
/**
* The qse_awk_rtx_makestrvalwithmbs() function creates a string value
* from a null-terminated multibyte string.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrvalwithmbs (
qse_awk_rtx_t* rtx,
const qse_mchar_t* mbs
);
/**
* The qse_awk_rtx_makestrvalwithwcs() function creates a string value
* from a null-terminated wide-character string.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrvalwithwcs (
qse_awk_rtx_t* rtx,
const qse_wchar_t* wcs
);
/**
* The qse_awk_rtx_makestrvalwithcstr() function creates a string value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrvalwithcstr (
qse_awk_rtx_t* rtx,
const qse_cstr_t* str
);
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrvalwithmcstr (
qse_awk_rtx_t* rtx,
const qse_mcstr_t* mcstr
);
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrvalwithwcstr (
qse_awk_rtx_t* rtx,
const qse_wcstr_t* wcstr
);
/**
* The qse_awk_rtx_makestrval() function creates a string value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrval (
qse_awk_rtx_t* rtx,
const qse_char_t* str,
qse_size_t len
);
/**
* The qse_awk_rtx_makestrval2() function creates a string value combining
* two strings.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makestrval2 (
qse_awk_rtx_t* rtx,
const qse_char_t* str1,
qse_size_t len1,
const qse_char_t* str2,
qse_size_t len2
);
/**
* The qse_awk_rtx_makenstrval() function creates a numeric string value.
* A numeric string is a string value whose one of the header fields @b nstr
* is 1.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makenstrvalwithcstr (
qse_awk_rtx_t* rtx,
const qse_cstr_t* str
);
/**
* The qse_awk_rtx_makerexval() function creates a regular expression value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makerexval (
qse_awk_rtx_t* rtx,
const qse_cstr_t* str,
void* code
);
/**
* The qse_awk_rtx_makemapval() function creates an empty map value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makemapval (
qse_awk_rtx_t* rtx
);
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makemapvalwithdata (
qse_awk_rtx_t* rtx,
qse_awk_val_map_data_t data[]
);
/**
* The qse_awk_rtx_setmapvalfld() function sets a field value in a map.
* You must make sure that the type of @a map is #QSE_AWK_VAL_MAP.
* @return value @a v on success, #QSE_NULL on failure.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_setmapvalfld (
qse_awk_rtx_t* rtx,
qse_awk_val_t* map,
const qse_char_t* kptr,
qse_size_t klen,
qse_awk_val_t* v
);
/**
* The qse_awk_rtx_setmapvalfld() function gets the field value in a map.
* You must make sure that the type of @a map is #QSE_AWK_VAL_MAP.
* If the field is not found, the function fails and sets the error number
* to #QSE_AWK_EINVAL. The function does not fail for other reasons.
* @return field value on success, #QSE_NULL on failure.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getmapvalfld (
qse_awk_rtx_t* rtx,
qse_awk_val_t* map,
const qse_char_t* kptr,
qse_size_t klen
);
/**
* The qse_awk_rtx_getfirstmapvalitr() returns the iterator to the
* first pair in the map. It returns #QSE_NULL and sets the pair field of
* @a itr to #QSE_NULL if the map contains no pair. Otherwise, it returns
* @a itr pointing to the first pair.
*/
QSE_EXPORT qse_awk_val_map_itr_t* qse_awk_rtx_getfirstmapvalitr (
qse_awk_rtx_t* rtx,
qse_awk_val_t* map,
qse_awk_val_map_itr_t* itr
);
/**
* The qse_awk_rtx_getnextmapvalitr() returns the iterator to the
* next pair to @a itr in the map. It returns #QSE_NULL and sets the pair
* field of @a itr to #QSE_NULL if @a itr points to the last pair.
* Otherwise, it returns @a itr pointing to the next pair.
*/
QSE_EXPORT qse_awk_val_map_itr_t* qse_awk_rtx_getnextmapvalitr (
qse_awk_rtx_t* rtx,
qse_awk_val_t* map,
qse_awk_val_map_itr_t* itr
);
/**
* The qse_awk_rtx_makerefval() function creates a reference value.
* @return value on success, QSE_NULL on failure
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_makerefval (
qse_awk_rtx_t* rtx,
int id,
qse_awk_val_t** adr
);
/**
* The qse_awk_rtx_isstaticval() function determines if a value is static.
* A static value is allocated once and reused until a runtime context @ rtx
* is closed.
* @return QSE_TRUE if @a val is static, QSE_FALSE if @a val is false
*/
QSE_EXPORT int qse_awk_rtx_isstaticval (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_val_t* val /**< value to check */
);
/**
* The qse_awk_rtx_refupval() function increments a reference count of a
* value @a val.
*/
QSE_EXPORT void qse_awk_rtx_refupval (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_val_t* val /**< value */
);
/**
* The qse_awk_rtx_refdownval() function decrements a reference count of
* a value @a val. It destroys the value if it has reached the count of 0.
*/
QSE_EXPORT void qse_awk_rtx_refdownval (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_val_t* val /**< value pointer */
);
/**
* The qse_awk_rtx_refdownval() function decrements a reference count of
* a value @a val. It does not destroy the value if it has reached the
* count of 0.
*/
QSE_EXPORT void qse_awk_rtx_refdownval_nofree (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_val_t* val /**< value pointer */
);
/**
* The qse_awk_rtx_valtobool() function converts a value @a val to a boolean
* value.
*/
QSE_EXPORT int qse_awk_rtx_valtobool (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_val_t* val /**< value pointer */
);
/**
* The qse_awk_rtx_valtostr() function converts a value @a val to a string as
* instructed in the parameter out. Before the call to the function, you
* should initialize a variable of the #qse_awk_rtx_valtostr_out_t type.
*
* The type field is one of the following qse_awk_rtx_valtostr_type_t values:
*
* - #QSE_AWK_RTX_VALTOSTR_CPL
* - #QSE_AWK_RTX_VALTOSTR_CPLCPY
* - #QSE_AWK_RTX_VALTOSTR_CPLDUP
* - #QSE_AWK_RTX_VALTOSTR_STRP
* - #QSE_AWK_RTX_VALTOSTR_STRPCAT
*
* It can optionally be ORed with #QSE_AWK_RTX_VALTOSTR_PRINT. The option
* causes the function to use OFMT for real number conversion. Otherwise,
* it uses @b CONVFMT.
*
* You should initialize or free other fields before and after the call
* depending on the type field as shown below:
*
* If you have a static buffer, use #QSE_AWK_RTX_VALTOSTR_CPLCPY.
* the resulting string is copied to the buffer.
* @code
* qse_awk_rtx_valtostr_out_t out;
* qse_char_t buf[100];
* out.type = QSE_AWK_RTX_VALTOSTR_CPLCPY;
* out.u.cplcpy.ptr = buf;
* out.u.cplcpy.len = QSE_COUNTOF(buf);
* if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) goto oops;
* qse_printf (QSE_T("%.*s\n"), (int)out.u.cplcpy.len, out.u.cplcpy.ptr);
* @endcode
*
* #QSE_AWK_RTX_VALTOSTR_CPL is different from #QSE_AWK_RTX_VALTOSTR_CPLCPY
* in that it doesn't copy the string to the buffer if the type of the value
* is #QSE_AWK_VAL_STR. It copies the resulting string to the buffer if
* the value type is not #QSE_AWK_VAL_STR.
* @code
* qse_awk_rtx_valtostr_out_t out;
* qse_char_t buf[100];
* out.type = QSE_AWK_RTX_VALTOSTR_CPL;
* out.u.cpl.ptr = buf;
* out.u.cpl.len = QSE_COUNTOF(buf);
* if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) goto oops;
* qse_printf (QSE_T("%.*s\n"), (int)out.u.cpl.len, out.u.cpl.ptr);
* @endcode
*
* When unsure of the size of the string after conversion, you can use
* #QSE_AWK_RTX_VALTOSTR_CPLDUP. However, you should free the memory block
* pointed to by the u.cpldup.ptr field after use.
* @code
* qse_awk_rtx_valtostr_out_t out;
* out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
* if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) goto oops;
* qse_printf (QSE_T("%.*s\n"), (int)out.u.cpldup.len, out.u.cpldup.ptr);
* qse_awk_rtx_free (rtx, out.u.cpldup.ptr);
* @endcode
*
* You may like to store the result in a dynamically resizable string.
* Consider #QSE_AWK_RTX_VALTOSTR_STRP.
* @code
* qse_awk_rtx_valtostr_out_t out;
* qse_str_t str;
* qse_str_init (&str, qse_awk_rtx_getmmgr(rtx), 100);
* out.type = QSE_AWK_RTX_VALTOSTR_STRP;
* out.u.strp = str;
* if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) goto oops;
* qse_printf (QSE_T("%.*s\n"),
* (int)QSE_STR_LEN(out.u.strp), QSE_STR_PTR(out.u.strp));
* qse_str_fini (&str);
* @endcode
*
* If you want to append the converted string to an existing dynamically
* resizable string, #QSE_AWK_RTX_VALTOSTR_STRPCAT is the answer. The usage is
* the same as #QSE_AWK_RTX_VALTOSTR_STRP except that you have to use the
* u.strpcat field instead of the u.strp field.
*
* In the context where @a val is determined to be of the type
* #QSE_AWK_VAL_STR, you may access its string pointer and length directly
* instead of calling this function.
*
* @return 0 on success, -1 on failure
*/
QSE_EXPORT int qse_awk_rtx_valtostr (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_val_t* val, /**< value to convert */
qse_awk_rtx_valtostr_out_t* out /**< output buffer */
);
/**
* The qse_awk_rtx_valtostrdup() function provides a shortcut to the
* qse_awk_rtx_valtostr() function with the #QSE_AWK_RTX_VALTOSTR_CPLDUP type.
* It returns the pointer to a string converted from @a val and stores its
* length to memory pointed to by @a len. You should free the returned
* memory block after use. See the code snippet below for a simple usage.
*
* @code
* ptr = qse_awk_rtx_valtostrdup (rtx, v, &len);
* if (str == QSE_NULL) handle_error();
* qse_printf (QSE_T("%.*s\n"), (int)len, ptr);
* qse_awk_rtx_free (rtx, ptr);
* @endcode
*
* @return character pointer to a string converted on success,
* #QSE_NULL on failure
*/
QSE_EXPORT qse_char_t* qse_awk_rtx_valtostrdup (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_val_t* val, /**< value to convert */
qse_size_t* len /**< result length */
);
QSE_EXPORT qse_mchar_t* qse_awk_rtx_valtombsdup (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_val_t* val, /**< value to convert */
qse_size_t* len /**< result length */
);
QSE_EXPORT qse_wchar_t* qse_awk_rtx_valtowcsdup (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_awk_val_t* val, /**< value to convert */
qse_size_t* len /**< result length */
);
/**
* The qse_awk_rtx_valtonum() function converts a value to a number.
* If the value is converted to a long number, it is stored in the memory
* pointed to by l and 0 is returned. If the value is converted to a real
* number, it is stored in the memory pointed to by r and 1 is returned.
* The function never fails as long as @a val points to a valid value.
*
* The code below shows how to convert a value to a number and determine
* if it is an integer or a floating-point number.
*
* @code
* qse_long_t l;
* qse_flt_t r;
* int n;
* n = qse_awk_rtx_valtonum (v, &l, &r);
* if (n <= -1) error ();
* else if (n == 0) print_long (l);
* else if (n >= 1) print_real (r);
* @endcode
*
* @return -1 on failure, 0 if converted to a long number, 1 if converted to
* a floating-point number.
*/
QSE_EXPORT int qse_awk_rtx_valtonum (
qse_awk_rtx_t* rtx,
const qse_awk_val_t* val,
qse_long_t* l,
qse_flt_t* r
);
QSE_EXPORT int qse_awk_rtx_valtolong (
qse_awk_rtx_t* rtx,
const qse_awk_val_t* val,
qse_long_t* l
);
QSE_EXPORT int qse_awk_rtx_valtoflt (
qse_awk_rtx_t* rtx,
const qse_awk_val_t* val,
qse_flt_t* r
);
/**
* The qse_awk_rtx_strtonum() function converts a string to a number.
* A numeric string in the valid decimal, hexadecimal(0x), binary(0b),
* octal(0) notation is converted to an integer and it is stored into
* memory pointed to by @a l; A string containng '.', 'E', or 'e' is
* converted to a floating-pointer number and it is stored into memory
* pointed to by @a r. If @a strict is 0, the function takes up to the last
* valid character and never fails. If @a strict is non-zero, an invalid
* character causes the function to return an error.
*
* @return 0 if converted to an integer,
* 1 if converted to a floating-point number
* -1 on error.
*/
QSE_EXPORT int qse_awk_rtx_strtonum (
qse_awk_rtx_t* rtx, /**< runtime context */
int strict, /**< determines to perform strict check */
const qse_char_t* ptr, /**< points to a string to convert */
qse_size_t len, /**< number of characters in a string */
qse_long_t* l, /**< stores a converted integer */
qse_flt_t* r /**< stores a converted floating-poing number */
);
/**
* The qse_awk_rtx_hashval() function hashes a simple value
* to a positive integer. It returns -1 for a inhashable value.
*/
QSE_EXPORT qse_long_t qse_awk_rtx_hashval (
qse_awk_rtx_t* rtx,
qse_awk_val_t* v
);
/**
* The qse_awk_rtx_setrefval() function changes the value
* of a variable referenced in @a ref.
* @return 0 on success, -1 on failure.
*/
QSE_EXPORT int qse_awk_rtx_setrefval (
qse_awk_rtx_t* rtx,
qse_awk_val_ref_t* ref,
qse_awk_val_t* val
);
QSE_EXPORT void qse_awk_rtx_setnrflt (
qse_awk_rtx_t* rtx,
const qse_awk_nrflt_t* nrflt
);
QSE_EXPORT void qse_awk_rtx_getnrflt (
qse_awk_rtx_t* rtx,
qse_awk_nrflt_t* nrflt
);
/**
* The qse_awk_rtx_allocmem() function allocats a memory block of @a size bytes
* using the memory manager associated with a runtime context @a rtx.
* @return the pointer to a memory block on success, #QSE_NULL on failure.
*/
QSE_EXPORT void* qse_awk_rtx_allocmem (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_size_t size /**< block size in bytes */
);
/**
* The qse_awk_rtx_reallocmem() function resizes a memory block pointed to
* by @a ptr to @a size bytes using the memory manager associated with
* a runtime context @a rtx.
* @return the pointer to a memory block on success, #QSE_NULL on failure.
*/
QSE_EXPORT void* qse_awk_rtx_reallocmem (
qse_awk_rtx_t* rtx, /**< runtime context */
void* ptr, /**< memory block */
qse_size_t size /**< block size in bytes */
);
/**
* The qse_awk_rtx_callocmem() function allocates a memory block of
* the size of @a size bytes and initializes it with 0.
* @return a pointer to a memory block on success, #QSE_NULL on failure
*/
QSE_EXPORT void* qse_awk_rtx_callocmem (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_size_t size /**< block size in bytes */
);
/**
* The qse_awk_rtx_freemem() function frees a memory block pointed to by @a ptr
* using the memory manager of a runtime ocntext @a rtx.
*/
QSE_EXPORT void qse_awk_rtx_freemem (
qse_awk_rtx_t* rtx, /**< runtime context */
void* ptr /**< memory block pointer */
);
/**
* The qse_getawknilval() function returns the pointer to the predefined
* nil value. you can call this without creating a runtime context.
*/
QSE_EXPORT qse_awk_val_t* qse_getawknilval (
void
);
#ifdef __cplusplus
}
#endif
#endif