Added QSE_AWK_BLANKCONCAT

fixed getline parsing to accept $XXX
This commit is contained in:
hyung-hwan 2012-10-27 16:28:12 +00:00
parent c6a0a99e84
commit 4e92c0ef1c
4 changed files with 76 additions and 63 deletions

View File

@ -388,6 +388,7 @@ struct opttab_t
{ QSE_T("newline"), QSE_AWK_NEWLINE, QSE_T("enable a newline to terminate a statement") },
{ QSE_T("striprecspc"), QSE_AWK_STRIPRECSPC, QSE_T("strip spaces in splitting a record") },
{ QSE_T("stripstrspc"), QSE_AWK_STRIPSTRSPC, QSE_T("strip spaces in string-to-number conversion") },
{ QSE_T("blankconcat"), QSE_AWK_BLANKCONCAT, QSE_T("enable concatenation by blanks") },
{ QSE_T("crlf"), QSE_AWK_CRLF, QSE_T("use CRLF for a newline") },
{ QSE_T("maptovar"), QSE_AWK_MAPTOVAR, QSE_T("allow a map to be assigned or returned") },
{ QSE_T("pablock"), QSE_AWK_PABLOCK, QSE_T("enable pattern-action loop") },
@ -527,6 +528,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
{ QSE_T(":newline"), QSE_T('\0') },
{ QSE_T(":striprecspc"), QSE_T('\0') },
{ QSE_T(":stripstrspc"), QSE_T('\0') },
{ QSE_T(":blankconcat"), QSE_T('\0') },
{ QSE_T(":crlf"), QSE_T('\0') },
{ QSE_T(":maptovar"), QSE_T('\0') },
{ QSE_T(":pablock"), QSE_T('\0') },

View File

@ -964,6 +964,8 @@ enum qse_awk_trait_t
*/
QSE_AWK_STRIPSTRSPC = (1 << 7),
QSE_AWK_BLANKCONCAT = (1 << 8),
/** CR + LF by default */
QSE_AWK_CRLF = (1 << 10),
@ -1016,9 +1018,10 @@ enum qse_awk_trait_t
* makes #qse_awk_t to behave compatibly with classical AWK
* implementations
*/
QSE_AWK_CLASSIC = QSE_AWK_IMPLICIT | QSE_AWK_RIO |
QSE_AWK_NEWLINE | QSE_AWK_PABLOCK |
QSE_AWK_STRIPSTRSPC | QSE_AWK_STRICTNAMING
QSE_AWK_CLASSIC =
QSE_AWK_IMPLICIT | QSE_AWK_RIO |
QSE_AWK_NEWLINE | QSE_AWK_BLANKCONCAT | QSE_AWK_PABLOCK |
QSE_AWK_STRIPSTRSPC | QSE_AWK_STRICTNAMING
};
/* ------------------------------------------------------------------------ */

View File

