fixed a bug in run_delete()

This commit is contained in:
hyung-hwan 2009-03-02 21:34:43 +00:00
parent 8e221ca599
commit faf9c80f3f
6 changed files with 116 additions and 76 deletions

View File

@ -48,6 +48,14 @@ struct qse_sed_t
QSE_DEFINE_COMMON_FIELDS (sed)
qse_sed_errnum_t errnum;
/* source code pointers */
struct
{
const qse_char_t* ptr;
const qse_char_t* end;
const qse_char_t* cur;
} src;
void* lastrex;
qse_str_t rexbuf; /* temporary regular expression buffer */
@ -56,8 +64,8 @@ struct qse_sed_t
struct
{
qse_sed_c_t* buf;
qse_sed_c_t* cur;
qse_sed_c_t* end;
qse_sed_c_t* cur;
} cmd;
};

View File

@ -1,5 +1,5 @@
/*
* $Id: run.c 91 2009-03-01 14:54:28Z hyunghwan.chung $
* $Id: run.c 92 2009-03-02 03:34:43Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
@ -2574,11 +2574,10 @@ static int run_delete (qse_awk_rtx_t* run, qse_awk_nde_delete_t* nde)
out.type = QSE_AWK_RTX_VALTOSTR_CPL;
out.u.cpl.ptr = buf;
out.u.cpl.len = QSE_COUNTOF(buf);
key = qse_awk_rtx_valtostr (run, idx, &out);
if (key == QSE_NULL)
{
/* if it doesn't work, switch to dynamic mode */
/* retry it in dynamic mode */
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
key = qse_awk_rtx_valtostr (run, idx, &out);
}
@ -2592,15 +2591,12 @@ static int run_delete (qse_awk_rtx_t* run, qse_awk_nde_delete_t* nde)
return -1;
}
if (out.type == QSE_AWK_RTX_VALTOSTR_CPL)
keylen = out.u.cpl.len;
else
keylen = out.u.cpldup.len;
keylen = (out.type == QSE_AWK_RTX_VALTOSTR_CPL)?
out.u.cpl.len: out.u.cpldup.len;
qse_map_delete (map, key, keylen);
if (out.type == QSE_AWK_RTX_VALTOSTR_CPLDUP)
QSE_AWK_FREE (run->awk, out.u.cpldup.ptr);
if (key != buf) QSE_AWK_FREE (run->awk, key);
}
else
{
@ -2707,21 +2703,12 @@ static int run_delete (qse_awk_rtx_t* run, qse_awk_nde_delete_t* nde)
out.type = QSE_AWK_RTX_VALTOSTR_CPL;
out.u.cpl.ptr = buf;
out.u.cpl.len = QSE_COUNTOF(buf);
if (qse_awk_rtx_valtostr (run, idx, &out) == QSE_NULL)
key = qse_awk_rtx_valtostr (run, idx, &out);
if (key == QSE_NULL)
{
/* if it doesn't work, switch to dynamic mode */
/* retry it in the dynamic mode */
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
if (qse_awk_rtx_valtostr (run, idx, &out) != QSE_NULL)
{
key = out.u.cpldup.ptr;
keylen = out.u.cpldup.len;
}
}
else
{
key = out.u.cpl.ptr;
keylen = out.u.cpl.len;
QSE_ASSERT (key == buf);
key = qse_awk_rtx_valtostr (run, idx, &out);
}
qse_awk_rtx_refdownval (run, idx);
@ -2732,7 +2719,11 @@ static int run_delete (qse_awk_rtx_t* run, qse_awk_nde_delete_t* nde)
return -1;
}
keylen = (out.type == QSE_AWK_RTX_VALTOSTR_CPL)?
out.u.cpl.len: out.u.cpldup.len;
qse_map_delete (map, key, keylen);
if (key != buf) QSE_AWK_FREE (run->awk, key);
}
else

View File

