From 934a5da3e12852e4a0f1867873db8071c164e780 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 29 Jan 2006 18:28:14 +0000 Subject: [PATCH] *** empty log message *** --- ase/awk/Makefile.cl | 2 +- ase/awk/awk.c | 18 ++++- ase/awk/awk.h | 9 ++- ase/awk/hash.h | 25 +++++- ase/awk/parse.c | 193 +++++++++++++++++++++++++++++--------------- ase/awk/sa.h | 5 +- ase/awk/tab.c | 161 ++++++++++++++++++++++++++++++++++++ ase/awk/tab.h | 54 +++++++++++++ 8 files changed, 392 insertions(+), 75 deletions(-) create mode 100644 ase/awk/tab.c create mode 100644 ase/awk/tab.h diff --git a/ase/awk/Makefile.cl b/ase/awk/Makefile.cl index f508c659..7936f7de 100644 --- a/ase/awk/Makefile.cl +++ b/ase/awk/Makefile.cl @@ -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) OUT = xpawk.lib diff --git a/ase/awk/awk.c b/ase/awk/awk.c index c98f1913..39250f6b 100644 --- a/ase/awk/awk.c +++ b/ase/awk/awk.c @@ -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 @@ -23,6 +23,12 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk) 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->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.funcs = XP_NULL; + awk->lex.curc = XP_CHAR_EOF; awk->lex.ungotc_count = 0; @@ -49,14 +56,21 @@ int xp_awk_close (xp_awk_t* awk) { xp_awk_clear (awk); if (xp_awk_detsrc(awk) == -1) return -1; + + xp_awk_tab_close(&awk->parse.func); xp_str_close (&awk->token.name); + if (awk->__dynamic) xp_free (awk); 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) { - + /* clear parse trees */ if (awk->tree.begin != XP_NULL) { xp_assert (awk->tree.begin->next == XP_NULL); xp_awk_clrpt (awk->tree.begin); diff --git a/ase/awk/awk.h b/ase/awk/awk.h index aaabcf0b..b0f8c766 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -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_ @@ -14,6 +14,7 @@ #endif #include +#include enum { @@ -39,8 +40,9 @@ enum XP_AWK_EASSIGN, /* assignment statement expected */ XP_AWK_EIDENT, /* identifier expected */ XP_AWK_EDUPBEGIN, /* duplicate BEGIN */ - XP_AWK_EDUPEND, /* duplicate END */ - XP_AWK_EDUPFUNC /* duplicate function name */ + XP_AWK_EDUPEND, /* duplicate END */ + 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 */ struct { + xp_awk_tab_t func; // TODO: locals, globals??? xp_char_t* vars; /* global and local variable names... */ xp_char_t* args; /* function arguments */ diff --git a/ase/awk/hash.h b/ase/awk/hash.h index a5cfa870..cac66720 100644 --- a/ase/awk/hash.h +++ b/ase/awk/hash.h @@ -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_ #define _XP_AWK_HASH_H_ +#ifdef __STAND_ALONE +#include +#else +#include +#include +#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 extern "C" { #endif diff --git a/ase/awk/parse.c b/ase/awk/parse.c index 374d1235..1e4e2b15 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -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 @@ -75,6 +75,13 @@ enum { 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_function (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 __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 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 { const xp_char_t* name; @@ -188,9 +199,13 @@ int xp_awk_parse (xp_awk_t* awk) if (__parse_progunit(awk) == XP_NULL) { // TODO: cleanup the parse tree created so far.... + // function tables also etc... xp_printf (XP_TEXT("error - %d\n"), awk->errnum); return -1; } + +xp_awk_prnpt(node); + } 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)) { node = __parse_function(awk); - if (node == XP_NULL) { - // TODO: cleanup - return XP_NULL; - } + if (node == XP_NULL) return XP_NULL; } else if (MATCH(awk,TOKEN_BEGIN)) { node = __parse_begin (awk); - if (node == XP_NULL) { - // TODO: cleanup - return XP_NULL; - } + if (node == XP_NULL) return XP_NULL; } else if (MATCH(awk, TOKEN_END)) { node = __parse_end (awk); - if (node == XP_NULL) { - // TODO: cleanup - return XP_NULL; - } + if (node == XP_NULL) return XP_NULL; } /* TODO: process patterns and expressions */ /* @@ -239,55 +245,67 @@ static xp_awk_node_t* __parse_progunit (xp_awk_t* awk) else { /* pattern-less actions */ node = __parse_action (awk); - if (node == XP_NULL) { - // TODO: cleanup - return XP_NULL; - } + if (node == XP_NULL) return XP_NULL; // TODO: weave the action block into awk->tree.actions... } -xp_awk_prnpt(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) { xp_char_t* name; - //xp_awk_func_t* func; + xp_char_t* name_dup; xp_awk_node_t* body; + xp_size_t fnpos; + xp_size_t nargs = 0; if (__get_token(awk) == -1) return XP_NULL; /* function name */ if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, XP_AWK_EIDENT); - if (__function_defined(awk,XP_STR_BUF(&awk->token.name))) { - PANIC (awk, XP_AWK_EDUPFUNC); + name = XP_STR_BUF(&awk->token.name); + 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)); - if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); +// TODO: make this feature optional.. +// 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 */ if (__get_token(awk) == -1) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); return XP_NULL; } if (!MATCH(awk,TOKEN_LPAREN)) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); PANIC (awk, XP_AWK_ELPAREN); } if (__get_token(awk) == -1) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); return XP_NULL; } @@ -295,75 +313,97 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk) if (MATCH(awk,TOKEN_RPAREN)) { /* no function parameter */ if (__get_token(awk) == -1) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); return XP_NULL; } } else { while (1) { if (!MATCH(awk,TOKEN_IDENT)) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); PANIC (awk, XP_AWK_EIDENT); } + nargs++; + // TODO: push args to param list... + if (__get_token(awk) == -1) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); return XP_NULL; } if (MATCH(awk,TOKEN_RPAREN)) break; if (!MATCH(awk,TOKEN_COMMA)) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); PANIC (awk, XP_AWK_ECOMMA); } if (__get_token(awk) == -1) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); return XP_NULL; } } if (__get_token(awk) == -1) { + __remove_func_name (awk, fnpos); // TODO: cleanup parameter name list - xp_free (name); + xp_free (name_dup); return XP_NULL; } } + /* check if the function body starts with a left brace */ if (!MATCH(awk,TOKEN_LBRACE)) { + __remove_func_name (awk, fnpos); // TODO: cleanup parameter name list - xp_free (name); + xp_free (name_dup); PANIC (awk, XP_AWK_ELBRACE); } if (__get_token(awk) == -1) { + __remove_func_name (awk, fnpos); // TODO: cleanup parameter name list - xp_free (name); + xp_free (name_dup); return XP_NULL; } - /* function body */ + /* actual function body */ body = __parse_block (awk); if (body == XP_NULL) { + __remove_func_name (awk, fnpos); // TODO: cleanup parameter name list - xp_free (name); + xp_free (name_dup); return XP_NULL; } /* func = (xp_awk_func_t*) xp_malloc (xp_sizeof(xp_awk_func_t)); if (func == XP_NULL) { - xp_free (name); + __remove_func_name (awk, fnpos); + xp_free (name_dup); xp_awk_clrpt (body); return XP_NULL; } - func->name = name; - func->nargs = 0; - func->body = body; + func->name = name_dup; + func->nargs = nargs; + 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; } @@ -422,6 +462,7 @@ static xp_awk_node_t* __parse_block (xp_awk_t* awk) // TODO: cleanup the variable name list... return XP_NULL; } + head = XP_NULL; goto skip_block_body; } @@ -493,7 +534,7 @@ skip_block_body: block->lvc = lvc; block->body = head; - // TODO: cleanup the variable name list... +// TODO: cleanup the variable name list... return (xp_awk_node_t*)block; } @@ -1682,23 +1723,6 @@ static int __classfy_ident (const xp_char_t* 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) { xp_long_t n = 0; @@ -1710,3 +1734,38 @@ static xp_long_t __str_to_long (const xp_char_t* name) 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; +} + diff --git a/ase/awk/sa.h b/ase/awk/sa.h index dd4f185a..598c0654 100644 --- a/ase/awk/sa.h +++ b/ase/awk/sa.h @@ -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_ @@ -31,6 +31,9 @@ #define xp_strcmp wcscmp #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_list va_list #define xp_va_end(pvar) va_end(pvar) diff --git a/ase/awk/tab.c b/ase/awk/tab.c new file mode 100644 index 00000000..c5e1ff33 --- /dev/null +++ b/ase/awk/tab.c @@ -0,0 +1,161 @@ +/* + * $Id: tab.c,v 1.1 2006-01-29 18:28:14 bacon Exp $ + */ + +#include +#ifndef __STAND_ALONE +#include +#include +#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; +} + diff --git a/ase/awk/tab.h b/ase/awk/tab.h new file mode 100644 index 00000000..4a756dd9 --- /dev/null +++ b/ase/awk/tab.h @@ -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 +#else +#include +#include +#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