diff --git a/ase/awk/awk_i.h b/ase/awk/awk_i.h index 94a7441c..f022a131 100644 --- a/ase/awk/awk_i.h +++ b/ase/awk/awk_i.h @@ -1,5 +1,5 @@ /* - * $Id: awk_i.h,v 1.13 2006-06-16 07:35:07 bacon Exp $ + * $Id: awk_i.h,v 1.14 2006-06-16 14:31:42 bacon Exp $ */ #ifndef _XP_AWK_AWKI_H_ @@ -16,6 +16,7 @@ typedef struct xp_awk_cmd_t xp_awk_cmd_t; #include #include #include +#include #ifdef XP_AWK_STAND_ALONE #include diff --git a/ase/awk/func.c b/ase/awk/func.c new file mode 100644 index 00000000..8093bf87 --- /dev/null +++ b/ase/awk/func.c @@ -0,0 +1,36 @@ +/* + * $Id: func.c,v 1.1 2006-06-16 14:31:42 bacon Exp $ + */ + +#include + +#ifndef XP_AWK_STAND_ALONE +#include +#include +#endif + +enum +{ + BFN_SYSTEM, + BFN_CLOSE +}; + +static xp_awk_bfn_t __bfn[] = +{ + { XP_T("system"), BFN_SYSTEM, 0, 1, 1, XP_NULL }, + { XP_T("close"), BFN_CLOSE, 0, 1, 2, XP_NULL }, + { XP_NULL, 0, 0, 0, 0, XP_NULL } +}; + +xp_awk_bfn_t* xp_awk_getbfn (const xp_char_t* name) +{ + xp_awk_bfn_t* p = __bfn; + + while (p->name != XP_NULL) + { + if (xp_strcmp (p->name, name) == 0) return p; + p++; + } + + return XP_NULL; +} diff --git a/ase/awk/func.h b/ase/awk/func.h new file mode 100644 index 00000000..037c5647 --- /dev/null +++ b/ase/awk/func.h @@ -0,0 +1,36 @@ +/* + * $Id: func.h,v 1.1 2006-06-16 14:31:42 bacon Exp $ + */ + +#ifndef _XP_AWK_FUNC_H_ +#define _XP_AWK_FUNC_H_ + +#ifndef _XP_AWK_AWK_H_ +#error Never include this file directly. Include instead +#endif + +typedef struct xp_awk_bfn_t xp_awk_bfn_t; + +struct xp_awk_bfn_t +{ + const xp_char_t* name; + + int type; + int valid; /* the entry is valid when this option is set */ + + int max_args; + int min_args; + xp_awk_val_t* (*handler) (); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +xp_awk_bfn_t* xp_awk_getbfn (const xp_char_t* name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ase/awk/makefile.cl b/ase/awk/makefile.cl index 17838514..1e691db9 100644 --- a/ase/awk/makefile.cl +++ b/ase/awk/makefile.cl @@ -1,4 +1,4 @@ -SRCS = awk.c err.c tree.c tab.c map.c parse.c run.c sa.c val.c misc.c extio.c +SRCS = awk.c err.c tree.c tab.c map.c parse.c run.c sa.c val.c func.c misc.c extio.c OBJS = $(SRCS:.c=.obj) OUT = xpawk diff --git a/ase/awk/map.h b/ase/awk/map.h index 033f747c..d5a9c807 100644 --- a/ase/awk/map.h +++ b/ase/awk/map.h @@ -1,5 +1,5 @@ /* - * $Id: map.h,v 1.11 2006-04-30 17:10:30 bacon Exp $ + * $Id: map.h,v 1.12 2006-06-16 14:31:42 bacon Exp $ */ #ifndef _XP_AWK_MAP_H_ @@ -9,13 +9,6 @@ #error Never include this file directly. Include instead #endif -#ifdef XP_AWK_STAND_ALONE -#include -#else -#include -#include -#endif - typedef struct xp_awk_map_t xp_awk_map_t; typedef struct xp_awk_pair_t xp_awk_pair_t; diff --git a/ase/awk/parse.c b/ase/awk/parse.c index da0f259f..d0833075 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.113 2006-06-13 15:11:39 bacon Exp $ + * $Id: parse.c,v 1.114 2006-06-16 14:31:42 bacon Exp $ */ #include @@ -140,6 +140,7 @@ static xp_awk_nde_t* __parse_multiplicative (xp_awk_t* awk); static xp_awk_nde_t* __parse_unary (xp_awk_t* awk); static xp_awk_nde_t* __parse_increment (xp_awk_t* awk); static xp_awk_nde_t* __parse_primary (xp_awk_t* awk); +static xp_awk_nde_t* __parse_primary_ident (xp_awk_t* awk); static xp_awk_nde_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name); static xp_awk_nde_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name); @@ -204,7 +205,7 @@ static struct __kwent __kwtab[] = { XP_T("in"), TOKEN_IN, 0 }, - { XP_NULL, 0, 0 } + { XP_NULL, 0, 0 } }; /* TODO: @@ -231,7 +232,7 @@ static struct __kwent __bvtab[] = { XP_T("RSTART"), TOKEN_RSTART, 0 }, { XP_T("RLENGTH"), TOKEN_RLENGTH, 0 }, { XP_T("SUBSEP"), TOKEN_SUBSEP, 0 }, - { XP_NULL, 0, 0 } + { XP_NULL, 0, 0 } }; */ @@ -1723,104 +1724,7 @@ static xp_awk_nde_t* __parse_primary (xp_awk_t* awk) { if (MATCH(awk,TOKEN_IDENT)) { - xp_char_t* name_dup; - - name_dup = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name)); - if (name_dup == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); - - if (__get_token(awk) == -1) - { - xp_free (name_dup); - return XP_NULL; - } - - if (MATCH(awk,TOKEN_LBRACK)) - { - xp_awk_nde_t* nde; - nde = __parse_hashidx (awk, name_dup); - if (nde == XP_NULL) xp_free (name_dup); - return (xp_awk_nde_t*)nde; - } - else if (MATCH(awk,TOKEN_LPAREN)) - { - /* function call */ - xp_awk_nde_t* nde; - nde = __parse_funcall (awk, name_dup); - if (nde == XP_NULL) xp_free (name_dup); - return (xp_awk_nde_t*)nde; - } - else - { - /* normal variable */ - xp_awk_nde_var_t* nde; - xp_size_t idxa; - - nde = (xp_awk_nde_var_t*) - xp_malloc (xp_sizeof(xp_awk_nde_var_t)); - if (nde == XP_NULL) - { - xp_free (name_dup); - PANIC (awk, XP_AWK_ENOMEM); - } - - /* search the parameter name list */ - idxa = xp_awk_tab_find(&awk->parse.params, name_dup, 0); - if (idxa != (xp_size_t)-1) - { - nde->type = XP_AWK_NDE_ARG; - nde->next = XP_NULL; - /*nde->id.name = XP_NULL;*/ - nde->id.name = name_dup; - nde->id.idxa = idxa; - nde->idx = XP_NULL; - - return (xp_awk_nde_t*)nde; - } - - /* search the local variable list */ - idxa = xp_awk_tab_rrfind(&awk->parse.locals, name_dup, 0); - if (idxa != (xp_size_t)-1) - { - nde->type = XP_AWK_NDE_LOCAL; - nde->next = XP_NULL; - /*nde->id.name = XP_NULL;*/ - nde->id.name = name_dup; - nde->id.idxa = idxa; - nde->idx = XP_NULL; - - return (xp_awk_nde_t*)nde; - } - - /* search the global variable list */ - idxa = xp_awk_tab_rrfind(&awk->parse.globals, name_dup, 0); - if (idxa != (xp_size_t)-1) - { - nde->type = XP_AWK_NDE_GLOBAL; - nde->next = XP_NULL; - /*nde->id.name = XP_NULL;*/ - nde->id.name = name_dup; - nde->id.idxa = idxa; - nde->idx = XP_NULL; - - return (xp_awk_nde_t*)nde; - } - - if (awk->opt.parse & XP_AWK_IMPLICIT) - { - nde->type = XP_AWK_NDE_NAMED; - nde->next = XP_NULL; - nde->id.name = name_dup; - nde->id.idxa = (xp_size_t)-1; - nde->idx = XP_NULL; - - return (xp_awk_nde_t*)nde; - } - - /* undefined variable */ - xp_free (name_dup); - xp_free (nde); - PANIC (awk, XP_AWK_EUNDEF); - } + return __parse_primary_ident (awk); } else if (MATCH(awk,TOKEN_INT)) { @@ -2094,6 +1998,139 @@ static xp_awk_nde_t* __parse_primary (xp_awk_t* awk) PANIC (awk, XP_AWK_EEXPRESSION); } +static xp_awk_nde_t* __parse_primary_ident (xp_awk_t* awk) +{ + xp_char_t* name_dup; + xp_awk_bfn_t* bfn; + + xp_assert (MATCH(awk,TOKEN_IDENT)); + + name_dup = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name)); + if (name_dup == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); + + if (__get_token(awk) == -1) + { + xp_free (name_dup); + return XP_NULL; + } + + /* what if name_dup is a built-in function name */ + bfn = xp_awk_getbfn (name_dup); + if (bfn != XP_NULL) + { + xp_awk_nde_t* nde; + + if (!MATCH(awk,TOKEN_LPAREN)) + { + /* built-in function should be in the form + * of the function call */ + xp_free (name_dup); + PANIC (awk, XP_AWK_ELPAREN); + } + + /* bfn->handler... */ + nde = __parse_funcall (awk, name_dup); + if (nde == XP_NULL) xp_free (name_dup); + return (xp_awk_nde_t*)nde; + } + + /* TODO: user-defined functions */ + /* + if (__is_ufname (name_dup)) + { + } + */ + + /* now we know that name_dup is a normal identifier. */ + if (MATCH(awk,TOKEN_LBRACK)) + { + xp_awk_nde_t* nde; + nde = __parse_hashidx (awk, name_dup); + if (nde == XP_NULL) xp_free (name_dup); + return (xp_awk_nde_t*)nde; + } + else if (MATCH(awk,TOKEN_LPAREN)) + { + /* function call */ + xp_awk_nde_t* nde; + nde = __parse_funcall (awk, name_dup); + if (nde == XP_NULL) xp_free (name_dup); + return (xp_awk_nde_t*)nde; + } + else + { + /* normal variable */ + xp_awk_nde_var_t* nde; + xp_size_t idxa; + + nde = (xp_awk_nde_var_t*) + xp_malloc (xp_sizeof(xp_awk_nde_var_t)); + if (nde == XP_NULL) + { + xp_free (name_dup); + PANIC (awk, XP_AWK_ENOMEM); + } + + /* search the parameter name list */ + idxa = xp_awk_tab_find(&awk->parse.params, name_dup, 0); + if (idxa != (xp_size_t)-1) + { + nde->type = XP_AWK_NDE_ARG; + nde->next = XP_NULL; + /*nde->id.name = XP_NULL;*/ + nde->id.name = name_dup; + nde->id.idxa = idxa; + nde->idx = XP_NULL; + + return (xp_awk_nde_t*)nde; + } + + /* search the local variable list */ + idxa = xp_awk_tab_rrfind(&awk->parse.locals, name_dup, 0); + if (idxa != (xp_size_t)-1) + { + nde->type = XP_AWK_NDE_LOCAL; + nde->next = XP_NULL; + /*nde->id.name = XP_NULL;*/ + nde->id.name = name_dup; + nde->id.idxa = idxa; + nde->idx = XP_NULL; + + return (xp_awk_nde_t*)nde; + } + + /* search the global variable list */ + idxa = xp_awk_tab_rrfind(&awk->parse.globals, name_dup, 0); + if (idxa != (xp_size_t)-1) + { + nde->type = XP_AWK_NDE_GLOBAL; + nde->next = XP_NULL; + /*nde->id.name = XP_NULL;*/ + nde->id.name = name_dup; + nde->id.idxa = idxa; + nde->idx = XP_NULL; + + return (xp_awk_nde_t*)nde; + } + + if (awk->opt.parse & XP_AWK_IMPLICIT) + { + nde->type = XP_AWK_NDE_NAMED; + nde->next = XP_NULL; + nde->id.name = name_dup; + nde->id.idxa = (xp_size_t)-1; + nde->idx = XP_NULL; + + return (xp_awk_nde_t*)nde; + } + + /* undefined variable */ + xp_free (name_dup); + xp_free (nde); + PANIC (awk, XP_AWK_EUNDEF); + } +} + static xp_awk_nde_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name) { xp_awk_nde_t* idx, * tmp, * last; @@ -2832,6 +2869,8 @@ static int __get_token (xp_awk_t* awk) } else if (xp_isalpha(c) || c == XP_T('_')) { + int type; + /* identifier */ do { @@ -2840,7 +2879,8 @@ static int __get_token (xp_awk_t* awk) } while (xp_isalpha(c) || c == XP_T('_') || xp_isdigit(c)); - SET_TOKEN_TYPE (awk, __classify_ident(awk,XP_STR_BUF(&awk->token.name))); + type = __classify_ident (awk,XP_STR_BUF(&awk->token.name)); + SET_TOKEN_TYPE (awk, type); } else if (c == XP_T('\"')) { @@ -3482,12 +3522,15 @@ static int __skip_comment (xp_awk_t* awk) static int __classify_ident (xp_awk_t* awk, const xp_char_t* ident) { - struct __kwent* p; + struct __kwent* kwp; - for (p = __kwtab; p->name != XP_NULL; p++) + for (kwp = __kwtab; kwp->name != XP_NULL; kwp++) { - if (p->valid != 0 && (awk->opt.parse & p->valid) == 0) continue; - if (xp_strcmp(p->name, ident) == 0) return p->type; + if (kwp->valid != 0 && (awk->opt.parse & kwp->valid) == 0) + { + continue; + } + if (xp_strcmp(kwp->name, ident) == 0) return kwp->type; } return TOKEN_IDENT; diff --git a/ase/awk/tab.h b/ase/awk/tab.h index b1c44f53..23f7cf28 100644 --- a/ase/awk/tab.h +++ b/ase/awk/tab.h @@ -1,5 +1,5 @@ /* - * $Id: tab.h,v 1.7 2006-04-16 04:31:38 bacon Exp $ + * $Id: tab.h,v 1.8 2006-06-16 14:31:42 bacon Exp $ */ #ifndef _XP_AWK_TAB_H_ @@ -9,13 +9,6 @@ #error Never include this file directly. Include instead #endif -#ifdef XP_AWK_STAND_ALONE -#include -#else -#include -#include -#endif - /* TODO: you have to turn this into a hash table. as of now, this is an arrayed table. */