*** empty log message ***
This commit is contained in:
parent
aaad83e199
commit
40c5fef59c
@ -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_
|
||||
@ -146,6 +146,8 @@ enum
|
||||
XP_AWK_EWHILE, /* keyword 'while' is expected */
|
||||
XP_AWK_EASSIGNMENT, /* assignment statement 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_EDUPEND, /* duplicate END */
|
||||
XP_AWK_EDUPFUNC, /* duplicate function name */
|
||||
@ -175,6 +177,8 @@ enum
|
||||
XP_AWK_ENOTSCALARIZABLE, /* not scalarizable variable */
|
||||
XP_AWK_EVALTYPE, /* wrong value type */
|
||||
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_EINTERNAL /* internal error */
|
||||
};
|
||||
|
@ -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_
|
||||
@ -177,6 +177,8 @@ struct xp_awk_run_t
|
||||
xp_size_t icache_count;
|
||||
xp_size_t rcache_count;
|
||||
|
||||
xp_awk_nde_blk_t* active_block;
|
||||
|
||||
struct
|
||||
{
|
||||
xp_char_t buf[1024];
|
||||
|
@ -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>
|
||||
@ -64,6 +64,8 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk)
|
||||
XP_T("keyword 'while' expected"),
|
||||
XP_T("assignment statement 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 END"),
|
||||
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("wrong value type"),
|
||||
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("internal error that should never have happened")
|
||||
};
|
||||
|
||||
|
@ -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>
|
||||
@ -102,12 +102,14 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
PARSE_BLOCK_GLOBAL,
|
||||
PARSE_BLOCK_FUNCTION,
|
||||
PARSE_BLOCK_BEGIN,
|
||||
PARSE_BLOCK_END,
|
||||
PARSE_BLOCK_PATTERN,
|
||||
PARSE_BLOCK_ACTION
|
||||
PARSE_GLOBAL,
|
||||
PARSE_FUNCTION,
|
||||
PARSE_BEGIN,
|
||||
PARSE_END,
|
||||
PARSE_BEGIN_BLOCK,
|
||||
PARSE_END_BLOCK,
|
||||
PARSE_PATTERN,
|
||||
PARSE_ACTION_BLOCK
|
||||
};
|
||||
|
||||
enum
|
||||
@ -139,7 +141,6 @@ static xp_awk_nde_t* __parse_end (xp_awk_t* awk);
|
||||
static xp_awk_chain_t* __parse_pattern_block (
|
||||
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_statement (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;
|
||||
|
||||
awk->parse.id.block = PARSE_BLOCK_GLOBAL;
|
||||
awk->parse.id.block = PARSE_GLOBAL;
|
||||
|
||||
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))
|
||||
{
|
||||
awk->parse.id.block = PARSE_BLOCK_FUNCTION;
|
||||
awk->parse.id.block = PARSE_FUNCTION;
|
||||
if (__parse_function (awk) == XP_NULL) return XP_NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
else if (MATCH(awk,TOKEN_LBRACE))
|
||||
{
|
||||
/* patternless block */
|
||||
awk->parse.id.block = PARSE_BLOCK_ACTION;
|
||||
awk->parse.id.block = PARSE_ACTION_BLOCK;
|
||||
if (__parse_pattern_block (
|
||||
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;
|
||||
|
||||
awk->parse.id.block = PARSE_BLOCK_PATTERN;
|
||||
awk->parse.id.block = PARSE_PATTERN;
|
||||
|
||||
ptn = __parse_expression (awk);
|
||||
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)))
|
||||
{
|
||||
/* blockless pattern */
|
||||
|
||||
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 (
|
||||
awk, ptn, xp_true) == XP_NULL)
|
||||
{
|
||||
@ -554,14 +580,13 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk)
|
||||
else
|
||||
{
|
||||
/* parse the action block */
|
||||
|
||||
if (!MATCH(awk,TOKEN_LBRACE))
|
||||
{
|
||||
xp_awk_clrpt (ptn);
|
||||
PANIC (awk, XP_AWK_ELBRACE);
|
||||
}
|
||||
|
||||
awk->parse.id.block = PARSE_BLOCK_ACTION;
|
||||
awk->parse.id.block = PARSE_ACTION_BLOCK;
|
||||
if (__parse_pattern_block (
|
||||
awk, ptn, xp_false) == XP_NULL)
|
||||
{
|
||||
@ -586,6 +611,7 @@ static xp_awk_nde_t* __parse_function (xp_awk_t* awk)
|
||||
int n;
|
||||
|
||||
/* eat up the keyword 'function' and get the next token */
|
||||
xp_assert (MATCH(awk,TOKEN_FUNCTION));
|
||||
if (__get_token(awk) == -1) return XP_NULL;
|
||||
|
||||
/* match a function name */
|
||||
@ -802,10 +828,10 @@ static xp_awk_nde_t* __parse_begin (xp_awk_t* awk)
|
||||
{
|
||||
xp_awk_nde_t* nde;
|
||||
|
||||
if (awk->tree.begin != XP_NULL) PANIC (awk, XP_AWK_EDUPBEGIN);
|
||||
if (__get_token(awk) == -1) return XP_NULL;
|
||||
xp_assert (MATCH(awk,TOKEN_LBRACE));
|
||||
|
||||
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;
|
||||
|
||||
awk->tree.begin = nde;
|
||||
@ -816,10 +842,10 @@ static xp_awk_nde_t* __parse_end (xp_awk_t* awk)
|
||||
{
|
||||
xp_awk_nde_t* nde;
|
||||
|
||||
if (awk->tree.end != XP_NULL) PANIC (awk, XP_AWK_EDUPEND);
|
||||
if (__get_token(awk) == -1) return XP_NULL;
|
||||
xp_assert (MATCH(awk,TOKEN_LBRACE));
|
||||
|
||||
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;
|
||||
|
||||
awk->tree.end = nde;
|
||||
@ -835,7 +861,9 @@ static xp_awk_chain_t* __parse_pattern_block (
|
||||
if (blockless) nde = XP_NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -865,13 +893,6 @@ static xp_awk_chain_t* __parse_pattern_block (
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (awk->parse.id.block == PARSE_BLOCK_BEGIN ||
|
||||
awk->parse.id.block == PARSE_BLOCK_END)
|
||||
if (awk->parse.id.block == PARSE_BEGIN_BLOCK ||
|
||||
awk->parse.id.block == PARSE_END_BLOCK)
|
||||
{
|
||||
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;
|
||||
|
||||
if (awk->parse.id.block == PARSE_BLOCK_BEGIN ||
|
||||
awk->parse.id.block == PARSE_BLOCK_END)
|
||||
if (awk->parse.id.block == PARSE_BEGIN_BLOCK ||
|
||||
awk->parse.id.block == PARSE_END_BLOCK)
|
||||
{
|
||||
PANIC (awk, XP_AWK_ENEXTFILE);
|
||||
}
|
||||
@ -3207,13 +3228,14 @@ static int __get_token (xp_awk_t* awk)
|
||||
}
|
||||
while (n == 1);
|
||||
|
||||
|
||||
xp_str_clear (&awk->token.name);
|
||||
awk->token.line = awk->lex.line;
|
||||
awk->token.column = awk->lex.column;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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>
|
||||
@ -458,6 +458,7 @@ static int __run_main (xp_awk_run_t* run)
|
||||
blk = (xp_awk_nde_blk_t*)run->awk->tree.begin;
|
||||
xp_assert (blk->type == XP_AWK_NDE_BLK);
|
||||
|
||||
run->active_block = blk;
|
||||
run->exit_level = EXIT_NONE;
|
||||
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;
|
||||
xp_assert (blk->type == XP_AWK_NDE_BLK);
|
||||
|
||||
run->active_block = blk;
|
||||
run->exit_level = EXIT_NONE;
|
||||
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)
|
||||
{
|
||||
/* just execute the block */
|
||||
run->active_block = blk;
|
||||
if (__run_block (run, blk) == -1) return -1;
|
||||
}
|
||||
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))
|
||||
{
|
||||
run->active_block = blk;
|
||||
if (__run_block (run, blk) == -1)
|
||||
{
|
||||
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))
|
||||
{
|
||||
run->active_block = blk;
|
||||
if (__run_block (run, blk) == -1)
|
||||
{
|
||||
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;
|
||||
xp_awk_refupval (v2);
|
||||
|
||||
run->active_block = blk;
|
||||
if (__run_block (run, blk) == -1)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
if (nde->val != XP_NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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";
|
||||
* what about awk -i in1,in2,in3 -o out1,out2,out3 ?
|
||||
*/
|
||||
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 (
|
||||
run, XP_AWK_IN_CONSOLE, XP_T(""), &errnum);
|
||||
if (n == -1)
|
||||
|
@ -10,4 +10,4 @@
|
||||
print /ABC/ ~ /DEF/;
|
||||
}
|
||||
|
||||
/zzz/
|
||||
/zzz/
|
||||
|
13
ase/test/awk/t26.awk
Normal file
13
ase/test/awk/t26.awk
Normal file
@ -0,0 +1,13 @@
|
||||
function call_next ()
|
||||
{
|
||||
next;
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
//call_next ();
|
||||
}
|
||||
|
||||
END {
|
||||
call_next ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user