*** empty log message ***

This commit is contained in:
hyung-hwan 2006-01-29 18:28:14 +00:00
parent e701a98406
commit 934a5da3e1
8 changed files with 392 additions and 75 deletions

View File

@ -1,4 +1,4 @@
SRCS = awk.c tree.c parse.c run.c sa.c SRCS = awk.c tree.c tab.c parse.c run.c sa.c
OBJS = $(SRCS:.c=.obj) OBJS = $(SRCS:.c=.obj)
OUT = xpawk.lib OUT = xpawk.lib

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.c,v 1.11 2006-01-24 16:14:28 bacon Exp $ * $Id: awk.c,v 1.12 2006-01-29 18:28:14 bacon Exp $
*/ */
#include <xp/awk/awk.h> #include <xp/awk/awk.h>
@ -23,6 +23,12 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk)
return XP_NULL; return XP_NULL;
} }
if (xp_awk_tab_open(&awk->parse.func) == XP_NULL) {
xp_str_close (&awk->token.name);
if (awk->__dynamic) xp_free (awk);
return XP_NULL;
}
awk->opt = 0; awk->opt = 0;
awk->errnum = XP_AWK_ENOERR; awk->errnum = XP_AWK_ENOERR;
@ -39,6 +45,7 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk)
awk->tree.unnamed = XP_NULL; awk->tree.unnamed = XP_NULL;
//awk->tree.funcs = XP_NULL; //awk->tree.funcs = XP_NULL;
awk->lex.curc = XP_CHAR_EOF; awk->lex.curc = XP_CHAR_EOF;
awk->lex.ungotc_count = 0; awk->lex.ungotc_count = 0;
@ -49,14 +56,21 @@ int xp_awk_close (xp_awk_t* awk)
{ {
xp_awk_clear (awk); xp_awk_clear (awk);
if (xp_awk_detsrc(awk) == -1) return -1; if (xp_awk_detsrc(awk) == -1) return -1;
xp_awk_tab_close(&awk->parse.func);
xp_str_close (&awk->token.name); xp_str_close (&awk->token.name);
if (awk->__dynamic) xp_free (awk); if (awk->__dynamic) xp_free (awk);
return 0; return 0;
} }
// TODO: write a function to clear awk->parse data structure.
// this would be need either as a separate function or as a part of xp_awk_clear...
// do i have to pass an option to xp_awk_clear to do this???
void xp_awk_clear (xp_awk_t* awk) void xp_awk_clear (xp_awk_t* awk)
{ {
/* clear parse trees */
if (awk->tree.begin != XP_NULL) { if (awk->tree.begin != XP_NULL) {
xp_assert (awk->tree.begin->next == XP_NULL); xp_assert (awk->tree.begin->next == XP_NULL);
xp_awk_clrpt (awk->tree.begin); xp_awk_clrpt (awk->tree.begin);

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.h,v 1.20 2006-01-26 15:35:20 bacon Exp $ * $Id: awk.h,v 1.21 2006-01-29 18:28:14 bacon Exp $
*/ */
#ifndef _XP_AWK_AWK_H_ #ifndef _XP_AWK_AWK_H_
@ -14,6 +14,7 @@
#endif #endif
#include <xp/awk/tree.h> #include <xp/awk/tree.h>
#include <xp/awk/tab.h>
enum enum
{ {
@ -40,7 +41,8 @@ enum
XP_AWK_EIDENT, /* identifier expected */ XP_AWK_EIDENT, /* identifier expected */
XP_AWK_EDUPBEGIN, /* duplicate BEGIN */ XP_AWK_EDUPBEGIN, /* duplicate BEGIN */
XP_AWK_EDUPEND, /* duplicate END */ XP_AWK_EDUPEND, /* duplicate END */
XP_AWK_EDUPFUNC /* duplicate function name */ XP_AWK_EDUPFUNC, /* duplicate function name */
XP_AWK_EDUPNAME /* duplicate name - function, variable, etc */
}; };
/* /*
@ -94,6 +96,7 @@ struct xp_awk_t
/* temporary information that the parser needs */ /* temporary information that the parser needs */
struct struct
{ {
xp_awk_tab_t func;
// TODO: locals, globals??? // TODO: locals, globals???
xp_char_t* vars; /* global and local variable names... */ xp_char_t* vars; /* global and local variable names... */
xp_char_t* args; /* function arguments */ xp_char_t* args; /* function arguments */

View File

@ -1,10 +1,33 @@
/* /*
* $Id: hash.h,v 1.1 2005-11-07 16:02:44 bacon Exp $ * $Id: hash.h,v 1.2 2006-01-29 18:28:14 bacon Exp $
*/ */
#ifndef _XP_AWK_HASH_H_ #ifndef _XP_AWK_HASH_H_
#define _XP_AWK_HASH_H_ #define _XP_AWK_HASH_H_
#ifdef __STAND_ALONE
#include <xp/awk/sa.h>
#else
#include <xp/types.h>
#include <xp/macros.h>
#endif
typedef struct xp_awk_hash_t xp_awk_hash_t;
typedef struct xp_awk_hashdatum_t xp_awk_hashdatum_t;
struct xp_awk_hashdatum_t
{
xp_char_t* key;
void* value;
};
struct xp_awk_hash_t
{
xp_size_t size;
xp_size_t capa;
xp_bool_t __dynamic;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parse.c,v 1.36 2006-01-28 06:38:01 bacon Exp $ * $Id: parse.c,v 1.37 2006-01-29 18:28:14 bacon Exp $
*/ */
#include <xp/awk/awk.h> #include <xp/awk/awk.h>
@ -75,6 +75,13 @@ enum {
BINOP_MOD BINOP_MOD
}; };
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define INLINE
#else
#define INLINE inline
#endif
static xp_awk_node_t* __parse_progunit (xp_awk_t* awk); static xp_awk_node_t* __parse_progunit (xp_awk_t* awk);
static xp_awk_node_t* __parse_function (xp_awk_t* awk); static xp_awk_node_t* __parse_function (xp_awk_t* awk);
static xp_awk_node_t* __parse_begin (xp_awk_t* awk); static xp_awk_node_t* __parse_begin (xp_awk_t* awk);
@ -109,10 +116,14 @@ static int __skip_spaces (xp_awk_t* awk);
static int __skip_comment (xp_awk_t* awk); static int __skip_comment (xp_awk_t* awk);
static int __classfy_ident (const xp_char_t* ident); static int __classfy_ident (const xp_char_t* ident);
static xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name);
static xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name);
static xp_long_t __str_to_long (const xp_char_t* name); static xp_long_t __str_to_long (const xp_char_t* name);
static INLINE xp_size_t __add_func_name (xp_awk_t* awk, const xp_char_t* name);
static INLINE xp_size_t __find_func_name (xp_awk_t* awk, const xp_char_t* name);
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name);
static INLINE xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name);
struct __kwent struct __kwent
{ {
const xp_char_t* name; const xp_char_t* name;
@ -188,9 +199,13 @@ int xp_awk_parse (xp_awk_t* awk)
if (__parse_progunit(awk) == XP_NULL) { if (__parse_progunit(awk) == XP_NULL) {
// TODO: cleanup the parse tree created so far.... // TODO: cleanup the parse tree created so far....
// function tables also etc...
xp_printf (XP_TEXT("error - %d\n"), awk->errnum); xp_printf (XP_TEXT("error - %d\n"), awk->errnum);
return -1; return -1;
} }
xp_awk_prnpt(node);
} }
xp_printf (XP_TEXT("sucessful end - %d\n"), awk->errnum); xp_printf (XP_TEXT("sucessful end - %d\n"), awk->errnum);
@ -207,24 +222,15 @@ static xp_awk_node_t* __parse_progunit (xp_awk_t* awk)
if (MATCH(awk,TOKEN_FUNCTION)) { if (MATCH(awk,TOKEN_FUNCTION)) {
node = __parse_function(awk); node = __parse_function(awk);
if (node == XP_NULL) { if (node == XP_NULL) return XP_NULL;
// TODO: cleanup
return XP_NULL;
}
} }
else if (MATCH(awk,TOKEN_BEGIN)) { else if (MATCH(awk,TOKEN_BEGIN)) {
node = __parse_begin (awk); node = __parse_begin (awk);
if (node == XP_NULL) { if (node == XP_NULL) return XP_NULL;
// TODO: cleanup
return XP_NULL;
}
} }
else if (MATCH(awk, TOKEN_END)) { else if (MATCH(awk, TOKEN_END)) {
node = __parse_end (awk); node = __parse_end (awk);
if (node == XP_NULL) { if (node == XP_NULL) return XP_NULL;
// TODO: cleanup
return XP_NULL;
}
} }
/* TODO: process patterns and expressions */ /* TODO: process patterns and expressions */
/* /*
@ -239,55 +245,67 @@ static xp_awk_node_t* __parse_progunit (xp_awk_t* awk)
else { else {
/* pattern-less actions */ /* pattern-less actions */
node = __parse_action (awk); node = __parse_action (awk);
if (node == XP_NULL) { if (node == XP_NULL) return XP_NULL;
// TODO: cleanup
return XP_NULL;
}
// TODO: weave the action block into awk->tree.actions... // TODO: weave the action block into awk->tree.actions...
} }
xp_awk_prnpt(node);
return node; return node;
} }
static xp_bool_t __function_defined (xp_awk_t* awk, const xp_char_t* name)
{
// TODO: complete this...
return xp_false;
}
static xp_awk_node_t* __parse_function (xp_awk_t* awk) static xp_awk_node_t* __parse_function (xp_awk_t* awk)
{ {
xp_char_t* name; xp_char_t* name;
//xp_awk_func_t* func; xp_char_t* name_dup;
xp_awk_node_t* body; xp_awk_node_t* body;
xp_size_t fnpos;
xp_size_t nargs = 0;
if (__get_token(awk) == -1) return XP_NULL; if (__get_token(awk) == -1) return XP_NULL;
/* function name */ /* function name */
if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, XP_AWK_EIDENT); if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, XP_AWK_EIDENT);
if (__function_defined(awk,XP_STR_BUF(&awk->token.name))) { name = XP_STR_BUF(&awk->token.name);
PANIC (awk, XP_AWK_EDUPFUNC); if (__find_func_name(awk,name) != (xp_size_t)-1) {
// TODO: do i have to tell DUPFUNC from DUPNAME???
//PANIC (awk, XP_AWK_EDUPFUNC);
PANIC (awk, XP_AWK_EDUPNAME);
} }
name = xp_strdup (XP_STR_BUF(&awk->token.name)); // TODO: make this feature optional..
if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); // find in the global variable list...
if (__find_variable(awk,name) != (xp_size_t)-1) {
PANIC (awk, XP_AWK_EDUPNAME);
}
fnpos = __add_func_name (awk, name);
if (fnpos == -1) PANIC (awk, XP_AWK_ENOMEM);
// TODO: move this strdup down the function....
// maybe just before func_t is allocated...
name_dup = xp_strdup (name);
if (name_dup == XP_NULL) {
__remove_func_name (awk, fnpos);
PANIC (awk, XP_AWK_ENOMEM);
}
/* skip the function name */ /* skip the function name */
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
if (!MATCH(awk,TOKEN_LPAREN)) { if (!MATCH(awk,TOKEN_LPAREN)) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
PANIC (awk, XP_AWK_ELPAREN); PANIC (awk, XP_AWK_ELPAREN);
} }
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
@ -295,75 +313,97 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
if (MATCH(awk,TOKEN_RPAREN)) { if (MATCH(awk,TOKEN_RPAREN)) {
/* no function parameter */ /* no function parameter */
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
} }
else { else {
while (1) { while (1) {
if (!MATCH(awk,TOKEN_IDENT)) { if (!MATCH(awk,TOKEN_IDENT)) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
PANIC (awk, XP_AWK_EIDENT); PANIC (awk, XP_AWK_EIDENT);
} }
nargs++;
// TODO: push args to param list...
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
if (MATCH(awk,TOKEN_RPAREN)) break; if (MATCH(awk,TOKEN_RPAREN)) break;
if (!MATCH(awk,TOKEN_COMMA)) { if (!MATCH(awk,TOKEN_COMMA)) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
PANIC (awk, XP_AWK_ECOMMA); PANIC (awk, XP_AWK_ECOMMA);
} }
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
} }
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list // TODO: cleanup parameter name list
xp_free (name); xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
} }
/* check if the function body starts with a left brace */
if (!MATCH(awk,TOKEN_LBRACE)) { if (!MATCH(awk,TOKEN_LBRACE)) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list // TODO: cleanup parameter name list
xp_free (name); xp_free (name_dup);
PANIC (awk, XP_AWK_ELBRACE); PANIC (awk, XP_AWK_ELBRACE);
} }
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list // TODO: cleanup parameter name list
xp_free (name); xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
/* function body */ /* actual function body */
body = __parse_block (awk); body = __parse_block (awk);
if (body == XP_NULL) { if (body == XP_NULL) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list // TODO: cleanup parameter name list
xp_free (name); xp_free (name_dup);
return XP_NULL; return XP_NULL;
} }
/* /*
func = (xp_awk_func_t*) xp_malloc (xp_sizeof(xp_awk_func_t)); func = (xp_awk_func_t*) xp_malloc (xp_sizeof(xp_awk_func_t));
if (func == XP_NULL) { if (func == XP_NULL) {
xp_free (name); __remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_clrpt (body); xp_awk_clrpt (body);
return XP_NULL; return XP_NULL;
} }
func->name = name; func->name = name_dup;
func->nargs = 0; func->nargs = nargs;
func->body = body; func->body = body;
xp_assert (xp_awk_hash_get(&awk->tree.func, name_dup) == XP_NULL);
if (xp_awk_hash_put(&awk->tree.func, name_dup, func) == XP_NULL) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_clrpt (body);
xp_free (func);
PANIC (awk, XP_AWK_ENOMEM);
}
*/ */
/* TODO: weave the function body into awk->tree.funcs */
return body; return body;
} }
@ -422,6 +462,7 @@ static xp_awk_node_t* __parse_block (xp_awk_t* awk)
// TODO: cleanup the variable name list... // TODO: cleanup the variable name list...
return XP_NULL; return XP_NULL;
} }
head = XP_NULL;
goto skip_block_body; goto skip_block_body;
} }
@ -1682,23 +1723,6 @@ static int __classfy_ident (const xp_char_t* ident)
return TOKEN_IDENT; return TOKEN_IDENT;
} }
static xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name)
{
return (xp_size_t)-1;
}
static xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name)
{
/*
if (awk->curfunc != XP_NULL) {
// TODO: finish this....
}
*/
return (xp_size_t)-1;
}
static xp_long_t __str_to_long (const xp_char_t* name) static xp_long_t __str_to_long (const xp_char_t* name)
{ {
xp_long_t n = 0; xp_long_t n = 0;
@ -1710,3 +1734,38 @@ static xp_long_t __str_to_long (const xp_char_t* name)
return n; return n;
} }
static INLINE xp_size_t __add_func_name (xp_awk_t* awk, const xp_char_t* name)
{
xp_assert (__find_func_name(awk,name) == (xp_size_t)-1);
return xp_awk_tab_adddatum(&awk->parse.func, name);
}
static INLINE int __remove_func_name (xp_awk_t* awk, xp_size_t index)
{
return xp_awk_tab_remrange (&awk->parse.func, index, 1);
}
static INLINE xp_size_t __find_func_name (xp_awk_t* awk, const xp_char_t* name)
{
return xp_awk_tab_find(&awk->parse.func, name, 0);
}
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name)
{
/*
if (awk->curfunc != XP_NULL) {
// TODO: finish this....
}
*/
return (xp_size_t)-1;
}
static xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name)
{
return (xp_size_t)-1;
}

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sa.h,v 1.7 2006-01-25 04:27:01 bacon Exp $ * $Id: sa.h,v 1.8 2006-01-29 18:28:14 bacon Exp $
*/ */
#ifndef _XP_AWK_SA_H_ #ifndef _XP_AWK_SA_H_
@ -31,6 +31,9 @@
#define xp_strcmp wcscmp #define xp_strcmp wcscmp
#define xp_strlen wcslen #define xp_strlen wcslen
#define xp_memcpy memcpy
#define xp_memcmp memcmp
#define xp_va_start(pvar,param) va_start(pvar,param) #define xp_va_start(pvar,param) va_start(pvar,param)
#define xp_va_list va_list #define xp_va_list va_list
#define xp_va_end(pvar) va_end(pvar) #define xp_va_end(pvar) va_end(pvar)