@ -3533,13 +3533,13 @@ static qse_awk_nde_t* parse_binary (
{
qse_awk_nde_t* left = QSE_NULL;
qse_awk_nde_t* right = QSE_NULL;
qse_awk_loc_t rloc;
left = next_level_func (awk, xloc);
if (left == QSE_NULL) goto oops;
do
{
qse_awk_loc_t rloc;
const binmap_t* p = binmap;
int matched = 0;
int opcode, fold;
@ -3626,8 +3626,7 @@ static qse_awk_nde_t* parse_binary (
tmp = new_exp_bin_node (awk, xloc, opcode, left, right);
if (tmp == QSE_NULL) goto oops;
left = tmp;
right = QSE_NULL;
left = tmp; right = QSE_NULL;
break;
}
}
@ -3807,6 +3806,7 @@ static qse_awk_nde_t* parse_concat (qse_awk_t* awk, const qse_awk_loc_t* xloc)
{
qse_awk_nde_t* left = QSE_NULL;
qse_awk_nde_t* right = QSE_NULL;
qse_awk_loc_t rloc;
left = parse_additive (awk, xloc);
if (left == QSE_NULL) goto oops;
@ -3814,25 +3814,26 @@ static qse_awk_nde_t* parse_concat (qse_awk_t* awk, const qse_awk_loc_t* xloc)
do
{
qse_awk_nde_t* tmp;
qse_awk_loc_t rloc;
if (MATCH(awk,TOK_CONCAT))
{
if (get_token(awk) <= -1) goto oops;
}
else if (MATCH(awk,TOK_LPAREN) ||
MATCH(awk,TOK_DOLLAR) ||
MATCH(awk,TOK_PLUS) ||
MATCH(awk,TOK_MINUS) ||
MATCH(awk,TOK_PLUSPLUS) ||
MATCH(awk,TOK_MINUSMINUS) ||
MATCH(awk,TOK_LNOT) ||
((awk->opt.trait & QSE_AWK_TOLERANT) &&
(awk->tok.type == TOK_PRINT || awk->tok.type == TOK_PRINTF)) ||
awk->tok.type >= TOK_GETLINE)
else if (awk->opt.trait & QSE_AWK_BLANKCONCAT)
{
/* TODO: is the check above sufficient? */
if (!(awk->opt.trait & QSE_AWK_IMPLICIT)) break;
if (MATCH(awk,TOK_LPAREN) || MATCH(awk,TOK_DOLLAR) ||
/* unary operators */
MATCH(awk,TOK_PLUS) || MATCH(awk,TOK_MINUS) ||
MATCH(awk,TOK_LNOT) || MATCH(awk,TOK_BNOT) ||
/* increment operators */
MATCH(awk,TOK_PLUSPLUS) || MATCH(awk,TOK_MINUSMINUS) ||
((awk->opt.trait & QSE_AWK_TOLERANT) &&
(awk->tok.type == TOK_PRINT || awk->tok.type == TOK_PRINTF)) ||
awk->tok.type >= TOK_GETLINE)
{
/* proceed to handle concatenation expression */
}
else break;
}
else break;
@ -3840,11 +3841,9 @@ static qse_awk_nde_t* parse_concat (qse_awk_t* awk, const qse_awk_loc_t* xloc)
right = parse_additive (awk, &rloc);
if (right == QSE_NULL) goto oops;
tmp = new_exp_bin_node (
awk, xloc, QSE_AWK_BINOP_CONCAT, left, right);
if (left == QSE_NULL) goto oops;
left = tmp;
right = QSE_NULL;
tmp = new_exp_bin_node (awk, xloc, QSE_AWK_BINOP_CONCAT, left, right);
if (tmp == QSE_NULL) goto oops;
left = tmp; right = QSE_NULL;
}
while (1);
@ -4523,32 +4522,43 @@ static qse_awk_nde_t* parse_primary_nogetline (
if (get_token(awk) <= -1) return QSE_NULL;
if (MATCH(awk,TOK_IDENT))
if (MATCH(awk,TOK_IDENT) || MATCH(awk,TOK_DOLLAR))
{
/* getline var */
/* getline var
* getline $XXX */
qse_awk_loc_t gloc = awk->tok.loc;
var = parse_primary (awk, &gloc);
if (var == QSE_NULL) return QSE_NULL;
if (!is_var(var) && var->type != QSE_AWK_NDE_POS)
{
/* this is 'getline' followed by an expression probably.
* getline a()
* getline sys::WNOHANG
*/
SETERR_LOC (awk, QSE_AWK_EBADARG, &gloc);
qse_awk_clrpt (awk, var);
return QSE_NULL;
}
}
if (MATCH(awk, TOK_LT))
{
qse_awk_loc_t ploc;
/* getline [var] < file */
if (get_token(awk) <= -1)
{
if (var != QSE_NULL) qse_awk_clrpt (awk, var);
if (var) qse_awk_clrpt (awk, var);
return QSE_NULL;
}
{
qse_awk_loc_t ploc = awk->tok.loc;
/* TODO: is this correct? */
/*in = parse_expr_dc (awk, &ploc);*/
in = parse_primary (awk, &ploc);
}
ploc = awk->tok.loc;
/* TODO: is this correct? */
/*in = parse_expr_dc (awk, &ploc);*/
in = parse_primary (awk, &ploc);
if (in == QSE_NULL)
{
if (var != QSE_NULL) qse_awk_clrpt (awk, var);
if (var) qse_awk_clrpt (awk, var);
return QSE_NULL;
}
}
@ -4557,9 +4567,9 @@ static qse_awk_nde_t* parse_primary_nogetline (
awk, QSE_SIZEOF(qse_awk_nde_getline_t));
if (nde == QSE_NULL)
{
if (var != QSE_NULL) qse_awk_clrpt (awk, var);
if (in != QSE_NULL) qse_awk_clrpt (awk, in);
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
if (var) qse_awk_clrpt (awk, var);
if (in) qse_awk_clrpt (awk, in);
return QSE_NULL;
}
@ -4602,12 +4612,11 @@ static qse_awk_nde_t* parse_primary_nogetline (
return QSE_NULL;
}
static qse_awk_nde_t* parse_primary (
qse_awk_t* awk, const qse_awk_loc_t* xloc)
static qse_awk_nde_t* parse_primary (qse_awk_t* awk, const qse_awk_loc_t* xloc)
{
qse_awk_nde_t* left;
qse_awk_nde_getline_t* nde;
qse_awk_nde_t* var;
qse_awk_nde_t* var = QSE_NULL;
left = parse_primary_nogetline (awk, xloc);
@ -4621,46 +4630,40 @@ static qse_awk_nde_t* parse_primary (
{
intype = QSE_AWK_IN_PIPE;
}
else if (MATCH(awk,TOK_LOR))
else if (MATCH(awk,TOK_LOR) &&
(awk->opt.trait & QSE_AWK_RWPIPE))
{
if (awk->opt.trait & QSE_AWK_RWPIPE)
intype = QSE_AWK_IN_RWPIPE;
intype = QSE_AWK_IN_RWPIPE;
}
}
if (intype == -1) break;
if (preget_token(awk) <= -1)
{
qse_awk_clrpt (awk, left);
return QSE_NULL;
}
if (preget_token(awk) <= -1) goto oops;
if (awk->ntok.type != TOK_GETLINE) break;
var = QSE_NULL;
/* consume ntok */
/* consume ntok('getline') */
get_token (awk);
/* get the next token */
if (get_token(awk) <= -1)
{
qse_awk_clrpt (awk, left);
return QSE_NULL;
}
if (get_token(awk) <= -1) goto oops;
/* TODO: is this correct? */
if (MATCH(awk,TOK_IDENT))
if (MATCH(awk,TOK_IDENT) || MATCH(awk,TOK_DOLLAR))
{
/* command | getline var
* command || getline var */
qse_awk_loc_t gloc = awk->tok.loc;
var = parse_primary_ident (awk, &gloc);
if (var == QSE_NULL)
var = parse_primary (awk, &gloc);
if (var == QSE_NULL) goto oops;
if (!is_var(var) & var->type != QSE_AWK_NDE_POS)
{
qse_awk_clrpt (awk, left);
return QSE_NULL;
/* fucntion a() {}
* print ("ls -laF" | getline a()) */
SETERR_LOC (awk, QSE_AWK_EBADARG, &gloc);
goto oops;
}
}
@ -4668,9 +4671,8 @@ static qse_awk_nde_t* parse_primary (
awk, QSE_SIZEOF(qse_awk_nde_getline_t));
if (nde == QSE_NULL)
{
qse_awk_clrpt (awk, left);
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
return QSE_NULL;
goto oops;
}
nde->type = QSE_AWK_NDE_GETLINE;
@ -4681,10 +4683,16 @@ static qse_awk_nde_t* parse_primary (
nde->in = left;
left = (qse_awk_nde_t*)nde;
var = QSE_NULL;
}
while (1);
return left;
oops:
if (var) qse_awk_clrpt (awk, var);
qse_awk_clrpt (awk, left);
return QSE_NULL;
}
#define FNTYPE_UNKNOWN 0

View File

@ -230,7 +230,7 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde)
QSE_ASSERT (px->left->next == QSE_NULL);
PUT_SRCSTR (awk, QSE_T(" "));
PUT_SRCSTR (awk, binop_str[px->opcode][(awk->opt.trait & QSE_AWK_IMPLICIT)? 0: 1]);
PUT_SRCSTR (awk, binop_str[px->opcode][(awk->opt.trait & QSE_AWK_BLANKCONCAT)? 0: 1]);
PUT_SRCSTR (awk, QSE_T(" "));
if (px->right->type == QSE_AWK_NDE_ASS)