added qse_sed_setexechook()

added qse_strfnmat() and related functions
This commit is contained in:
hyung-hwan 2011-09-24 08:52:22 +00:00
parent cd1c245670
commit b9e365f148
10 changed files with 1078 additions and 16 deletions

View File

@ -429,6 +429,25 @@ static void unset_intr_run (void)
#endif
}
static void trace (qse_sed_t* sed, qse_sed_exec_op_t op, const qse_sed_cmd_t* cmd)
{
switch (op)
{
case QSE_SED_EXEC_READ:
qse_printf (QSE_T("reading...\n"));
break;
case QSE_SED_EXEC_WRITE:
qse_printf (QSE_T("wrting...\n"));
break;
case QSE_SED_EXEC_MATCH:
qse_printf (QSE_T("matching...\n"));
break;
case QSE_SED_EXEC_EXEC:
qse_printf (QSE_T("executing...\n"));
break;
}
}
int sed_main (int argc, qse_char_t* argv[])
{
qse_mmgr_t* mmgr = QSE_NULL;
@ -499,6 +518,10 @@ int sed_main (int argc, qse_char_t* argv[])
goto oops;
}
#if 0
if (g_trace) qse_sed_setexechook (sed, trace);
#endif
if (g_separate && g_infile_pos > 0)
{
qse_sed_iostd_t out;

View File

@ -1,5 +1,5 @@
/*
* $Id: str.h 556 2011-08-31 15:43:46Z hyunghwan.chung $
* $Id: str.h 576 2011-09-23 14:52:22Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -317,6 +317,34 @@ enum qse_wcstrmx_op_t
# define QSE_STRTRMX_RIGHT QSE_WCSTRMX_RIGHT
#endif
enum qse_mbsfnmat_flag_t
{
QSE_MBSFNMAT_PATHNAME = (1 << 0),
QSE_MBSFNMAT_NOESCAPE = (1 << 1),
QSE_MBSFNMAT_PERIOD = (1 << 2),
QSE_MBSFNMAT_IGNORECASE = (1 << 3)
};
enum qse_wcsfnmat_flag_t
{
QSE_WCSFNMAT_PATHNAME = (1 << 0),
QSE_WCSFNMAT_NOESCAPE = (1 << 1),
QSE_WCSFNMAT_PERIOD = (1 << 2),
QSE_WCSFNMAT_IGNORECASE = (1 << 3)
};
#ifdef QSE_CHAR_IS_MCHAR
# define QSE_STRFNMAT_PATHNAME QSE_MBSFNMAT_PATHNAME
# define QSE_STRFNMAT_NOESCAPE QSE_MBSFNMAT_NOESCAPE
# define QSE_STRFNMAT_PERIOD QSE_MBSFNMAT_PERIOD
# define QSE_STRFNMAT_IGNORECASE QSE_MBSFNMAT_IGNORECASE
#else
# define QSE_STRFNMAT_PATHNAME QSE_WCSFNMAT_PATHNAME
# define QSE_STRFNMAT_NOESCAPE QSE_WCSFNMAT_NOESCAPE
# define QSE_STRFNMAT_PERIOD QSE_WCSFNMAT_PERIOD
# define QSE_STRFNMAT_IGNORECASE QSE_WCSFNMAT_IGNORECASE
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -1489,6 +1517,23 @@ qse_mchar_t* qse_mbspbrk (
const qse_mchar_t* str2
);
qse_mchar_t* qse_mbsxpbrk (
const qse_mchar_t* str1,
qse_size_t len,
const qse_mchar_t* str2
);
qse_mchar_t* qse_mbsrpbrk (
const qse_mchar_t* str1,
const qse_mchar_t* str2
);
qse_mchar_t* qse_mbsxrpbrk (
const qse_mchar_t* str1,
qse_size_t len,
const qse_mchar_t* str2
);
/*
* The qse_wcspbrk() function searches @a str1 for the first occurrence of
* a character in @a str2.
@ -1500,10 +1545,33 @@ qse_wchar_t* qse_wcspbrk (
const qse_wchar_t* str2
);
qse_wchar_t* qse_wcsxpbrk (
const qse_wchar_t* str1,
qse_size_t len,
const qse_wchar_t* str2
);
qse_wchar_t* qse_wcsrpbrk (
const qse_wchar_t* str1,
const qse_wchar_t* str2
);
qse_wchar_t* qse_wcsxrpbrk (
const qse_wchar_t* str1,
qse_size_t len,
const qse_wchar_t* str2
);
#ifdef QSE_CHAR_IS_MCHAR
# define qse_strpbrk(str1,str2) qse_mbspbrk(str1,str2)
# define qse_strpbrk(str1,str2) qse_mbspbrk(str1,str2)
# define qse_strxpbrk(str1,len,str2) qse_mbsxpbrk(str1,len,str2)
# define qse_strrpbrk(str1,str2) qse_mbsrpbrk(str1,str2)
# define qse_strxrpbrk(str1,len,str2) qse_mbsxrpbrk(str1,len,str2)
#else
# define qse_strpbrk(str1,str2) qse_wcspbrk(str1,str2)
# define qse_strpbrk(str1,str2) qse_wcspbrk(str1,str2)
# define qse_strxpbrk(str1,len,str2) qse_wcsxpbrk(str1,len,str2)
# define qse_strrpbrk(str1,str2) qse_wcsrpbrk(str1,str2)
# define qse_strxrpbrk(str1,len,str2) qse_wcsxrpbrk(str1,len,str2)
#endif
/*
@ -2101,6 +2169,74 @@ qse_size_t qse_wcsxpac (
# define qse_strxpac(str,len) qse_wcsxpac(str,len)
#endif
int qse_mbsfnmat (
const qse_mchar_t* str,
const qse_mchar_t* ptn,
int flags
);
int qse_mbsxfnmat (
const qse_mchar_t* str,
qse_size_t slen,
const qse_mchar_t* ptn,
int flags
);
int qse_mbsnfnmat (
const qse_mchar_t* str,
const qse_mchar_t* ptn,
qse_size_t plen,
int flags
);
int qse_mbsxnfnmat (
const qse_mchar_t* str,
qse_size_t slen,
const qse_mchar_t* ptn,
qse_size_t plen,
int flags
);
int qse_wcsfnmat (
const qse_wchar_t* str,
const qse_wchar_t* ptn,
int flags
);
int qse_wcsxfnmat (
const qse_wchar_t* str,
qse_size_t slen,
const qse_wchar_t* ptn,
int flags
);
int qse_wcsnfnmat (
const qse_wchar_t* str,
const qse_wchar_t* ptn,
qse_size_t plen,
int flags
);
int qse_wcsxnfnmat (
const qse_wchar_t* str,
qse_size_t slen,
const qse_wchar_t* ptn,
qse_size_t plen,
int flags
);
#ifdef QSE_CHAR_IS_MCHAR
# define qse_strfnmat(str,ptn,flags) qse_mbsfnmat(str,ptn,flags)
# define qse_strxfnmat(str,slen,ptn,flags) qse_mbsxfnmat(str,slen,ptn,flags)
# define qse_strnfnmat(str,ptn,plen,flags) qse_mbsnfnmat(str,ptn,plen,flags)
# define qse_strxnfnmat(str,slen,ptn,plen,flags) qse_mbsxnfnmat(str,slen,ptn,plen,flags)
#else
# define qse_strfnmat(str,ptn,flags) qse_wcsfnmat(str,ptn,flags)
# define qse_strxfnmat(str,slen,ptn,flags) qse_wcsxfnmat(str,slen,ptn,flags)
# define qse_strnfnmat(str,ptn,plen,flags) qse_wcsnfnmat(str,ptn,plen,flags)
# define qse_strxnfnmat(str,slen,ptn,plen,flags) qse_wcsxnfnmat(str,slen,ptn,plen,flags)
#endif
/**
* The qse_mbstowcslen() function scans a null-terminated multibyte string
* to calculate the number of wide characters it can be converted to.

View File

@ -1,5 +1,5 @@
/*
* $Id: sed.h 570 2011-09-20 04:40:45Z hyunghwan.chung $
* $Id: sed.h 576 2011-09-23 14:52:22Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -65,6 +65,8 @@
*/
typedef struct qse_sed_t qse_sed_t;
typedef struct qse_sed_cmd_t qse_sed_cmd_t;
/**
* The qse_sed_loc_t defines a structure to store location information.
*/
@ -193,6 +195,21 @@ typedef int (*qse_sed_lformatter_t) (
int (*cwriter) (qse_sed_t*, qse_char_t)
);
enum qse_sed_exec_op_t
{
QSE_SED_EXEC_READ,
QSE_SED_EXEC_WRITE,
QSE_SED_EXEC_MATCH,
QSE_SED_EXEC_EXEC
};
typedef enum qse_sed_exec_op_t qse_sed_exec_op_t;
typedef void (*qse_sed_exec_hook_t) (
qse_sed_t* sed,
qse_sed_exec_op_t op,
const qse_sed_cmd_t* cmd
);
#ifdef __cplusplus
extern "C" {
#endif
@ -415,6 +432,15 @@ void qse_sed_setlinnum (
qse_size_t num /**< a line number */
);
qse_sed_exec_hook_t qse_sed_getexechook (
qse_sed_t* sed
);
void qse_sed_setexechook (
qse_sed_t* sed,
qse_sed_exec_hook_t hook
);
#ifdef __cplusplus
}
#endif

View File

@ -47,6 +47,7 @@ libqsecmn_la_SOURCES = \
str-end.c \
str-excl.c \
str-fcpy.c \
str-fnmat.c \
str-incl.c \
str-len.c \
str-pac.c \

View File

@ -79,12 +79,13 @@ am_libqsecmn_la_OBJECTS = alg-search.lo alg-sort.lo assert.lo chr.lo \
rex.lo sio.lo sll.lo str-beg.lo str-cat.lo str-chr.lo \
str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo str-dup.lo \
str-dynm.lo str-dynw.lo str-end.lo str-excl.lo str-fcpy.lo \
str-incl.lo str-len.lo str-pac.lo str-pbrk.lo str-put.lo \
str-rev.lo str-rot.lo str-set.lo str-spl.lo str-spn.lo \
str-str.lo str-subst.lo str-tok.lo str-trm.lo str-word.lo \
time.lo tio.lo tio-get.lo tio-put.lo tre.lo tre-ast.lo \
tre-compile.lo tre-match-backtrack.lo tre-match-parallel.lo \
tre-parse.lo tre-stack.lo stdio.lo xma.lo
str-fnmat.lo str-incl.lo str-len.lo str-pac.lo str-pbrk.lo \
str-put.lo str-rev.lo str-rot.lo str-set.lo str-spl.lo \
str-spn.lo str-str.lo str-subst.lo str-tok.lo str-trm.lo \
str-word.lo time.lo tio.lo tio-get.lo tio-put.lo tre.lo \
tre-ast.lo tre-compile.lo tre-match-backtrack.lo \
tre-match-parallel.lo tre-parse.lo tre-stack.lo stdio.lo \
xma.lo
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -312,6 +313,7 @@ libqsecmn_la_SOURCES = \
str-end.c \
str-excl.c \
str-fcpy.c \
str-fnmat.c \
str-incl.c \
str-len.c \
str-pac.c \
@ -469,6 +471,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-end.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-excl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-fcpy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-fnmat.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-incl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-len.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-pac.Plo@am__quote@

692
qse/lib/cmn/str-fnmat.c Normal file
View File

@ -0,0 +1,692 @@
/*
* $Id$
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qse/cmn/str.h>
#include <qse/cmn/chr.h>
/* ------------------------------------------------------------------------- */
/* | MBS VERSION | */
/* ------------------------------------------------------------------------- */
/* separator to use in a pattern.
* this also matches a backslash in non-unix OS where a blackslash
* is used as a path separator. MBS_SEPCHS defines OS path separators. */
#define MBS_SEP QSE_MT('/')
#define MBS_ESC QSE_MT('\\')
#define MBS_DOT QSE_MT('.')
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define MBS_ISSEPCH(c) ((c) == QSE_MT('/') || (c) == QSE_MT('\\'))
# define MBS_SEPCHS QSE_MT("/\\")
#else
# define MBS_ISSEPCH(c) ((c) == QSE_MT('/'))
# define MBS_SEPCHS QSE_MT("/")
#endif
static int __mbsxnfnmat (
const qse_mchar_t* str, qse_size_t slen,
const qse_mchar_t* ptn, qse_size_t plen, int flags, int no_first_period)
{
const qse_mchar_t* sp = str;
const qse_mchar_t* pp = ptn;
const qse_mchar_t* se = str + slen;
const qse_mchar_t* pe = ptn + plen;
qse_mchar_t sc, pc, pc2;
while (1)
{
if (pp < pe && *pp == MBS_ESC &&
!(flags & QSE_MBSFNMAT_NOESCAPE))
{
/* pattern is escaped and escaping is allowed. */
if ((++pp) >= pe)
{
/*
* the last character of the pattern is an MBS_ESC.
* matching is performed as if the end of the pattern is
* reached just without an MBS_ESC.
*/
if (sp < se) return 0;
return 1;
}
if (sp >= se) return 0; /* premature string termination */
sc = *sp; pc = *pp; /* pc is just a normal character */
if ((flags & QSE_MBSFNMAT_IGNORECASE) != 0)
{
/* make characters to lower-case */
sc = QSE_TOMLOWER(sc);
pc = QSE_TOMLOWER(pc);
}
if (sc != pc) return 0;
sp++; pp++;
continue;
}
if (pp >= pe)
{
/*
* the end of the pattern has been reached.
* the string must terminate too.
*/
return sp >= se;
}
if (sp >= se)
{
/* the string terminats prematurely */
while (pp < pe && *pp == QSE_MT('*')) pp++;
return pp >= pe;
}
sc = *sp; pc = *pp;
if (sc == MBS_DOT && (flags & QSE_MBSFNMAT_PERIOD))
{
/*
* a leading period in the staring must match
* a period in the pattern explicitly
*/
if ((!no_first_period && sp == str) ||
(MBS_ISSEPCH(sp[-1]) && (flags & QSE_MBSFNMAT_PATHNAME)))
{
if (pc != MBS_DOT) return 0;
sp++; pp++;
continue;
}
}
else if (MBS_ISSEPCH(sc) && (flags & QSE_MBSFNMAT_PATHNAME))
{
while (pc == QSE_MT('*'))
{
if ((++pp) >= pe) return 0;
pc = *pp;
}
/* a path separator must be matched explicitly */
if (pc != MBS_SEP) return 0;
sp++; pp++;
continue;
}
/* the handling of special pattern characters begins here */
if (pc == QSE_MT('?'))
{
/* match any single character */
sp++; pp++;
}
else if (pc == QSE_MT('*'))
{
/* match zero or more characters */
/* compact asterisks */
do { pp++; } while (pp < pe && *pp == QSE_MT('*'));
if (pp >= pe)
{
/*
* if the last character in the pattern is an asterisk,
* the string should not have any directory separators
* when QSE_MBSFNMAT_PATHNAME is set.
*/
if (flags & QSE_MBSFNMAT_PATHNAME)
{
if (qse_mbsxpbrk(sp, se-sp, MBS_SEPCHS) != QSE_NULL) return 0;
}
return 1;
}
else
{
do
{
if (__mbsxnfnmat(sp, se - sp, pp, pe - pp, flags, 1))
{
return 1;
}
if (MBS_ISSEPCH(*sp) &&
(flags & QSE_MBSFNMAT_PATHNAME)) break;
sp++;
}
while (sp < se);
return 0;
}
}
else if (pc == QSE_MT('['))
{
/* match range */
int negate = 0;
int matched = 0;
if ((++pp) >= pe) return 0;
if (*pp == QSE_MT('!')) { negate = 1; pp++; }
while (pp < pe && *pp != QSE_MT(']'))
{
if (*pp == QSE_MT('['))
{
qse_size_t pl = pe - pp;
if (pl >= 10)
{
if (qse_mbszcmp(pp, QSE_MT("[:xdigit:]"), 10) == 0)
{
matched = QSE_ISMXDIGIT(sc);
pp += 10; continue;
}
}
if (pl >= 9)
{
if (qse_mbszcmp(pp, QSE_MT("[:upper:]"), 9) == 0)
{
matched = QSE_ISMUPPER(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:lower:]"), 9) == 0)
{
matched = QSE_ISMLOWER(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:alpha:]"), 9) == 0)
{
matched = QSE_ISMALPHA(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:digit:]"), 9) == 0)
{
matched = QSE_ISMDIGIT(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:alnum:]"), 9) == 0)
{
matched = QSE_ISMALNUM(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:space:]"), 9) == 0)
{
matched = QSE_ISMSPACE(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:print:]"), 9) == 0)
{
matched = QSE_ISMPRINT(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:graph:]"), 9) == 0)
{
matched = QSE_ISMGRAPH(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:cntrl:]"), 9) == 0)
{
matched = QSE_ISMCNTRL(sc);
pp += 9; continue;
}
else if (qse_mbszcmp(pp, QSE_MT("[:punct:]"), 9) == 0)
{
matched = QSE_ISMPUNCT(sc);
pp += 9; continue;
}
}
/*
* characters in an invalid class name are
* just treated as normal characters
*/
}
if (*pp == MBS_ESC &&
!(flags & QSE_MBSFNMAT_NOESCAPE)) pp++;
else if (*pp == QSE_MT(']')) break;
if (pp >= pe) break;
pc = *pp;
if ((flags & QSE_MBSFNMAT_IGNORECASE) != 0)
{
sc = QSE_TOMLOWER(sc);
pc = QSE_TOMLOWER(pc);
}
if (pp + 1 < pe && pp[1] == QSE_MT('-'))
{
pp += 2; /* move the a character next to a dash */
if (pp >= pe)
{
if (sc >= pc) matched = 1;
break;
}
if (*pp == MBS_ESC &&
!(flags & QSE_MBSFNMAT_NOESCAPE))
{
if ((++pp) >= pe)
{
if (sc >= pc) matched = 1;
break;
}
}
else if (*pp == QSE_MT(']'))
{
if (sc >= pc) matched = 1;
break;
}
pc2 = *pp;
if ((flags & QSE_MBSFNMAT_IGNORECASE) != 0)
pc2 = QSE_TOMLOWER(pc2);
if (sc >= pc && sc <= pc2) matched = 1;
pp++;
}
else
{
if (sc == pc) matched = 1;
pp++;
}
}
if (negate) matched = !matched;
if (!matched) return 0;
sp++; if (pp < pe) pp++;
}
else
{
/* a normal character */
if ((flags & QSE_MBSFNMAT_IGNORECASE) != 0)
{
sc = QSE_TOMLOWER(sc);
pc = QSE_TOMLOWER(pc);
}
if (sc != pc) return 0;
sp++; pp++;
}
}
/* will never reach here. but make some immature compilers happy... */
return 0;
}
int qse_mbsfnmat (const qse_mchar_t* str, const qse_mchar_t* ptn, int flags)
{
return __mbsxnfnmat (
str, qse_mbslen(str), ptn, qse_mbslen(ptn), flags, 0);
}
int qse_mbsxfnmat (
const qse_mchar_t* str, qse_size_t slen, const qse_mchar_t* ptn, int flags)
{
return __mbsxnfnmat (str, slen, ptn, qse_mbslen(ptn), flags, 0);
}
int qse_mbsnfnmat (
const qse_mchar_t* str, const qse_mchar_t* ptn, qse_size_t plen, int flags)
{
return __mbsxnfnmat (str, qse_mbslen(str), ptn, plen, flags, 0);
}
int qse_mbsxnfnmat (
const qse_mchar_t* str, qse_size_t slen,
const qse_mchar_t* ptn, qse_size_t plen, int flags)
{
return __mbsxnfnmat (str, slen, ptn, plen, flags, 0);
}
/* ------------------------------------------------------------------------- */
/* | WCS VERSION | */
/* ------------------------------------------------------------------------- */
/* separator to use in a pattern.
* this also matches a backslash in non-unix OS where a blackslash
* is used as a path separator. WCS_SEPCHS defines OS path separators. */
#define WCS_SEP QSE_WT('/')
#define WCS_ESC QSE_WT('\\')
#define WCS_DOT QSE_WT('.')
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define WCS_ISSEPCH(c) ((c) == QSE_WT('/') || (c) == QSE_WT('\\'))
# define WCS_SEPCHS QSE_WT("/\\")
#else
# define WCS_ISSEPCH(c) ((c) == QSE_WT('/'))
# define WCS_SEPCHS QSE_WT("/")
#endif
static int __wcsxnfnmat (
const qse_wchar_t* str, qse_size_t slen,
const qse_wchar_t* ptn, qse_size_t plen, int flags, int no_first_period)
{
const qse_wchar_t* sp = str;
const qse_wchar_t* pp = ptn;
const qse_wchar_t* se = str + slen;
const qse_wchar_t* pe = ptn + plen;
qse_wchar_t sc, pc, pc2;
while (1)
{
if (pp < pe && *pp == WCS_ESC &&
!(flags & QSE_WCSFNMAT_NOESCAPE))
{
/* pattern is escaped and escaping is allowed. */
if ((++pp) >= pe)
{
/*
* the last character of the pattern is an WCS_ESC.
* matching is performed as if the end of the pattern is
* reached just without an WCS_ESC.
*/
if (sp < se) return 0;
return 1;
}
if (sp >= se) return 0; /* premature string termination */
sc = *sp; pc = *pp; /* pc is just a normal character */
if ((flags & QSE_WCSFNMAT_IGNORECASE) != 0)
{
/* make characters to lower-case */
sc = QSE_TOWLOWER(sc);
pc = QSE_TOWLOWER(pc);
}
if (sc != pc) return 0;
sp++; pp++;
continue;
}
if (pp >= pe)
{
/*
* the end of the pattern has been reached.
* the string must terminate too.
*/
return sp >= se;
}
if (sp >= se)
{
/* the string terminats prematurely */
while (pp < pe && *pp == QSE_WT('*')) pp++;
return pp >= pe;
}
sc = *sp; pc = *pp;
if (sc == WCS_DOT && (flags & QSE_WCSFNMAT_PERIOD))
{
/*
* a leading period in the staring must match
* a period in the pattern explicitly
*/
if ((!no_first_period && sp == str) ||
(WCS_ISSEPCH(sp[-1]) && (flags & QSE_WCSFNMAT_PATHNAME)))
{
if (pc != WCS_DOT) return 0;
sp++; pp++;
continue;
}
}
else if (WCS_ISSEPCH(sc) && (flags & QSE_WCSFNMAT_PATHNAME))
{
while (pc == QSE_WT('*'))
{
if ((++pp) >= pe) return 0;
pc = *pp;
}
/* a path separator must be matched explicitly */
if (pc != WCS_SEP) return 0;
sp++; pp++;
continue;
}
/* the handling of special pattern characters begins here */
if (pc == QSE_WT('?'))
{
/* match any single character */
sp++; pp++;
}
else if (pc == QSE_WT('*'))
{
/* match zero or more characters */
/* compact asterisks */
do { pp++; } while (pp < pe && *pp == QSE_WT('*'));
if (pp >= pe)
{
/*
* if the last character in the pattern is an asterisk,
* the string should not have any directory separators
* when QSE_WCSFNMAT_PATHNAME is set.
*/
if (flags & QSE_WCSFNMAT_PATHNAME)
{
if (qse_wcsxpbrk(sp, se-sp, WCS_SEPCHS) != QSE_NULL) return 0;
}
return 1;
}
else
{
do
{
if (__wcsxnfnmat(sp, se - sp, pp, pe - pp, flags, 1))
{
return 1;
}
if (WCS_ISSEPCH(*sp) &&
(flags & QSE_WCSFNMAT_PATHNAME)) break;
sp++;
}
while (sp < se);
return 0;
}
}
else if (pc == QSE_WT('['))
{
/* match range */
int negate = 0;
int matched = 0;
if ((++pp) >= pe) return 0;
if (*pp == QSE_WT('!')) { negate = 1; pp++; }
while (pp < pe && *pp != QSE_WT(']'))
{
if (*pp == QSE_WT('['))
{
qse_size_t pl = pe - pp;
if (pl >= 10)
{
if (qse_wcszcmp(pp, QSE_WT("[:xdigit:]"), 10) == 0)
{
matched = QSE_ISWXDIGIT(sc);
pp += 10; continue;
}
}
if (pl >= 9)
{
if (qse_wcszcmp(pp, QSE_WT("[:upper:]"), 9) == 0)
{
matched = QSE_ISWUPPER(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:lower:]"), 9) == 0)
{
matched = QSE_ISWLOWER(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:alpha:]"), 9) == 0)
{
matched = QSE_ISWALPHA(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:digit:]"), 9) == 0)
{
matched = QSE_ISWDIGIT(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:alnum:]"), 9) == 0)
{
matched = QSE_ISWALNUM(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:space:]"), 9) == 0)
{
matched = QSE_ISWSPACE(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:print:]"), 9) == 0)
{
matched = QSE_ISWPRINT(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:graph:]"), 9) == 0)
{
matched = QSE_ISWGRAPH(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:cntrl:]"), 9) == 0)
{
matched = QSE_ISWCNTRL(sc);
pp += 9; continue;
}
else if (qse_wcszcmp(pp, QSE_WT("[:punct:]"), 9) == 0)
{
matched = QSE_ISWPUNCT(sc);
pp += 9; continue;
}
}
/*
* characters in an invalid class name are
* just treated as normal characters
*/
}
if (*pp == WCS_ESC &&
!(flags & QSE_WCSFNMAT_NOESCAPE)) pp++;
else if (*pp == QSE_WT(']')) break;
if (pp >= pe) break;
pc = *pp;
if ((flags & QSE_WCSFNMAT_IGNORECASE) != 0)
{
sc = QSE_TOWLOWER(sc);
pc = QSE_TOWLOWER(pc);
}
if (pp + 1 < pe && pp[1] == QSE_WT('-'))
{
pp += 2; /* move the a character next to a dash */
if (pp >= pe)
{
if (sc >= pc) matched = 1;
break;
}
if (*pp == WCS_ESC &&
!(flags & QSE_WCSFNMAT_NOESCAPE))
{
if ((++pp) >= pe)
{
if (sc >= pc) matched = 1;
break;
}
}
else if (*pp == QSE_WT(']'))
{
if (sc >= pc) matched = 1;
break;
}
pc2 = *pp;
if ((flags & QSE_WCSFNMAT_IGNORECASE) != 0)
pc2 = QSE_TOWLOWER(pc2);
if (sc >= pc && sc <= pc2) matched = 1;
pp++;
}
else
{
if (sc == pc) matched = 1;
pp++;
}
}
if (negate) matched = !matched;
if (!matched) return 0;
sp++; if (pp < pe) pp++;
}
else
{
/* a normal character */
if ((flags & QSE_WCSFNMAT_IGNORECASE) != 0)
{
sc = QSE_TOWLOWER(sc);
pc = QSE_TOWLOWER(pc);
}
if (sc != pc) return 0;
sp++; pp++;
}
}
/* will never reach here. but make some immature compilers happy... */
return 0;
}
int qse_wcsfnmat (const qse_wchar_t* str, const qse_wchar_t* ptn, int flags)
{
return __wcsxnfnmat (
str, qse_wcslen(str), ptn, qse_wcslen(ptn), flags, 0);
}
int qse_wcsxfnmat (
const qse_wchar_t* str, qse_size_t slen, const qse_wchar_t* ptn, int flags)
{
return __wcsxnfnmat (str, slen, ptn, qse_wcslen(ptn), flags, 0);
}
int qse_wcsnfnmat (
const qse_wchar_t* str, const qse_wchar_t* ptn, qse_size_t plen, int flags)
{
return __wcsxnfnmat (str, qse_wcslen(str), ptn, plen, flags, 0);
}
int qse_wcsxnfnmat (
const qse_wchar_t* str, qse_size_t slen,
const qse_wchar_t* ptn, qse_size_t plen, int flags)
{
return __wcsxnfnmat (str, slen, ptn, plen, flags, 0);
}

View File

@ -1,5 +1,5 @@
/*
* $Id: str-pbrk.c 556 2011-08-31 15:43:46Z hyunghwan.chung $
* $Id: str-pbrk.c 576 2011-09-23 14:52:22Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -35,6 +35,61 @@ qse_mchar_t* qse_mbspbrk (const qse_mchar_t* str1, const qse_mchar_t* str2)
return QSE_NULL;
}
qse_mchar_t* qse_mbsxpbrk (
const qse_mchar_t* str1, qse_size_t len, const qse_mchar_t* str2)
{
const qse_mchar_t* p1, * p2;
const qse_mchar_t* e1 = str1 + len;
for (p1 = str1; p1 < e1; p1++)
{
for (p2 = str2; *p2 != QSE_MT('\0'); p2++)
{
if (*p2 == *p1) return (qse_mchar_t*)p1;
}
}
return QSE_NULL;
}
qse_mchar_t* qse_mbsrpbrk (const qse_mchar_t* str1, const qse_mchar_t* str2)
{
const qse_mchar_t* p1, * p2;
for (p1 = str1; *p1 != QSE_MT('\0'); p1++);
while (p1 > str1)
{
p1--;
for (p2 = str2; *p2 != QSE_MT('\0'); p2++)
{
if (*p2 == *p1) return (qse_mchar_t*)p1;
}
}
return QSE_NULL;
}
qse_mchar_t* qse_mbsxrpbrk (const qse_mchar_t* str1, qse_size_t len, const qse_mchar_t* str2)
{
const qse_mchar_t* p1, * p2;
p1 = str1 + len;
while (p1 > str1)
{
p1--;
for (p2 = str2; *p2 != QSE_MT('\0'); p2++)
{
if (*p2 == *p1) return (qse_mchar_t*)p1;
}
}
return QSE_NULL;
}
qse_wchar_t* qse_wcspbrk (const qse_wchar_t* str1, const qse_wchar_t* str2)
{
const qse_wchar_t* p1, * p2;
@ -50,3 +105,56 @@ qse_wchar_t* qse_wcspbrk (const qse_wchar_t* str1, const qse_wchar_t* str2)
return QSE_NULL;
}
qse_wchar_t* qse_wcsxpbrk (
const qse_wchar_t* str1, qse_size_t len, const qse_wchar_t* str2)
{
const qse_wchar_t* p1, * p2;
const qse_wchar_t* e1 = str1 + len;
for (p1 = str1; p1 < e1; p1++)
{
for (p2 = str2; *p2 != QSE_WT('\0'); p2++)
{
if (*p2 == *p1) return (qse_wchar_t*)p1;
}
}
return QSE_NULL;
}
qse_wchar_t* qse_wcsrpbrk (const qse_wchar_t* str1, const qse_wchar_t* str2)
{
const qse_wchar_t* p1, * p2;
for (p1 = str1; *p1 != QSE_WT('\0'); p1++);
while (p1 > str1)
{
p1--;
for (p2 = str2; *p2 != QSE_WT('\0'); p2++)
{
if (*p2 == *p1) return (qse_wchar_t*)p1;
}
}
return QSE_NULL;
}
qse_wchar_t* qse_wcsxrpbrk (const qse_wchar_t* str1, qse_size_t len, const qse_wchar_t* str2)
{
const qse_wchar_t* p1, * p2;
p1 = str1 + len;
while (p1 > str1)
{
p1--;
for (p2 = str2; *p2 != QSE_WT('\0'); p2++)
{
if (*p2 == *p1) return (qse_wchar_t*)p1;
}
}
return QSE_NULL;
}

View File

@ -1,5 +1,5 @@
/*
* $Id: sed.c 575 2011-09-22 07:07:18Z hyunghwan.chung $
* $Id: sed.c 576 2011-09-23 14:52:22Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -3241,6 +3241,8 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
while (!sed->e.stopreq)
{
if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_READ, QSE_NULL);
n = read_line (sed, 0);
if (n <= -1) { ret = -1; goto done; }
if (n == 0) goto done;
@ -3249,7 +3251,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
{
/* the first command block contains at least 1 command
* to execute. an empty script like ' ' has no commands,
* so this block is skipped. */
* so we execute no commands */
qse_sed_cmd_t* c, * j;
@ -3258,6 +3260,8 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
while (c != &sed->cmd.over)
{
if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_MATCH, c);
n = match_address (sed, c);
if (n <= -1) { ret = -1; goto done; }
@ -3268,6 +3272,8 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
continue;
}
if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_EXEC, c);
j = exec_cmd (sed, c);
if (j == QSE_NULL) { ret = -1; goto done; }
if (j == &sed->cmd.quit_quiet) goto done;
@ -3284,6 +3290,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
}
}
if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_WRITE, QSE_NULL);
if (emit_output (sed, 0) <= -1) { ret = -1; goto done; }
}
@ -3327,3 +3334,13 @@ void qse_sed_setlinnum (qse_sed_t* sed, qse_size_t num)
{
sed->e.in.num = num;
}
qse_sed_exec_hook_t qse_sed_getexechook (qse_sed_t* sed)
{
return sed->e.hook;
}
void qse_sed_setexechook (qse_sed_t* sed, qse_sed_exec_hook_t hook)
{
sed->e.hook = hook;
}

View File

@ -1,5 +1,5 @@
/*
* $Id: sed.h 572 2011-09-21 05:10:09Z hyunghwan.chung $
* $Id: sed.h 576 2011-09-23 14:52:22Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -27,7 +27,6 @@
#define QSE_MAP_AS_RBT
#include <qse/cmn/map.h>
/*
* Define USE_REX to use rex.h on behalf of tre.h
* rex.h currently does not support backreference.
@ -45,7 +44,6 @@ typedef enum qse_sed_depth_t qse_sed_depth_t;
#define QSE_SED_CMD_QUIT QSE_T('q')
typedef struct qse_sed_adr_t qse_sed_adr_t;
typedef struct qse_sed_cmd_t qse_sed_cmd_t;
typedef struct qse_sed_cmd_blk_t qse_sed_cmd_blk_t;
struct qse_sed_adr_t
@ -274,6 +272,9 @@ struct qse_sed_t
/** stop requested */
int stopreq;
/** hook function */
qse_sed_exec_hook_t hook;
} e;
};

View File

@ -586,6 +586,59 @@ static int test14 (void)
return 0;
}
static int test15 (void)
{
const qse_char_t* x = QSE_T("this is good");
qse_printf (QSE_T("[%s]\n"), qse_strpbrk (x, QSE_T("si")));
qse_printf (QSE_T("[%s]\n"), qse_strrpbrk (x, QSE_T("si")));
qse_printf (QSE_T("[%s]\n"), qse_strpbrk (x, QSE_T("d")));
qse_printf (QSE_T("[%s]\n"), qse_strrpbrk (x, QSE_T("d")));
qse_printf (QSE_T("[%s]\n"), qse_strpbrk (x, QSE_T("t")));
qse_printf (QSE_T("[%s]\n"), qse_strrpbrk (x, QSE_T("t")));
return 0;
}
static int test16 (void)
{
const qse_char_t* ptn[] =
{
QSE_T("*.c"),
QSE_T("h??lo.???"),
QSE_T("[a-z]*.cpp")
};
const qse_char_t* name[] =
{
QSE_T("hello.c"),
QSE_T("hello.cpp"),
QSE_T("heLLo.Cpp"),
QSE_T("/tmp/hello.c"),
QSE_T("/tmp/Hello.c")
};
int i, j;
qse_printf (QSE_T("flags => 0\n"));
for (i = 0; i < QSE_COUNTOF(ptn); i++)
for (j = 0; j < QSE_COUNTOF(name); j++)
qse_printf (QSE_T("[%s] [%s] %d\n"), ptn[i], name[j], qse_strfnmat (name[j], ptn[i], 0));
qse_printf (QSE_T("flags => QSE_STRFNMAT_PATHNAME\n"));
for (i = 0; i < QSE_COUNTOF(ptn); i++)
for (j = 0; j < QSE_COUNTOF(name); j++)
qse_printf (QSE_T("[%s] [%s] %d\n"), ptn[i], name[j], qse_strfnmat (name[j], ptn[i], QSE_STRFNMAT_PATHNAME));
qse_printf (QSE_T("flags => QSE_STRFNMAT_PATHNAME | QSE_STRFNMAT_IGNORECASE\n"));
for (i = 0; i < QSE_COUNTOF(ptn); i++)
for (j = 0; j < QSE_COUNTOF(name); j++)
qse_printf (QSE_T("[%s] [%s] %d\n"), ptn[i], name[j], qse_strfnmat (name[j], ptn[i], QSE_STRFNMAT_PATHNAME | QSE_STRFNMAT_IGNORECASE));
return 0;
}
int main ()
{
@ -609,6 +662,8 @@ int main ()
R (test12);
R (test13);
R (test14);
R (test15);
R (test16);
return 0;
}