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("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("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("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("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("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") }, { 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(":newline"), QSE_T('\0') },
{ QSE_T(":striprecspc"), QSE_T('\0') }, { QSE_T(":striprecspc"), QSE_T('\0') },
{ QSE_T(":stripstrspc"), QSE_T('\0') }, { QSE_T(":stripstrspc"), QSE_T('\0') },
{ QSE_T(":blankconcat"), QSE_T('\0') },
{ QSE_T(":crlf"), QSE_T('\0') }, { QSE_T(":crlf"), QSE_T('\0') },
{ QSE_T(":maptovar"), QSE_T('\0') }, { QSE_T(":maptovar"), QSE_T('\0') },
{ QSE_T(":pablock"), 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_STRIPSTRSPC = (1 << 7),
QSE_AWK_BLANKCONCAT = (1 << 8),
/** CR + LF by default */ /** CR + LF by default */
QSE_AWK_CRLF = (1 << 10), QSE_AWK_CRLF = (1 << 10),
@ -1016,9 +1018,10 @@ enum qse_awk_trait_t
* makes #qse_awk_t to behave compatibly with classical AWK * makes #qse_awk_t to behave compatibly with classical AWK
* implementations * implementations
*/ */
QSE_AWK_CLASSIC = QSE_AWK_IMPLICIT | QSE_AWK_RIO | QSE_AWK_CLASSIC =
QSE_AWK_NEWLINE | QSE_AWK_PABLOCK | QSE_AWK_IMPLICIT | QSE_AWK_RIO |
QSE_AWK_STRIPSTRSPC | QSE_AWK_STRICTNAMING 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* left = QSE_NULL;
qse_awk_nde_t* right = QSE_NULL; qse_awk_nde_t* right = QSE_NULL;
qse_awk_loc_t rloc;
left = next_level_func (awk, xloc); left = next_level_func (awk, xloc);
if (left == QSE_NULL) goto oops; if (left == QSE_NULL) goto oops;
do do
{ {
qse_awk_loc_t rloc;
const binmap_t* p = binmap; const binmap_t* p = binmap;
int matched = 0; int matched = 0;
int opcode, fold; int opcode, fold;
@ -3626,8 +3626,7 @@ static qse_awk_nde_t* parse_binary (
tmp = new_exp_bin_node (awk, xloc, opcode, left, right); tmp = new_exp_bin_node (awk, xloc, opcode, left, right);
if (tmp == QSE_NULL) goto oops; if (tmp == QSE_NULL) goto oops;
left = tmp; left = tmp; right = QSE_NULL;
right = QSE_NULL;
break; 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* left = QSE_NULL;
qse_awk_nde_t* right = QSE_NULL; qse_awk_nde_t* right = QSE_NULL;
qse_awk_loc_t rloc;
left = parse_additive (awk, xloc); left = parse_additive (awk, xloc);
if (left == QSE_NULL) goto oops; 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 do
{ {
qse_awk_nde_t* tmp; qse_awk_nde_t* tmp;
qse_awk_loc_t rloc;
if (MATCH(awk,TOK_CONCAT)) if (MATCH(awk,TOK_CONCAT))
{ {
if (get_token(awk) <= -1) goto oops; if (get_token(awk) <= -1) goto oops;
} }
else if (MATCH(awk,TOK_LPAREN) || else if (awk->opt.trait & QSE_AWK_BLANKCONCAT)
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)
{ {
/* TODO: is the check above sufficient? */ if (MATCH(awk,TOK_LPAREN) || MATCH(awk,TOK_DOLLAR) ||
if (!(awk->opt.trait & QSE_AWK_IMPLICIT)) break; /* 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; 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); right = parse_additive (awk, &rloc);
if (right == QSE_NULL) goto oops; if (right == QSE_NULL) goto oops;
tmp = new_exp_bin_node ( tmp = new_exp_bin_node (awk, xloc, QSE_AWK_BINOP_CONCAT, left, right);
awk, xloc, QSE_AWK_BINOP_CONCAT, left, right); if (tmp == QSE_NULL) goto oops;
if (left == QSE_NULL) goto oops; left = tmp; right = QSE_NULL;
left = tmp;
right = QSE_NULL;
} }
while (1); while (1);
@ -4523,32 +4522,43 @@ static qse_awk_nde_t* parse_primary_nogetline (
if (get_token(awk) <= -1) return QSE_NULL; 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; qse_awk_loc_t gloc = awk->tok.loc;
var = parse_primary (awk, &gloc); var = parse_primary (awk, &gloc);
if (var == QSE_NULL) return QSE_NULL; 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)) if (MATCH(awk, TOK_LT))
{ {
qse_awk_loc_t ploc;
/* getline [var] < file */ /* getline [var] < file */
if (get_token(awk) <= -1) if (get_token(awk) <= -1)
{ {
if (var != QSE_NULL) qse_awk_clrpt (awk, var); if (var) qse_awk_clrpt (awk, var);
return QSE_NULL; return QSE_NULL;
} }
{ ploc = awk->tok.loc;
qse_awk_loc_t ploc = awk->tok.loc; /* TODO: is this correct? */
/* TODO: is this correct? */ /*in = parse_expr_dc (awk, &ploc);*/
/*in = parse_expr_dc (awk, &ploc);*/ in = parse_primary (awk, &ploc);
in = parse_primary (awk, &ploc);
}
if (in == QSE_NULL) if (in == QSE_NULL)
{ {
if (var != QSE_NULL) qse_awk_clrpt (awk, var); if (var) qse_awk_clrpt (awk, var);
return QSE_NULL; return QSE_NULL;
} }
} }
@ -4557,9 +4567,9 @@ static qse_awk_nde_t* parse_primary_nogetline (
awk, QSE_SIZEOF(qse_awk_nde_getline_t)); awk, QSE_SIZEOF(qse_awk_nde_getline_t));
if (nde == QSE_NULL) 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); SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
if (var) qse_awk_clrpt (awk, var);
if (in) qse_awk_clrpt (awk, in);
return QSE_NULL; return QSE_NULL;
} }
@ -4602,12 +4612,11 @@ static qse_awk_nde_t* parse_primary_nogetline (
return QSE_NULL; return QSE_NULL;
} }
static qse_awk_nde_t* parse_primary ( static qse_awk_nde_t* parse_primary (qse_awk_t* awk, const qse_awk_loc_t* xloc)
qse_awk_t* awk, const qse_awk_loc_t* xloc)
{ {
qse_awk_nde_t* left; qse_awk_nde_t* left;
qse_awk_nde_getline_t* nde; qse_awk_nde_getline_t* nde;
qse_awk_nde_t* var; qse_awk_nde_t* var = QSE_NULL;
left = parse_primary_nogetline (awk, xloc); left = parse_primary_nogetline (awk, xloc);
@ -4621,46 +4630,40 @@ static qse_awk_nde_t* parse_primary (
{ {
intype = QSE_AWK_IN_PIPE; 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 (intype == -1) break;
if (preget_token(awk) <= -1) if (preget_token(awk) <= -1) goto oops;
{
qse_awk_clrpt (awk, left);
return QSE_NULL;
}
if (awk->ntok.type != TOK_GETLINE) break; if (awk->ntok.type != TOK_GETLINE) break;
var = QSE_NULL; /* consume ntok('getline') */
/* consume ntok */
get_token (awk); get_token (awk);
/* get the next token */ /* get the next token */
if (get_token(awk) <= -1) if (get_token(awk) <= -1) goto oops;
{
qse_awk_clrpt (awk, left);
return QSE_NULL;
}
/* TODO: is this correct? */ /* TODO: is this correct? */
if (MATCH(awk,TOK_IDENT)) if (MATCH(awk,TOK_IDENT) || MATCH(awk,TOK_DOLLAR))
{ {
/* command | getline var /* command | getline var
* command || getline var */ * command || getline var */
qse_awk_loc_t gloc = awk->tok.loc; qse_awk_loc_t gloc = awk->tok.loc;
var = parse_primary_ident (awk, &gloc); var = parse_primary (awk, &gloc);
if (var == QSE_NULL) if (var == QSE_NULL) goto oops;
if (!is_var(var) & var->type != QSE_AWK_NDE_POS)
{ {
qse_awk_clrpt (awk, left); /* fucntion a() {}
return QSE_NULL; * 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)); awk, QSE_SIZEOF(qse_awk_nde_getline_t));
if (nde == QSE_NULL) if (nde == QSE_NULL)
{ {
qse_awk_clrpt (awk, left);
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
return QSE_NULL; goto oops;
} }
nde->type = QSE_AWK_NDE_GETLINE; nde->type = QSE_AWK_NDE_GETLINE;
@ -4681,10 +4683,16 @@ static qse_awk_nde_t* parse_primary (
nde->in = left; nde->in = left;
left = (qse_awk_nde_t*)nde; left = (qse_awk_nde_t*)nde;
var = QSE_NULL;
} }
while (1); while (1);
return left; return left;
oops:
if (var) qse_awk_clrpt (awk, var);
qse_awk_clrpt (awk, left);
return QSE_NULL;
} }
#define FNTYPE_UNKNOWN 0 #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); QSE_ASSERT (px->left->next == QSE_NULL);
PUT_SRCSTR (awk, QSE_T(" ")); 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(" ")); PUT_SRCSTR (awk, QSE_T(" "));
if (px->right->type == QSE_AWK_NDE_ASS) if (px->right->type == QSE_AWK_NDE_ASS)