*** empty log message ***

This commit is contained in:
hyung-hwan 2006-08-03 15:50:04 +00:00
parent aaad83e199
commit 40c5fef59c
7 changed files with 110 additions and 47 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.h,v 1.86 2006-08-03 09:53:42 bacon Exp $ * $Id: awk.h,v 1.87 2006-08-03 15:49:37 bacon Exp $
*/ */
#ifndef _XP_AWK_AWK_H_ #ifndef _XP_AWK_AWK_H_
@ -146,6 +146,8 @@ enum
XP_AWK_EWHILE, /* keyword 'while' is expected */ XP_AWK_EWHILE, /* keyword 'while' is expected */
XP_AWK_EASSIGNMENT, /* assignment statement expected */ XP_AWK_EASSIGNMENT, /* assignment statement expected */
XP_AWK_EIDENT, /* identifier expected */ XP_AWK_EIDENT, /* identifier expected */
XP_AWK_EBEGINBLOCK, /* BEGIN requires an action block */
XP_AWK_EENDBLOCK, /* END requires an action block */
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 */
@ -175,6 +177,8 @@ enum
XP_AWK_ENOTSCALARIZABLE, /* not scalarizable variable */ XP_AWK_ENOTSCALARIZABLE, /* not scalarizable variable */
XP_AWK_EVALTYPE, /* wrong value type */ XP_AWK_EVALTYPE, /* wrong value type */
XP_AWK_EPIPE, /* pipe operation error */ XP_AWK_EPIPE, /* pipe operation error */
XP_AWK_ENEXTCALL, /* next called from BEGIN or END */
XP_AWK_ENEXTFILECALL, /* nextfile called from BEGIN or END */
XP_AWK_EIOIMPL, /* wrong implementation of user io handler */ XP_AWK_EIOIMPL, /* wrong implementation of user io handler */
XP_AWK_EINTERNAL /* internal error */ XP_AWK_EINTERNAL /* internal error */
}; };

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk_i.h,v 1.37 2006-08-02 14:36:22 bacon Exp $ * $Id: awk_i.h,v 1.38 2006-08-03 15:49:37 bacon Exp $
*/ */
#ifndef _XP_AWK_AWKI_H_ #ifndef _XP_AWK_AWKI_H_
@ -177,6 +177,8 @@ struct xp_awk_run_t
xp_size_t icache_count; xp_size_t icache_count;
xp_size_t rcache_count; xp_size_t rcache_count;
xp_awk_nde_blk_t* active_block;
struct struct
{ {
xp_char_t buf[1024]; xp_char_t buf[1024];

View File

@ -1,5 +1,5 @@
/* /*
* $Id: err.c,v 1.30 2006-08-03 09:53:42 bacon Exp $ * $Id: err.c,v 1.31 2006-08-03 15:49:37 bacon Exp $
*/ */
#include <xp/awk/awk_i.h> #include <xp/awk/awk_i.h>
@ -64,6 +64,8 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk)
XP_T("keyword 'while' expected"), XP_T("keyword 'while' expected"),
XP_T("assignment statement expected"), XP_T("assignment statement expected"),
XP_T("identifier expected"), XP_T("identifier expected"),
XP_T("BEGIN requires an action block"),
XP_T("END requires an action block"),
XP_T("duplicate BEGIN"), XP_T("duplicate BEGIN"),
XP_T("duplicate END"), XP_T("duplicate END"),
XP_T("duplicate function name"), XP_T("duplicate function name"),
@ -92,8 +94,9 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk)
XP_T("variable not scalarizable"), XP_T("variable not scalarizable"),
XP_T("wrong value type"), XP_T("wrong value type"),
XP_T("pipe operation error"), XP_T("pipe operation error"),
XP_T("next cannot be called from the BEGIN or END block"),
XP_T("nextfile cannot be called from the BEGIN or END block"),
XP_T("wrong implementation of user-defined io handler"), XP_T("wrong implementation of user-defined io handler"),
XP_T("internal error that should never have happened") XP_T("internal error that should never have happened")
}; };

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parse.c,v 1.154 2006-08-03 09:58:15 bacon Exp $ * $Id: parse.c,v 1.155 2006-08-03 15:49:37 bacon Exp $
*/ */
#include <xp/awk/awk_i.h> #include <xp/awk/awk_i.h>
@ -102,12 +102,14 @@ enum
enum enum
{ {
PARSE_BLOCK_GLOBAL, PARSE_GLOBAL,
PARSE_BLOCK_FUNCTION, PARSE_FUNCTION,
PARSE_BLOCK_BEGIN, PARSE_BEGIN,
PARSE_BLOCK_END, PARSE_END,
PARSE_BLOCK_PATTERN, PARSE_BEGIN_BLOCK,
PARSE_BLOCK_ACTION PARSE_END_BLOCK,
PARSE_PATTERN,
PARSE_ACTION_BLOCK
}; };
enum enum
@ -139,7 +141,6 @@ static xp_awk_nde_t* __parse_end (xp_awk_t* awk);
static xp_awk_chain_t* __parse_pattern_block ( static xp_awk_chain_t* __parse_pattern_block (
xp_awk_t* awk, xp_awk_nde_t* ptn, xp_bool_t blockless); xp_awk_t* awk, xp_awk_nde_t* ptn, xp_bool_t blockless);
static xp_awk_nde_t* __parse_action (xp_awk_t* awk);
static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top); static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top);
static xp_awk_nde_t* __parse_statement (xp_awk_t* awk); static xp_awk_nde_t* __parse_statement (xp_awk_t* awk);
static xp_awk_nde_t* __parse_statement_nb (xp_awk_t* awk); static xp_awk_nde_t* __parse_statement_nb (xp_awk_t* awk);
@ -456,7 +457,7 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk)
{ {
xp_size_t nglobals; xp_size_t nglobals;
awk->parse.id.block = PARSE_BLOCK_GLOBAL; awk->parse.id.block = PARSE_GLOBAL;
if (__get_token(awk) == -1) return XP_NULL; if (__get_token(awk) == -1) return XP_NULL;
@ -471,23 +472,49 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk)
} }
else if (MATCH(awk,TOKEN_FUNCTION)) else if (MATCH(awk,TOKEN_FUNCTION))
{ {
awk->parse.id.block = PARSE_BLOCK_FUNCTION; awk->parse.id.block = PARSE_FUNCTION;
if (__parse_function (awk) == XP_NULL) return XP_NULL; if (__parse_function (awk) == XP_NULL) return XP_NULL;
} }
else if (MATCH(awk,TOKEN_BEGIN)) else if (MATCH(awk,TOKEN_BEGIN))
{ {
awk->parse.id.block = PARSE_BLOCK_BEGIN; awk->parse.id.block = PARSE_BEGIN;
if (__get_token(awk) == -1) return XP_NULL;
if ((awk->opt.parse & XP_AWK_BLOCKLESS) &&
(MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF)))
{
/* when the blockless pattern is supported
* BEGIN and { should be located on the same line */
PANIC (awk, XP_AWK_EBEGINBLOCK);
}
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
awk->parse.id.block = PARSE_BEGIN_BLOCK;
if (__parse_begin (awk) == XP_NULL) return XP_NULL; if (__parse_begin (awk) == XP_NULL) return XP_NULL;
} }
else if (MATCH(awk,TOKEN_END)) else if (MATCH(awk,TOKEN_END))
{ {
awk->parse.id.block = PARSE_BLOCK_END; awk->parse.id.block = PARSE_END;
if (__get_token(awk) == -1) return XP_NULL;
if ((awk->opt.parse & XP_AWK_BLOCKLESS) &&
(MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF)))
{
/* when the blockless pattern is supported
* END and { should be located on the same line */
PANIC (awk, XP_AWK_EENDBLOCK);
}
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
awk->parse.id.block = PARSE_END_BLOCK;
if (__parse_end (awk) == XP_NULL) return XP_NULL; if (__parse_end (awk) == XP_NULL) return XP_NULL;
} }
else if (MATCH(awk,TOKEN_LBRACE)) else if (MATCH(awk,TOKEN_LBRACE))
{ {
/* patternless block */ /* patternless block */
awk->parse.id.block = PARSE_BLOCK_ACTION; awk->parse.id.block = PARSE_ACTION_BLOCK;
if (__parse_pattern_block ( if (__parse_pattern_block (
awk, XP_NULL, xp_false) == XP_NULL) return XP_NULL; awk, XP_NULL, xp_false) == XP_NULL) return XP_NULL;
} }
@ -504,7 +531,7 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk)
*/ */
xp_awk_nde_t* ptn; xp_awk_nde_t* ptn;
awk->parse.id.block = PARSE_BLOCK_PATTERN; awk->parse.id.block = PARSE_PATTERN;
ptn = __parse_expression (awk); ptn = __parse_expression (awk);
if (ptn == XP_NULL) return XP_NULL; if (ptn == XP_NULL) return XP_NULL;
@ -531,10 +558,9 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk)
(MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF))) (MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF)))
{ {
/* blockless pattern */ /* blockless pattern */
xp_bool_t newline = MATCH(awk,TOKEN_NEWLINE); xp_bool_t newline = MATCH(awk,TOKEN_NEWLINE);
awk->parse.id.block = PARSE_BLOCK_ACTION; awk->parse.id.block = PARSE_ACTION_BLOCK;
if (__parse_pattern_block ( if (__parse_pattern_block (
awk, ptn, xp_true) == XP_NULL) awk, ptn, xp_true) == XP_NULL)
{ {
@ -554,14 +580,13 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk)
else else
{ {
/* parse the action block */ /* parse the action block */
if (!MATCH(awk,TOKEN_LBRACE)) if (!MATCH(awk,TOKEN_LBRACE))
{ {
xp_awk_clrpt (ptn); xp_awk_clrpt (ptn);
PANIC (awk, XP_AWK_ELBRACE); PANIC (awk, XP_AWK_ELBRACE);
} }
awk->parse.id.block = PARSE_BLOCK_ACTION; awk->parse.id.block = PARSE_ACTION_BLOCK;
if (__parse_pattern_block ( if (__parse_pattern_block (
awk, ptn, xp_false) == XP_NULL) awk, ptn, xp_false) == XP_NULL)
{ {
@ -586,6 +611,7 @@ static xp_awk_nde_t* __parse_function (xp_awk_t* awk)
int n; int n;
/* eat up the keyword 'function' and get the next token */ /* eat up the keyword 'function' and get the next token */
xp_assert (MATCH(awk,TOKEN_FUNCTION));
if (__get_token(awk) == -1) return XP_NULL; if (__get_token(awk) == -1) return XP_NULL;
/* match a function name */ /* match a function name */
@ -802,10 +828,10 @@ static xp_awk_nde_t* __parse_begin (xp_awk_t* awk)
{ {
xp_awk_nde_t* nde; xp_awk_nde_t* nde;
if (awk->tree.begin != XP_NULL) PANIC (awk, XP_AWK_EDUPBEGIN); xp_assert (MATCH(awk,TOKEN_LBRACE));
if (__get_token(awk) == -1) return XP_NULL;
nde = __parse_action (awk); if (__get_token(awk) == -1) return XP_NULL;
nde = __parse_block(awk, xp_true);
if (nde == XP_NULL) return XP_NULL; if (nde == XP_NULL) return XP_NULL;
awk->tree.begin = nde; awk->tree.begin = nde;
@ -816,10 +842,10 @@ static xp_awk_nde_t* __parse_end (xp_awk_t* awk)
{ {
xp_awk_nde_t* nde; xp_awk_nde_t* nde;
if (awk->tree.end != XP_NULL) PANIC (awk, XP_AWK_EDUPEND); xp_assert (MATCH(awk,TOKEN_LBRACE));
if (__get_token(awk) == -1) return XP_NULL;
nde = __parse_action (awk); if (__get_token(awk) == -1) return XP_NULL;
nde = __parse_block(awk, xp_true);
if (nde == XP_NULL) return XP_NULL; if (nde == XP_NULL) return XP_NULL;
awk->tree.end = nde; awk->tree.end = nde;
@ -835,7 +861,9 @@ static xp_awk_chain_t* __parse_pattern_block (
if (blockless) nde = XP_NULL; if (blockless) nde = XP_NULL;
else else
{ {
nde = __parse_action (awk); xp_assert (MATCH(awk,TOKEN_LBRACE));
if (__get_token(awk) == -1) return XP_NULL;
nde = __parse_block(awk, xp_true);
if (nde == XP_NULL) return XP_NULL; if (nde == XP_NULL) return XP_NULL;
} }
@ -865,13 +893,6 @@ static xp_awk_chain_t* __parse_pattern_block (
return chain; return chain;
} }
static xp_awk_nde_t* __parse_action (xp_awk_t* awk)
{
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
if (__get_token(awk) == -1) return XP_NULL;
return __parse_block(awk, xp_true);
}
static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top) static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top)
{ {
xp_awk_nde_t* head, * curr, * nde; xp_awk_nde_t* head, * curr, * nde;
@ -3160,8 +3181,8 @@ static xp_awk_nde_t* __parse_next (xp_awk_t* awk)
{ {
xp_awk_nde_next_t* nde; xp_awk_nde_next_t* nde;
if (awk->parse.id.block == PARSE_BLOCK_BEGIN || if (awk->parse.id.block == PARSE_BEGIN_BLOCK ||
awk->parse.id.block == PARSE_BLOCK_END) awk->parse.id.block == PARSE_END_BLOCK)
{ {
PANIC (awk, XP_AWK_ENEXT); PANIC (awk, XP_AWK_ENEXT);
} }
@ -3178,8 +3199,8 @@ static xp_awk_nde_t* __parse_nextfile (xp_awk_t* awk)
{ {
xp_awk_nde_nextfile_t* nde; xp_awk_nde_nextfile_t* nde;
if (awk->parse.id.block == PARSE_BLOCK_BEGIN || if (awk->parse.id.block == PARSE_BEGIN_BLOCK ||
awk->parse.id.block == PARSE_BLOCK_END) awk->parse.id.block == PARSE_END_BLOCK)
{ {
PANIC (awk, XP_AWK_ENEXTFILE); PANIC (awk, XP_AWK_ENEXTFILE);
} }
@ -3207,13 +3228,14 @@ static int __get_token (xp_awk_t* awk)
} }
while (n == 1); while (n == 1);
xp_str_clear (&awk->token.name); xp_str_clear (&awk->token.name);
awk->token.line = awk->lex.line; awk->token.line = awk->lex.line;
awk->token.column = awk->lex.column; awk->token.column = awk->lex.column;
if (line != 0 && (awk->opt.parse & XP_AWK_BLOCKLESS) && if (line != 0 && (awk->opt.parse & XP_AWK_BLOCKLESS) &&
awk->parse.id.block == PARSE_BLOCK_PATTERN) (awk->parse.id.block == PARSE_PATTERN ||
awk->parse.id.block == PARSE_BEGIN ||
awk->parse.id.block == PARSE_END))
{ {
if (awk->token.line != line) if (awk->token.line != line)
{ {

View File

@ -1,5 +1,5 @@
/* /*
* $Id: run.c,v 1.158 2006-08-03 09:53:45 bacon Exp $ * $Id: run.c,v 1.159 2006-08-03 15:49:37 bacon Exp $
*/ */
#include <xp/awk/awk_i.h> #include <xp/awk/awk_i.h>
@ -458,6 +458,7 @@ static int __run_main (xp_awk_run_t* run)
blk = (xp_awk_nde_blk_t*)run->awk->tree.begin; blk = (xp_awk_nde_blk_t*)run->awk->tree.begin;
xp_assert (blk->type == XP_AWK_NDE_BLK); xp_assert (blk->type == XP_AWK_NDE_BLK);
run->active_block = blk;
run->exit_level = EXIT_NONE; run->exit_level = EXIT_NONE;
if (__run_block (run, blk) == -1) n = -1; if (__run_block (run, blk) == -1) n = -1;
} }
@ -474,6 +475,7 @@ static int __run_main (xp_awk_run_t* run)
blk = (xp_awk_nde_blk_t*)run->awk->tree.end; blk = (xp_awk_nde_blk_t*)run->awk->tree.end;
xp_assert (blk->type == XP_AWK_NDE_BLK); xp_assert (blk->type == XP_AWK_NDE_BLK);
run->active_block = blk;
run->exit_level = EXIT_NONE; run->exit_level = EXIT_NONE;
if (__run_block (run, blk) == -1) n = -1; if (__run_block (run, blk) == -1) n = -1;
} }
@ -619,6 +621,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain)
if (ptn == XP_NULL) if (ptn == XP_NULL)
{ {
/* just execute the block */ /* just execute the block */
run->active_block = blk;
if (__run_block (run, blk) == -1) return -1; if (__run_block (run, blk) == -1) return -1;
} }
else else
@ -635,6 +638,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain)
if (xp_awk_valtobool(v1)) if (xp_awk_valtobool(v1))
{ {
run->active_block = blk;
if (__run_block (run, blk) == -1) if (__run_block (run, blk) == -1)
{ {
xp_awk_refdownval (run, v1); xp_awk_refdownval (run, v1);
@ -659,6 +663,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain)
if (xp_awk_valtobool(v1)) if (xp_awk_valtobool(v1))
{ {
run->active_block = blk;
if (__run_block (run, blk) == -1) if (__run_block (run, blk) == -1)
{ {
xp_awk_refdownval (run, v1); xp_awk_refdownval (run, v1);
@ -678,6 +683,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain)
if (v2 == XP_NULL) return -1; if (v2 == XP_NULL) return -1;
xp_awk_refupval (v2); xp_awk_refupval (v2);
run->active_block = blk;
if (__run_block (run, blk) == -1) if (__run_block (run, blk) == -1)
{ {
xp_awk_refdownval (run, v2); xp_awk_refdownval (run, v2);
@ -1164,7 +1170,6 @@ static int __run_continue (xp_awk_run_t* run, xp_awk_nde_continue_t* nde)
static int __run_return (xp_awk_run_t* run, xp_awk_nde_return_t* nde) static int __run_return (xp_awk_run_t* run, xp_awk_nde_return_t* nde)
{ {
if (nde->val != XP_NULL) if (nde->val != XP_NULL)
{ {
xp_awk_val_t* val; xp_awk_val_t* val;
@ -1212,19 +1217,33 @@ static int __run_exit (xp_awk_run_t* run, xp_awk_nde_exit_t* nde)
static int __run_next (xp_awk_run_t* run, xp_awk_nde_next_t* nde) static int __run_next (xp_awk_run_t* run, xp_awk_nde_next_t* nde)
{ {
/* TODO: trigger an error if "next" is called from BEGIN or END */ /* the parser checks if next has been called in the begin/end
* block or whereever inappropriate. so the runtime doesn't
* check that explicitly */
if (run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.begin ||
run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.end)
{
PANIC_I (run, XP_AWK_ENEXTCALL);
}
run->exit_level = EXIT_NEXT; run->exit_level = EXIT_NEXT;
return 0; return 0;
} }
static int __run_nextfile (xp_awk_run_t* run, xp_awk_nde_nextfile_t* nde) static int __run_nextfile (xp_awk_run_t* run, xp_awk_nde_nextfile_t* nde)
{ {
/* TODO: trigger an error if "nextfile" is called from BEGIN or END */
/* TODO: some extentions such as nextfile "in/out"; /* TODO: some extentions such as nextfile "in/out";
* what about awk -i in1,in2,in3 -o out1,out2,out3 ? * what about awk -i in1,in2,in3 -o out1,out2,out3 ?
*/ */
int n, errnum; int n, errnum;
if (run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.begin ||
run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.end)
{
PANIC_I (run, XP_AWK_ENEXTFILECALL);
}
n = xp_awk_nextextio_read ( n = xp_awk_nextextio_read (
run, XP_AWK_IN_CONSOLE, XP_T(""), &errnum); run, XP_AWK_IN_CONSOLE, XP_T(""), &errnum);
if (n == -1) if (n == -1)

13
ase/test/awk/t26.awk Normal file
View File

@ -0,0 +1,13 @@
function call_next ()
{
next;
}
BEGIN {
//call_next ();
}
END {
call_next ();
}