From 6d68da16695fabe4d453cb496b6cf7df483fd517 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 11 May 2009 07:27:35 +0000 Subject: [PATCH] added more code --- qse/include/qse/utl/sed.h | 1 + qse/lib/utl/sed.c | 134 ++++++++++++++++++++++++++------------ qse/lib/utl/sed.h | 5 +- 3 files changed, 98 insertions(+), 42 deletions(-) diff --git a/qse/include/qse/utl/sed.h b/qse/include/qse/utl/sed.h index 609f7404..952e5410 100644 --- a/qse/include/qse/utl/sed.h +++ b/qse/include/qse/utl/sed.h @@ -45,6 +45,7 @@ enum qse_sed_errnum_t QSE_SED_ELABTL, /* label too long */ QSE_SED_ELABEM, /* label name is empty */ QSE_SED_ELABDU, /* duplicate label name */ + QSE_SED_ELABNF, /* label not found */ QSE_SED_EFILEM, /* file name is empty */ QSE_SED_EFILIL, /* illegal file name */ QSE_SED_ENOTRM, /* not terminated properly */ diff --git a/qse/lib/utl/sed.c b/qse/lib/utl/sed.c index 5eda9be9..106168ae 100644 --- a/qse/lib/utl/sed.c +++ b/qse/lib/utl/sed.c @@ -140,6 +140,7 @@ const qse_char_t* qse_sed_geterrmsg (qse_sed_t* sed) QSE_T("label name too long"), QSE_T("empty label name"), QSE_T("duplicate label name"), + QSE_T("label not found"), QSE_T("empty file name"), QSE_T("illegal file name"), QSE_T("command not terminated properly"), @@ -213,7 +214,7 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_MMGR_FREE (sed->mmgr, cmd->u.text.ptr); break; - case QSE_SED_CMD_B: + case QSE_SED_CMD_BRANCH: case QSE_SED_CMD_T: if (cmd->u.branch.label.ptr != QSE_NULL) QSE_MMGR_FREE (sed->mmgr, cmd->u.branch.label.ptr); @@ -979,7 +980,7 @@ qse_printf (QSE_T("command not recognized [%c]\n"), c); * of a group. this way, all the commands in a group * can be skipped. the branch target is set once a * corresponding } is met. */ - cmd->type = QSE_SED_CMD_B; + cmd->type = QSE_SED_CMD_BRANCH; cmd->negated = !cmd->negated; if (sed->grplvl >= QSE_COUNTOF(sed->grpcmd)) @@ -1005,20 +1006,6 @@ qse_printf (QSE_T("command not recognized [%c]\n"), c); ADVSCP (sed); return 0; - case QSE_T('='): - cmd->type = c; - if (sed->option & QSE_SED_CLASSIC && - cmd->a2.type != QSE_SED_A_NONE) - { - sed->errnum = QSE_SED_EA2PHB; - return -1; - } - - ADVSCP (sed); - if (terminate_command (sed) <= -1) return -1; -qse_printf (QSE_T("command %c\n"), cmd->type); - break; - case QSE_T('q'): case QSE_T('Q'): cmd->type = c; @@ -1081,7 +1068,15 @@ qse_printf (QSE_T("%s%s"), ttt, cmd->u.text.ptr); break; } - + case QSE_T('='): + if (sed->option & QSE_SED_CLASSIC && + cmd->a2.type != QSE_SED_A_NONE) + { + sed->errnum = QSE_SED_EA2PHB; + return -1; + } + case QSE_T('p'): + case QSE_T('P'): case QSE_T('d'): case QSE_T('D'): case QSE_T('h'): @@ -1091,8 +1086,6 @@ qse_printf (QSE_T("%s%s"), ttt, cmd->u.text.ptr); case QSE_T('l'): case QSE_T('n'): case QSE_T('N'): - case QSE_T('p'): - case QSE_T('P'): case QSE_T('x'): cmd->type = c; ADVSCP (sed); @@ -1235,9 +1228,14 @@ static int compile_source ( if (c == QSE_T('!')) { - /* negate */ - cmd->negated = 1; - do { ADVSCP (sed); } while (IS_SPACE(c)); + /* allow any number of the negation indicators */ + do { + cmd->negated = !cmd->negated; + c = NXTSC(sed); + } + while (c== QSE_T('!')); + + while (IS_SPACE(c)) c = NXTSC (sed); } @@ -1528,9 +1526,11 @@ static int match_address (qse_sed_t* sed, qse_sed_cmd_t* cmd) { int n; + cmd->state.c_ready = 0; if (cmd->a1.type == QSE_SED_A_NONE) { QSE_ASSERT (cmd->a2.type == QSE_SED_A_NONE); + cmd->state.c_ready = 1; return 1; } else if (cmd->a2.type != QSE_SED_A_NONE) @@ -1545,38 +1545,53 @@ static int match_address (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (cmd->a2.type == QSE_SED_A_LINE && sed->eio.in.num > cmd->a2.u.line) { + /* exit the range */ cmd->state.a1_matched = 0; return 0; } + /* still in the range. return match + * despite the actual mismatch */ return 1; } + /* exit the range */ cmd->state.a1_matched = 0; - //lastaddr = 1; + cmd->state.c_ready = 1; return 1; } else { n = match_a (sed, &cmd->a1); if (n <= -1) return -1; - if (n == 0) return 0; + if (n == 0) + { + return 0; + } if (cmd->a2.type == QSE_SED_A_LINE && sed->eio.in.num >= cmd->a2.u.line) { - //lastaddr = 1; + /* the line number specified in the second + * address is equal to or less than the current + * line number. */ + cmd->state.c_ready = 1; } else { + /* mark that the first is matched so as to + * move on to the range test */ cmd->state.a1_matched = 1; } + return 1; } } else { /* single address */ + cmd->state.c_ready = 1; + n = match_a (sed, &cmd->a1); return (n <= -1)? -1: (n == 0)? 0: 1; @@ -1599,10 +1614,6 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) jumpto = sed->cmd.cur + 1; break; - case QSE_SED_CMD_PRINT_LNUM: - if (write_num (sed, sed->eio.in.num) <= -1) return QSE_NULL; - if (write_char (sed, QSE_T('\n')) <= -1) return QSE_NULL; - break; case QSE_SED_CMD_APPEND: if (qse_lda_insert ( @@ -1623,20 +1634,30 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) break; case QSE_SED_CMD_CHANGE: - /* change the input space */ - n = qse_str_ncpy ( - &sed->eio.in.line, - QSE_STR_PTR(&cmd->u.text), - QSE_STR_LEN(&cmd->u.text)); - if (n == (qse_size_t)-1) + if (cmd->state.c_ready) { - sed->errnum = QSE_SED_ENOMEM; - return QSE_NULL; + /* change the input space */ + n = qse_str_ncpy ( + &sed->eio.in.line, + QSE_STR_PTR(&cmd->u.text), + QSE_STR_LEN(&cmd->u.text)); + if (n == (qse_size_t)-1) + { + sed->errnum = QSE_SED_ENOMEM; + return QSE_NULL; + } + + /* move past the last command so as to start + * the next cycle */ + jumpto = sed->cmd.cur; + } + else + { +/* TODO: prearrange for CHANGE to be executed on the lastline wihtout + matchng the second address */ + qse_str_clear (&sed->eio.in.line); } - /* move past the last command so as to start - * the next cycle */ - jumpto = sed->cmd.cur; break; case QSE_SED_CMD_DELETE: @@ -1646,6 +1667,39 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) * the next cycle */ jumpto = sed->cmd.cur; break; + + case QSE_SED_CMD_PRINT_LNUM: + if (write_num (sed, sed->eio.in.num) <= -1) return QSE_NULL; + if (write_char (sed, QSE_T('\n')) <= -1) return QSE_NULL; + break; + + case QSE_SED_CMD_PRINT: + n = write_str (sed, + QSE_STR_PTR(&sed->eio.in.line), + QSE_STR_LEN(&sed->eio.in.line)); + if (n <= -1) return QSE_NULL; + break; + + case QSE_SED_CMD_BRANCH: + if (cmd->u.branch.target == QSE_NULL) + { + qse_map_pair_t* pair; + qse_xstr_t* lab = &cmd->u.branch.label; + + QSE_ASSERT (lab->ptr != QSE_NULL && lab->len > 0); + pair = qse_map_search ( + &sed->labs, lab->ptr, lab->len); + if (pair == QSE_NULL) + { + sed->errnum = QSE_SED_ELABNF; + return QSE_NULL; + } + + cmd->u.branch.target = QSE_MAP_VPTR(pair); + } + + jumpto = cmd->u.branch.target; + break; } if (jumpto == NULL) jumpto = cmd + 1; diff --git a/qse/lib/utl/sed.h b/qse/lib/utl/sed.h index 7f517dad..fd5af299 100644 --- a/qse/lib/utl/sed.h +++ b/qse/lib/utl/sed.h @@ -71,13 +71,13 @@ struct qse_sed_cmd_t QSE_SED_CMD_L = QSE_T('l'), QSE_SED_CMD_N = QSE_T('n'), QSE_SED_CMD_NN = QSE_T('N'), - QSE_SED_CMD_P = QSE_T('p'), + QSE_SED_CMD_PRINT = QSE_T('p'), QSE_SED_CMD_PP = QSE_T('P'), /* exchange hold space and pattern space */ QSE_SED_CMD_X = QSE_T('x'), /* branch */ - QSE_SED_CMD_B = QSE_T('b'), + QSE_SED_CMD_BRANCH = QSE_T('b'), QSE_SED_CMD_T = QSE_T('t'), /* r filename - append a text from a file */ @@ -139,6 +139,7 @@ struct qse_sed_cmd_t struct { int a1_matched; + int c_ready; } state; };