161
ase/awk/tab.c Normal file
View File

@ -0,0 +1,161 @@
/*
* $Id: tab.c,v 1.1 2006-01-29 18:28:14 bacon Exp $
*/
#include <xp/awk/tab.h>
#ifndef __STAND_ALONE
#include <xp/bas/memory.h>
#include <xp/bas/assert.h>
#endif
xp_awk_tab_t* xp_awk_tab_open (xp_awk_tab_t* tab)
{
if (tab == XP_NULL) {
tab = (xp_awk_tab_t*) xp_malloc (xp_sizeof(xp_awk_tab_t));
if (tab == XP_NULL) return XP_NULL;
tab->__dynamic = xp_true;
}
else tab->__dynamic = xp_false;
tab->buf = XP_NULL;
tab->size = 0;
tab->capa = 0;
return tab;
}
void xp_awk_tab_close (xp_awk_tab_t* tab)
{
xp_awk_tab_clear (tab);
if (tab->buf != XP_NULL) {
xp_free (tab->buf);
tab->buf = XP_NULL;
tab->capa = 0;
}
if (tab->__dynamic) xp_free (tab);
}
xp_size_t xp_awk_tab_getsize (xp_awk_tab_t* tab)
{
return tab->size;
}
xp_size_t xp_awk_tab_getcapa (xp_awk_tab_t* tab)
{
return tab->capa;
}
xp_awk_tab_t* xp_awk_tab_setcapa (xp_awk_tab_t* tab, xp_size_t capa)
{
xp_char_t** tmp;
if (tab->size > capa) {
xp_awk_tab_remrange (tab, capa, tab->size - capa);
xp_assert (tab->size <= capa);
}
if (capa > 0) {
tmp = (xp_char_t**)xp_realloc (
tab->buf, xp_sizeof(xp_char_t*) * capa);
if (tmp == XP_NULL) return XP_NULL;
}
else {
if (tab->buf != XP_NULL) xp_free (tab->buf);
tmp = XP_NULL;
}
tab->buf = tmp;
tab->capa = capa;
return tab;
}
void xp_awk_tab_clear (xp_awk_tab_t* tab)
{
xp_size_t i;
xp_assert (tab != XP_NULL);
for (i = 0; i < tab->size; i++) {
xp_free (tab->buf[i]);
tab->buf[i] = XP_NULL;
}
tab->size = 0;
}
xp_size_t xp_awk_tab_insdatum (
xp_awk_tab_t* tab, xp_size_t index, const xp_char_t* value)
{
xp_size_t i;
xp_char_t* value_dup;
value_dup = xp_strdup(value);
if (value_dup == XP_NULL) return (xp_size_t)-1;
if (index >= tab->capa) {
xp_size_t capa;
if (tab->capa <= 0) capa = (index + 1);
else {
do { capa = tab->capa * 2; } while (index >= capa);
}
if (xp_awk_tab_setcapa(tab,capa) == XP_NULL) {
xp_free (value_dup);
return (xp_size_t)-1;
}
}
for (i = tab->size; i > index; i--) tab->buf[i] = tab->buf[i-1];
tab->buf[index] = value_dup;
if (index > tab->size) tab->size = index + 1;
else tab->size++;
return index;
}
xp_size_t xp_awk_tab_remrange (
xp_awk_tab_t* tab, xp_size_t index, xp_size_t count)
{
xp_size_t i, j, k;
if (index >= tab->size) return 0;
if (count > tab->size - index) count = tab->size - index;
i = index;
j = index + count;
k = index + count;
while (i < k) {
xp_free (tab->buf[i]);
if (j >= tab->size)
tab->buf[i] = (j >= tab->size)? XP_NULL: tab->buf[j];
i++; j++;
}
tab->size -= count;
return count;
}
xp_size_t xp_awk_tab_adddatum (xp_awk_tab_t* tab, const xp_char_t* value)
{
return xp_awk_tab_insdatum (tab, tab->size, value);
}
xp_size_t xp_awk_tab_find (
xp_awk_tab_t* tab, const xp_char_t* value, xp_size_t index)
{
xp_size_t i;
for (i = index; i < tab->size; i++) {
if (xp_strcmp(tab->buf[i], value) == 0) return i;
}
return (xp_size_t)-1;
}