@ -83,14 +83,13 @@ void qse_sed_fini (qse_sed_t* sed)
qse_str_fini (&sed->rexbuf);
}
/* get the current character without advancing the pointer */
#define CC(ptr,end) ((ptr < end)? *ptr: QSE_CHAR_EOF)
/* get the current character advancing the pointer */
#define NC(ptr,end) ((ptr < end)? *ptr++: QSE_CHAR_EOF)
/* get the current charanter of the source code */
#define CURSC(sed) \
(((sed)->src.cur < (sed)->src.end)? *(sed)->src.cur: QSE_CHAR_EOF)
/* advance the current pointer of the source code */
#define ADVSCP(sed) ((sed)->src.cur++)
static const void* compile (
qse_sed_t* sed, const qse_char_t* ptr,
const qse_char_t* end, qse_char_t seof)
static void* compile_regex (qse_sed_t* sed, qse_char_t seof)
{
void* code;
qse_cint_t c;
@ -99,7 +98,8 @@ static const void* compile (
for (;;)
{
c = NC (ptr, end);
ADVSCP (sed);
c = CURSC (sed);
if (c == QSE_CHAR_EOF || c == QSE_T('\n'))
{
sed->errnum = QSE_SED_ETMTXT;
@ -110,7 +110,8 @@ static const void* compile (
if (c == QSE_T('\\'))
{
c = NC (ptr, end);
ADVSCP (sed);
c = CURSC (sed);
if (c == QSE_CHAR_EOF || c == QSE_T('\n'))
{
sed->errnum = QSE_SED_ETMTXT;
@ -141,25 +142,23 @@ static const void* compile (
}
sed->lastrex = code;
return ptr;
return code;
}
static const qse_char_t* address (
qse_sed_t* sed, const qse_char_t* ptr,
const qse_char_t* end, qse_sed_a_t* a)
static qse_sed_a_t* address (qse_sed_t* sed, qse_sed_a_t* a)
{
qse_cint_t c;
c = NC (ptr, end);
if ((c = *ptr) == QSE_T('$'))
c = CURSC (sed);
if (c == QSE_T('$'))
{
a->type = QSE_SED_A_DOL;
ptr++;
ADVSCP (sed);
}
else if (c == QSE_T('/'))
{
ptr++;
if (compile (sed, ptr, end, c) == QSE_NULL)
ADVSCP (sed);
if (compile_regex (sed, c) == QSE_NULL)
return QSE_NULL;
a->u.rex = sed->lastrex;
@ -171,9 +170,9 @@ static const qse_char_t* address (
do
{
lno = lno * 10 + c - QSE_T('0');
ptr++;
ADVSCP (sed);
}
while ((c = *ptr) >= QSE_T('0') && c <= QSE_T('9'));
while ((c = CURSC(sed)) >= QSE_T('0') && c <= QSE_T('9'));
/* line number 0 is illegal */
if (lno == 0) return QSE_NULL;
@ -190,22 +189,21 @@ static const qse_char_t* address (
a->type = QSE_SED_A_NONE;
}
return ptr;
return a;
}
static const qse_char_t* command (
qse_sed_t* sed, const qse_char_t* ptr, const qse_char_t* end)
static int command (qse_sed_t* sed)
{
qse_cint_t c;
qse_sed_c_t* cmd = sed->cmd.cur;
c = NC (ptr, end);
c = CURSC (sed);
switch (c)
{
default:
sed->errnum = QSE_SED_ECMDNR;
return QSE_NULL;
return -1;
case QSE_T('{'):
/* insert a negated branch command at the beginning
@ -224,7 +222,7 @@ static const qse_char_t* command (
{
/* label cannot have an address */
sed->errnum = QSE_SED_EA1PHB;
return QSE_NULL;
return -1;
}
/* skip white spaces */
@ -237,7 +235,7 @@ static const qse_char_t* command (
if (cmd->a2.type != QSE_SED_A_NONE)
{
sed->errnum = QSE_SED_EA2PHB;
return QSE_NULL;
return -1;
}
break;
@ -246,16 +244,24 @@ static const qse_char_t* command (
if (cmd->a2.type != QSE_SED_A_NONE)
{
sed->errnum = QSE_SED_EA2PHB;
return QSE_NULL;
return -1;
}
c = CURSC (sed);
if (c == QSE_T('\\'))
{
ADVSCP (sed);
c = CURSC (sed);
/* TODO: something wrong??? */
}
c = CC (ptr, end);
if (c == QSE_T('\\')) c = NC (ptr, end);
if (c != QSE_T('\n')) /* TODO: handle \r\n or others */
{
/* new line is expected */
sed->errnum = QSE_SED_ENEWLN;
return QSE_NULL;
return -1;
}
/* TODO: get the next line... */
@ -325,17 +331,20 @@ static const qse_char_t* command (
break;
}
return ptr;
return 0;
}
static const qse_char_t* fcomp (
static int compile_source (
qse_sed_t* sed, const qse_char_t* ptr, qse_size_t len)
{
qse_cint_t c;
const qse_char_t* end = ptr + len;
qse_sed_c_t* cmd = sed->cmd.cur;
/* store the source code pointers */
sed->src.ptr = ptr;
sed->src.end = ptr + len;
sed->src.cur = ptr;
/*
* # comment
* :label
@ -345,13 +354,13 @@ static const qse_char_t* fcomp (
*/
while (1)
{
c = CC (ptr, end);
c = CURSC (sed);
/* skip white spaces */
while (c == QSE_T(' ') || c == QSE_T('\t'))
{
ptr++;
c = CC (ptr, end);
ADVSCP (sed);
c = CURSC (sed);
}
/* check if it has reached the end or is commented */
@ -359,8 +368,8 @@ static const qse_char_t* fcomp (
if (c == QSE_T(';'))
{
/* semicolon without a meaningful address-command pair */
ptr++;
/* semicolon without a address-command pair */
ADVSCP (sed);
continue;
}
@ -368,10 +377,9 @@ static const qse_char_t* fcomp (
QSE_MEMSET (cmd, 0, QSE_SIZEOF(*cmd));
/* process address */
ptr = address (sed, ptr, end, &cmd->a1);
if (ptr == QSE_NULL) return QSE_NULL;
if (address (sed, &cmd->a1) == QSE_NULL) return -1;
c = CC (ptr, end);
c = CURSC (sed);
if (cmd->a1.type != QSE_SED_A_NONE)
{
/* if (cmd->a1.type == QSE_SED_A_LAST)
@ -381,12 +389,13 @@ static const qse_char_t* fcomp (
if (c == QSE_T(',') || c == QSE_T(';'))
{
/* maybe an address range */
ptr++;
ADVSCP (sed);
/* TODO: skip white spaces??? */
ptr = address (sed, ptr, end, &cmd->a2);
if (ptr == QSE_NULL) return QSE_NULL;
c = CC (ptr, end);
if (address (sed, &cmd->a2) == QSE_NULL)
return -1;
c = CURSC (sed);
}
else cmd->a2.type = QSE_SED_A_NONE;
}
@ -394,8 +403,8 @@ static const qse_char_t* fcomp (
/* skip white spaces */
while (c == QSE_T(' ') || c == QSE_T('\t'))
{
ptr++;
c = CC (ptr, end);
ADVSCP (sed);
c = CURSC (sed);
}
if (c == QSE_T('!'))
@ -404,8 +413,7 @@ static const qse_char_t* fcomp (
cmd->negfl = 1;
}
ptr = command (sed, ptr, end);
if (ptr == QSE_NULL) return QSE_NULL;
if (command (sed) == -1) return -1;
if (sed->cmd.cur >= sed->cmd.end)
{
@ -415,5 +423,5 @@ static const qse_char_t* fcomp (
cmd = ++sed->cmd.cur;
}
return ptr;
return 0;
}

View File

@ -1 +1 @@
SUBDIRS = cmn awk
SUBDIRS = cmn utl awk

8
qse/test/utl/Makefile.am Normal file
View File

@ -0,0 +1,8 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
bin_PROGRAMS = sed01
LDFLAGS = -L../../lib/cmn -L../../lib/utl -L../../lib/sed
LDADD = -lqseutl -lqsecmn $(LIBM)
sed01_SOURCES = sed01.c

25
qse/test/utl/sed01.c Normal file
View File

@ -0,0 +1,25 @@
/*
* $Id$
*
Copyright 2006-2009 Chung, Hyung-Hwan.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <qse/utl/sed.h>
#include <qse/utl/stdio.h>
int main ()
{
return 0;
}