diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 0bc9c915..45bef3a4 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.15 2006-01-19 16:28:21 bacon Exp $ + * $Id: awk.h,v 1.16 2006-01-20 07:29:53 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -36,7 +36,8 @@ enum XP_AWK_EEXPR, /* expression expected */ XP_AWK_EWHILE, /* keyword 'while' is expected */ - XP_AWK_EASSIGN /* assignment statement expected */ + XP_AWK_EASSIGN, /* assignment statement expected */ + XP_AWK_EIDENT /* identifier expected */ }; /* diff --git a/ase/awk/makefile.in b/ase/awk/makefile.in index 8dc958c3..92f169ef 100644 --- a/ase/awk/makefile.in +++ b/ase/awk/makefile.in @@ -1,4 +1,4 @@ -SRCS = awk.c parse.c +SRCS = awk.c parse.c tree.c sa.c OBJS = $(SRCS:.c=.o) OUT = libxpawk.a diff --git a/ase/awk/parse.c b/ase/awk/parse.c index bf187aeb..1d94bec1 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.26 2006-01-19 16:28:21 bacon Exp $ + * $Id: parse.c,v 1.27 2006-01-20 07:29:54 bacon Exp $ */ #include @@ -94,6 +94,8 @@ static xp_awk_node_t* __parse_break (xp_awk_t* awk); static xp_awk_node_t* __parse_continue (xp_awk_t* awk); static xp_awk_node_t* __parse_return (xp_awk_t* awk); static xp_awk_node_t* __parse_exit (xp_awk_t* awk); +static xp_awk_node_t* __parse_next (xp_awk_t* awk); +static xp_awk_node_t* __parse_nextfile (xp_awk_t* awk); static int __get_token (xp_awk_t* awk); static int __get_char (xp_awk_t* awk); @@ -203,7 +205,89 @@ break; static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk) { - return XP_NULL; + xp_char_t* name; + xp_awk_node_t* body; + +/* TODO: *******************************/ + + /* skip the keyword 'function' */ + if (__get_token(awk) == -1) return XP_NULL; + if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, XP_AWK_EIDENT); + + name = xp_strdup (XP_STR_BUF(&awk->token.name)); + if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); + + /* skip the function name */ + if (__get_token(awk) == -1) { + xp_free (name); + return XP_NULL; + } + + if (!MATCH(awk,TOKEN_LPAREN)) { + xp_free (name); + PANIC (awk, XP_AWK_ELPAREN); + } + + if (__get_token(awk) == -1) { + xp_free (name); + return XP_NULL; + } + + if (MATCH(awk,TOKEN_RPAREN)) { + /* no function parameter */ + if (__get_token(awk) == -1) { + xp_free (name); + return XP_NULL; + } + } + else { + while (1) { + if (!MATCH(awk,TOKEN_IDENT)) { + xp_free (name); + PANIC (awk, XP_AWK_EIDENT); + } + + if (__get_token(awk) == -1) { + xp_free (name); + return XP_NULL; + } + + if (MATCH(awk,TOKEN_RPAREN)) break; + + if (!MATCH(awk,TOKEN_COMMA)) { + xp_free (name); + PANIC (awk, XP_AWK_ECOMMA); + } + + if (__get_token(awk) == -1) { + xp_free (name); + return XP_NULL; + } + } + + if (__get_token(awk) == -1) { + xp_free (name); + return XP_NULL; + } + } + + if (!MATCH(awk,TOKEN_LBRACE)) { +// TODO: cleanup + PANIC (awk, XP_AWK_ELBRACE); + } + if (__get_token(awk) == -1) { +// TODO: cleanup + return XP_NULL; + } + + body = __parse_block (awk); + if (body == XP_NULL) { +// TODO: cleanup; + return XP_NULL; + } + +// TODO: return something else... + return body; } static xp_awk_node_t* __parse_patnact (xp_awk_t* awk) @@ -366,12 +450,13 @@ static xp_awk_node_t* __parse_statement_nb (xp_awk_t* awk) if (__get_token(awk) == -1) return XP_NULL; node = __parse_exit(awk); } -/* -TODO: + +/* TODO: else if (MATCH(awk,TOKEN_DELETE)) { if (__get_token(awk) == -1) return XP_NULL; node = __parse_delete(awk); } +*/ else if (MATCH(awk,TOKEN_NEXT)) { if (__get_token(awk) == -1) return XP_NULL; node = __parse_next(awk); @@ -380,7 +465,6 @@ TODO: if (__get_token(awk) == -1) return XP_NULL; node = __parse_nextfile(awk); } -*/ else { node = __parse_expression(awk); } @@ -411,8 +495,48 @@ static xp_awk_node_t* __parse_expression (xp_awk_t* awk) * ::= */ - xp_awk_node_t* x; + xp_awk_node_t* x, * y; + xp_awk_node_assign_t* node; + + x = __parse_basic_expr (awk, XP_NULL); + if (x == XP_NULL) return XP_NULL; + if (!MATCH(awk,TOKEN_ASSIGN)) return x; + + xp_assert (x->next == XP_NULL); + if (x->type != XP_AWK_NODE_VAR && x->type != XP_AWK_NODE_IDX) { + xp_awk_clrpt (x); + PANIC (awk, XP_AWK_EASSIGN); + } + + if (__get_token(awk) == -1) { + xp_awk_clrpt (x); + return XP_NULL; + } + + y = __parse_basic_expr (awk, XP_NULL); + if (y == XP_NULL) { + xp_awk_clrpt (x); + return XP_NULL; + } + + node = (xp_awk_node_assign_t*)xp_malloc (xp_sizeof(xp_awk_node_assign_t)); + if (node == XP_NULL) { + xp_awk_clrpt (x); + xp_awk_clrpt (y); + PANIC (awk, XP_AWK_ENOMEM); + } + + node->type = XP_AWK_NODE_ASSIGN; + node->next = XP_NULL; + node->left = x; + node->right = y; + + return (xp_awk_node_t*)node; + +#if 0 + xp_awk_node_t* x; + if (MATCH(awk,TOKEN_IDENT)) { /* the expression starts with an identifier */ @@ -424,15 +548,6 @@ static xp_awk_node_t* __parse_expression (xp_awk_t* awk) return XP_NULL; } -/* - if (MATCH(awk,TOKEN_LBRACK)) { -// TODO: hashidx.... - xp_awk_node_t* node; - node = __parse_hashidx (awk, name); - if (node == XP_NULL) xp_free (name); - return (xp_awk_node_t*)node; - } -*/ if (MATCH(awk,TOKEN_ASSIGN)) { if (__get_token(awk) == -1) { @@ -463,8 +578,10 @@ static xp_awk_node_t* __parse_expression (xp_awk_t* awk) } return x; +#endif } +#if 0 static xp_awk_node_t* __parse_assignment (xp_awk_t* awk, xp_char_t* ident) { xp_awk_node_assign_t* node; @@ -496,6 +613,7 @@ static xp_awk_node_t* __parse_assignment (xp_awk_t* awk, xp_char_t* ident) return (xp_awk_node_t*)node; } +#endif static xp_awk_node_t* __parse_basic_expr (xp_awk_t* awk, xp_char_t* ident) { @@ -734,36 +852,30 @@ static xp_awk_node_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name) if (__get_token(awk) == -1) return XP_NULL; -xp_printf (XP_TEXT("----------------\n")); idx = __parse_expression (awk); if (idx == XP_NULL) return XP_NULL; -xp_printf (XP_TEXT("+++++++++++++++++++\n")); if (!MATCH(awk,TOKEN_RBRACK)) { xp_awk_clrpt (idx); PANIC (awk, XP_AWK_ERBRACK); } -xp_printf (XP_TEXT("$$$$$$$$$$$$$$$$$$$$$$\n")); if (__get_token(awk) == -1) { xp_awk_clrpt (idx); return XP_NULL; } -xp_printf (XP_TEXT("#######################\n")); node = (xp_awk_node_idx_t*) xp_malloc (xp_sizeof(xp_awk_node_idx_t)); if (node == XP_NULL) { xp_awk_clrpt (idx); PANIC (awk, XP_AWK_ENOMEM); } -xp_printf (XP_TEXT("~~~~~~~~~~~~~~~~~~~~~~~~~`\n")); node->type = XP_AWK_NODE_IDX; node->next = XP_NULL; node->name = name; node->idx = idx; -xp_printf (XP_TEXT("%%%%%%%%%%%%%%%%%%%%%%%%%[%s]\n"), XP_STR_BUF(&awk->token.name)); return (xp_awk_node_t*)node; } @@ -1152,6 +1264,30 @@ static xp_awk_node_t* __parse_exit (xp_awk_t* awk) return (xp_awk_node_t*)node; } +static xp_awk_node_t* __parse_next (xp_awk_t* awk) +{ + xp_awk_node_t* node; + + node = (xp_awk_node_t*) xp_malloc (xp_sizeof(xp_awk_node_t)); + if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); + node->type = XP_AWK_NODE_NEXT; + node->next = XP_NULL; + + return node; +} + +static xp_awk_node_t* __parse_nextfile (xp_awk_t* awk) +{ + xp_awk_node_t* node; + + node = (xp_awk_node_t*) xp_malloc (xp_sizeof(xp_awk_node_t)); + if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); + node->type = XP_AWK_NODE_NEXTFILE; + node->next = XP_NULL; + + return node; +} + static int __get_token (xp_awk_t* awk) { xp_cint_t c; diff --git a/ase/awk/sa.c b/ase/awk/sa.c new file mode 100644 index 00000000..4c3bdcc1 --- /dev/null +++ b/ase/awk/sa.c @@ -0,0 +1,87 @@ +/* + * $Id: sa.c,v 1.1 2006-01-20 07:32:38 bacon Exp $ + */ + +#include + +#ifdef __STAND_ALONE + +xp_str_t* xp_str_open (xp_str_t* str, xp_size_t capa) +{ + if (str == XP_NULL) { + str = (xp_str_t*)xp_malloc (sizeof(xp_str_t)); + if (str == XP_NULL) return XP_NULL; + str->__dynamic = xp_true; + } + else str->__dynamic = xp_false; + + str->buf = (xp_char_t*)xp_malloc ( + xp_sizeof(xp_char_t) * (capa + 1)); + if (str->buf == XP_NULL) { + if (str->__dynamic) xp_free (str); + return XP_NULL; + } + + str->size = 0; + str->capa = capa; + str->buf[0] = XP_CHAR('\0'); + + return str; +} + +void xp_str_close (xp_str_t* str) +{ + xp_free (str->buf); + if (str->__dynamic) xp_free (str); +} + +xp_size_t xp_str_cat (xp_str_t* str, const xp_char_t* s) +{ + /* TODO: improve it */ + return xp_str_ncat (str, s, xp_strlen(s)); +} + +static xp_size_t __strncpy (xp_char_t* buf, const xp_char_t* str, xp_size_t len) +{ + const xp_char_t* end = str + len; + while (str < end) *buf++ = *str++; + *buf = XP_CHAR('\0'); + return len; +} + +xp_size_t xp_str_ncat (xp_str_t* str, const xp_char_t* s, xp_size_t len) +{ + xp_char_t* buf; + xp_size_t capa; + + if (len > str->capa - str->size) { + capa = str->size + len; + + /* double the capa if necessary for concatenation */ + if (capa < str->capa * 2) capa = str->capa * 2; + + buf = (xp_char_t*)xp_realloc ( + str->buf, xp_sizeof(xp_char_t) * (capa + 1)); + if (buf == XP_NULL) return (xp_size_t)-1; + + str->capa = capa; + str->buf = buf; + } + + str->size += __strncpy (&str->buf[str->size], s, len); + str->buf[str->size] = XP_CHAR('\0'); + return str->size; +} + +xp_size_t xp_str_ccat (xp_str_t* str, xp_char_t c) +{ + return xp_str_ncat (str, &c, 1); +} + +void xp_str_clear (xp_str_t* str) +{ + str->size = 0; + str->buf[0] = XP_CHAR('\0'); +} + +#endif diff --git a/ase/awk/sa.h b/ase/awk/sa.h new file mode 100644 index 00000000..f6f6a871 --- /dev/null +++ b/ase/awk/sa.h @@ -0,0 +1,93 @@ +/* + * $Id: sa.h,v 1.1 2006-01-20 07:32:38 bacon Exp $ + */ + +#ifndef _XP_AWK_SA_H_ +#define _XP_AWK_SA_H_ + +#ifdef __STAND_ALONE + +#include +#include +#include +#include +#include +#include + +#define xp_malloc malloc +#define xp_realloc realloc +#define xp_free free +#define xp_assert assert +#define xp_printf wprintf + +#define xp_isdigit iswdigit +#define xp_isalpha iswalpha +#define xp_isalnum iswalnum +#define xp_isspace iswspace + +#define xp_strcmp wcscmp +#define xp_strlen wcslen +#ifdef _WIN32 +#define xp_strdup _wcsdup +#else +#define xp_strdup wcsdup +#endif + +#define xp_main main + +#define XP_CHAR(c) L##c +#define XP_TEXT(c) L##c +#define XP_CHAR_EOF WEOF + +#define XP_NULL NULL + +#define xp_sizeof(n) (sizeof(n)) +#define xp_countof(n) (sizeof(n) / sizeof(n[0])) + +#define xp_true (0 == 0) +#define xp_false (0 != 0) + +typedef wchar_t xp_char_t; +typedef wint_t xp_cint_t; +typedef size_t xp_size_t; +typedef int xp_bool_t; + +#ifdef _WIN32 +typedef long xp_ssize_t; +#else +typedef ssize_t xp_ssize_t; +#endif + +#define XP_STR_LEN(x) ((x)->size) +#define XP_STR_SIZE(x) ((x)->size + 1) +#define XP_STR_CAPA(x) ((x)->capa) +#define XP_STR_BUF(x) ((x)->buf) + +typedef struct xp_str_t xp_str_t; + +struct xp_str_t +{ + xp_char_t* buf; + xp_size_t size; + xp_size_t capa; + xp_bool_t __dynamic; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +xp_str_t* xp_str_open (xp_str_t* str, xp_size_t capa); +void xp_str_close (xp_str_t* str); +xp_size_t xp_str_cat (xp_str_t* str, const xp_char_t* s); +xp_size_t xp_str_ncat (xp_str_t* str, const xp_char_t* s, xp_size_t len); +xp_size_t xp_str_ccat (xp_str_t* str, xp_char_t c); +void xp_str_clear (xp_str_t* str); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/ase/awk/tree.c b/ase/awk/tree.c index 405bc584..c14dc369 100644 --- a/ase/awk/tree.c +++ b/ase/awk/tree.c @@ -1,5 +1,5 @@ /* - * $Id: tree.c,v 1.8 2006-01-19 16:28:21 bacon Exp $ + * $Id: tree.c,v 1.9 2006-01-20 07:29:54 bacon Exp $ */ #include @@ -34,7 +34,8 @@ static int __print_expr_node (xp_awk_node_t* node) { switch (node->type) { case XP_AWK_NODE_ASSIGN: - xp_printf (XP_TEXT("%s = "), ((xp_awk_node_assign_t*)node)->left); + if (__print_expr_node (((xp_awk_node_assign_t*)node)->left) == -1) return -1; + xp_printf (XP_TEXT(" = ")); if (__print_expr_node (((xp_awk_node_assign_t*)node)->right) == -1) return -1; xp_assert ((((xp_awk_node_assign_t*)node)->right)->next == XP_NULL); break; @@ -44,7 +45,9 @@ static int __print_expr_node (xp_awk_node_t* node) if (__print_expr_node (((xp_awk_node_expr_t*)node)->left) == -1) return -1; xp_assert ((((xp_awk_node_expr_t*)node)->left)->next == XP_NULL); xp_printf (XP_TEXT(" %c "), __binop_char[((xp_awk_node_expr_t*)node)->opcode]); + if (((xp_awk_node_expr_t*)node)->right->type == XP_AWK_NODE_ASSIGN) xp_printf (XP_TEXT("(")); if (__print_expr_node (((xp_awk_node_expr_t*)node)->right) == -1) return -1; + if (((xp_awk_node_expr_t*)node)->right->type == XP_AWK_NODE_ASSIGN) xp_printf (XP_TEXT(")")); xp_assert ((((xp_awk_node_expr_t*)node)->right)->next == XP_NULL); xp_printf (XP_TEXT(")")); break; @@ -227,6 +230,16 @@ static void __print_statements (xp_awk_node_t* tree, int depth) } break; + case XP_AWK_NODE_NEXT: + __print_tabs (depth); + xp_printf (XP_TEXT("next;\n")); + break; + + case XP_AWK_NODE_NEXTFILE: + __print_tabs (depth); + xp_printf (XP_TEXT("nextfile;\n")); + break; + default: __print_tabs (depth); if (__print_expr_node(p) == 0) { @@ -293,6 +306,8 @@ void xp_awk_clrpt (xp_awk_node_t* tree) case XP_AWK_NODE_BREAK: case XP_AWK_NODE_CONTINUE: + case XP_AWK_NODE_NEXT: + case XP_AWK_NODE_NEXTFILE: xp_free (p); break; @@ -303,7 +318,7 @@ void xp_awk_clrpt (xp_awk_node_t* tree) break; case XP_AWK_NODE_ASSIGN: - xp_free (((xp_awk_node_assign_t*)p)->left); + xp_awk_clrpt (((xp_awk_node_assign_t*)p)->left); xp_awk_clrpt (((xp_awk_node_assign_t*)p)->right); xp_free (p); break; diff --git a/ase/awk/tree.h b/ase/awk/tree.h index 4f3ba72c..c17d318a 100644 --- a/ase/awk/tree.h +++ b/ase/awk/tree.h @@ -1,5 +1,5 @@ /* - * $Id: tree.h,v 1.13 2006-01-19 16:28:21 bacon Exp $ + * $Id: tree.h,v 1.14 2006-01-20 07:29:54 bacon Exp $ */ #ifndef _XP_AWK_TREE_H_ @@ -13,6 +13,8 @@ enum XP_AWK_NODE_CONTINUE, XP_AWK_NODE_RETURN, XP_AWK_NODE_EXIT, + XP_AWK_NODE_NEXT, + XP_AWK_NODE_NEXTFILE, XP_AWK_NODE_ASSIGN, XP_AWK_NODE_BINARY, XP_AWK_NODE_UNARY, @@ -56,7 +58,7 @@ struct xp_awk_node_block_t struct xp_awk_node_assign_t { XP_AWK_NODE_HDR; - xp_char_t* left; + xp_awk_node_t* left; xp_awk_node_t* right; };