54
ase/awk/tab.h Normal file
View File

@ -0,0 +1,54 @@
/*
* $Id: tab.h,v 1.1 2006-01-29 18:28:14 bacon Exp $
*/
#ifndef _XP_AWK_TAB_H_
#define _XP_AWK_TAB_H_
#ifdef __STAND_ALONE
#include <xp/awk/sa.h>
#else
#include <xp/types.h>
#include <xp/macros.h>
#endif
// TODO: you have to turn this into a hash table.
// as of now, this is an arrayed table.
typedef struct xp_awk_tab_t xp_awk_tab_t;
struct xp_awk_tab_t
{
xp_char_t** buf;
xp_size_t size;
xp_size_t capa;
xp_bool_t __dynamic;
};
#ifdef __cplusplus
extern "C" {
#endif
xp_awk_tab_t* xp_awk_tab_open (xp_awk_tab_t* tab);
void xp_awk_tab_close (xp_awk_tab_t* tab);
xp_size_t xp_awk_tab_getsize (xp_awk_tab_t* tab);
xp_size_t xp_awk_tab_getcapa (xp_awk_tab_t* tab);
xp_awk_tab_t* xp_awk_tab_setcapa (xp_awk_tab_t* tab, xp_size_t capa);
void xp_awk_tab_clear (xp_awk_tab_t* tab);
xp_size_t xp_awk_tab_insdatum (
xp_awk_tab_t* tab, xp_size_t index, const xp_char_t* value);
xp_size_t xp_awk_tab_remrange (
xp_awk_tab_t* tab, xp_size_t index, xp_size_t count);
xp_size_t xp_awk_tab_adddatum (xp_awk_tab_t* tab, const xp_char_t* value);
xp_size_t xp_awk_tab_find (
xp_awk_tab_t* tab, const xp_char_t* value, xp_size_t index);
#ifdef __cplusplus
}
#endif
#endif