qse/ase/awk/parse.c

4371 lines
92 KiB
C
Raw Normal View History

2005-11-06 12:01:29 +00:00
/*
2006-10-22 12:39:30 +00:00
* $Id: parse.c,v 1.193 2006-10-22 12:39:29 bacon Exp $
2005-11-06 12:01:29 +00:00
*/
2006-10-22 11:34:53 +00:00
#include <sse/awk/awk_i.h>
2006-01-18 15:16:01 +00:00
2005-11-14 15:23:54 +00:00
enum
{
TOKEN_EOF,
2006-08-03 09:54:16 +00:00
TOKEN_NEWLINE,
2005-11-15 15:32:39 +00:00
2006-08-03 09:54:16 +00:00
/* TOKEN_XXX_ASSIGNs should in sync
* with __assop in __assign_to_opcode */
2005-11-14 15:23:54 +00:00
TOKEN_ASSIGN,
2006-04-11 15:44:30 +00:00
TOKEN_PLUS_ASSIGN,
TOKEN_MINUS_ASSIGN,
TOKEN_MUL_ASSIGN,
TOKEN_DIV_ASSIGN,
TOKEN_MOD_ASSIGN,
2006-10-22 12:39:30 +00:00
TOKEN_EXP_ASSIGN,
2006-04-11 15:44:30 +00:00
2005-11-14 15:23:54 +00:00
TOKEN_EQ,
TOKEN_NE,
2006-02-08 16:14:31 +00:00
TOKEN_LE,
TOKEN_LT,
TOKEN_GE,
TOKEN_GT,
2006-04-11 15:44:30 +00:00
TOKEN_NM, /* not match */
2005-11-14 15:23:54 +00:00
TOKEN_NOT,
TOKEN_PLUS,
2006-03-31 12:04:14 +00:00
TOKEN_PLUSPLUS,
2005-11-14 15:23:54 +00:00
TOKEN_MINUS,
2006-03-31 12:04:14 +00:00
TOKEN_MINUSMINUS,
2006-01-10 13:57:54 +00:00
TOKEN_MUL,
TOKEN_DIV,
TOKEN_MOD,
2006-03-29 16:39:04 +00:00
TOKEN_LOR,
TOKEN_LAND,
TOKEN_BOR,
2006-03-30 16:24:10 +00:00
TOKEN_BXOR,
2006-03-29 16:39:04 +00:00
TOKEN_BAND,
2006-06-18 10:53:06 +00:00
TOKEN_BORAND,
2006-04-12 03:54:12 +00:00
TOKEN_TILDE, /* used for unary bitwise-not and regex match */
2006-04-11 15:44:30 +00:00
TOKEN_RSHIFT,
TOKEN_LSHIFT,
2006-04-25 15:20:10 +00:00
TOKEN_IN,
2006-10-22 12:39:30 +00:00
TOKEN_EXP,
2005-11-14 15:23:54 +00:00
2005-11-15 15:32:39 +00:00
TOKEN_LPAREN,
TOKEN_RPAREN,
TOKEN_LBRACE,
TOKEN_RBRACE,
2006-01-19 16:28:21 +00:00
TOKEN_LBRACK,
TOKEN_RBRACK,
2005-11-15 15:32:39 +00:00
2006-01-25 14:50:57 +00:00
TOKEN_DOLLAR,
2006-01-13 14:16:56 +00:00
TOKEN_COMMA,
2006-04-16 04:31:38 +00:00
TOKEN_PERIOD,
2006-01-09 16:03:56 +00:00
TOKEN_SEMICOLON,
2006-04-10 15:52:07 +00:00
TOKEN_COLON,
TOKEN_QUEST,
2006-01-09 16:03:56 +00:00
2005-12-29 12:04:51 +00:00
TOKEN_BEGIN,
2005-11-14 15:23:54 +00:00
TOKEN_END,
2005-11-16 16:09:53 +00:00
TOKEN_FUNCTION,
2006-06-30 03:53:16 +00:00
TOKEN_LOCAL,
TOKEN_GLOBAL,
2005-11-16 16:09:53 +00:00
TOKEN_IF,
2006-01-14 16:09:58 +00:00
TOKEN_ELSE,
2005-11-16 16:09:53 +00:00
TOKEN_WHILE,
TOKEN_FOR,
2006-01-09 12:51:47 +00:00
TOKEN_DO,
TOKEN_BREAK,
2005-11-16 16:09:53 +00:00
TOKEN_CONTINUE,
2006-01-09 12:51:47 +00:00
TOKEN_RETURN,
TOKEN_EXIT,
TOKEN_NEXT,
2006-01-15 06:11:22 +00:00
TOKEN_NEXTFILE,
2006-07-01 16:07:06 +00:00
TOKEN_DELETE,
2006-06-13 08:35:53 +00:00
TOKEN_PRINT,
TOKEN_PRINTF,
2006-01-15 06:11:22 +00:00
2006-06-30 03:53:16 +00:00
TOKEN_GETLINE,
2006-06-29 15:40:30 +00:00
TOKEN_IDENT,
TOKEN_INT,
TOKEN_REAL,
TOKEN_STR,
TOKEN_REX,
2006-01-15 06:11:22 +00:00
__TOKEN_COUNT__
2005-11-14 15:23:54 +00:00
};
2006-08-01 15:57:43 +00:00
enum
{
2006-08-03 15:50:04 +00:00
PARSE_GLOBAL,
PARSE_FUNCTION,
PARSE_BEGIN,
PARSE_END,
PARSE_BEGIN_BLOCK,
PARSE_END_BLOCK,
PARSE_PATTERN,
PARSE_ACTION_BLOCK
2006-08-01 15:57:43 +00:00
};
enum
{
PARSE_LOOP_NONE,
PARSE_LOOP_WHILE,
PARSE_LOOP_FOR,
PARSE_LOOP_DOWHILE
};
2006-03-30 16:24:10 +00:00
typedef struct __binmap_t __binmap_t;
struct __binmap_t
{
int token;
int binop;
};
2006-01-29 18:28:14 +00:00
2006-10-22 11:34:53 +00:00
static sse_awk_t* __parse_progunit (sse_awk_t* awk);
static sse_awk_t* __collect_globals (sse_awk_t* awk);
static sse_awk_t* __add_builtin_globals (sse_awk_t* awk);
static sse_awk_t* __add_global (
sse_awk_t* awk, const sse_char_t* name, sse_size_t name_len);
static sse_awk_t* __collect_locals (sse_awk_t* awk, sse_size_t nlocals);
static sse_awk_nde_t* __parse_function (sse_awk_t* awk);
static sse_awk_nde_t* __parse_begin (sse_awk_t* awk);
static sse_awk_nde_t* __parse_end (sse_awk_t* awk);
static sse_awk_chain_t* __parse_pattern_block (
sse_awk_t* awk, sse_awk_nde_t* ptn, sse_bool_t blockless);
static sse_awk_nde_t* __parse_block (sse_awk_t* awk, sse_bool_t is_top);
static sse_awk_nde_t* __parse_statement (sse_awk_t* awk);
static sse_awk_nde_t* __parse_statement_nb (sse_awk_t* awk);
2006-10-22 12:39:30 +00:00
static sse_awk_nde_t* __parse_expression (sse_awk_t* awk);
2006-10-22 11:34:53 +00:00
2006-10-22 12:39:30 +00:00
static sse_awk_nde_t* __parse_basic_expr (sse_awk_t* awk);
2006-10-22 11:34:53 +00:00
2006-10-22 12:39:30 +00:00
static sse_awk_nde_t* __parse_binary_expr (
2006-10-22 11:34:53 +00:00
sse_awk_t* awk, const __binmap_t* binmap,
sse_awk_nde_t*(*next_level_func)(sse_awk_t*));
static sse_awk_nde_t* __parse_logical_or (sse_awk_t* awk);
static sse_awk_nde_t* __parse_logical_and (sse_awk_t* awk);
static sse_awk_nde_t* __parse_in (sse_awk_t* awk);
static sse_awk_nde_t* __parse_regex_match (sse_awk_t* awk);
static sse_awk_nde_t* __parse_bitwise_or (sse_awk_t* awk);
static sse_awk_nde_t* __parse_bitwise_or_with_extio (sse_awk_t* awk);
static sse_awk_nde_t* __parse_bitwise_xor (sse_awk_t* awk);
static sse_awk_nde_t* __parse_bitwise_and (sse_awk_t* awk);
static sse_awk_nde_t* __parse_equality (sse_awk_t* awk);
static sse_awk_nde_t* __parse_relational (sse_awk_t* awk);
static sse_awk_nde_t* __parse_shift (sse_awk_t* awk);
static sse_awk_nde_t* __parse_concat (sse_awk_t* awk);
static sse_awk_nde_t* __parse_additive (sse_awk_t* awk);
static sse_awk_nde_t* __parse_multiplicative (sse_awk_t* awk);
static sse_awk_nde_t* __parse_unary (sse_awk_t* awk);
static sse_awk_nde_t* __parse_increment (sse_awk_t* awk);
static sse_awk_nde_t* __parse_primary (sse_awk_t* awk);
static sse_awk_nde_t* __parse_primary_ident (sse_awk_t* awk);
static sse_awk_nde_t* __parse_hashidx (
sse_awk_t* awk, sse_char_t* name, sse_size_t name_len);
static sse_awk_nde_t* __parse_fncall (
sse_awk_t* awk, sse_char_t* name, sse_size_t name_len, sse_awk_bfn_t* bfn);
static sse_awk_nde_t* __parse_if (sse_awk_t* awk);
static sse_awk_nde_t* __parse_while (sse_awk_t* awk);
static sse_awk_nde_t* __parse_for (sse_awk_t* awk);
static sse_awk_nde_t* __parse_dowhile (sse_awk_t* awk);
static sse_awk_nde_t* __parse_break (sse_awk_t* awk);
static sse_awk_nde_t* __parse_continue (sse_awk_t* awk);
static sse_awk_nde_t* __parse_return (sse_awk_t* awk);
static sse_awk_nde_t* __parse_exit (sse_awk_t* awk);
static sse_awk_nde_t* __parse_next (sse_awk_t* awk);
static sse_awk_nde_t* __parse_nextfile (sse_awk_t* awk);
static sse_awk_nde_t* __parse_delete (sse_awk_t* awk);
static sse_awk_nde_t* __parse_print (sse_awk_t* awk);
static sse_awk_nde_t* __parse_printf (sse_awk_t* awk);
static int __get_token (sse_awk_t* awk);
static int __get_number (sse_awk_t* awk);
static int __get_charstr (sse_awk_t* awk);
static int __get_rexstr (sse_awk_t* awk);
2006-08-01 04:36:33 +00:00
static int __get_string (
2006-10-22 11:34:53 +00:00
sse_awk_t* awk, sse_char_t end_char,
sse_char_t esc_char, sse_bool_t keep_esc_char);
static int __get_char (sse_awk_t* awk);
static int __unget_char (sse_awk_t* awk, sse_cint_t c);
static int __skip_spaces (sse_awk_t* awk);
static int __skip_comment (sse_awk_t* awk);
2006-08-03 09:54:16 +00:00
static int __classify_ident (
2006-10-22 11:34:53 +00:00
sse_awk_t* awk, const sse_char_t* name, sse_size_t len);
static int __assign_to_opcode (sse_awk_t* awk);
static int __is_plain_var (sse_awk_nde_t* nde);
static int __is_var (sse_awk_nde_t* nde);
2005-11-15 15:32:39 +00:00
2006-10-22 11:34:53 +00:00
static int __deparse (sse_awk_t* awk);
static int __deparse_func (sse_awk_pair_t* pair, void* arg);
static int __put_char (sse_awk_t* awk, sse_char_t c);
static int __flush (sse_awk_t* awk);
2006-08-06 08:16:03 +00:00
2005-12-29 12:04:51 +00:00
struct __kwent
{
2006-10-22 11:34:53 +00:00
const sse_char_t* name;
sse_size_t name_len;
2005-11-15 15:32:39 +00:00
int type;
2006-02-04 19:31:51 +00:00
int valid; /* the entry is valid when this option is set */
2005-11-15 15:32:39 +00:00
};
static struct __kwent __kwtab[] =
{
2006-06-30 03:53:16 +00:00
/* operators */
2006-10-22 11:34:53 +00:00
{ SSE_T("in"), 2, TOKEN_IN, 0 },
2006-06-30 03:53:16 +00:00
/* top-level block starters */
2006-10-22 11:34:53 +00:00
{ SSE_T("BEGIN"), 5, TOKEN_BEGIN, 0 },
{ SSE_T("END"), 3, TOKEN_END, 0 },
{ SSE_T("function"), 8, TOKEN_FUNCTION, 0 },
{ SSE_T("func"), 4, TOKEN_FUNCTION, 0 },
2006-06-30 03:53:16 +00:00
/* keywords for variable declaration */
2006-10-22 12:39:30 +00:00
{ SSE_T("local"), 5, TOKEN_LOCAL, SSE_AWK_EXPLICIT },
{ SSE_T("global"), 6, TOKEN_GLOBAL, SSE_AWK_EXPLICIT },
2006-10-22 11:34:53 +00:00
2006-10-22 12:39:30 +00:00
/* keywords that start statements excluding expression statements */
2006-10-22 11:34:53 +00:00
{ SSE_T("if"), 2, TOKEN_IF, 0 },
{ SSE_T("else"), 4, TOKEN_ELSE, 0 },
{ SSE_T("while"), 5, TOKEN_WHILE, 0 },
{ SSE_T("for"), 3, TOKEN_FOR, 0 },
{ SSE_T("do"), 2, TOKEN_DO, 0 },
{ SSE_T("break"), 5, TOKEN_BREAK, 0 },
{ SSE_T("continue"), 8, TOKEN_CONTINUE, 0 },
{ SSE_T("return"), 6, TOKEN_RETURN, 0 },
{ SSE_T("exit"), 4, TOKEN_EXIT, 0 },
{ SSE_T("next"), 4, TOKEN_NEXT, 0 },
{ SSE_T("nextfile"), 8, TOKEN_NEXTFILE, 0 },
{ SSE_T("delete"), 6, TOKEN_DELETE, 0 },
{ SSE_T("print"), 5, TOKEN_PRINT, SSE_AWK_EXTIO },
{ SSE_T("printf"), 6, TOKEN_PRINTF, SSE_AWK_EXTIO },
2006-10-22 12:39:30 +00:00
/* keywords that can start an expression */
2006-10-22 11:34:53 +00:00
{ SSE_T("getline"), 7, TOKEN_GETLINE, SSE_AWK_EXTIO },
{ SSE_NULL, 0, 0 }
2005-11-15 15:32:39 +00:00
};
2005-11-14 15:23:54 +00:00
2006-07-10 14:28:46 +00:00
struct __bvent
2006-04-16 04:31:38 +00:00
{
2006-10-22 11:34:53 +00:00
const sse_char_t* name;
sse_size_t name_len;
2006-07-10 14:28:46 +00:00
int valid;
};
static struct __bvent __bvtab[] =
{
2006-10-22 11:34:53 +00:00
{ SSE_T("ARGC"), 4, 0 },
{ SSE_T("ARGV"), 4, 0 },
{ SSE_T("CONVFMT"), 7, 0 },
{ SSE_T("ENVIRON"), 7, 0 },
{ SSE_T("ERRNO"), 5, 0 },
{ SSE_T("FILENAME"), 8, 0 },
{ SSE_T("FNR"), 3, 0 },
{ SSE_T("FS"), 2, 0 },
{ SSE_T("IGNORECASE"), 10, 0 },
{ SSE_T("NF"), 2, 0 },
{ SSE_T("NR"), 2, 0 },
{ SSE_T("OFMT"), 4, 0 },
{ SSE_T("OFS"), 3, 0 },
{ SSE_T("ORS"), 3, 0 },
{ SSE_T("RS"), 2, 0 },
{ SSE_T("RT"), 2, 0 },
{ SSE_T("RSTART"), 6, 0 },
{ SSE_T("RLENGTH"), 7, 0 },
{ SSE_T("SUBSEP"), 6, 0 },
{ SSE_NULL, 0, 0 }
2006-04-16 04:31:38 +00:00
};
2005-11-14 15:23:54 +00:00
#define GET_CHAR(awk) \
do { if (__get_char(awk) == -1) return -1; } while(0)
2006-03-04 10:08:13 +00:00
#define GET_CHAR_TO(awk,c) \
2006-05-13 16:33:07 +00:00
do { \
if (__get_char(awk) == -1) return -1; \
2006-08-06 08:16:03 +00:00
c = (awk)->src.lex.curc; \
2006-05-13 16:33:07 +00:00
} while(0)
2005-11-14 15:23:54 +00:00
2006-06-27 10:53:04 +00:00
#define SET_TOKEN_TYPE(awk,code) \
do { \
(awk)->token.prev = (awk)->token.type; \
(awk)->token.type = (code); \
} while (0);
2005-11-14 15:23:54 +00:00
2006-03-04 10:08:13 +00:00
#define ADD_TOKEN_CHAR(awk,c) \
2006-05-13 16:33:07 +00:00
do { \
2006-10-22 11:34:53 +00:00
if (sse_awk_str_ccat(&(awk)->token.name,(c)) == (sse_size_t)-1) { \
(awk)->errnum = SSE_AWK_ENOMEM; return -1; \
2006-05-13 16:33:07 +00:00
} \
} while (0)
2005-11-14 15:23:54 +00:00
2006-03-04 10:08:13 +00:00
#define ADD_TOKEN_STR(awk,str) \
2006-05-13 16:33:07 +00:00
do { \
2006-10-22 11:34:53 +00:00
if (sse_awk_str_cat(&(awk)->token.name,(str)) == (sse_size_t)-1) { \
(awk)->errnum = SSE_AWK_ENOMEM; return -1; \
2006-05-13 16:33:07 +00:00
} \
} while (0)
2005-11-06 12:01:29 +00:00
2006-01-09 12:51:47 +00:00
#define MATCH(awk,token_type) ((awk)->token.type == (token_type))
2006-04-14 16:26:00 +00:00
#define PANIC(awk,code) \
2006-10-22 11:34:53 +00:00
do { (awk)->errnum = (code); return SSE_NULL; } while (0)
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
int sse_awk_parse (sse_awk_t* awk, sse_awk_srcios_t* srcios)
2005-11-06 12:01:29 +00:00
{
2006-10-13 10:18:39 +00:00
int n = 0, op;
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, srcios != SSE_NULL && srcios->in != SSE_NULL);
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_clear (awk);
2006-08-06 08:16:03 +00:00
awk->src.ios = srcios;
2006-10-13 10:18:39 +00:00
op = awk->src.ios->in (
2006-10-22 11:34:53 +00:00
SSE_AWK_IO_OPEN, awk->src.ios->custom_data, SSE_NULL, 0);
2006-10-13 10:18:39 +00:00
if (op == -1)
2006-04-30 15:50:38 +00:00
{
2006-10-13 10:18:39 +00:00
/* cannot open the source file.
* it doesn't even have to call CLOSE */
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ESRCINOPEN;
2006-04-30 15:50:38 +00:00
return -1;
}
2006-10-22 11:34:53 +00:00
if (__add_builtin_globals (awk) == SSE_NULL)
2006-08-06 08:16:03 +00:00
{
n = -1;
goto exit_parse;
}
2006-01-09 12:51:47 +00:00
2006-10-13 10:18:39 +00:00
/* the user io handler for the source code input returns 0 when
* it doesn't have any files to open. this is the same condition
* as the source code file is empty. so it will perform the parsing
* when op is positive, which means there are something to parse */
if (op > 0)
2006-03-04 10:08:13 +00:00
{
2006-10-13 10:18:39 +00:00
/* get the first character */
if (__get_char(awk) == -1)
{
n = -1;
goto exit_parse;
}
2006-01-22 15:11:17 +00:00
2006-10-13 10:18:39 +00:00
/* get the first token */
if (__get_token(awk) == -1)
2006-03-04 10:08:13 +00:00
{
2006-08-06 08:16:03 +00:00
n = -1;
goto exit_parse;
2006-01-22 15:11:17 +00:00
}
2006-10-13 10:18:39 +00:00
while (1)
{
if (MATCH(awk,TOKEN_EOF)) break;
if (MATCH(awk,TOKEN_NEWLINE)) continue;
2006-10-22 11:34:53 +00:00
if (__parse_progunit (awk) == SSE_NULL)
2006-10-13 10:18:39 +00:00
{
n = -1;
goto exit_parse;
}
}
2006-01-09 16:03:56 +00:00
}
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
awk->tree.nglobals = sse_awk_tab_getsize(&awk->parse.globals);
2006-01-30 14:34:47 +00:00
2006-10-22 11:34:53 +00:00
if (awk->src.ios->out != SSE_NULL)
2006-08-06 12:35:06 +00:00
{
if (__deparse (awk) == -1)
{
n = -1;
goto exit_parse;
}
}
2006-08-06 08:16:03 +00:00
exit_parse:
if (awk->src.ios->in (
2006-10-22 11:34:53 +00:00
SSE_AWK_IO_CLOSE, awk->src.ios->custom_data, SSE_NULL, 0) == -1)
2006-08-06 08:16:03 +00:00
{
2006-10-13 10:18:39 +00:00
if (n != -1)
2006-08-06 08:16:03 +00:00
{
/* this is to keep the earlier error above
* that might be more critical than this */
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ESRCINCLOSE;
2006-08-06 08:16:03 +00:00
n = -1;
}
}
2006-10-22 11:34:53 +00:00
if (n == -1) sse_awk_clear (awk);
2006-08-06 08:16:03 +00:00
return n;
2005-11-14 15:23:54 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_t* __parse_progunit (sse_awk_t* awk)
2005-11-14 15:23:54 +00:00
{
2005-11-21 15:46:47 +00:00
/*
pattern { action }
function name (parameter-list) { statement }
*/
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, awk->parse.depth.loop == 0);
2006-08-01 15:57:43 +00:00
2006-10-22 12:39:30 +00:00
if ((awk->option & SSE_AWK_EXPLICIT) && MATCH(awk,TOKEN_GLOBAL))
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_size_t nglobals;
2006-02-05 16:00:33 +00:00
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_GLOBAL;
2006-08-01 15:57:43 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-05 16:00:33 +00:00
2006-10-22 11:34:53 +00:00
nglobals = sse_awk_tab_getsize(&awk->parse.globals);
if (__collect_globals (awk) == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 16:00:33 +00:00
&awk->parse.globals, nglobals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.globals) - nglobals);
return SSE_NULL;
2006-02-05 16:00:33 +00:00
}
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_FUNCTION))
{
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_FUNCTION;
2006-10-22 11:34:53 +00:00
if (__parse_function (awk) == SSE_NULL) return SSE_NULL;
2006-01-22 15:11:17 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_BEGIN))
{
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_BEGIN;
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-08-03 15:50:04 +00:00
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_BLOCKLESS) &&
2006-08-03 15:50:04 +00:00
(MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF)))
{
/* when the blockless pattern is supported
* BEGIN and { should be located on the same line */
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EBEGINBLOCK);
2006-08-03 15:50:04 +00:00
}
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, SSE_AWK_ELBRACE);
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_BEGIN_BLOCK;
2006-10-22 11:34:53 +00:00
if (__parse_begin (awk) == SSE_NULL) return SSE_NULL;
2006-01-22 15:11:17 +00:00
}
2006-04-24 15:34:52 +00:00
else if (MATCH(awk,TOKEN_END))
2006-03-04 10:08:13 +00:00
{
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_END;
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-08-03 15:50:04 +00:00
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_BLOCKLESS) &&
2006-08-03 15:50:04 +00:00
(MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF)))
{
/* when the blockless pattern is supported
* END and { should be located on the same line */
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EENDBLOCK);
2006-08-03 15:50:04 +00:00
}
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, SSE_AWK_ELBRACE);
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_END_BLOCK;
2006-10-22 11:34:53 +00:00
if (__parse_end (awk) == SSE_NULL) return SSE_NULL;
2006-01-22 15:11:17 +00:00
}
2006-04-24 15:34:52 +00:00
else if (MATCH(awk,TOKEN_LBRACE))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
/* patternless block */
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_ACTION_BLOCK;
2006-08-03 05:05:48 +00:00
if (__parse_pattern_block (
2006-10-22 11:34:53 +00:00
awk, SSE_NULL, sse_false) == SSE_NULL) return SSE_NULL;
2005-11-15 15:59:23 +00:00
}
2006-04-24 15:34:52 +00:00
else
{
/*
2006-10-22 12:39:30 +00:00
expressions
/regular expression/
2006-04-24 15:34:52 +00:00
pattern && pattern
pattern || pattern
!pattern
(pattern)
pattern, pattern
*/
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* ptn;
2006-05-07 17:45:08 +00:00
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_PATTERN;
2006-08-01 15:57:43 +00:00
2006-10-22 12:39:30 +00:00
ptn = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (ptn == SSE_NULL) return SSE_NULL;
2006-05-07 17:45:08 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, ptn->next == SSE_NULL);
2006-05-07 17:45:08 +00:00
if (MATCH(awk,TOKEN_COMMA))
{
2006-08-03 09:54:16 +00:00
if (__get_token (awk) == -1)
2006-05-07 17:45:08 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, ptn);
return SSE_NULL;
2006-05-07 17:45:08 +00:00
}
2006-10-22 12:39:30 +00:00
ptn->next = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (ptn->next == SSE_NULL)
2006-05-07 17:45:08 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, ptn);
return SSE_NULL;
2006-05-07 17:45:08 +00:00
}
}
2006-04-24 15:34:52 +00:00
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_BLOCKLESS) &&
2006-08-03 09:54:16 +00:00
(MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF)))
2006-04-24 15:34:52 +00:00
{
2006-08-03 09:54:16 +00:00
/* blockless pattern */
2006-10-22 11:34:53 +00:00
sse_bool_t newline = MATCH(awk,TOKEN_NEWLINE);
2006-08-03 09:54:16 +00:00
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_ACTION_BLOCK;
2006-08-03 09:54:16 +00:00
if (__parse_pattern_block (
2006-10-22 11:34:53 +00:00
awk, ptn, sse_true) == SSE_NULL)
2006-05-07 17:45:08 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, ptn);
return SSE_NULL;
2006-05-07 17:45:08 +00:00
}
2006-08-03 09:54:16 +00:00
if (newline)
{
if (__get_token (awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, ptn);
return SSE_NULL;
2006-08-03 09:54:16 +00:00
}
}
2006-04-24 15:34:52 +00:00
}
else
{
2006-08-03 09:54:16 +00:00
/* parse the action block */
if (!MATCH(awk,TOKEN_LBRACE))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, ptn);
PANIC (awk, SSE_AWK_ELBRACE);
2006-08-03 09:54:16 +00:00
}
2006-08-03 15:50:04 +00:00
awk->parse.id.block = PARSE_ACTION_BLOCK;
2006-08-03 09:54:16 +00:00
if (__parse_pattern_block (
2006-10-22 11:34:53 +00:00
awk, ptn, sse_false) == SSE_NULL)
2006-08-03 09:54:16 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, ptn);
return SSE_NULL;
2006-08-03 09:54:16 +00:00
}
}
2006-04-24 15:34:52 +00:00
}
2005-11-15 15:59:23 +00:00
2006-02-05 16:00:33 +00:00
return awk;
2005-11-16 16:09:53 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_function (sse_awk_t* awk)
2005-11-16 16:09:53 +00:00
{
2006-10-22 11:34:53 +00:00
sse_char_t* name;
sse_char_t* name_dup;
sse_size_t name_len;
sse_awk_nde_t* body;
sse_awk_afn_t* afn;
sse_size_t nargs;
sse_awk_pair_t* pair;
2006-04-19 03:42:08 +00:00
int n;
2006-01-20 07:33:46 +00:00
2006-01-31 16:57:45 +00:00
/* eat up the keyword 'function' and get the next token */
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, MATCH(awk,TOKEN_FUNCTION));
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-22 15:11:17 +00:00
2006-01-31 16:57:45 +00:00
/* match a function name */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_IDENT))
{
2006-01-31 16:57:45 +00:00
/* cannot find a valid identifier for a function name */
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EIDENT);
2006-01-31 16:57:45 +00:00
}
2006-01-20 07:33:46 +00:00
2006-10-22 11:34:53 +00:00
name = SSE_AWK_STR_BUF(&awk->token.name);
name_len = SSE_AWK_STR_LEN(&awk->token.name);
if (sse_awk_map_get(&awk->tree.afns, name, name_len) != SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-01-31 16:57:45 +00:00
/* the function is defined previously */
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPFUNC);
2006-01-29 18:28:14 +00:00
}
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_UNIQUE)
2006-03-04 10:08:13 +00:00
{
2006-02-04 19:31:51 +00:00
/* check if it coincides to be a global variable name */
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_find (
&awk->parse.globals, 0, name, name_len) != (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPNAME);
2006-01-31 16:57:45 +00:00
}
}
2006-01-29 18:28:14 +00:00
2006-01-31 16:57:45 +00:00
/* clone the function name before it is overwritten */
2006-10-22 11:34:53 +00:00
name_dup = sse_awk_strxdup (awk, name, name_len);
if (name_dup == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-01-20 07:33:46 +00:00
2006-01-31 16:57:45 +00:00
/* get the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
2006-01-31 16:57:45 +00:00
/* match a left parenthesis */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_LPAREN))
{
2006-01-31 16:57:45 +00:00
/* a function name is not followed by a left parenthesis */
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
PANIC (awk, SSE_AWK_ELPAREN);
2006-01-20 07:33:46 +00:00
}
2006-01-31 16:57:45 +00:00
/* get the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
2006-01-31 16:57:45 +00:00
/* make sure that parameter table is empty */
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, sse_awk_tab_getsize(&awk->parse.params) == 0);
2006-01-31 16:57:45 +00:00
/* read parameter list */
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RPAREN))
{
2006-01-31 16:57:45 +00:00
/* no function parameter found. get the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
}
2006-03-04 10:08:13 +00:00
else
{
while (1)
{
2006-10-22 11:34:53 +00:00
sse_char_t* param;
sse_size_t param_len;
2006-02-04 19:31:51 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_IDENT))
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_EIDENT);
2006-01-20 07:33:46 +00:00
}
2006-10-22 11:34:53 +00:00
param = SSE_AWK_STR_BUF(&awk->token.name);
param_len = SSE_AWK_STR_LEN(&awk->token.name);
2006-02-04 19:31:51 +00:00
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_UNIQUE)
2006-03-04 10:08:13 +00:00
{
2006-02-04 19:31:51 +00:00
/* check if a parameter conflicts with a function */
2006-10-22 11:34:53 +00:00
if (sse_awk_strxncmp (name_dup, name_len, param, param_len) == 0 ||
sse_awk_map_get (&awk->tree.afns, param, param_len) != SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_EDUPNAME);
2006-02-04 19:31:51 +00:00
}
/* NOTE: the following is not a conflict
* global x;
* function f (x) { print x; }
* x in print x is a parameter
*/
}
2006-01-31 16:57:45 +00:00
2006-02-04 19:31:51 +00:00
/* check if a parameter conflicts with other parameters */
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_find (
2006-08-03 09:54:16 +00:00
&awk->parse.params,
2006-10-22 11:34:53 +00:00
0, param, param_len) != (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_EDUPPARAM);
2006-01-31 16:57:45 +00:00
}
2006-02-04 19:31:51 +00:00
/* push the parameter to the parameter list */
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_getsize (
&awk->parse.params) >= SSE_AWK_MAX_PARAMS)
2006-08-06 15:03:42 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_ETOOMANYPARAMS);
2006-08-06 15:03:42 +00:00
}
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_add (
2006-08-03 09:54:16 +00:00
&awk->parse.params,
2006-10-22 11:34:53 +00:00
param, param_len) == (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-31 16:57:45 +00:00
}
2006-01-29 18:28:14 +00:00
2006-08-03 06:06:27 +00:00
if (__get_token (awk) == -1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
if (MATCH(awk,TOKEN_RPAREN)) break;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_ECOMMA);
2006-01-20 07:33:46 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
}
2006-01-29 18:28:14 +00:00
/* check if the function body starts with a left brace */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_LBRACE))
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
PANIC (awk, SSE_AWK_ELBRACE);
2006-01-20 07:33:46 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
2006-01-29 18:28:14 +00:00
/* actual function body */
2006-10-22 11:34:53 +00:00
body = __parse_block (awk, sse_true);
if (body == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_tab_clear (&awk->parse.params);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
2006-07-01 16:07:06 +00:00
/* TODO: study furthur if the parameter names should be saved
* for some reasons */
2006-10-22 11:34:53 +00:00
nargs = sse_awk_tab_getsize (&awk->parse.params);
2006-01-31 16:57:45 +00:00
/* parameter names are not required anymore. clear them */
2006-10-22 11:34:53 +00:00
sse_awk_tab_clear (&awk->parse.params);
2006-01-31 16:57:45 +00:00
2006-10-22 11:34:53 +00:00
afn = (sse_awk_afn_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_afn_t));
if (afn == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_clrpt (awk, body);
return SSE_NULL;
2006-01-22 15:11:17 +00:00
}
2006-10-22 11:34:53 +00:00
afn->name = SSE_NULL; /* function name set below */
2006-08-06 08:16:03 +00:00
afn->name_len = 0;
2006-06-20 15:27:50 +00:00
afn->nargs = nargs;
afn->body = body;
2006-01-29 18:28:14 +00:00
2006-10-22 11:34:53 +00:00
n = sse_awk_map_putx (&awk->tree.afns, name_dup, name_len, afn, &pair);
2006-04-19 03:42:08 +00:00
if (n < 0)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
sse_awk_clrpt (awk, body);
SSE_AWK_FREE (awk, afn);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-29 18:28:14 +00:00
}
2006-01-22 15:11:17 +00:00
2006-04-19 03:42:08 +00:00
/* duplicate functions should have been detected previously */
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, n != 0);
2006-04-19 03:42:08 +00:00
2006-06-20 15:27:50 +00:00
afn->name = pair->key; /* do some trick to save a string. */
2006-08-06 08:16:03 +00:00
afn->name_len = pair->key_len;
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
2006-04-19 03:42:08 +00:00
2006-01-20 07:33:46 +00:00
return body;
2005-11-14 15:23:54 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_begin (sse_awk_t* awk)
2005-11-15 15:59:23 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, MATCH(awk,TOKEN_LBRACE));
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
nde = __parse_block(awk, sse_true);
if (nde == SSE_NULL) return SSE_NULL;
2006-01-22 15:11:17 +00:00
2006-03-03 11:45:45 +00:00
awk->tree.begin = nde;
return nde;
2006-01-22 15:11:17 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_end (sse_awk_t* awk)
2006-01-22 15:11:17 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
2006-01-22 15:11:17 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, MATCH(awk,TOKEN_LBRACE));
2005-11-15 15:59:23 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
nde = __parse_block(awk, sse_true);
if (nde == SSE_NULL) return SSE_NULL;
2006-01-09 12:51:47 +00:00
2006-03-03 11:45:45 +00:00
awk->tree.end = nde;
return nde;
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_chain_t* __parse_pattern_block (
sse_awk_t* awk, sse_awk_nde_t* ptn, sse_bool_t blockless)
2006-02-07 15:28:05 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
sse_awk_chain_t* chain;
2006-02-07 15:28:05 +00:00
2006-10-22 11:34:53 +00:00
if (blockless) nde = SSE_NULL;
2006-08-03 09:54:16 +00:00
else
{
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, MATCH(awk,TOKEN_LBRACE));
if (__get_token(awk) == -1) return SSE_NULL;
nde = __parse_block(awk, sse_true);
if (nde == SSE_NULL) return SSE_NULL;
2006-08-03 09:54:16 +00:00
}
2006-02-07 15:28:05 +00:00
2006-10-22 11:34:53 +00:00
chain = (sse_awk_chain_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_chain_t));
if (chain == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
PANIC (awk, SSE_AWK_ENOMEM);
2006-02-07 15:28:05 +00:00
}
2006-05-07 17:45:08 +00:00
chain->pattern = ptn;
2006-03-03 11:45:45 +00:00
chain->action = nde;
2006-10-22 11:34:53 +00:00
chain->next = SSE_NULL;
2006-02-07 15:28:05 +00:00
2006-10-22 11:34:53 +00:00
if (awk->tree.chain == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-02-07 15:28:05 +00:00
awk->tree.chain = chain;
awk->tree.chain_tail = chain;
2006-08-13 05:55:02 +00:00
awk->tree.chain_size++;
2006-02-07 15:28:05 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-07 15:28:05 +00:00
awk->tree.chain_tail->next = chain;
awk->tree.chain_tail = chain;
2006-08-13 05:55:02 +00:00
awk->tree.chain_size++;
2006-02-07 15:28:05 +00:00
}
2006-08-03 09:54:16 +00:00
return chain;
2006-02-07 15:28:05 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_block (sse_awk_t* awk, sse_bool_t is_top)
2006-01-09 12:51:47 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* head, * curr, * nde;
sse_awk_nde_blk_t* block;
sse_size_t nlocals, nlocals_max, tmp;
2006-01-25 16:11:43 +00:00
2006-10-22 11:34:53 +00:00
nlocals = sse_awk_tab_getsize(&awk->parse.locals);
2006-02-05 06:10:43 +00:00
nlocals_max = awk->parse.nlocals_max;
2006-02-04 19:31:51 +00:00
/* local variable declarations */
2006-10-22 12:39:30 +00:00
if (awk->option & SSE_AWK_EXPLICIT)
2006-03-04 10:08:13 +00:00
{
while (1)
{
2006-02-04 19:31:51 +00:00
if (!MATCH(awk,TOKEN_LOCAL)) break;
2006-01-09 12:51:47 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.locals) - nlocals);
return SSE_NULL;
2006-01-25 16:11:43 +00:00
}
2006-10-22 11:34:53 +00:00
if (__collect_locals(awk, nlocals) == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.locals) - nlocals);
return SSE_NULL;
2006-02-04 19:31:51 +00:00
}
2006-01-25 16:11:43 +00:00
}
}
/* block body */
2006-10-22 11:34:53 +00:00
head = SSE_NULL; curr = SSE_NULL;
2006-01-09 12:51:47 +00:00
2006-03-04 10:08:13 +00:00
while (1)
{
if (MATCH(awk,TOKEN_EOF))
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.locals) - nlocals);
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
PANIC (awk, SSE_AWK_EENDSRC);
2006-01-09 16:03:56 +00:00
}
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RBRACE))
{
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.locals) - nlocals);
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-01-09 12:51:47 +00:00
break;
}
2006-03-03 11:45:45 +00:00
nde = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.locals) - nlocals);
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-02-04 19:31:51 +00:00
/* remove unnecessary statements */
2006-10-22 11:34:53 +00:00
if (nde->type == SSE_AWK_NDE_NULL ||
(nde->type == SSE_AWK_NDE_BLK &&
((sse_awk_nde_blk_t*)nde)->body == SSE_NULL)) continue;
2006-02-04 19:31:51 +00:00
2006-10-22 11:34:53 +00:00
if (curr == SSE_NULL) head = nde;
2006-03-03 11:45:45 +00:00
else curr->next = nde;
curr = nde;
2006-01-14 14:09:52 +00:00
}
2006-01-10 13:57:54 +00:00
2006-10-22 11:34:53 +00:00
block = (sse_awk_nde_blk_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_blk_t));
if (block == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-10-22 11:34:53 +00:00
sse_awk_tab_getsize(&awk->parse.locals) - nlocals);
sse_awk_clrpt (awk, head);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
tmp = sse_awk_tab_getsize(&awk->parse.locals);
2006-02-05 06:10:43 +00:00
if (tmp > awk->parse.nlocals_max) awk->parse.nlocals_max = tmp;
2006-10-22 11:34:53 +00:00
sse_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals, tmp - nlocals);
2006-02-04 19:31:51 +00:00
2006-04-10 14:53:48 +00:00
/* adjust the number of locals for a block without any statements */
2006-10-22 11:34:53 +00:00
/* if (head == SSE_NULL) tmp = 0; */
2006-02-04 19:31:51 +00:00
2006-10-22 11:34:53 +00:00
block->type = SSE_AWK_NDE_BLK;
block->next = SSE_NULL;
2006-01-14 14:09:52 +00:00
block->body = head;
2006-04-05 15:56:20 +00:00
/* TODO: not only local variables but also nested blocks,
2006-02-05 16:12:50 +00:00
unless it is part of other constructs such as if, can be promoted
and merged to top-level block */
2006-02-05 06:10:43 +00:00
/* migrate all block-local variables to a top-level block */
2006-03-04 10:08:13 +00:00
if (is_top)
{
2006-02-04 19:31:51 +00:00
block->nlocals = awk->parse.nlocals_max - nlocals;
2006-02-05 06:10:43 +00:00
awk->parse.nlocals_max = nlocals_max;
2006-02-04 19:31:51 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-05 06:10:43 +00:00
/*block->nlocals = tmp - nlocals;*/
2006-02-04 19:31:51 +00:00
block->nlocals = 0;
}
2006-01-25 16:11:43 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)block;
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_t* __add_builtin_globals (sse_awk_t* awk)
2006-07-10 14:28:46 +00:00
{
struct __bvent* p = __bvtab;
2006-08-04 16:31:22 +00:00
awk->tree.nbglobals = 0;
2006-10-22 11:34:53 +00:00
while (p->name != SSE_NULL)
2006-07-10 14:28:46 +00:00
{
2006-08-03 05:05:48 +00:00
if (__add_global (awk,
2006-10-22 11:34:53 +00:00
p->name, p->name_len) == SSE_NULL) return SSE_NULL;
2006-08-04 16:31:22 +00:00
awk->tree.nbglobals++;
2006-07-10 14:28:46 +00:00
p++;
}
return awk;
}
2006-10-22 11:34:53 +00:00
static sse_awk_t* __add_global (
sse_awk_t* awk, const sse_char_t* name, sse_size_t len)
2006-07-10 14:28:46 +00:00
{
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_UNIQUE)
2006-07-10 14:28:46 +00:00
{
/* check if it conflict with a function name */
2006-10-22 11:34:53 +00:00
if (sse_awk_map_get(&awk->tree.afns, name, len) != SSE_NULL)
2006-07-10 14:28:46 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPNAME);
2006-07-10 14:28:46 +00:00
}
}
/* check if it conflicts with other global variable names */
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_find (&awk->parse.globals, 0, name, len) != (sse_size_t)-1)
2006-07-10 14:28:46 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPVAR);
2006-07-10 14:28:46 +00:00
}
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_getsize(&awk->parse.globals) >= SSE_AWK_MAX_GLOBALS)
2006-08-06 15:03:42 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ETOOMANYGLOBALS);
2006-08-06 15:03:42 +00:00
}
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_add (&awk->parse.globals, name, len) == (sse_size_t)-1)
2006-07-10 14:28:46 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ENOMEM);
2006-07-10 14:28:46 +00:00
}
return awk;
}
2006-10-22 11:34:53 +00:00
static sse_awk_t* __collect_globals (sse_awk_t* awk)
2006-02-05 16:00:33 +00:00
{
2006-03-04 10:08:13 +00:00
while (1)
{
if (!MATCH(awk,TOKEN_IDENT))
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EIDENT);
2006-02-05 16:00:33 +00:00
}
2006-08-03 05:05:48 +00:00
if (__add_global (awk,
2006-10-22 11:34:53 +00:00
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name)) == SSE_NULL) return SSE_NULL;
2006-02-05 16:00:33 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-05 16:00:33 +00:00
if (MATCH(awk,TOKEN_SEMICOLON)) break;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ECOMMA);
2006-02-05 16:00:33 +00:00
}
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-05 16:00:33 +00:00
}
/* skip a semicolon */
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-05 16:00:33 +00:00
return awk;
}
2006-10-22 11:34:53 +00:00
static sse_awk_t* __collect_locals (sse_awk_t* awk, sse_size_t nlocals)
2006-02-04 19:31:51 +00:00
{
2006-10-22 11:34:53 +00:00
sse_char_t* local;
sse_size_t local_len;
2006-02-04 19:31:51 +00:00
2006-03-04 10:08:13 +00:00
while (1)
{
if (!MATCH(awk,TOKEN_IDENT))
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EIDENT);
2006-02-04 19:31:51 +00:00
}
2006-10-22 11:34:53 +00:00
local = SSE_AWK_STR_BUF(&awk->token.name);
local_len = SSE_AWK_STR_LEN(&awk->token.name);
2006-02-04 19:31:51 +00:00
/* NOTE: it is not checked againt globals names */
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_UNIQUE)
2006-03-04 10:08:13 +00:00
{
2006-02-04 19:31:51 +00:00
/* check if it conflict with a function name */
2006-10-22 11:34:53 +00:00
if (sse_awk_map_get (
&awk->tree.afns, local, local_len) != SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPNAME);
2006-02-04 19:31:51 +00:00
}
}
/* check if it conflicts with a paremeter name */
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_find (&awk->parse.params,
0, local, local_len) != (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPNAME);
2006-02-04 19:31:51 +00:00
}
/* check if it conflicts with other local variable names */
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_find (&awk->parse.locals,
((awk->option & SSE_AWK_SHADING)? nlocals: 0),
local, local_len) != (sse_size_t)-1)
2006-04-05 15:56:20 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_EDUPVAR);
2006-02-04 19:31:51 +00:00
}
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_getsize(&awk->parse.locals) >= SSE_AWK_MAX_LOCALS)
2006-08-06 15:03:42 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ETOOMANYLOCALS);
2006-08-06 15:03:42 +00:00
}
2006-10-22 11:34:53 +00:00
if (sse_awk_tab_add (
&awk->parse.locals, local, local_len) == (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ENOMEM);
2006-02-04 19:31:51 +00:00
}
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-04 19:31:51 +00:00
if (MATCH(awk,TOKEN_SEMICOLON)) break;
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_COMMA)) PANIC (awk, SSE_AWK_ECOMMA);
2006-02-04 19:31:51 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-04 19:31:51 +00:00
}
/* skip a semicolon */
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-02-04 19:31:51 +00:00
return awk;
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_statement (sse_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
2006-01-10 13:57:54 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-18 16:12:59 +00:00
/* null statement */
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-01-18 16:12:59 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_NULL;
nde->next = SSE_NULL;
2006-01-18 16:12:59 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-01-18 16:12:59 +00:00
}
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_LBRACE))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
nde = __parse_block (awk, sse_false);
2006-01-14 16:09:58 +00:00
}
2006-10-15 15:46:14 +00:00
else
{
nde = __parse_statement_nb (awk);
awk->parse.nl_semicolon = 0;
}
2006-01-14 16:09:58 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-14 16:09:58 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_statement_nb (sse_awk_t* awk)
2006-01-14 16:09:58 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
2006-01-14 16:09:58 +00:00
2006-01-15 06:11:22 +00:00
/*
* keywords that don't require any terminating semicolon
*/
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_IF))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-18 16:12:59 +00:00
return __parse_if (awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_WHILE))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-08-01 15:57:43 +00:00
awk->parse.depth.loop++;
nde = __parse_while (awk);
awk->parse.depth.loop--;
return nde;
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_FOR))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-08-01 15:57:43 +00:00
awk->parse.depth.loop++;
nde = __parse_for (awk);
awk->parse.depth.loop--;
return nde;
2006-01-10 13:57:54 +00:00
}
2006-01-15 06:11:22 +00:00
2006-10-15 15:46:14 +00:00
awk->parse.nl_semicolon = 1;
2006-01-15 06:11:22 +00:00
/*
* keywords that require a terminating semicolon
*/
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_DO))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-08-01 15:57:43 +00:00
awk->parse.depth.loop++;
2006-03-03 11:45:45 +00:00
nde = __parse_dowhile (awk);
2006-08-01 15:57:43 +00:00
awk->parse.depth.loop--;
return nde;
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_BREAK))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_break (awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_CONTINUE))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_continue (awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_RETURN))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_return (awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_EXIT))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_exit (awk);
2006-01-10 13:57:54 +00:00
}
2006-07-01 16:07:06 +00:00
else if (MATCH(awk,TOKEN_NEXT))
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_next (awk);
2006-01-10 13:57:54 +00:00
}
2006-07-01 16:07:06 +00:00
else if (MATCH(awk,TOKEN_NEXTFILE))
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_nextfile (awk);
2006-01-10 13:57:54 +00:00
}
2006-07-01 16:07:06 +00:00
else if (MATCH(awk,TOKEN_DELETE))
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_delete (awk);
2006-01-10 13:57:54 +00:00
}
2006-06-13 08:35:53 +00:00
else if (MATCH(awk,TOKEN_PRINT))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_print (awk);
2006-06-13 08:35:53 +00:00
}
else if (MATCH(awk,TOKEN_PRINTF))
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-07-01 16:07:06 +00:00
nde = __parse_printf (awk);
2006-06-13 08:35:53 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-10-22 12:39:30 +00:00
nde = __parse_expression(awk);
2006-01-10 13:57:54 +00:00
}
2006-10-15 15:46:14 +00:00
awk->parse.nl_semicolon = 0;
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL) return SSE_NULL;
2006-01-13 14:16:56 +00:00
2006-01-11 11:52:17 +00:00
/* check if a statement ends with a semicolon */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON))
{
2006-10-22 11:34:53 +00:00
if (nde != SSE_NULL) sse_awk_clrpt (awk, nde);
PANIC (awk, SSE_AWK_ESEMICOLON);
2006-01-11 11:52:17 +00:00
}
/* eat up the semicolon and read in the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
if (nde != SSE_NULL) sse_awk_clrpt (awk, nde);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-01-11 11:52:17 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-10 13:57:54 +00:00
}
2006-10-22 12:39:30 +00:00
static sse_awk_nde_t* __parse_expression (sse_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* x, * y;
sse_awk_nde_ass_t* nde;
2006-04-14 16:26:00 +00:00
int opcode;
2006-01-20 07:33:46 +00:00
2006-10-22 12:39:30 +00:00
x = __parse_basic_expr (awk);
2006-10-22 11:34:53 +00:00
if (x == SSE_NULL) return SSE_NULL;
2006-01-20 07:33:46 +00:00
2006-04-14 16:26:00 +00:00
opcode = __assign_to_opcode (awk);
2006-06-29 14:38:01 +00:00
if (opcode == -1)
{
/* no assignment operator found. */
return x;
}
2006-04-14 16:26:00 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, x->next == SSE_NULL);
if (!__is_var(x) && x->type != SSE_AWK_NDE_POS)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, x);
PANIC (awk, SSE_AWK_EASSIGNMENT);
2006-01-20 07:33:46 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, x);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
2006-10-22 12:39:30 +00:00
y = __parse_basic_expr (awk);
2006-10-22 11:34:53 +00:00
if (y == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, x);
return SSE_NULL;
2006-01-20 07:33:46 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_ass_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_ass_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, x);
sse_awk_clrpt (awk, y);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-20 07:33:46 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_ASS;
nde->next = SSE_NULL;
2006-04-14 16:26:00 +00:00
nde->opcode = opcode;
2006-03-03 11:45:45 +00:00
nde->left = x;
nde->right = y;
2006-01-20 07:33:46 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-11 11:52:17 +00:00
}
2006-10-22 12:39:30 +00:00
static sse_awk_nde_t* __parse_basic_expr (sse_awk_t* awk)
2006-04-10 15:52:07 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde, * n1, * n2;
2006-04-10 15:52:07 +00:00
nde = __parse_logical_or (awk);
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL) return SSE_NULL;
2006-04-10 15:52:07 +00:00
if (MATCH(awk,TOKEN_QUEST))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_cnd_t* tmp;
2006-04-11 09:16:20 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-04-10 15:52:07 +00:00
2006-10-22 12:39:30 +00:00
n1 = __parse_basic_expr (awk);
2006-10-22 11:34:53 +00:00
if (n1 == SSE_NULL)
2006-04-10 15:52:07 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
return SSE_NULL;
2006-04-10 15:52:07 +00:00
}
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_COLON)) PANIC (awk, SSE_AWK_ECOLON);
if (__get_token(awk) == -1) return SSE_NULL;
2006-04-10 15:52:07 +00:00
2006-10-22 12:39:30 +00:00
n2 = __parse_basic_expr (awk);
2006-10-22 11:34:53 +00:00
if (n2 == SSE_NULL)
2006-04-10 15:52:07 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
sse_awk_clrpt (awk, n1);
return SSE_NULL;
2006-04-11 09:16:20 +00:00
}
2006-10-22 11:34:53 +00:00
tmp = (sse_awk_nde_cnd_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_cnd_t));
if (tmp == SSE_NULL)
2006-04-11 09:16:20 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
sse_awk_clrpt (awk, n1);
sse_awk_clrpt (awk, n2);
return SSE_NULL;
2006-04-10 15:52:07 +00:00
}
2006-10-22 11:34:53 +00:00
tmp->type = SSE_AWK_NDE_CND;
tmp->next = SSE_NULL;
2006-04-11 09:16:20 +00:00
tmp->test = nde;
tmp->left = n1;
tmp->right = n2;
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_t*)tmp;
2006-04-10 15:52:07 +00:00
}
return nde;
}
2006-10-22 12:39:30 +00:00
static sse_awk_nde_t* __parse_binary_expr (
2006-10-22 11:34:53 +00:00
sse_awk_t* awk, const __binmap_t* binmap,
sse_awk_nde_t*(*next_level_func)(sse_awk_t*))
2006-03-29 16:39:04 +00:00
{
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* nde;
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* left, * right;
2006-03-29 16:39:04 +00:00
int opcode;
2006-03-30 16:24:10 +00:00
left = next_level_func (awk);
2006-10-22 11:34:53 +00:00
if (left == SSE_NULL) return SSE_NULL;
2006-03-29 16:39:04 +00:00
while (1)
{
2006-03-30 16:24:10 +00:00
const __binmap_t* p = binmap;
2006-10-22 11:34:53 +00:00
sse_bool_t matched = sse_false;
2006-03-30 16:24:10 +00:00
while (p->token != TOKEN_EOF)
{
if (MATCH(awk,p->token))
{
opcode = p->binop;
2006-10-22 11:34:53 +00:00
matched = sse_true;
2006-03-30 16:24:10 +00:00
break;
}
p++;
}
if (!matched) break;
2006-03-29 16:39:04 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-03-29 16:39:04 +00:00
}
2006-03-30 16:24:10 +00:00
right = next_level_func (awk);
2006-10-22 11:34:53 +00:00
if (right == SSE_NULL)
2006-03-29 16:39:04 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-03-29 16:39:04 +00:00
}
2006-10-06 03:37:40 +00:00
#if 0
2006-03-31 16:35:37 +00:00
/* TODO: enhance constant folding. do it in a better way */
/* TODO: differentiate different types of numbers ... */
2006-10-22 11:34:53 +00:00
if (left->type == SSE_AWK_NDE_INT &&
right->type == SSE_AWK_NDE_INT)
2006-03-31 16:35:37 +00:00
{
2006-10-22 11:34:53 +00:00
sse_long_t l, r;
2006-03-29 16:39:04 +00:00
2006-10-22 11:34:53 +00:00
l = ((sse_awk_nde_int_t*)left)->val;
r = ((sse_awk_nde_int_t*)right)->val;
2006-03-31 16:35:37 +00:00
/* TODO: more operators */
2006-10-22 11:34:53 +00:00
if (opcode == SSE_AWK_BINOP_PLUS) l += r;
else if (opcode == SSE_AWK_BINOP_MINUS) l -= r;
else if (opcode == SSE_AWK_BINOP_MUL) l *= r;
else if (opcode == SSE_AWK_BINOP_DIV && r != 0) l /= r;
else if (opcode == SSE_AWK_BINOP_MOD && r != 0) l %= r;
2006-03-31 16:35:37 +00:00
else goto skip_constant_folding;
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, right);
((sse_awk_nde_int_t*)left)->val = l;
2006-09-28 14:21:45 +00:00
2006-10-22 11:34:53 +00:00
if (((sse_awk_nde_int_t*)left)->str != SSE_NULL)
2006-09-28 14:21:45 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, ((sse_awk_nde_int_t*)left)->str);
((sse_awk_nde_int_t*)left)->str = SSE_NULL;
((sse_awk_nde_int_t*)left)->len = 0;
2006-09-28 14:21:45 +00:00
}
2006-03-31 16:35:37 +00:00
continue;
}
2006-10-22 11:34:53 +00:00
else if (left->type == SSE_AWK_NDE_REAL &&
right->type == SSE_AWK_NDE_REAL)
2006-03-31 16:35:37 +00:00
{
2006-10-22 11:34:53 +00:00
sse_real_t l, r;
2006-04-05 15:56:20 +00:00
2006-10-22 11:34:53 +00:00
l = ((sse_awk_nde_real_t*)left)->val;
r = ((sse_awk_nde_real_t*)right)->val;
2006-04-05 15:56:20 +00:00
/* TODO: more operators */
2006-10-22 11:34:53 +00:00
if (opcode == SSE_AWK_BINOP_PLUS) l += r;
else if (opcode == SSE_AWK_BINOP_MINUS) l -= r;
else if (opcode == SSE_AWK_BINOP_MUL) l *= r;
else if (opcode == SSE_AWK_BINOP_DIV) l /= r;
2006-04-05 15:56:20 +00:00
else goto skip_constant_folding;
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, right);
((sse_awk_nde_real_t*)left)->val = l;
2006-09-28 14:21:45 +00:00
2006-10-22 11:34:53 +00:00
if (((sse_awk_nde_real_t*)left)->str != SSE_NULL)
2006-09-28 14:21:45 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, ((sse_awk_nde_real_t*)left)->str);
((sse_awk_nde_real_t*)left)->str = SSE_NULL;
((sse_awk_nde_real_t*)left)->len = 0;
2006-09-28 14:21:45 +00:00
}
2006-04-05 15:56:20 +00:00
continue;
2006-03-31 16:35:37 +00:00
}
2006-04-14 10:56:42 +00:00
/* TODO: enhance constant folding more... */
2006-03-31 16:35:37 +00:00
skip_constant_folding:
2006-10-06 03:37:40 +00:00
#endif
2006-10-22 12:39:30 +00:00
nde = (sse_awk_nde_exp_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_exp_t));
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-03-29 16:39:04 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, right);
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOMEM);
2006-03-29 16:39:04 +00:00
}
2006-10-22 12:39:30 +00:00
nde->type = SSE_AWK_NDE_EXP_BIN;
2006-10-22 11:34:53 +00:00
nde->next = SSE_NULL;
2006-03-29 16:39:04 +00:00
nde->opcode = opcode;
nde->left = left;
nde->right = right;
2006-10-22 11:34:53 +00:00
left = (sse_awk_nde_t*)nde;
2006-03-29 16:39:04 +00:00
}
return left;
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_logical_or (sse_awk_t* awk)
2006-03-30 16:24:10 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-29 16:39:04 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_LOR, SSE_AWK_BINOP_LOR },
2006-03-30 16:24:10 +00:00
{ TOKEN_EOF, 0 }
};
2006-03-29 16:39:04 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_logical_and);
2006-03-30 16:24:10 +00:00
}
2006-03-29 16:39:04 +00:00
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_logical_and (sse_awk_t* awk)
2006-03-30 16:24:10 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-30 16:24:10 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_LAND, SSE_AWK_BINOP_LAND },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 }
};
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_in);
2006-04-25 15:20:10 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_in (sse_awk_t* awk)
2006-04-25 15:20:10 +00:00
{
2006-04-26 15:53:17 +00:00
/*
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-04-25 15:20:10 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_IN, SSE_AWK_BINOP_IN },
2006-04-26 15:53:17 +00:00
{ TOKEN_EOF, 0 }
2006-04-25 15:20:10 +00:00
};
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_regex_match);
2006-04-26 15:53:17 +00:00
*/
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* nde;
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* left, * right;
2006-04-26 15:53:17 +00:00
left = __parse_regex_match (awk);
2006-10-22 11:34:53 +00:00
if (left == SSE_NULL) return SSE_NULL;
2006-04-26 15:53:17 +00:00
while (1)
{
if (!MATCH(awk,TOKEN_IN)) break;
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-04-26 15:53:17 +00:00
}
right = __parse_regex_match (awk);
2006-10-22 11:34:53 +00:00
if (right == SSE_NULL)
2006-04-26 15:53:17 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-04-26 15:53:17 +00:00
}
2006-04-29 12:41:47 +00:00
if (!__is_plain_var(right))
2006-04-26 15:53:17 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, right);
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOTVAR);
2006-04-26 15:53:17 +00:00
}
2006-10-22 12:39:30 +00:00
nde = (sse_awk_nde_exp_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_exp_t));
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-04-26 15:53:17 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, right);
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOMEM);
2006-04-26 15:53:17 +00:00
}
2006-10-22 12:39:30 +00:00
nde->type = SSE_AWK_NDE_EXP_BIN;
2006-10-22 11:34:53 +00:00
nde->next = SSE_NULL;
nde->opcode = SSE_AWK_BINOP_IN;
2006-04-26 15:53:17 +00:00
nde->left = left;
nde->right = right;
2006-10-22 11:34:53 +00:00
left = (sse_awk_nde_t*)nde;
2006-04-26 15:53:17 +00:00
}
return left;
2006-04-12 03:54:12 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_regex_match (sse_awk_t* awk)
2006-04-12 03:54:12 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-04-12 03:54:12 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_TILDE, SSE_AWK_BINOP_MA },
{ TOKEN_NM, SSE_AWK_BINOP_NM },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 },
2006-03-30 16:24:10 +00:00
};
2006-03-29 16:39:04 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_bitwise_or);
2006-03-29 16:39:04 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_bitwise_or (sse_awk_t* awk)
2006-03-29 16:39:04 +00:00
{
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_EXTIO)
2006-03-29 16:39:04 +00:00
{
2006-06-18 11:18:49 +00:00
return __parse_bitwise_or_with_extio (awk);
}
else
{
static __binmap_t map[] =
{
2006-10-22 11:34:53 +00:00
{ TOKEN_BOR, SSE_AWK_BINOP_BOR },
2006-06-18 11:18:49 +00:00
{ TOKEN_EOF, 0 }
};
2006-03-29 16:39:04 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_bitwise_xor);
2006-06-18 11:18:49 +00:00
}
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_bitwise_or_with_extio (sse_awk_t* awk)
2006-06-18 11:18:49 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* left, * right;
2006-06-07 14:59:52 +00:00
2006-06-11 15:26:12 +00:00
left = __parse_bitwise_xor (awk);
2006-10-22 11:34:53 +00:00
if (left == SSE_NULL) return SSE_NULL;
2006-06-07 14:59:52 +00:00
while (1)
{
2006-06-18 10:53:06 +00:00
int in_type;
if (MATCH(awk,TOKEN_BOR))
2006-10-22 11:34:53 +00:00
in_type = SSE_AWK_IN_PIPE;
2006-06-18 10:53:06 +00:00
else if (MATCH(awk,TOKEN_BORAND))
2006-10-22 11:34:53 +00:00
in_type = SSE_AWK_IN_COPROC;
2006-06-18 10:53:06 +00:00
else break;
2006-06-07 14:59:52 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-06-07 14:59:52 +00:00
}
if (MATCH(awk,TOKEN_GETLINE))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_getline_t* nde;
sse_awk_nde_t* var = SSE_NULL;
2006-06-12 15:11:02 +00:00
2006-06-11 15:26:12 +00:00
/* piped getline */
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-06-11 15:26:12 +00:00
}
2006-06-12 15:11:02 +00:00
/* TODO: is this correct? */
2006-06-11 15:26:12 +00:00
if (MATCH(awk,TOKEN_IDENT))
{
/* command | getline var */
2006-06-12 15:11:02 +00:00
var = __parse_primary (awk);
2006-10-22 11:34:53 +00:00
if (var == SSE_NULL)
2006-06-11 15:26:12 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-06-11 15:26:12 +00:00
}
}
2006-06-12 15:11:02 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_getline_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_getline_t));
if (nde == SSE_NULL)
2006-06-11 15:26:12 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOMEM);
2006-06-12 15:11:02 +00:00
}
2006-06-11 15:26:12 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_GETLINE;
nde->next = SSE_NULL;
2006-06-12 15:11:02 +00:00
nde->var = var;
2006-06-18 10:53:06 +00:00
nde->in_type = in_type;
2006-06-13 15:11:39 +00:00
nde->in = left;
2006-06-11 15:26:12 +00:00
2006-10-22 11:34:53 +00:00
left = (sse_awk_nde_t*)nde;
2006-06-07 14:59:52 +00:00
}
else
{
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* nde;
2006-06-12 15:11:02 +00:00
2006-10-22 11:34:53 +00:00
if (in_type == SSE_AWK_IN_COPROC)
2006-06-18 10:53:06 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_EGETLINE);
2006-06-18 10:53:06 +00:00
}
2006-06-11 15:26:12 +00:00
right = __parse_bitwise_xor (awk);
2006-10-22 11:34:53 +00:00
if (right == SSE_NULL)
2006-06-11 15:26:12 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-06-11 15:26:12 +00:00
}
2006-07-01 16:07:06 +00:00
/* TODO: do constant folding */
2006-06-11 15:26:12 +00:00
2006-10-22 12:39:30 +00:00
nde = (sse_awk_nde_exp_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_exp_t));
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-06-11 15:26:12 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, right);
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOMEM);
2006-06-11 15:26:12 +00:00
}
2006-10-22 12:39:30 +00:00
nde->type = SSE_AWK_NDE_EXP_BIN;
2006-10-22 11:34:53 +00:00
nde->next = SSE_NULL;
nde->opcode = SSE_AWK_BINOP_BOR;
2006-06-11 15:26:12 +00:00
nde->left = left;
nde->right = right;
2006-10-22 11:34:53 +00:00
left = (sse_awk_nde_t*)nde;
2006-06-07 14:59:52 +00:00
}
}
return left;
2006-03-29 16:39:04 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_bitwise_xor (sse_awk_t* awk)
2006-03-29 16:39:04 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-30 16:24:10 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_BXOR, SSE_AWK_BINOP_BXOR },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 }
2006-03-30 16:24:10 +00:00
};
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_bitwise_and);
2006-03-31 12:04:14 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_bitwise_and (sse_awk_t* awk)
2006-03-31 12:04:14 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-31 12:04:14 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_BAND, SSE_AWK_BINOP_BAND },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 }
2006-03-31 12:04:14 +00:00
};
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_equality);
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_equality (sse_awk_t* awk)
2006-02-08 16:14:31 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_EQ, SSE_AWK_BINOP_EQ },
{ TOKEN_NE, SSE_AWK_BINOP_NE },
2006-03-30 16:38:51 +00:00
{ TOKEN_EOF, 0 }
};
2006-02-08 16:14:31 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_relational);
2006-02-08 16:14:31 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_relational (sse_awk_t* awk)
2006-02-08 16:14:31 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_GT, SSE_AWK_BINOP_GT },
{ TOKEN_GE, SSE_AWK_BINOP_GE },
{ TOKEN_LT, SSE_AWK_BINOP_LT },
{ TOKEN_LE, SSE_AWK_BINOP_LE },
2006-03-31 12:04:14 +00:00
{ TOKEN_EOF, 0 }
};
2006-02-08 16:14:31 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_shift);
2006-02-08 16:14:31 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_shift (sse_awk_t* awk)
2006-02-08 16:14:31 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_LSHIFT, SSE_AWK_BINOP_LSHIFT },
{ TOKEN_RSHIFT, SSE_AWK_BINOP_RSHIFT },
2006-03-31 12:04:14 +00:00
{ TOKEN_EOF, 0 }
};
2006-02-08 16:14:31 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_concat);
2006-06-29 15:40:30 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_concat (sse_awk_t* awk)
2006-06-29 15:40:30 +00:00
{
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* nde;
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* left, * right;
2006-06-29 15:40:30 +00:00
left = __parse_additive (awk);
2006-10-22 11:34:53 +00:00
if (left == SSE_NULL) return SSE_NULL;
2006-06-29 15:40:30 +00:00
/* TODO: write a better code to do this....
2006-07-01 16:07:06 +00:00
* first of all, is the following check sufficient? */
2006-07-07 09:48:23 +00:00
while (MATCH(awk,TOKEN_LPAREN) ||
MATCH(awk,TOKEN_DOLLAR) ||
awk->token.type >= TOKEN_GETLINE)
2006-06-29 15:40:30 +00:00
{
right = __parse_additive (awk);
2006-10-22 11:34:53 +00:00
if (right == SSE_NULL)
2006-06-29 15:40:30 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
return SSE_NULL;
2006-06-29 15:40:30 +00:00
}
2006-10-22 12:39:30 +00:00
nde = (sse_awk_nde_exp_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_exp_t));
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-06-29 15:40:30 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
sse_awk_clrpt (awk, right);
PANIC (awk, SSE_AWK_ENOMEM);
2006-06-29 15:40:30 +00:00
}
2006-10-22 12:39:30 +00:00
nde->type = SSE_AWK_NDE_EXP_BIN;
2006-10-22 11:34:53 +00:00
nde->next = SSE_NULL;
nde->opcode = SSE_AWK_BINOP_CONCAT;
2006-06-29 15:40:30 +00:00
nde->left = left;
nde->right = right;
2006-10-22 11:34:53 +00:00
left = (sse_awk_nde_t*)nde;
2006-06-29 15:40:30 +00:00
}
return left;
2006-02-08 16:14:31 +00:00
}
2006-01-12 14:20:17 +00:00
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_additive (sse_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_PLUS, SSE_AWK_BINOP_PLUS },
{ TOKEN_MINUS, SSE_AWK_BINOP_MINUS },
2006-03-31 12:04:14 +00:00
{ TOKEN_EOF, 0 }
};
2006-01-10 13:57:54 +00:00
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_multiplicative);
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_multiplicative (sse_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-06-18 11:18:49 +00:00
static __binmap_t map[] =
2006-03-31 12:04:14 +00:00
{
2006-10-22 11:34:53 +00:00
{ TOKEN_MUL, SSE_AWK_BINOP_MUL },
{ TOKEN_DIV, SSE_AWK_BINOP_DIV },
{ TOKEN_MOD, SSE_AWK_BINOP_MOD },
2006-10-22 12:39:30 +00:00
{ TOKEN_EXP, SSE_AWK_BINOP_EXP },
2006-03-31 12:04:14 +00:00
{ TOKEN_EOF, 0 }
};
2006-10-22 12:39:30 +00:00
return __parse_binary_expr (awk, map, __parse_unary);
2006-04-02 12:45:04 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_unary (sse_awk_t* awk)
2006-04-02 12:45:04 +00:00
{
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* nde;
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* left;
2006-01-12 14:20:17 +00:00
int opcode;
2006-01-10 13:57:54 +00:00
2006-10-22 11:34:53 +00:00
opcode = (MATCH(awk,TOKEN_PLUS))? SSE_AWK_UNROP_PLUS:
(MATCH(awk,TOKEN_MINUS))? SSE_AWK_UNROP_MINUS:
(MATCH(awk,TOKEN_NOT))? SSE_AWK_UNROP_NOT:
(MATCH(awk,TOKEN_TILDE))? SSE_AWK_UNROP_BNOT: -1;
2006-04-02 12:45:04 +00:00
if (opcode == -1) return __parse_increment (awk);
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-04-02 12:45:04 +00:00
2006-01-25 14:50:57 +00:00
left = __parse_unary (awk);
2006-10-22 11:34:53 +00:00
if (left == SSE_NULL) return SSE_NULL;
2006-04-02 12:45:04 +00:00
2006-10-22 12:39:30 +00:00
nde = (sse_awk_nde_exp_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_exp_t));
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOMEM);
2006-04-02 12:45:04 +00:00
}
2006-01-10 13:57:54 +00:00
2006-10-22 12:39:30 +00:00
nde->type = SSE_AWK_NDE_EXP_UNR;
2006-10-22 11:34:53 +00:00
nde->next = SSE_NULL;
2006-04-02 12:45:04 +00:00
nde->opcode = opcode;
nde->left = left;
2006-10-22 11:34:53 +00:00
nde->right = SSE_NULL;
2006-01-14 14:09:52 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-04-02 12:45:04 +00:00
}
2006-01-12 14:20:17 +00:00
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_increment (sse_awk_t* awk)
2006-04-02 12:45:04 +00:00
{
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* nde;
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* left;
2006-04-02 12:45:04 +00:00
int type, opcode, opcode1, opcode2;
2006-01-25 04:27:01 +00:00
2006-10-22 11:34:53 +00:00
opcode1 = MATCH(awk,TOKEN_PLUSPLUS)? SSE_AWK_INCOP_PLUS:
MATCH(awk,TOKEN_MINUSMINUS)? SSE_AWK_INCOP_MINUS: -1;
2006-01-25 04:27:01 +00:00
2006-04-02 12:45:04 +00:00
if (opcode1 != -1)
{
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-04-02 12:45:04 +00:00
}
2006-01-25 04:27:01 +00:00
2006-04-02 12:45:04 +00:00
left = __parse_primary (awk);
2006-10-22 11:34:53 +00:00
if (left == SSE_NULL) return SSE_NULL;
2006-01-12 14:20:17 +00:00
2006-10-22 11:34:53 +00:00
opcode2 = MATCH(awk,TOKEN_PLUSPLUS)? SSE_AWK_INCOP_PLUS:
MATCH(awk,TOKEN_MINUSMINUS)? SSE_AWK_INCOP_MINUS: -1;
2006-01-12 14:20:17 +00:00
2006-04-02 12:45:04 +00:00
if (opcode1 != -1 && opcode2 != -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ELVALUE);
2006-04-02 12:45:04 +00:00
}
else if (opcode1 == -1 && opcode2 == -1)
{
return left;
2006-01-10 13:57:54 +00:00
}
2006-04-02 12:45:04 +00:00
else if (opcode1 != -1)
{
2006-10-22 12:39:30 +00:00
type = SSE_AWK_NDE_EXP_INCPRE;
2006-04-02 12:45:04 +00:00
opcode = opcode1;
}
else if (opcode2 != -1)
{
2006-10-22 12:39:30 +00:00
type = SSE_AWK_NDE_EXP_INCPST;
2006-04-02 12:45:04 +00:00
opcode = opcode2;
2006-01-10 13:57:54 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-04-02 12:45:04 +00:00
}
2006-01-10 13:57:54 +00:00
2006-10-22 12:39:30 +00:00
nde = (sse_awk_nde_exp_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_exp_t));
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-03-31 12:04:14 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, left);
PANIC (awk, SSE_AWK_ENOMEM);
2006-03-31 12:04:14 +00:00
}
2006-04-02 12:45:04 +00:00
nde->type = type;
2006-10-22 11:34:53 +00:00
nde->next = SSE_NULL;
2006-04-02 12:45:04 +00:00
nde->opcode = opcode;
nde->left = left;
2006-10-22 11:34:53 +00:00
nde->right = SSE_NULL;
2006-04-02 12:45:04 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_primary (sse_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-04-05 15:56:20 +00:00
if (MATCH(awk,TOKEN_IDENT))
{
2006-06-16 14:31:42 +00:00
return __parse_primary_ident (awk);
2006-01-13 14:16:56 +00:00
}
2006-03-31 12:04:14 +00:00
else if (MATCH(awk,TOKEN_INT))
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_int_t* nde;
2006-01-13 14:16:56 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_int_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_int_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-01-10 13:57:54 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_INT;
nde->next = SSE_NULL;
nde->val = sse_awk_strxtolong (awk,
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name), 0, SSE_NULL);
nde->str = sse_awk_strxdup (awk,
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name));
if (nde->str == SSE_NULL)
2006-09-11 14:29:23 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-09-11 14:29:23 +00:00
}
2006-10-22 11:34:53 +00:00
nde->len = SSE_AWK_STR_LEN(&awk->token.name);
2006-03-05 17:07:33 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk,
SSE_AWK_STR_LEN(&awk->token.name) ==
sse_awk_strlen(SSE_AWK_STR_BUF(&awk->token.name)));
2006-01-10 13:57:54 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde->str);
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-10 13:57:54 +00:00
}
2006-04-05 15:56:20 +00:00
else if (MATCH(awk,TOKEN_REAL))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_real_t* nde;
2006-03-31 12:04:14 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_real_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_real_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-03-31 12:04:14 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_REAL;
nde->next = SSE_NULL;
nde->val = sse_awk_strxtoreal (awk,
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name), SSE_NULL);
nde->str = sse_awk_strxdup (awk,
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name));
if (nde->str == SSE_NULL)
2006-09-11 14:29:23 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-09-11 14:29:23 +00:00
}
2006-10-22 11:34:53 +00:00
nde->len = SSE_AWK_STR_LEN(&awk->token.name);
2006-03-31 12:04:14 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk,
SSE_AWK_STR_LEN(&awk->token.name) ==
sse_awk_strlen(SSE_AWK_STR_BUF(&awk->token.name)));
2006-03-31 12:04:14 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde->str);
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-03-31 12:04:14 +00:00
}
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-03-05 17:07:33 +00:00
}
2006-04-07 04:23:11 +00:00
else if (MATCH(awk,TOKEN_STR))
2006-04-05 15:56:20 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_str_t* nde;
2006-01-13 11:25:52 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_str_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_str_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-01-10 13:57:54 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_STR;
nde->next = SSE_NULL;
nde->len = SSE_AWK_STR_LEN(&awk->token.name);
nde->buf = sse_awk_strxdup (
awk, SSE_AWK_STR_BUF(&awk->token.name), nde->len);
if (nde->buf == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-12 14:20:17 +00:00
}
2006-01-10 13:57:54 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde->buf);
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-10 13:57:54 +00:00
}
2006-04-24 11:22:42 +00:00
else if (MATCH(awk,TOKEN_DIV))
2006-04-10 15:52:07 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_rex_t* nde;
2006-07-26 16:43:35 +00:00
int errnum;
2006-04-24 11:22:42 +00:00
2006-10-22 12:39:30 +00:00
/* the regular expression is tokenized here because
2006-07-25 16:41:40 +00:00
* of the context-sensitivity of the slash symbol */
2006-04-24 11:22:42 +00:00
SET_TOKEN_TYPE (awk, TOKEN_REX);
2006-10-22 11:34:53 +00:00
sse_awk_str_clear (&awk->token.name);
if (__get_rexstr (awk) == -1) return SSE_NULL;
sse_awk_assert (awk, MATCH(awk,TOKEN_REX));
2006-04-24 11:22:42 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_rex_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_rex_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-04-24 11:22:42 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_REX;
nde->next = SSE_NULL;
2006-07-25 16:41:40 +00:00
2006-10-22 11:34:53 +00:00
nde->len = SSE_AWK_STR_LEN(&awk->token.name);
nde->buf = sse_awk_strxdup (
2006-09-01 03:44:51 +00:00
awk,
2006-10-22 11:34:53 +00:00
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name));
if (nde->buf == SSE_NULL)
2006-07-26 15:00:01 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
PANIC (awk, SSE_AWK_ENOMEM);
2006-07-26 15:00:01 +00:00
}
2006-10-22 11:34:53 +00:00
nde->code = sse_awk_buildrex (
2006-09-01 03:44:51 +00:00
awk,
2006-10-22 11:34:53 +00:00
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name),
2006-07-26 16:43:35 +00:00
&errnum);
2006-10-22 11:34:53 +00:00
if (nde->code == SSE_NULL)
2006-04-24 11:22:42 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde->buf);
SSE_AWK_FREE (awk, nde);
2006-08-10 16:02:15 +00:00
PANIC (awk, errnum);
2006-04-24 11:22:42 +00:00
}
2006-07-25 16:41:40 +00:00
2006-04-24 11:22:42 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde->buf);
SSE_AWK_FREE (awk, nde->code);
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-04-24 11:22:42 +00:00
}
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-04-10 15:52:07 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_DOLLAR))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_pos_t* nde;
sse_awk_nde_t* prim;
2006-01-25 14:50:57 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk)) return SSE_NULL;
2006-01-25 14:50:57 +00:00
prim = __parse_primary (awk);
2006-10-22 11:34:53 +00:00
if (prim == SSE_NULL) return SSE_NULL;
2006-01-25 14:50:57 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_pos_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_pos_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, prim);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-25 14:50:57 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_POS;
nde->next = SSE_NULL;
2006-03-05 17:07:33 +00:00
nde->val = prim;
2006-01-25 14:50:57 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-25 14:50:57 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_LPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
sse_awk_nde_t* last;
2006-01-10 13:57:54 +00:00
2006-01-14 14:09:52 +00:00
/* eat up the left parenthesis */
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-14 14:09:52 +00:00
2006-10-22 12:39:30 +00:00
/* parse the sub-expression inside the parentheses */
nde = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL) return SSE_NULL;
2006-01-10 13:57:54 +00:00
2006-10-22 12:39:30 +00:00
/* parse subsequent expressions separated by a comma, if any */
2006-04-26 15:53:17 +00:00
last = nde;
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, last->next == SSE_NULL);
2006-04-26 15:53:17 +00:00
while (MATCH(awk,TOKEN_COMMA))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* tmp;
2006-04-26 15:53:17 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
return SSE_NULL;
2006-04-26 15:53:17 +00:00
}
2006-10-22 12:39:30 +00:00
tmp = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (tmp == SSE_NULL)
2006-04-26 15:53:17 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
return SSE_NULL;
2006-04-26 15:53:17 +00:00
}
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, tmp->next == SSE_NULL);
2006-04-26 15:53:17 +00:00
last->next = tmp;
last = tmp;
}
2006-06-13 15:11:39 +00:00
/* ----------------- */
2006-04-26 15:53:17 +00:00
2006-01-14 14:09:52 +00:00
/* check for the closing parenthesis */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
PANIC (awk, SSE_AWK_ERPAREN);
2006-01-11 14:03:17 +00:00
}
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-01-11 14:03:17 +00:00
2006-06-13 15:11:39 +00:00
/* check if it is a chained node */
2006-10-22 11:34:53 +00:00
if (nde->next != SSE_NULL)
2006-04-26 15:53:17 +00:00
{
2006-10-22 12:39:30 +00:00
/* if so, it is a expression group */
/* (expr1, expr2, expr2) */
2006-06-13 15:11:39 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_nde_grp_t* tmp;
2006-04-26 15:53:17 +00:00
if (!MATCH(awk,TOKEN_IN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
PANIC (awk, SSE_AWK_EIN);
2006-04-26 15:53:17 +00:00
}
2006-10-22 11:34:53 +00:00
tmp = (sse_awk_nde_grp_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_grp_t));
if (tmp == SSE_NULL)
2006-04-26 15:53:17 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, nde);
PANIC (awk, SSE_AWK_ENOMEM);
2006-04-26 15:53:17 +00:00
}
2006-10-22 11:34:53 +00:00
tmp->type = SSE_AWK_NDE_GRP;
tmp->next = SSE_NULL;
2006-04-26 15:53:17 +00:00
tmp->body = nde;
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_t*)tmp;
2006-04-26 15:53:17 +00:00
}
2006-06-13 15:11:39 +00:00
/* ----------------- */
2006-04-26 15:53:17 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-10 13:57:54 +00:00
}
2006-06-13 15:11:39 +00:00
else if (MATCH(awk,TOKEN_GETLINE))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_getline_t* nde;
sse_awk_nde_t* var = SSE_NULL;
sse_awk_nde_t* in = SSE_NULL;
2006-06-13 15:11:39 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-06-13 15:11:39 +00:00
if (MATCH(awk,TOKEN_IDENT))
{
/* getline var */
var = __parse_primary (awk);
2006-10-22 11:34:53 +00:00
if (var == SSE_NULL) return SSE_NULL;
2006-06-13 15:11:39 +00:00
}
if (MATCH(awk, TOKEN_LT))
{
/* getline [var] < file */
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
if (var != SSE_NULL) sse_awk_clrpt (awk, var);
return SSE_NULL;
2006-06-13 15:11:39 +00:00
}
2006-07-30 15:53:42 +00:00
/* TODO: is this correct? */
2006-10-22 12:39:30 +00:00
/*in = __parse_expression (awk);*/
2006-07-30 15:53:42 +00:00
in = __parse_primary (awk);
2006-10-22 11:34:53 +00:00
if (in == SSE_NULL)
2006-06-13 15:11:39 +00:00
{
2006-10-22 11:34:53 +00:00
if (var != SSE_NULL) sse_awk_clrpt (awk, var);
return SSE_NULL;
2006-06-13 15:11:39 +00:00
}
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_getline_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_getline_t));
if (nde == SSE_NULL)
2006-06-13 15:11:39 +00:00
{
2006-10-22 11:34:53 +00:00
if (var != SSE_NULL) sse_awk_clrpt (awk, var);
if (in != SSE_NULL) sse_awk_clrpt (awk, in);
PANIC (awk, SSE_AWK_ENOMEM);
2006-06-13 15:11:39 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_GETLINE;
nde->next = SSE_NULL;
2006-06-13 15:11:39 +00:00
nde->var = var;
2006-10-22 11:34:53 +00:00
nde->in_type = (in == SSE_NULL)?
SSE_AWK_IN_CONSOLE: SSE_AWK_IN_FILE;
2006-06-13 15:11:39 +00:00
nde->in = in;
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-06-13 15:11:39 +00:00
}
2006-01-10 13:57:54 +00:00
2006-10-22 12:39:30 +00:00
/* valid expression introducer is expected */
PANIC (awk, SSE_AWK_EEXPRESSION);
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_primary_ident (sse_awk_t* awk)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
sse_char_t* name_dup;
sse_size_t name_len;
sse_awk_bfn_t* bfn;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, MATCH(awk,TOKEN_IDENT));
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
name_dup = sse_awk_strxdup (
2006-09-01 03:44:51 +00:00
awk,
2006-10-22 11:34:53 +00:00
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name));
if (name_dup == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
name_len = SSE_AWK_STR_LEN(&awk->token.name);
2006-06-16 14:31:42 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
return SSE_NULL;
2006-06-16 14:31:42 +00:00
}
2006-08-04 06:39:05 +00:00
/* check if name_dup is a built-in function name */
2006-10-22 11:34:53 +00:00
bfn = sse_awk_getbfn (awk, name_dup, name_len);
if (bfn != SSE_NULL)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
2006-06-16 14:31:42 +00:00
if (!MATCH(awk,TOKEN_LPAREN))
{
/* built-in function should be in the form
* of the function call */
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ELPAREN);
2006-06-16 14:31:42 +00:00
}
2006-10-22 11:34:53 +00:00
nde = __parse_fncall (awk, SSE_NULL, 0, bfn);
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
/* now we know that name_dup is a normal identifier. */
if (MATCH(awk,TOKEN_LBRACK))
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
2006-08-03 05:05:48 +00:00
nde = __parse_hashidx (awk, name_dup, name_len);
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL) SSE_AWK_FREE (awk, name_dup);
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
else if (MATCH(awk,TOKEN_LPAREN))
{
/* function call */
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* nde;
nde = __parse_fncall (awk, name_dup, name_len, SSE_NULL);
if (nde == SSE_NULL) SSE_AWK_FREE (awk, name_dup);
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
else
{
/* normal variable */
2006-10-22 11:34:53 +00:00
sse_awk_nde_var_t* nde;
sse_size_t idxa;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_var_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_var_t));
if (nde == SSE_NULL)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
PANIC (awk, SSE_AWK_ENOMEM);
2006-06-16 14:31:42 +00:00
}
/* search the parameter name list */
2006-10-22 11:34:53 +00:00
idxa = sse_awk_tab_find (
2006-08-03 06:06:27 +00:00
&awk->parse.params, 0, name_dup, name_len);
2006-10-22 11:34:53 +00:00
if (idxa != (sse_size_t)-1)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_ARG;
nde->next = SSE_NULL;
/*nde->id.name = SSE_NULL;*/
2006-06-16 14:31:42 +00:00
nde->id.name = name_dup;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-06-16 14:31:42 +00:00
nde->id.idxa = idxa;
2006-10-22 11:34:53 +00:00
nde->idx = SSE_NULL;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
/* search the local variable list */
2006-10-22 11:34:53 +00:00
idxa = sse_awk_tab_rrfind (
2006-08-03 06:06:27 +00:00
&awk->parse.locals, 0, name_dup, name_len);
2006-10-22 11:34:53 +00:00
if (idxa != (sse_size_t)-1)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_LOCAL;
nde->next = SSE_NULL;
/*nde->id.name = SSE_NULL;*/
2006-06-16 14:31:42 +00:00
nde->id.name = name_dup;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-06-16 14:31:42 +00:00
nde->id.idxa = idxa;
2006-10-22 11:34:53 +00:00
nde->idx = SSE_NULL;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
/* search the global variable list */
2006-10-22 11:34:53 +00:00
idxa = sse_awk_tab_rrfind (
2006-08-03 06:06:27 +00:00
&awk->parse.globals, 0, name_dup, name_len);
2006-10-22 11:34:53 +00:00
if (idxa != (sse_size_t)-1)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_GLOBAL;
nde->next = SSE_NULL;
/*nde->id.name = SSE_NULL;*/
2006-06-16 14:31:42 +00:00
nde->id.name = name_dup;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-06-16 14:31:42 +00:00
nde->id.idxa = idxa;
2006-10-22 11:34:53 +00:00
nde->idx = SSE_NULL;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_IMPLICIT)
2006-06-16 14:31:42 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_NAMED;
nde->next = SSE_NULL;
2006-06-16 14:31:42 +00:00
nde->id.name = name_dup;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-10-22 11:34:53 +00:00
nde->id.idxa = (sse_size_t)-1;
nde->idx = SSE_NULL;
2006-06-16 14:31:42 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-06-16 14:31:42 +00:00
}
/* undefined variable */
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, name_dup);
SSE_AWK_FREE (awk, nde);
PANIC (awk, SSE_AWK_EUNDEF);
2006-06-16 14:31:42 +00:00
}
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_hashidx (
sse_awk_t* awk, sse_char_t* name, sse_size_t name_len)
2006-01-19 16:28:21 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* idx, * tmp, * last;
sse_awk_nde_var_t* nde;
sse_size_t idxa;
2006-01-19 16:28:21 +00:00
2006-10-22 11:34:53 +00:00
idx = SSE_NULL;
last = SSE_NULL;
2006-05-02 15:06:01 +00:00
do
{
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
if (idx != SSE_NULL) sse_awk_clrpt (awk, idx);
return SSE_NULL;
2006-05-02 15:06:01 +00:00
}
2006-10-22 12:39:30 +00:00
tmp = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (tmp == SSE_NULL)
2006-05-02 15:06:01 +00:00
{
2006-10-22 11:34:53 +00:00
if (idx != SSE_NULL) sse_awk_clrpt (awk, idx);
return SSE_NULL;
2006-05-02 15:06:01 +00:00
}
2006-10-22 11:34:53 +00:00
if (idx == SSE_NULL)
2006-05-02 15:06:01 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, last == SSE_NULL);
2006-05-02 15:06:01 +00:00
idx = tmp; last = tmp;
}
else
{
2006-05-02 15:43:11 +00:00
last->next = tmp;
2006-05-02 15:06:01 +00:00
last = tmp;
}
}
while (MATCH(awk,TOKEN_COMMA));
2006-01-19 16:28:21 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, idx != SSE_NULL);
2006-01-19 16:28:21 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RBRACK))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, idx);
PANIC (awk, SSE_AWK_ERBRACK);
2006-01-19 16:28:21 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, idx);
return SSE_NULL;
2006-01-19 16:28:21 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_var_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_var_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, idx);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-19 16:28:21 +00:00
}
2006-01-31 16:57:45 +00:00
/* search the parameter name list */
2006-10-22 11:34:53 +00:00
idxa = sse_awk_tab_find (&awk->parse.params, 0, name, name_len);
if (idxa != (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_ARGIDX;
nde->next = SSE_NULL;
/*nde->id.name = SSE_NULL; */
2006-03-03 11:45:45 +00:00
nde->id.name = name;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-03-03 11:45:45 +00:00
nde->id.idxa = idxa;
nde->idx = idx;
2006-01-31 16:57:45 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-31 16:57:45 +00:00
}
2006-02-05 14:21:18 +00:00
/* search the local variable list */
2006-10-22 11:34:53 +00:00
idxa = sse_awk_tab_rrfind(&awk->parse.locals, 0, name, name_len);
if (idxa != (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_LOCALIDX;
nde->next = SSE_NULL;
/*nde->id.name = SSE_NULL; */
2006-03-03 11:45:45 +00:00
nde->id.name = name;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-03-03 11:45:45 +00:00
nde->id.idxa = idxa;
nde->idx = idx;
2006-01-19 16:28:21 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-02-05 14:21:18 +00:00
}
/* search the global variable list */
2006-10-22 11:34:53 +00:00
idxa = sse_awk_tab_rrfind(&awk->parse.globals, 0, name, name_len);
if (idxa != (sse_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_GLOBALIDX;
nde->next = SSE_NULL;
/*nde->id.name = SSE_NULL;*/
2006-03-03 11:45:45 +00:00
nde->id.name = name;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-03-03 11:45:45 +00:00
nde->id.idxa = idxa;
2006-04-16 16:30:59 +00:00
nde->idx = idx;
2006-02-05 16:00:33 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-02-05 16:00:33 +00:00
}
2006-02-05 14:21:18 +00:00
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_IMPLICIT)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_NAMEDIDX;
nde->next = SSE_NULL;
2006-03-03 11:45:45 +00:00
nde->id.name = name;
2006-08-03 05:05:48 +00:00
nde->id.name_len = name_len;
2006-10-22 11:34:53 +00:00
nde->id.idxa = (sse_size_t)-1;
2006-03-03 11:45:45 +00:00
nde->idx = idx;
2006-02-05 16:00:33 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-02-05 14:21:18 +00:00
}
/* undefined variable */
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, idx);
SSE_AWK_FREE (awk, nde);
PANIC (awk, SSE_AWK_EUNDEF);
2006-01-19 16:28:21 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_fncall (
sse_awk_t* awk, sse_char_t* name, sse_size_t name_len, sse_awk_bfn_t* bfn)
2006-01-13 14:16:56 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* head, * curr, * nde;
sse_awk_nde_call_t* call;
sse_size_t nargs;
2006-01-13 14:16:56 +00:00
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-14 14:09:52 +00:00
2006-10-22 11:34:53 +00:00
head = curr = SSE_NULL;
2006-04-18 16:04:59 +00:00
nargs = 0;
2006-01-13 14:16:56 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RPAREN))
{
2006-01-18 16:12:59 +00:00
/* no parameters to the function call */
2006-10-22 11:34:53 +00:00
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-18 16:12:59 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-08-13 16:05:04 +00:00
/* parse function parameters */
2006-03-04 10:08:13 +00:00
while (1)
{
2006-10-22 12:39:30 +00:00
nde = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
return SSE_NULL;
2006-01-14 16:09:58 +00:00
}
2006-10-22 11:34:53 +00:00
if (head == SSE_NULL) head = nde;
2006-03-03 11:45:45 +00:00
else curr->next = nde;
curr = nde;
2006-01-14 16:09:58 +00:00
2006-04-18 16:04:59 +00:00
nargs++;
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RPAREN))
{
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
if (head != SSE_NULL)
sse_awk_clrpt (awk, head);
return SSE_NULL;
2006-01-14 16:09:58 +00:00
}
break;
}
2006-01-13 14:16:56 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-10-22 11:34:53 +00:00
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
PANIC (awk, SSE_AWK_ECOMMA);
2006-01-14 16:09:58 +00:00
}
2006-01-13 14:16:56 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-01-13 14:16:56 +00:00
}
2006-01-14 16:09:58 +00:00
}
2006-10-22 11:34:53 +00:00
call = (sse_awk_nde_call_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_call_t));
if (call == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
if (head != SSE_NULL) sse_awk_clrpt (awk, head);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-14 16:09:58 +00:00
}
2006-10-22 11:34:53 +00:00
if (bfn != SSE_NULL)
2006-06-19 15:43:27 +00:00
{
2006-10-22 11:34:53 +00:00
call->type = SSE_AWK_NDE_BFN;
call->next = SSE_NULL;
2006-07-14 04:19:22 +00:00
/*call->what.bfn = bfn; */
2006-07-14 05:21:30 +00:00
call->what.bfn.name = bfn->name;
2006-08-03 05:05:48 +00:00
call->what.bfn.name_len = bfn->name_len;
2006-07-14 04:19:22 +00:00
call->what.bfn.min_args = bfn->min_args;
call->what.bfn.max_args = bfn->max_args;
2006-08-13 16:05:04 +00:00
call->what.bfn.arg_spec = bfn->arg_spec;
2006-07-14 05:21:30 +00:00
call->what.bfn.handler = bfn->handler;
2006-07-14 04:19:22 +00:00
2006-06-19 15:43:27 +00:00
call->args = head;
call->nargs = nargs;
}
else
{
2006-10-22 11:34:53 +00:00
call->type = SSE_AWK_NDE_AFN;
call->next = SSE_NULL;
2006-08-03 05:05:48 +00:00
call->what.afn.name = name;
call->what.afn.name_len = name_len;
2006-06-19 15:43:27 +00:00
call->args = head;
call->nargs = nargs;
}
2006-01-14 16:09:58 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)call;
2006-01-14 16:09:58 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_if (sse_awk_t* awk)
2006-01-14 16:09:58 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* test;
sse_awk_nde_t* then_part;
sse_awk_nde_t* else_part;
sse_awk_nde_if_t* nde;
2006-01-14 16:09:58 +00:00
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_LPAREN)) PANIC (awk, SSE_AWK_ELPAREN);
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-13 14:16:56 +00:00
2006-10-22 12:39:30 +00:00
test = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (test == SSE_NULL) return SSE_NULL;
2006-01-14 16:09:58 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ERPAREN);
2006-01-14 16:09:58 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-14 16:09:58 +00:00
}
then_part = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (then_part == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-14 16:09:58 +00:00
}
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_ELSE))
{
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, then_part);
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-14 16:09:58 +00:00
}
else_part = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (else_part == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, then_part);
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-14 14:09:52 +00:00
}
2006-01-13 14:16:56 +00:00
}
2006-10-22 11:34:53 +00:00
else else_part = SSE_NULL;
2006-01-13 14:16:56 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_if_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_if_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, else_part);
sse_awk_clrpt (awk, then_part);
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-14 16:09:58 +00:00
}
2006-01-14 14:09:52 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_IF;
nde->next = SSE_NULL;
2006-03-03 11:45:45 +00:00
nde->test = test;
nde->then_part = then_part;
nde->else_part = else_part;
2006-01-14 14:09:52 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-13 14:16:56 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_while (sse_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* test, * body;
sse_awk_nde_while_t* nde;
2006-01-18 16:12:59 +00:00
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_LPAREN)) PANIC (awk, SSE_AWK_ELPAREN);
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-18 16:12:59 +00:00
2006-10-22 12:39:30 +00:00
test = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (test == SSE_NULL) return SSE_NULL;
2006-01-18 16:12:59 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ERPAREN);
2006-01-18 16:12:59 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-18 16:12:59 +00:00
}
body = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (body == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-18 16:12:59 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_while_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_while_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-18 16:12:59 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_WHILE;
nde->next = SSE_NULL;
2006-03-03 11:45:45 +00:00
nde->test = test;
nde->body = body;
2006-01-18 16:12:59 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_for (sse_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* init, * test, * incr, * body;
sse_awk_nde_for_t* nde;
sse_awk_nde_foreach_t* nde2;
2006-01-25 04:41:56 +00:00
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_LPAREN)) PANIC (awk, SSE_AWK_ELPAREN);
if (__get_token(awk) == -1) return SSE_NULL;
2006-01-19 13:28:29 +00:00
2006-10-22 11:34:53 +00:00
if (MATCH(awk,TOKEN_SEMICOLON)) init = SSE_NULL;
2006-03-04 10:08:13 +00:00
else
{
2006-04-29 12:41:47 +00:00
/* this line is very ugly. it checks the entire next
2006-10-22 12:39:30 +00:00
* expression or the first element in the expression
2006-04-29 12:41:47 +00:00
* is wrapped by a parenthesis */
int no_foreach = MATCH(awk,TOKEN_LPAREN);
2006-10-22 12:39:30 +00:00
init = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (init == SSE_NULL) return SSE_NULL;
2006-01-19 13:28:29 +00:00
2006-10-22 12:39:30 +00:00
if (!no_foreach && init->type == SSE_AWK_NDE_EXP_BIN &&
((sse_awk_nde_exp_t*)init)->opcode == SSE_AWK_BINOP_IN &&
__is_plain_var(((sse_awk_nde_exp_t*)init)->left))
2006-04-29 12:09:29 +00:00
{
/* switch to foreach */
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
PANIC (awk, SSE_AWK_ERPAREN);
2006-04-29 12:09:29 +00:00
}
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
return SSE_NULL;
2006-04-29 12:09:29 +00:00
}
body = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (body == SSE_NULL)
2006-04-29 12:09:29 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
return SSE_NULL;
2006-04-29 12:09:29 +00:00
}
2006-10-22 11:34:53 +00:00
nde2 = (sse_awk_nde_foreach_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_foreach_t));
if (nde2 == SSE_NULL)
2006-04-29 12:09:29 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, body);
PANIC (awk, SSE_AWK_ENOMEM);
2006-04-29 12:09:29 +00:00
}
2006-10-22 11:34:53 +00:00
nde2->type = SSE_AWK_NDE_FOREACH;
nde2->next = SSE_NULL;
2006-04-29 12:09:29 +00:00
nde2->test = init;
nde2->body = body;
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde2;
2006-04-29 12:09:29 +00:00
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
PANIC (awk, SSE_AWK_ESEMICOLON);
2006-01-19 13:28:29 +00:00
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
return SSE_NULL;
2006-01-19 13:28:29 +00:00
}
2006-10-22 11:34:53 +00:00
if (MATCH(awk,TOKEN_SEMICOLON)) test = SSE_NULL;
2006-03-04 10:08:13 +00:00
else
{
2006-10-22 12:39:30 +00:00
test = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (test == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
return SSE_NULL;
2006-01-19 13:28:29 +00:00
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ESEMICOLON);
2006-01-19 13:28:29 +00:00
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-19 13:28:29 +00:00
}
2006-10-22 11:34:53 +00:00
if (MATCH(awk,TOKEN_RPAREN)) incr = SSE_NULL;
2006-03-04 10:08:13 +00:00
else
{
2006-10-22 12:39:30 +00:00
incr = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (incr == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-19 13:28:29 +00:00
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
sse_awk_clrpt (awk, incr);
PANIC (awk, SSE_AWK_ERPAREN);
2006-01-19 13:28:29 +00:00
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
sse_awk_clrpt (awk, incr);
return SSE_NULL;
2006-01-19 13:28:29 +00:00
}
body = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (body == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
sse_awk_clrpt (awk, incr);
return SSE_NULL;
2006-01-19 13:28:29 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_for_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_for_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, init);
sse_awk_clrpt (awk, test);
sse_awk_clrpt (awk, incr);
sse_awk_clrpt (awk, body);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-19 13:28:29 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_FOR;
nde->next = SSE_NULL;
2006-03-03 11:45:45 +00:00
nde->init = init;
nde->test = test;
nde->incr = incr;
nde->body = body;
2006-01-19 13:28:29 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_dowhile (sse_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* test, * body;
sse_awk_nde_while_t* nde;
2006-01-19 10:56:35 +00:00
body = __parse_statement (awk);
2006-10-22 11:34:53 +00:00
if (body == SSE_NULL) return SSE_NULL;
2006-01-19 10:56:35 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_WHILE))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
PANIC (awk, SSE_AWK_EWHILE);
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
return SSE_NULL;
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_LPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
PANIC (awk, SSE_AWK_ELPAREN);
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
return SSE_NULL;
2006-01-19 10:56:35 +00:00
}
2006-10-22 12:39:30 +00:00
test = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (test == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
return SSE_NULL;
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ERPAREN);
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
sse_awk_clrpt (awk, test);
return SSE_NULL;
2006-01-19 10:56:35 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_while_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_while_t));
if (nde == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, body);
sse_awk_clrpt (awk, test);
PANIC (awk, SSE_AWK_ENOMEM);
2006-01-19 10:56:35 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_DOWHILE;
nde->next = SSE_NULL;
2006-03-03 11:45:45 +00:00
nde->test = test;
nde->body = body;
2006-01-19 10:56:35 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_break (sse_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_break_t* nde;
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
if (awk->parse.depth.loop <= 0) PANIC (awk, SSE_AWK_EBREAK);
2006-08-01 15:57:43 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_break_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_break_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
nde->type = SSE_AWK_NDE_BREAK;
nde->next = SSE_NULL;
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_continue (sse_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_continue_t* nde;
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
if (awk->parse.depth.loop <= 0) PANIC (awk, SSE_AWK_ECONTINUE);
2006-08-01 15:57:43 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_continue_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_continue_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
nde->type = SSE_AWK_NDE_CONTINUE;
nde->next = SSE_NULL;
2006-01-09 12:51:47 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2005-11-15 15:59:23 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_return (sse_awk_t* awk)
2006-01-14 14:09:52 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_return_t* nde;
sse_awk_nde_t* val;
2006-01-14 14:09:52 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_return_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_return_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
nde->type = SSE_AWK_NDE_RETURN;
nde->next = SSE_NULL;
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-28 06:38:01 +00:00
/* no return value */
2006-10-22 11:34:53 +00:00
val = SSE_NULL;
2006-01-28 06:38:01 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-10-22 12:39:30 +00:00
val = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (val == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-01-28 06:38:01 +00:00
}
2006-01-14 14:09:52 +00:00
}
2006-03-05 17:07:33 +00:00
nde->val = val;
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-14 14:09:52 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_exit (sse_awk_t* awk)
2006-01-14 14:09:52 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_exit_t* nde;
sse_awk_nde_t* val;
2006-01-14 14:09:52 +00:00
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_exit_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_exit_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
nde->type = SSE_AWK_NDE_EXIT;
nde->next = SSE_NULL;
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-28 06:38:01 +00:00
/* no exit code */
2006-10-22 11:34:53 +00:00
val = SSE_NULL;
2006-01-28 06:38:01 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-10-22 12:39:30 +00:00
val = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (val == SSE_NULL)
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, nde);
return SSE_NULL;
2006-01-28 06:38:01 +00:00
}
2006-01-14 14:09:52 +00:00
}
2006-03-05 17:07:33 +00:00
nde->val = val;
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-14 14:09:52 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_delete (sse_awk_t* awk)
2006-03-31 16:35:37 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_delete_t* nde;
sse_awk_nde_t* var;
2006-06-27 14:18:19 +00:00
2006-10-22 11:34:53 +00:00
if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, SSE_AWK_EIDENT);
2006-06-27 14:18:19 +00:00
var = __parse_primary_ident (awk);
2006-10-22 11:34:53 +00:00
if (var == SSE_NULL) return SSE_NULL;
2006-06-27 14:18:19 +00:00
2006-06-27 14:32:03 +00:00
if (!__is_var (var))
2006-06-27 14:18:19 +00:00
{
2006-10-22 12:39:30 +00:00
/* a normal identifier is expected */
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, var);
PANIC (awk, SSE_AWK_EIDENT);
2006-06-27 14:18:19 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_delete_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_delete_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
2006-06-27 14:18:19 +00:00
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_DELETE;
nde->next = SSE_NULL;
2006-06-27 14:18:19 +00:00
nde->var = var;
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-03-31 16:35:37 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_print (sse_awk_t* awk)
2006-06-13 08:35:53 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_print_t* nde;
sse_awk_nde_t* args = SSE_NULL;
sse_awk_nde_t* args_tail = SSE_NULL;
sse_awk_nde_t* tail_prev = SSE_NULL;
sse_awk_nde_t* out = SSE_NULL;
2006-06-25 15:26:57 +00:00
int out_type;
2006-06-13 08:35:53 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON) &&
!MATCH(awk,TOKEN_GT) &&
2006-06-22 14:15:02 +00:00
!MATCH(awk,TOKEN_RSHIFT) &&
2006-06-18 10:53:06 +00:00
!MATCH(awk,TOKEN_BOR) &&
!MATCH(awk,TOKEN_BORAND))
2006-06-13 08:35:53 +00:00
{
2006-10-22 12:39:30 +00:00
args = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (args == SSE_NULL) return SSE_NULL;
2006-06-13 08:35:53 +00:00
2006-06-27 10:53:04 +00:00
args_tail = args;
2006-10-22 11:34:53 +00:00
tail_prev = SSE_NULL;
2006-06-13 08:35:53 +00:00
2006-06-27 10:53:04 +00:00
while (MATCH(awk,TOKEN_COMMA))
2006-06-13 08:35:53 +00:00
{
2006-06-27 10:53:04 +00:00
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, args);
return SSE_NULL;
2006-06-27 10:53:04 +00:00
}
2006-10-22 12:39:30 +00:00
args_tail->next = __parse_expression (awk);
2006-10-22 11:34:53 +00:00
if (args_tail->next == SSE_NULL)
2006-06-27 10:53:04 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_clrpt (awk, args);
return SSE_NULL;
2006-06-27 10:53:04 +00:00
}
tail_prev = args_tail;
args_tail = args_tail->next;
2006-06-13 08:35:53 +00:00
}
2006-06-27 10:53:04 +00:00
/* print 1 > 2 would print 1 to the file named 2.
* print (1 > 2) would print (1 > 2) in the console */
if (awk->token.prev != TOKEN_RPAREN &&
2006-10-22 12:39:30 +00:00
args_tail->type == SSE_AWK_NDE_EXP_BIN)
2006-06-13 08:35:53 +00:00
{
2006-10-22 12:39:30 +00:00
sse_awk_nde_exp_t* ep = (sse_awk_nde_exp_t*)args_tail;
2006-10-22 11:34:53 +00:00
if (ep->opcode == SSE_AWK_BINOP_GT)
2006-06-27 10:53:04 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* tmp = args_tail;
2006-06-27 10:53:04 +00:00
2006-10-22 11:34:53 +00:00
if (tail_prev != SSE_NULL)
2006-06-27 10:53:04 +00:00
tail_prev->next = ep->left;
else args = ep->left;
out = ep->right;
2006-10-22 11:34:53 +00:00
out_type = SSE_AWK_OUT_FILE;
2006-06-27 10:53:04 +00:00
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, tmp);
2006-06-27 10:53:04 +00:00
}
2006-10-22 11:34:53 +00:00
else if (ep->opcode == SSE_AWK_BINOP_RSHIFT)
2006-06-27 10:53:04 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* tmp = args_tail;
2006-06-27 10:53:04 +00:00
2006-10-22 11:34:53 +00:00
if (tail_prev != SSE_NULL)
2006-06-27 10:53:04 +00:00
tail_prev->next = ep->left;
else args = ep->left;
out = ep->right;
2006-10-22 11:34:53 +00:00
out_type = SSE_AWK_OUT_FILE_APPEND;
2006-06-27 10:53:04 +00:00
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, tmp);
2006-08-23 15:42:16 +00:00
}
2006-10-22 11:34:53 +00:00
else if (ep->opcode == SSE_AWK_BINOP_BOR)
2006-08-23 15:42:16 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_t* tmp = args_tail;
2006-08-23 15:42:16 +00:00
2006-10-22 11:34:53 +00:00
if (tail_prev != SSE_NULL)
2006-08-23 15:42:16 +00:00
tail_prev->next = ep->left;
else args = ep->left;
out = ep->right;
2006-10-22 11:34:53 +00:00
out_type = SSE_AWK_OUT_PIPE;
2006-08-23 15:42:16 +00:00
2006-10-22 11:34:53 +00:00
SSE_AWK_FREE (awk, tmp);
2006-06-27 10:53:04 +00:00
}
}
}
2006-10-22 11:34:53 +00:00
if (out == SSE_NULL)
2006-06-27 10:53:04 +00:00
{
2006-10-22 11:34:53 +00:00
out_type = MATCH(awk,TOKEN_GT)? SSE_AWK_OUT_FILE:
MATCH(awk,TOKEN_RSHIFT)? SSE_AWK_OUT_FILE_APPEND:
MATCH(awk,TOKEN_BOR)? SSE_AWK_OUT_PIPE:
MATCH(awk,TOKEN_BORAND)? SSE_AWK_OUT_COPROC:
SSE_AWK_OUT_CONSOLE;
2006-06-27 10:53:04 +00:00
2006-10-22 11:34:53 +00:00
if (out_type != SSE_AWK_OUT_CONSOLE)
2006-06-27 10:53:04 +00:00
{
if (__get_token(awk) == -1)
{
2006-10-22 11:34:53 +00:00
if (args != SSE_NULL) sse_awk_clrpt (awk, args);
return SSE_NULL;
2006-06-27 10:53:04 +00:00
}
2006-10-22 12:39:30 +00:00
out = __parse_expression(awk);
2006-10-22 11:34:53 +00:00
if (out == SSE_NULL)
2006-06-27 10:53:04 +00:00
{
2006-10-22 11:34:53 +00:00
if (args != SSE_NULL) sse_awk_clrpt (awk, args);
return SSE_NULL;
2006-06-27 10:53:04 +00:00
}
2006-06-13 08:35:53 +00:00
}
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_print_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_print_t));
if (nde == SSE_NULL)
2006-06-13 08:35:53 +00:00
{
2006-10-22 11:34:53 +00:00
if (args != SSE_NULL) sse_awk_clrpt (awk, args);
if (out != SSE_NULL) sse_awk_clrpt (awk, out);
PANIC (awk, SSE_AWK_ENOMEM);
2006-06-13 08:35:53 +00:00
}
2006-10-22 11:34:53 +00:00
nde->type = SSE_AWK_NDE_PRINT;
nde->next = SSE_NULL;
2006-06-13 08:35:53 +00:00
nde->args = args;
nde->out_type = out_type;
nde->out = out;
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-06-13 08:35:53 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_printf (sse_awk_t* awk)
2006-06-13 08:35:53 +00:00
{
2006-07-01 16:07:06 +00:00
/* TODO: implement this... */
2006-10-22 11:34:53 +00:00
return SSE_NULL;
2006-06-13 08:35:53 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_next (sse_awk_t* awk)
2006-01-20 07:33:46 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_next_t* nde;
2006-01-20 07:33:46 +00:00
2006-08-03 15:50:04 +00:00
if (awk->parse.id.block == PARSE_BEGIN_BLOCK ||
awk->parse.id.block == PARSE_END_BLOCK)
2006-08-01 15:57:43 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ENEXT);
2006-08-01 15:57:43 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_next_t*) SSE_AWK_MALLOC (awk, sse_sizeof(sse_awk_nde_next_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
nde->type = SSE_AWK_NDE_NEXT;
nde->next = SSE_NULL;
2006-01-20 07:33:46 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-20 07:33:46 +00:00
}
2006-10-22 11:34:53 +00:00
static sse_awk_nde_t* __parse_nextfile (sse_awk_t* awk)
2006-01-20 07:33:46 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_nde_nextfile_t* nde;
2006-01-20 07:33:46 +00:00
2006-08-03 15:50:04 +00:00
if (awk->parse.id.block == PARSE_BEGIN_BLOCK ||
awk->parse.id.block == PARSE_END_BLOCK)
2006-08-01 15:57:43 +00:00
{
2006-10-22 11:34:53 +00:00
PANIC (awk, SSE_AWK_ENEXTFILE);
2006-08-01 15:57:43 +00:00
}
2006-10-22 11:34:53 +00:00
nde = (sse_awk_nde_nextfile_t*) SSE_AWK_MALLOC (
awk, sse_sizeof(sse_awk_nde_nextfile_t));
if (nde == SSE_NULL) PANIC (awk, SSE_AWK_ENOMEM);
nde->type = SSE_AWK_NDE_NEXTFILE;
nde->next = SSE_NULL;
2006-01-20 07:33:46 +00:00
2006-10-22 11:34:53 +00:00
return (sse_awk_nde_t*)nde;
2006-01-20 07:33:46 +00:00
}
2006-10-22 11:34:53 +00:00
static int __get_token (sse_awk_t* awk)
2005-11-14 15:23:54 +00:00
{
2006-10-22 11:34:53 +00:00
sse_cint_t c;
sse_size_t line;
2005-11-14 15:23:54 +00:00
int n;
2006-08-03 09:54:16 +00:00
line = awk->token.line;
2006-04-07 04:23:11 +00:00
do
{
2005-11-14 15:23:54 +00:00
if (__skip_spaces(awk) == -1) return -1;
if ((n = __skip_comment(awk)) == -1) return -1;
2006-04-07 04:23:11 +00:00
}
while (n == 1);
2005-11-14 15:23:54 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_str_clear (&awk->token.name);
2006-08-06 08:16:03 +00:00
awk->token.line = awk->src.lex.line;
awk->token.column = awk->src.lex.column;
2006-05-13 16:33:07 +00:00
2006-10-22 11:34:53 +00:00
if (line != 0 && (awk->option & SSE_AWK_BLOCKLESS) &&
2006-08-03 15:50:04 +00:00
(awk->parse.id.block == PARSE_PATTERN ||
awk->parse.id.block == PARSE_BEGIN ||
awk->parse.id.block == PARSE_END))
2006-08-03 09:54:16 +00:00
{
if (awk->token.line != line)
{
SET_TOKEN_TYPE (awk, TOKEN_NEWLINE);
return 0;
}
}
2006-08-06 08:16:03 +00:00
c = awk->src.lex.curc;
2005-11-14 15:23:54 +00:00
2006-10-22 11:34:53 +00:00
if (c == SSE_CHAR_EOF)
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_EOF);
}
2006-10-22 11:34:53 +00:00
else if (SSE_AWK_ISDIGIT (awk, c) || c == SSE_T('.'))
2006-03-04 10:08:13 +00:00
{
2006-09-01 06:23:58 +00:00
if (__get_number (awk) == -1) return -1;
2005-11-14 15:23:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (SSE_AWK_ISALPHA (awk, c) || c == SSE_T('_'))
2006-03-04 10:08:13 +00:00
{
2006-06-16 14:31:42 +00:00
int type;
2005-11-15 15:32:39 +00:00
/* identifier */
2006-04-07 04:23:11 +00:00
do
{
2005-11-15 15:32:39 +00:00
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
2006-10-22 11:34:53 +00:00
while (SSE_AWK_ISALPHA (awk, c) ||
c == SSE_T('_') || SSE_AWK_ISDIGIT(awk,c));
2005-11-15 15:32:39 +00:00
2006-08-03 09:54:16 +00:00
type = __classify_ident (awk,
2006-10-22 11:34:53 +00:00
SSE_AWK_STR_BUF(&awk->token.name),
SSE_AWK_STR_LEN(&awk->token.name));
2006-06-16 14:31:42 +00:00
SET_TOKEN_TYPE (awk, type);
2005-11-14 15:23:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('\"'))
2006-03-04 10:08:13 +00:00
{
2006-04-07 04:23:11 +00:00
SET_TOKEN_TYPE (awk, TOKEN_STR);
2006-01-11 14:03:17 +00:00
2006-08-01 04:36:33 +00:00
if (__get_charstr(awk) == -1) return -1;
2006-07-30 15:53:42 +00:00
2006-10-22 11:34:53 +00:00
while (awk->option & SSE_AWK_STRCONCAT)
2006-04-07 04:23:11 +00:00
{
do
{
if (__skip_spaces(awk) == -1) return -1;
if ((n = __skip_comment(awk)) == -1) return -1;
}
while (n == 1);
2006-08-06 08:16:03 +00:00
c = awk->src.lex.curc;
2006-10-22 11:34:53 +00:00
if (c != SSE_T('\"')) break;
2006-04-07 04:23:11 +00:00
2006-08-01 04:36:33 +00:00
if (__get_charstr(awk) == -1) return -1;
2006-04-07 04:23:11 +00:00
}
2006-07-30 15:53:42 +00:00
2005-11-15 15:32:39 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_EQ);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_ASSIGN);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('!'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_NE);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('~'))
2006-04-11 15:44:30 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_NM);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-04-11 15:44:30 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_NOT);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('>'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_SHIFT) && c == SSE_T('>'))
2006-03-04 10:08:13 +00:00
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RSHIFT);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_GE);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_GT);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('<'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
2006-08-03 09:54:16 +00:00
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_SHIFT) && c == SSE_T('<'))
2006-03-04 10:08:13 +00:00
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LSHIFT);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LE);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LT);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('|'))
2006-03-29 16:39:04 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-03-29 16:39:04 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('|'))
2006-03-29 16:39:04 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_LOR);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-03-29 16:39:04 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('&'))
2006-06-18 10:53:06 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_BORAND);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-06-18 10:53:06 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-29 16:39:04 +00:00
else
{
SET_TOKEN_TYPE (awk, TOKEN_BOR);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('&'))
2006-03-29 16:39:04 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-03-29 16:39:04 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('&'))
2006-03-29 16:39:04 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_LAND);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-03-29 16:39:04 +00:00
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_BAND);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('~'))
2006-03-31 12:04:14 +00:00
{
2006-04-12 03:54:12 +00:00
SET_TOKEN_TYPE (awk, TOKEN_TILDE);
2006-03-31 12:04:14 +00:00
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('^'))
2006-04-11 15:44:30 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_BXOR);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('+'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('+'))
2006-03-04 10:08:13 +00:00
{
2006-03-31 12:04:14 +00:00
SET_TOKEN_TYPE (awk, TOKEN_PLUSPLUS);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_PLUS_ASSIGN);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_PLUS);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('-'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('-'))
2006-03-04 10:08:13 +00:00
{
2006-03-31 12:04:14 +00:00
SET_TOKEN_TYPE (awk, TOKEN_MINUSMINUS);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('='))
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_MINUS_ASSIGN);
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_MINUS);
}
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('*'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-10 13:57:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-11 15:44:30 +00:00
2006-10-22 11:34:53 +00:00
if (c == SSE_T('='))
2006-04-11 15:44:30 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_MUL_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('*'))
2006-04-11 15:44:30 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-04-11 15:44:30 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('='))
2006-04-11 15:44:30 +00:00
{
2006-10-22 12:39:30 +00:00
SET_TOKEN_TYPE (awk, TOKEN_EXP_ASSIGN);
2006-04-11 15:44:30 +00:00
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else
{
2006-10-22 12:39:30 +00:00
SET_TOKEN_TYPE (awk, TOKEN_EXP);
2006-04-11 15:44:30 +00:00
}
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_MUL);
}
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('/'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-10 13:57:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-11 15:44:30 +00:00
2006-10-22 11:34:53 +00:00
if (c == SSE_T('='))
2006-04-11 15:44:30 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_DIV_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_DIV);
}
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('%'))
2006-03-04 10:08:13 +00:00
{
2006-08-03 09:54:16 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-10 13:57:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-11 15:44:30 +00:00
2006-10-22 11:34:53 +00:00
if (c == SSE_T('='))
2006-04-11 15:44:30 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_MOD_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_MOD);
}
2006-01-10 13:57:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('('))
2006-03-04 10:08:13 +00:00
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LPAREN);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T(')'))
2006-03-04 10:08:13 +00:00
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RPAREN);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('{'))
2006-03-04 10:08:13 +00:00
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LBRACE);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('}'))
2006-03-04 10:08:13 +00:00
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RBRACE);
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('['))
2006-03-04 10:08:13 +00:00
{
2006-01-19 16:28:21 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LBRACK);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T(']'))
2006-03-04 10:08:13 +00:00
{
2006-01-19 16:28:21 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RBRACK);
2005-11-15 15:32:39 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('$'))
2006-03-04 10:08:13 +00:00
{
2006-01-25 14:50:57 +00:00
SET_TOKEN_TYPE (awk, TOKEN_DOLLAR);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T(','))
2006-03-04 10:08:13 +00:00
{
2006-01-13 14:16:56 +00:00
SET_TOKEN_TYPE (awk, TOKEN_COMMA);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('.'))
2006-04-16 04:31:38 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_PERIOD);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T(';') ||
(c == SSE_T('\n') && (awk->option & SSE_AWK_NEWLINE)))
2006-03-04 10:08:13 +00:00
{
2006-10-15 15:46:14 +00:00
/* TODO: more check on the newline terminator... */
2006-01-09 16:03:56 +00:00
SET_TOKEN_TYPE (awk, TOKEN_SEMICOLON);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2005-11-14 15:23:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T(':'))
2006-04-10 15:52:07 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_COLON);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('?'))
2006-04-10 15:52:07 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_QUEST);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ELXCHR;
2005-11-14 15:23:54 +00:00
return -1;
}
2006-10-22 12:39:30 +00:00
/*xp_printf (SSE_T("token -> [%s]\n"), SSE_AWK_STR_BUF(&awk->token.name));*/
2005-11-14 15:23:54 +00:00
return 0;
2005-11-06 12:01:29 +00:00
}
2005-11-14 15:23:54 +00:00
2006-10-22 11:34:53 +00:00
static int __get_number (sse_awk_t* awk)
2006-04-04 06:26:56 +00:00
{
2006-10-22 11:34:53 +00:00
sse_cint_t c;
2006-04-04 06:26:56 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, SSE_AWK_STR_LEN(&awk->token.name) == 0);
2006-04-04 06:26:56 +00:00
SET_TOKEN_TYPE (awk, TOKEN_INT);
2006-08-06 08:16:03 +00:00
c = awk->src.lex.curc;
2006-04-04 06:26:56 +00:00
2006-10-22 11:34:53 +00:00
if (c == SSE_T('0'))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('x') || c == SSE_T('X'))
2006-04-04 06:26:56 +00:00
{
/* hexadecimal number */
do
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
2006-10-22 11:34:53 +00:00
while (SSE_AWK_ISXDIGIT (awk, c));
2006-04-04 06:26:56 +00:00
2006-04-04 16:22:01 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('b') || c == SSE_T('B'))
2006-04-04 16:22:01 +00:00
{
/* binary number */
do
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
2006-10-22 11:34:53 +00:00
while (c == SSE_T('0') || c == SSE_T('1'));
2006-04-04 16:22:01 +00:00
return 0;
2006-04-04 06:26:56 +00:00
}
else if (c != '.')
{
/* octal number */
2006-10-22 11:34:53 +00:00
while (c >= SSE_T('0') && c <= SSE_T('7'))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-05 15:56:20 +00:00
}
2006-04-04 06:26:56 +00:00
2006-04-04 16:22:01 +00:00
return 0;
2006-04-04 06:26:56 +00:00
}
}
2006-10-22 11:34:53 +00:00
while (SSE_AWK_ISDIGIT (awk, c))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
if (c == SSE_T('.'))
2006-04-04 06:26:56 +00:00
{
/* floating-point number */
SET_TOKEN_TYPE (awk, TOKEN_REAL);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
while (SSE_AWK_ISDIGIT (awk, c))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
}
2006-10-22 11:34:53 +00:00
if (c == SSE_T('E') || c == SSE_T('e'))
2006-04-04 06:26:56 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_REAL);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_T('+') || c == SSE_T('-'))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
while (SSE_AWK_ISDIGIT (awk, c))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
}
return 0;
}
2006-10-22 11:34:53 +00:00
static int __get_charstr (sse_awk_t* awk)
2006-08-01 04:36:33 +00:00
{
2006-10-22 11:34:53 +00:00
if (awk->src.lex.curc != SSE_T('\"'))
2006-08-03 09:54:16 +00:00
{
2006-08-30 07:15:14 +00:00
/* the starting quote has been consumed before this function
2006-08-03 09:54:16 +00:00
* has been called */
2006-08-06 08:16:03 +00:00
ADD_TOKEN_CHAR (awk, awk->src.lex.curc);
2006-08-03 09:54:16 +00:00
}
2006-10-22 11:34:53 +00:00
return __get_string (awk, SSE_T('\"'), SSE_T('\\'), sse_false);
2006-08-01 04:36:33 +00:00
}
2006-10-22 11:34:53 +00:00
static int __get_rexstr (sse_awk_t* awk)
2006-08-01 04:36:33 +00:00
{
2006-10-22 11:34:53 +00:00
if (awk->src.lex.curc == SSE_T('/'))
2006-08-30 07:15:14 +00:00
{
/* this part of the function is different from __get_charstr
* because of the way this function is called */
GET_CHAR (awk);
return 0;
}
else
2006-08-03 09:54:16 +00:00
{
2006-08-06 08:16:03 +00:00
ADD_TOKEN_CHAR (awk, awk->src.lex.curc);
2006-10-22 11:34:53 +00:00
return __get_string (awk, SSE_T('/'), SSE_T('\\'), sse_true);
2006-08-03 09:54:16 +00:00
}
2006-08-01 04:36:33 +00:00
}
static int __get_string (
2006-10-22 11:34:53 +00:00
sse_awk_t* awk, sse_char_t end_char,
sse_char_t esc_char, sse_bool_t keep_esc_char)
2006-04-07 04:23:11 +00:00
{
2006-10-22 11:34:53 +00:00
sse_cint_t c;
2006-07-01 16:24:36 +00:00
int escaped = 0;
2006-07-02 12:16:24 +00:00
int digit_count = 0;
2006-10-22 11:34:53 +00:00
sse_cint_t c_acc;
2006-04-07 04:23:11 +00:00
while (1)
{
2006-07-02 12:16:24 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_CHAR_EOF)
2006-04-07 04:23:11 +00:00
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_EENDSTR;
2006-04-07 04:23:11 +00:00
return -1;
}
2006-07-02 12:16:24 +00:00
if (escaped == 3)
{
2006-10-22 11:34:53 +00:00
if (c >= SSE_T('0') && c <= SSE_T('7'))
2006-07-02 12:16:24 +00:00
{
2006-10-22 11:34:53 +00:00
c_acc = c_acc * 8 + c - SSE_T('0');
2006-07-02 12:16:24 +00:00
digit_count++;
if (digit_count >= escaped)
{
ADD_TOKEN_CHAR (awk, c_acc);
escaped = 0;
}
continue;
}
else
{
ADD_TOKEN_CHAR (awk, c_acc);
escaped = 0;
}
}
else if (escaped == 2 || escaped == 4 || escaped == 8)
{
2006-10-22 11:34:53 +00:00
if (c >= SSE_T('0') && c <= SSE_T('9'))
2006-07-02 12:16:24 +00:00
{
2006-10-22 11:34:53 +00:00
c_acc = c_acc * 16 + c - SSE_T('0');
2006-07-02 12:16:24 +00:00
digit_count++;
if (digit_count >= escaped)
{
ADD_TOKEN_CHAR (awk, c_acc);
escaped = 0;
}
continue;
}
2006-10-22 11:34:53 +00:00
else if (c >= SSE_T('A') && c <= SSE_T('F'))
2006-07-02 12:16:24 +00:00
{
2006-10-22 11:34:53 +00:00
c_acc = c_acc * 16 + c - SSE_T('A') + 10;
2006-07-02 12:16:24 +00:00
digit_count++;
if (digit_count >= escaped)
{
ADD_TOKEN_CHAR (awk, c_acc);
escaped = 0;
}
continue;
}
2006-10-22 11:34:53 +00:00
else if (c >= SSE_T('a') && c <= SSE_T('f'))
2006-07-02 12:16:24 +00:00
{
2006-10-22 11:34:53 +00:00
c_acc = c_acc * 16 + c - SSE_T('a') + 10;
2006-07-02 12:16:24 +00:00
digit_count++;
if (digit_count >= escaped)
{
ADD_TOKEN_CHAR (awk, c_acc);
escaped = 0;
}
continue;
}
else
{
2006-10-22 11:34:53 +00:00
sse_char_t rc;
2006-07-02 12:16:24 +00:00
2006-10-22 11:34:53 +00:00
rc = (escaped == 2)? SSE_T('x'):
(escaped == 4)? SSE_T('u'): SSE_T('U');
2006-07-02 12:16:24 +00:00
if (digit_count == 0) ADD_TOKEN_CHAR (awk, rc);
else ADD_TOKEN_CHAR (awk, c_acc);
escaped = 0;
}
}
2006-08-01 04:36:33 +00:00
if (escaped == 0 && c == end_char)
2006-04-07 04:23:11 +00:00
{
2006-07-02 12:16:24 +00:00
/* terminating quote */
2006-04-07 04:23:11 +00:00
GET_CHAR_TO (awk, c);
break;
}
2006-08-01 04:36:33 +00:00
if (escaped == 0 && c == esc_char)
2006-04-07 04:23:11 +00:00
{
2006-07-01 16:24:36 +00:00
escaped = 1;
2006-04-07 04:23:11 +00:00
continue;
}
2006-07-01 16:24:36 +00:00
if (escaped == 1)
2006-04-07 04:23:11 +00:00
{
2006-10-22 11:34:53 +00:00
if (c == SSE_T('n')) c = SSE_T('\n');
else if (c == SSE_T('r')) c = SSE_T('\r');
else if (c == SSE_T('t')) c = SSE_T('\t');
else if (c == SSE_T('f')) c = SSE_T('\f');
else if (c == SSE_T('b')) c = SSE_T('\b');
else if (c == SSE_T('v')) c = SSE_T('\v');
else if (c == SSE_T('a')) c = SSE_T('\a');
else if (c >= SSE_T('0') && c <= SSE_T('7'))
2006-07-02 12:16:24 +00:00
{
escaped = 3;
digit_count = 1;
2006-10-22 11:34:53 +00:00
c_acc = c - SSE_T('0');
2006-07-02 12:16:24 +00:00
continue;
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('x'))
2006-07-02 12:16:24 +00:00
{
escaped = 2;
digit_count = 0;
c_acc = 0;
continue;
}
2006-10-22 11:34:53 +00:00
#ifdef SSE_CHAR_IS_WCHAR
else if (c == SSE_T('u') && sse_sizeof(sse_char_t) >= 2)
2006-07-02 12:16:24 +00:00
{
escaped = 4;
digit_count = 0;
c_acc = 0;
continue;
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('U') && sse_sizeof(sse_char_t) >= 4)
2006-07-02 12:16:24 +00:00
{
escaped = 8;
digit_count = 0;
c_acc = 0;
continue;
}
2006-07-01 16:24:36 +00:00
#endif
2006-08-01 04:36:33 +00:00
else if (keep_esc_char)
{
ADD_TOKEN_CHAR (awk, esc_char);
}
2006-07-01 16:24:36 +00:00
2006-07-02 12:16:24 +00:00
escaped = 0;
2006-07-01 16:24:36 +00:00
}
2006-04-07 04:23:11 +00:00
ADD_TOKEN_CHAR (awk, c);
}
2006-08-03 09:54:16 +00:00
2006-04-07 04:23:11 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
static int __get_char (sse_awk_t* awk)
2005-11-14 15:23:54 +00:00
{
2006-10-22 11:34:53 +00:00
sse_ssize_t n;
/*sse_char_t c;*/
2006-01-09 16:03:56 +00:00
2006-08-06 08:16:03 +00:00
if (awk->src.lex.ungotc_count > 0)
2006-03-04 10:08:13 +00:00
{
2006-08-06 08:16:03 +00:00
awk->src.lex.curc = awk->src.lex.ungotc[--awk->src.lex.ungotc_count];
2005-11-14 15:23:54 +00:00
return 0;
}
2006-08-06 08:16:03 +00:00
if (awk->src.shared.buf_pos >= awk->src.shared.buf_len)
2006-05-10 16:02:39 +00:00
{
2006-08-06 08:16:03 +00:00
n = awk->src.ios->in (
2006-10-22 11:34:53 +00:00
SSE_AWK_IO_READ, awk->src.ios->custom_data,
awk->src.shared.buf, sse_countof(awk->src.shared.buf));
2006-05-10 16:02:39 +00:00
if (n == -1)
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ESRCINREAD;
2006-05-10 16:02:39 +00:00
return -1;
}
if (n == 0)
{
2006-10-22 11:34:53 +00:00
awk->src.lex.curc = SSE_CHAR_EOF;
2006-05-10 16:02:39 +00:00
return 0;
}
2006-08-06 08:16:03 +00:00
awk->src.shared.buf_pos = 0;
awk->src.shared.buf_len = n;
2006-05-10 16:02:39 +00:00
}
2006-08-06 08:16:03 +00:00
awk->src.lex.curc = awk->src.shared.buf[awk->src.shared.buf_pos++];
2006-05-13 16:33:07 +00:00
2006-10-22 11:34:53 +00:00
if (awk->src.lex.curc == SSE_T('\n'))
2006-05-13 16:33:07 +00:00
{
2006-08-06 08:16:03 +00:00
awk->src.lex.line++;
awk->src.lex.column = 1;
2006-05-13 16:33:07 +00:00
}
2006-08-06 08:16:03 +00:00
else awk->src.lex.column++;
2006-05-13 16:33:07 +00:00
2005-11-14 15:23:54 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
static int __unget_char (sse_awk_t* awk, sse_cint_t c)
2005-11-14 15:23:54 +00:00
{
2006-10-22 11:34:53 +00:00
if (awk->src.lex.ungotc_count >= sse_countof(awk->src.lex.ungotc))
2006-03-04 10:08:13 +00:00
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ELXUNG;
2005-11-14 15:23:54 +00:00
return -1;
}
2006-08-06 08:16:03 +00:00
awk->src.lex.ungotc[awk->src.lex.ungotc_count++] = c;
2005-11-14 15:23:54 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
static int __skip_spaces (sse_awk_t* awk)
2005-11-14 15:23:54 +00:00
{
2006-10-22 11:34:53 +00:00
sse_cint_t c = awk->src.lex.curc;
2006-08-03 09:54:16 +00:00
2006-10-22 11:34:53 +00:00
if (awk->option & SSE_AWK_NEWLINE && awk->parse.nl_semicolon)
2006-10-15 15:46:14 +00:00
{
2006-10-22 11:34:53 +00:00
while (c != SSE_T('\n') &&
SSE_AWK_ISSPACE (awk, c)) GET_CHAR_TO (awk, c);
2006-10-15 15:46:14 +00:00
}
else
{
2006-10-22 11:34:53 +00:00
while (SSE_AWK_ISSPACE (awk, c)) GET_CHAR_TO (awk, c);
2006-10-15 15:46:14 +00:00
}
2005-11-14 15:23:54 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
static int __skip_comment (sse_awk_t* awk)
2005-11-14 15:23:54 +00:00
{
2006-10-22 11:34:53 +00:00
sse_cint_t c = awk->src.lex.curc;
2005-11-14 15:23:54 +00:00
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_HASHSIGN) && c == SSE_T('#'))
2006-04-07 04:23:11 +00:00
{
do
{
GET_CHAR_TO (awk, c);
}
2006-10-22 11:34:53 +00:00
while (c != SSE_T('\n') && c != SSE_CHAR_EOF);
2006-04-07 04:23:11 +00:00
GET_CHAR (awk);
return 1; /* comment by # */
}
2006-10-22 11:34:53 +00:00
if (c != SSE_T('/')) return 0; /* not a comment */
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if ((awk->option & SSE_AWK_DBLSLASHES) && c == SSE_T('/'))
2006-03-04 10:08:13 +00:00
{
2006-04-07 04:23:11 +00:00
do
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
2006-10-22 11:34:53 +00:00
while (c != SSE_T('\n') && c != SSE_CHAR_EOF);
2006-04-07 04:23:11 +00:00
2005-11-14 15:23:54 +00:00
GET_CHAR (awk);
2006-04-07 04:23:11 +00:00
return 1; /* comment by // */
2005-11-14 15:23:54 +00:00
}
2006-10-22 11:34:53 +00:00
else if (c == SSE_T('*'))
2006-03-04 10:08:13 +00:00
{
2006-04-07 04:23:11 +00:00
do
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_CHAR_EOF)
2006-08-29 15:01:45 +00:00
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_EENDCOMMENT;
2006-08-29 15:01:45 +00:00
return -1;
}
2006-10-22 11:34:53 +00:00
if (c == SSE_T('*'))
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-10-22 11:34:53 +00:00
if (c == SSE_CHAR_EOF)
2006-08-29 15:01:45 +00:00
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_EENDCOMMENT;
2006-08-29 15:01:45 +00:00
return -1;
}
2006-10-22 11:34:53 +00:00
if (c == SSE_T('/'))
2006-03-04 10:08:13 +00:00
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
break;
}
}
2006-04-07 04:23:11 +00:00
}
while (1);
return 1; /* c-style comment */
2005-11-14 15:23:54 +00:00
}
2006-04-07 04:23:11 +00:00
if (__unget_char(awk,c) == -1) return -1; /* error */
2006-10-22 11:34:53 +00:00
awk->src.lex.curc = SSE_T('/');
2006-01-12 14:20:17 +00:00
2005-11-14 15:23:54 +00:00
return 0;
}
2006-08-03 09:54:16 +00:00
static int __classify_ident (
2006-10-22 11:34:53 +00:00
sse_awk_t* awk, const sse_char_t* name, sse_size_t len)
2005-11-15 15:32:39 +00:00
{
2006-06-16 14:31:42 +00:00
struct __kwent* kwp;
2005-11-15 15:32:39 +00:00
2006-10-22 11:34:53 +00:00
for (kwp = __kwtab; kwp->name != SSE_NULL; kwp++)
2006-03-04 10:08:13 +00:00
{
2006-06-21 15:37:51 +00:00
if (kwp->valid != 0 &&
2006-08-04 17:36:40 +00:00
(awk->option & kwp->valid) == 0) continue;
2006-08-03 09:54:16 +00:00
2006-10-22 11:34:53 +00:00
if (sse_awk_strxncmp (kwp->name, kwp->name_len, name, len) == 0)
2006-08-03 09:54:16 +00:00
{
return kwp->type;
}
2005-11-15 15:32:39 +00:00
}
return TOKEN_IDENT;
}
2006-01-24 16:14:28 +00:00
2006-10-22 11:34:53 +00:00
static int __assign_to_opcode (sse_awk_t* awk)
2006-04-14 16:26:00 +00:00
{
2006-08-03 09:54:16 +00:00
static int __assop[] =
{
2006-10-22 11:34:53 +00:00
SSE_AWK_ASSOP_NONE,
SSE_AWK_ASSOP_PLUS,
SSE_AWK_ASSOP_MINUS,
SSE_AWK_ASSOP_MUL,
SSE_AWK_ASSOP_DIV,
SSE_AWK_ASSOP_MOD,
2006-10-22 12:39:30 +00:00
SSE_AWK_ASSOP_EXP
2006-08-03 09:54:16 +00:00
};
if (awk->token.type >= TOKEN_ASSIGN &&
2006-10-22 12:39:30 +00:00
awk->token.type <= TOKEN_EXP_ASSIGN)
2006-08-03 09:54:16 +00:00
{
return __assop[awk->token.type - TOKEN_ASSIGN];
}
2006-04-14 16:26:00 +00:00
return -1;
}
2006-04-29 12:41:47 +00:00
2006-10-22 11:34:53 +00:00
static int __is_plain_var (sse_awk_nde_t* nde)
2006-04-29 12:41:47 +00:00
{
2006-10-22 11:34:53 +00:00
return nde->type == SSE_AWK_NDE_GLOBAL ||
nde->type == SSE_AWK_NDE_LOCAL ||
nde->type == SSE_AWK_NDE_ARG ||
nde->type == SSE_AWK_NDE_NAMED;
2006-04-29 12:41:47 +00:00
}
2006-06-27 14:32:03 +00:00
2006-10-22 11:34:53 +00:00
static int __is_var (sse_awk_nde_t* nde)
2006-06-27 14:32:03 +00:00
{
2006-10-22 11:34:53 +00:00
return nde->type == SSE_AWK_NDE_GLOBAL ||
nde->type == SSE_AWK_NDE_LOCAL ||
nde->type == SSE_AWK_NDE_ARG ||
nde->type == SSE_AWK_NDE_NAMED ||
nde->type == SSE_AWK_NDE_GLOBALIDX ||
nde->type == SSE_AWK_NDE_LOCALIDX ||
nde->type == SSE_AWK_NDE_ARGIDX ||
nde->type == SSE_AWK_NDE_NAMEDIDX;
2006-06-27 14:32:03 +00:00
}
2006-08-06 08:16:03 +00:00
struct __deparse_func_t
{
2006-10-22 11:34:53 +00:00
sse_awk_t* awk;
sse_char_t* tmp;
sse_size_t tmp_len;
2006-08-06 08:16:03 +00:00
};
2006-10-22 11:34:53 +00:00
static int __deparse (sse_awk_t* awk)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
sse_awk_chain_t* chain;
sse_char_t tmp[sse_sizeof(sse_size_t)*8 + 32];
2006-08-06 08:16:03 +00:00
struct __deparse_func_t df;
2006-10-13 10:18:39 +00:00
int n = 0, op;
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, awk->src.ios->out != SSE_NULL);
2006-08-06 08:16:03 +00:00
awk->src.shared.buf_len = 0;
awk->src.shared.buf_pos = 0;
2006-10-13 10:18:39 +00:00
op = awk->src.ios->out (
2006-10-22 11:34:53 +00:00
SSE_AWK_IO_OPEN, awk->src.ios->custom_data, SSE_NULL, 0);
2006-10-13 10:18:39 +00:00
if (op == -1)
2006-08-06 12:35:06 +00:00
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ESRCOUTOPEN;
2006-08-06 12:35:06 +00:00
return -1;
}
2006-10-13 10:18:39 +00:00
if (op == 0)
{
/* the result of the open operation indicates that the
* file has been open but reached the end. so it has to
* skip the entire deparsing procedure as it can't write
* any single characters on such an io handler. but note
* that this is not really an error for the parse and deparser.
*
* in fact, there are two ways to skip deparsing.
* 1. set awk->src.ios.out to NULL.
* 2. set awk->src.ios.out to a normal handler but
* make it return 0 on the OPEN request.
*/
n = 0;
goto exit_deparse;
}
2006-08-06 15:03:42 +00:00
#define EXIT_DEPARSE(num) \
do { n = -1; awk->errnum = num ; goto exit_deparse; } while(0)
2006-08-06 08:16:03 +00:00
if (awk->tree.nglobals > awk->tree.nbglobals)
{
2006-10-22 11:34:53 +00:00
sse_size_t i, len;
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, awk->tree.nglobals > 0);
if (sse_awk_putsrcstr (awk, SSE_T("global ")) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
for (i = awk->tree.nbglobals; i < awk->tree.nglobals - 1; i++)
{
2006-10-22 11:34:53 +00:00
len = sse_awk_longtostr ((sse_long_t)i,
10, SSE_T("__global"), tmp, sse_countof(tmp));
sse_awk_assert (awk, len != (sse_size_t)-1);
if (sse_awk_putsrcstrx (awk, tmp, len) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
if (sse_awk_putsrcstr (awk, SSE_T(", ")) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
2006-08-06 12:35:06 +00:00
2006-10-22 11:34:53 +00:00
len = sse_awk_longtostr ((sse_long_t)i,
10, SSE_T("__global"), tmp, sse_countof(tmp));
sse_awk_assert (awk, len != (sse_size_t)-1);
if (sse_awk_putsrcstrx (awk, tmp, len) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
if (sse_awk_putsrcstr (awk, SSE_T(";\n\n")) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
df.awk = awk;
df.tmp = tmp;
2006-10-22 11:34:53 +00:00
df.tmp_len = sse_countof(tmp);
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
if (sse_awk_map_walk (&awk->tree.afns, __deparse_func, &df) == -1)
2006-08-06 15:03:42 +00:00
{
2006-10-22 11:34:53 +00:00
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 15:03:42 +00:00
}
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
if (awk->tree.begin != SSE_NULL)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
if (sse_awk_putsrcstr (awk, SSE_T("BEGIN ")) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 15:03:42 +00:00
2006-10-22 11:34:53 +00:00
if (sse_awk_prnpt (awk, awk->tree.begin) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 15:03:42 +00:00
2006-10-22 11:34:53 +00:00
if (__put_char (awk, SSE_T('\n')) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
chain = awk->tree.chain;
2006-10-22 11:34:53 +00:00
while (chain != SSE_NULL)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
if (chain->pattern != SSE_NULL)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
if (sse_awk_prnptnpt (awk, chain->pattern) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
2006-10-22 11:34:53 +00:00
if (chain->action == SSE_NULL)
2006-08-06 08:16:03 +00:00
{
/* blockless pattern */
2006-10-22 11:34:53 +00:00
if (__put_char (awk, SSE_T('\n')) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
else
{
2006-10-22 11:34:53 +00:00
if (sse_awk_prnpt (awk, chain->action) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
2006-10-22 11:34:53 +00:00
if (__put_char (awk, SSE_T('\n')) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 15:03:42 +00:00
2006-08-06 08:16:03 +00:00
chain = chain->next;
}
2006-10-22 11:34:53 +00:00
if (awk->tree.end != SSE_NULL)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
if (sse_awk_putsrcstr (awk, SSE_T("END ")) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
if (sse_awk_prnpt (awk, awk->tree.end) == -1)
EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 08:16:03 +00:00
}
2006-10-22 11:34:53 +00:00
if (__flush (awk) == -1) EXIT_DEPARSE (SSE_AWK_ESRCOUTWRITE);
2006-08-06 12:35:06 +00:00
exit_deparse:
if (awk->src.ios->out (
2006-10-22 11:34:53 +00:00
SSE_AWK_IO_CLOSE, awk->src.ios->custom_data, SSE_NULL, 0) == -1)
2006-08-06 12:35:06 +00:00
{
if (n != -1)
{
2006-10-22 11:34:53 +00:00
awk->errnum = SSE_AWK_ESRCOUTCLOSE;
2006-08-06 12:35:06 +00:00
n = -1;
}
}
return 0;
2006-08-06 08:16:03 +00:00
}
2006-10-22 11:34:53 +00:00
static int __deparse_func (sse_awk_pair_t* pair, void* arg)
2006-08-06 08:16:03 +00:00
{
struct __deparse_func_t* df = (struct __deparse_func_t*)arg;
2006-10-22 11:34:53 +00:00
sse_awk_afn_t* afn = (sse_awk_afn_t*)pair->val;
sse_size_t i, n;
2006-08-06 08:16:03 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (df->awk, sse_awk_strxncmp (
2006-08-06 08:16:03 +00:00
pair->key, pair->key_len, afn->name, afn->name_len) == 0);
2006-10-22 11:34:53 +00:00
if (sse_awk_putsrcstr (df->awk, SSE_T("function ")) == -1) return -1;
if (sse_awk_putsrcstr (df->awk, afn->name) == -1) return -1;
if (sse_awk_putsrcstr (df->awk, SSE_T(" (")) == -1) return -1;
2006-08-06 08:16:03 +00:00
for (i = 0; i < afn->nargs; )
{
2006-10-22 11:34:53 +00:00
n = sse_awk_longtostr (i++, 10,
SSE_T("__param"), df->tmp, df->tmp_len);
sse_awk_assert (df->awk, n != (sse_size_t)-1);
if (sse_awk_putsrcstrx (df->awk, df->tmp, n) == -1) return -1;
2006-08-06 08:16:03 +00:00
if (i >= afn->nargs) break;
2006-10-22 11:34:53 +00:00
if (sse_awk_putsrcstr (df->awk, SSE_T(", ")) == -1) return -1;
2006-08-06 08:16:03 +00:00
}
2006-10-22 11:34:53 +00:00
if (sse_awk_putsrcstr (df->awk, SSE_T(")\n")) == -1) return -1;
2006-08-06 15:03:42 +00:00
2006-10-22 11:34:53 +00:00
if (sse_awk_prnpt (df->awk, afn->body) == -1) return -1;
if (sse_awk_putsrcstr (df->awk, SSE_T("\n")) == -1) return -1;
2006-08-06 08:16:03 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
static int __put_char (sse_awk_t* awk, sse_char_t c)
2006-08-06 08:16:03 +00:00
{
awk->src.shared.buf[awk->src.shared.buf_len++] = c;
2006-10-22 11:34:53 +00:00
if (awk->src.shared.buf_len >= sse_countof(awk->src.shared.buf))
2006-08-06 08:16:03 +00:00
{
if (__flush (awk) == -1) return -1;
}
return 0;
}
2006-10-22 11:34:53 +00:00
static int __flush (sse_awk_t* awk)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
sse_ssize_t n;
2006-08-06 15:03:42 +00:00
2006-10-22 11:34:53 +00:00
sse_awk_assert (awk, awk->src.ios->out != SSE_NULL);
2006-08-06 15:03:42 +00:00
while (awk->src.shared.buf_pos < awk->src.shared.buf_len)
2006-08-06 08:16:03 +00:00
{
2006-08-06 15:03:42 +00:00
n = awk->src.ios->out (
2006-10-22 11:34:53 +00:00
SSE_AWK_IO_WRITE, awk->src.ios->custom_data,
2006-08-06 15:03:42 +00:00
&awk->src.shared.buf[awk->src.shared.buf_pos],
awk->src.shared.buf_len - awk->src.shared.buf_pos);
if (n <= 0) return -1;
awk->src.shared.buf_pos += n;
2006-08-06 08:16:03 +00:00
}
2006-08-06 15:03:42 +00:00
awk->src.shared.buf_pos = 0;
awk->src.shared.buf_len = 0;
2006-08-06 08:16:03 +00:00
return 0;
}
2006-10-22 11:34:53 +00:00
int sse_awk_putsrcstr (sse_awk_t* awk, const sse_char_t* str)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
while (*str != SSE_T('\0'))
2006-08-06 08:16:03 +00:00
{
if (__put_char (awk, *str) == -1) return -1;
str++;
}
return 0;
}
2006-10-22 11:34:53 +00:00
int sse_awk_putsrcstrx (
sse_awk_t* awk, const sse_char_t* str, sse_size_t len)
2006-08-06 08:16:03 +00:00
{
2006-10-22 11:34:53 +00:00
const sse_char_t* end = str + len;
2006-08-06 08:16:03 +00:00
2006-08-06 15:03:42 +00:00
while (str < end)
2006-08-06 08:16:03 +00:00
{
2006-08-06 15:03:42 +00:00
if (__put_char (awk, *str) == -1) return -1;
str++;
2006-08-06 08:16:03 +00:00
}
return 0;
}
2006-08-06 15:03:42 +00:00