added qse_globmbs() and qse_globwcs()
This commit is contained in:
parent
77939a5940
commit
ac61c3044a
@ -35,12 +35,17 @@
|
|||||||
* in a path name.
|
* in a path name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef int (*qse_glob_cbimpl_t) (
|
typedef int (*qse_glob_mbscbimpl_t) (
|
||||||
const qse_cstr_t* path,
|
const qse_mcstr_t* path,
|
||||||
void* cbctx
|
void* cbctx
|
||||||
);
|
);
|
||||||
|
|
||||||
enum qse_glob_flags_t
|
typedef int (*qse_glob_wcscbimpl_t) (
|
||||||
|
const qse_wcstr_t* path,
|
||||||
|
void* cbctx
|
||||||
|
);
|
||||||
|
|
||||||
|
enum qse_glob_flag_t
|
||||||
{
|
{
|
||||||
/** Don't use the backslash as an escape charcter.
|
/** Don't use the backslash as an escape charcter.
|
||||||
* This option is on in Win32/OS2/DOS. */
|
* This option is on in Win32/OS2/DOS. */
|
||||||
@ -58,30 +63,58 @@ enum qse_glob_flags_t
|
|||||||
|
|
||||||
/** Exclude special entries from matching.
|
/** Exclude special entries from matching.
|
||||||
* Special entries include . and .. */
|
* Special entries include . and .. */
|
||||||
QSE_GLOB_SKIPSPCDIR = (1 << 4)
|
QSE_GLOB_SKIPSPCDIR = (1 << 4),
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bitsise-ORed of all valid enumerators
|
||||||
|
*/
|
||||||
|
QSE_GLOB_ALL = (QSE_GLOB_NOESCAPE | QSE_GLOB_PERIOD |
|
||||||
|
QSE_GLOB_IGNORECASE | QSE_GLOB_TOLERANT |
|
||||||
|
QSE_GLOB_SKIPSPCDIR)
|
||||||
};
|
};
|
||||||
|
typedef enum qse_glob_flag_t qse_glob_flag_t;
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_glob() function finds path names matchin the \a pattern.
|
* The qse_globmbs() function finds path names matchin the \a pattern.
|
||||||
* It calls the call-back function \a cbimpl for each path name found.
|
* It calls the call-back function \a cbimpl for each path name found.
|
||||||
*
|
*
|
||||||
* \return -1 on failure, 0 on no match, 1 if matches are found.
|
* \return -1 on failure, 0 on no match, 1 if matches are found.
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT int qse_glob (
|
QSE_EXPORT int qse_globmbs (
|
||||||
const qse_char_t* pattern,
|
const qse_mchar_t* pattern,
|
||||||
qse_glob_cbimpl_t cbimpl,
|
qse_glob_mbscbimpl_t cbimpl,
|
||||||
void* cbctx,
|
void* cbctx,
|
||||||
int flags,
|
int flags,
|
||||||
qse_mmgr_t* mmgr,
|
qse_mmgr_t* mmgr,
|
||||||
qse_cmgr_t* cmgr
|
qse_cmgr_t* cmgr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_globwcs (
|
||||||
|
const qse_wchar_t* pattern,
|
||||||
|
qse_glob_wcscbimpl_t cbimpl,
|
||||||
|
void* cbctx,
|
||||||
|
int flags,
|
||||||
|
qse_mmgr_t* mmgr,
|
||||||
|
qse_cmgr_t* cmgr
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
|
typedef qse_glob_mbscbimpl_t qse_glob_cbimpl_t;
|
||||||
|
# define qse_glob(pattern,cbimpl,cbctx,flags,mmgr,cmgr) qse_globmbs(pattern,cbimpl,cbctx,flags,mmgr,cmgr)
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef qse_glob_wcscbimpl_t qse_glob_cbimpl_t;
|
||||||
|
# define qse_glob(pattern,cbimpl,cbctx,flags,mmgr,cmgr) qse_globwcs(pattern,cbimpl,cbctx,flags,mmgr,cmgr)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -50,22 +50,21 @@ enum qse_canonpath_flag_t
|
|||||||
# define QSE_ISPATHMBSEP(c) ((c) == QSE_MT('/') || (c) == QSE_MT('\\'))
|
# define QSE_ISPATHMBSEP(c) ((c) == QSE_MT('/') || (c) == QSE_MT('\\'))
|
||||||
# define QSE_ISPATHWCSEP(c) ((c) == QSE_WT('/') || (c) == QSE_WT('\\'))
|
# define QSE_ISPATHWCSEP(c) ((c) == QSE_WT('/') || (c) == QSE_WT('\\'))
|
||||||
|
|
||||||
# define QSE_ISPATHMBDRIVE(s) \
|
|
||||||
(((s[0] >= QSE_MT('A') && s[0] <= QSE_MT('Z')) || \
|
|
||||||
(s[0] >= QSE_MT('a') && s[0] <= QSE_MT('z'))) && \
|
|
||||||
s[1] == QSE_MT(':'))
|
|
||||||
# define QSE_ISPATHWCDRIVE(s) \
|
|
||||||
(((s[0] >= QSE_WT('A') && s[0] <= QSE_WT('Z')) || \
|
|
||||||
(s[0] >= QSE_WT('a') && s[0] <= QSE_WT('z'))) && \
|
|
||||||
s[1] == QSE_WT(':'))
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define QSE_ISPATHMBSEP(c) ((c) == QSE_MT('/'))
|
# define QSE_ISPATHMBSEP(c) ((c) == QSE_MT('/'))
|
||||||
# define QSE_ISPATHWCSEP(c) ((c) == QSE_WT('/'))
|
# define QSE_ISPATHWCSEP(c) ((c) == QSE_WT('/'))
|
||||||
|
|
||||||
/* QSE_ISPATHMBDRIVE() and QSE_ISPATHWCDRIVE() are not defined for this platform */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define QSE_ISPATHMBDRIVE(s) \
|
||||||
|
(((s[0] >= QSE_MT('A') && s[0] <= QSE_MT('Z')) || \
|
||||||
|
(s[0] >= QSE_MT('a') && s[0] <= QSE_MT('z'))) && \
|
||||||
|
s[1] == QSE_MT(':'))
|
||||||
|
#define QSE_ISPATHWCDRIVE(s) \
|
||||||
|
(((s[0] >= QSE_WT('A') && s[0] <= QSE_WT('Z')) || \
|
||||||
|
(s[0] >= QSE_WT('a') && s[0] <= QSE_WT('z'))) && \
|
||||||
|
s[1] == QSE_WT(':'))
|
||||||
|
|
||||||
#define QSE_ISPATHMBSEPORNIL(c) (QSE_ISPATHMBSEP(c) || (c) == QSE_MT('\0'))
|
#define QSE_ISPATHMBSEPORNIL(c) (QSE_ISPATHMBSEP(c) || (c) == QSE_MT('\0'))
|
||||||
#define QSE_ISPATHWCSEPORNIL(c) (QSE_ISPATHWCSEP(c) || (c) == QSE_WT('\0'))
|
#define QSE_ISPATHWCSEPORNIL(c) (QSE_ISPATHWCSEP(c) || (c) == QSE_WT('\0'))
|
||||||
|
|
||||||
|
@ -3259,12 +3259,12 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
|
|||||||
);
|
);
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
# define qse_str_setmmgr(str,mmgr) qse_mbs_wetmmgr(str,mmgr)
|
|
||||||
# define qse_str_getmmgr(str) qse_mbs_getmmgr(str)
|
|
||||||
# define qse_str_open(mmgr,ext,capa) qse_mbs_open(mmgr,ext,capa)
|
# define qse_str_open(mmgr,ext,capa) qse_mbs_open(mmgr,ext,capa)
|
||||||
# define qse_str_close(str) qse_mbs_close(str)
|
# define qse_str_close(str) qse_mbs_close(str)
|
||||||
# define qse_str_init(str,mmgr,capa) qse_mbs_init(str,mmgr,capa)
|
# define qse_str_init(str,mmgr,capa) qse_mbs_init(str,mmgr,capa)
|
||||||
# define qse_str_fini(str) qse_mbs_fini(str)
|
# define qse_str_fini(str) qse_mbs_fini(str)
|
||||||
|
# define qse_str_setmmgr(str,mmgr) qse_mbs_setmmgr(str,mmgr)
|
||||||
|
# define qse_str_getmmgr(str) qse_mbs_getmmgr(str)
|
||||||
# define qse_str_yield(str,buf,ncapa) qse_mbs_yield(str,buf,ncapa)
|
# define qse_str_yield(str,buf,ncapa) qse_mbs_yield(str,buf,ncapa)
|
||||||
# define qse_str_yieldptr(str,ncapa) qse_mbs_yieldptr(str,ncapa)
|
# define qse_str_yieldptr(str,ncapa) qse_mbs_yieldptr(str,ncapa)
|
||||||
# define qse_str_getsizer(str) qse_mbs_getsizer(str)
|
# define qse_str_getsizer(str) qse_mbs_getsizer(str)
|
||||||
@ -3291,12 +3291,12 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
|
|||||||
# define qse_str_fmt qse_mbs_fmt
|
# define qse_str_fmt qse_mbs_fmt
|
||||||
# define qse_str_vfmt qse_mbs_vfmt
|
# define qse_str_vfmt qse_mbs_vfmt
|
||||||
#else
|
#else
|
||||||
# define qse_str_setmmgr(str,mmgr) qse_wcs_wetmmgr(str,mmgr)
|
|
||||||
# define qse_str_getmmgr(str) qse_wcs_getmmgr(str)
|
|
||||||
# define qse_str_open(mmgr,ext,capa) qse_wcs_open(mmgr,ext,capa)
|
# define qse_str_open(mmgr,ext,capa) qse_wcs_open(mmgr,ext,capa)
|
||||||
# define qse_str_close(str) qse_wcs_close(str)
|
# define qse_str_close(str) qse_wcs_close(str)
|
||||||
# define qse_str_init(str,mmgr,capa) qse_wcs_init(str,mmgr,capa)
|
# define qse_str_init(str,mmgr,capa) qse_wcs_init(str,mmgr,capa)
|
||||||
# define qse_str_fini(str) qse_wcs_fini(str)
|
# define qse_str_fini(str) qse_wcs_fini(str)
|
||||||
|
# define qse_str_setmmgr(str,mmgr) qse_wcs_setmmgr(str,mmgr)
|
||||||
|
# define qse_str_getmmgr(str) qse_wcs_getmmgr(str)
|
||||||
# define qse_str_yield(str,buf,ncapa) qse_wcs_yield(str,buf,ncapa)
|
# define qse_str_yield(str,buf,ncapa) qse_wcs_yield(str,buf,ncapa)
|
||||||
# define qse_str_yieldptr(str,ncapa) qse_wcs_yieldptr(str,ncapa)
|
# define qse_str_yieldptr(str,ncapa) qse_wcs_yieldptr(str,ncapa)
|
||||||
# define qse_str_getsizer(str) qse_wcs_getsizer(str)
|
# define qse_str_getsizer(str) qse_wcs_getsizer(str)
|
||||||
@ -3324,7 +3324,6 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
|
|||||||
# define qse_str_vfmt qse_wcs_vfmt
|
# define qse_str_vfmt qse_wcs_vfmt
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@ noinst_HEADERS = \
|
|||||||
fmt-intmax.h \
|
fmt-intmax.h \
|
||||||
fmt-out.h \
|
fmt-out.h \
|
||||||
fs.h \
|
fs.h \
|
||||||
|
glob.h \
|
||||||
mem.h \
|
mem.h \
|
||||||
str-dyn.h \
|
str-dyn.h \
|
||||||
str-fcpy.h \
|
str-fcpy.h \
|
||||||
|
@ -397,6 +397,7 @@ noinst_HEADERS = \
|
|||||||
fmt-intmax.h \
|
fmt-intmax.h \
|
||||||
fmt-out.h \
|
fmt-out.h \
|
||||||
fs.h \
|
fs.h \
|
||||||
|
glob.h \
|
||||||
mem.h \
|
mem.h \
|
||||||
str-dyn.h \
|
str-dyn.h \
|
||||||
str-fcpy.h \
|
str-fcpy.h \
|
||||||
|
@ -46,596 +46,158 @@
|
|||||||
# include "syscall.h"
|
# include "syscall.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NO_RECURSION 1
|
||||||
|
|
||||||
|
enum segment_type_t
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
ROOT,
|
||||||
|
NORMAL
|
||||||
|
};
|
||||||
|
typedef enum segment_type_t segment_type_t;
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
/* i don't support escaping in these systems */
|
/* i don't support escaping in these systems */
|
||||||
# define IS_ESC(c) (0)
|
# define IS_ESC_MBS(c) (0)
|
||||||
|
# define IS_ESC_WCS(c) (0)
|
||||||
#else
|
#else
|
||||||
# define IS_ESC(c) ((c) == QSE_T('\\'))
|
# define IS_ESC_MBS(c) ((c) == QSE_MT('\\'))
|
||||||
|
# define IS_ESC_WCS(c) ((c) == QSE_WT('\\'))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IS_SEP(c) QSE_ISPATHSEP(c)
|
#define IS_NIL_MBS(c) ((c) == QSE_MT('\0'))
|
||||||
|
#define IS_NIL_WCS(c) ((c) == QSE_WT('\0'))
|
||||||
#define IS_NIL(c) ((c) == QSE_T('\0'))
|
|
||||||
#define IS_SEP_OR_NIL(c) (IS_SEP(c) || IS_NIL(c))
|
|
||||||
|
|
||||||
/* only for win32/os2/dos */
|
|
||||||
#define IS_DRIVE(s) \
|
|
||||||
(((s[0] >= QSE_T('A') && s[0] <= QSE_T('Z')) || \
|
|
||||||
(s[0] >= QSE_T('a') && s[0] <= QSE_T('z'))) && \
|
|
||||||
s[1] == QSE_T(':'))
|
|
||||||
|
|
||||||
/* this macro only checks for top-level wild-cards among these.
|
/* this macro only checks for top-level wild-cards among these.
|
||||||
* *, ?, [], !, -
|
* *, ?, [], !, -
|
||||||
* see str-fnmat.c for more wild-card letters
|
* see str-fnmat.c for more wild-card letters
|
||||||
*/
|
*/
|
||||||
#define IS_WILD(c) ((c) == QSE_T('*') || (c) == QSE_T('?') || (c) == QSE_T('['))
|
#define IS_WILD_MBS(c) ((c) == QSE_MT('*') || (c) == QSE_MT('?') || (c) == QSE_MT('['))
|
||||||
|
#define IS_WILD_WCS(c) ((c) == QSE_WT('*') || (c) == QSE_WT('?') || (c) == QSE_WT('['))
|
||||||
|
|
||||||
#define NO_RECURSION 1
|
|
||||||
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
typedef struct stack_node_t stack_node_t;
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define glob qse_globmbs
|
||||||
|
#define cbimpl_t qse_glob_mbscbimpl_t
|
||||||
|
#define glob_t mbs_glob_t
|
||||||
|
#define segment_t mbs_segment_t
|
||||||
|
#define stack_node_t mbs_stack_node_t
|
||||||
|
#define char_t qse_mchar_t
|
||||||
|
#define cstr_t qse_mcstr_t
|
||||||
|
#define T(x) QSE_MT(x)
|
||||||
|
#define IS_ESC(x) IS_ESC_MBS(x)
|
||||||
|
#define IS_DRIVE(x) QSE_ISPATHMBDRIVE(x)
|
||||||
|
#define IS_SEP(x) QSE_ISPATHMBSEP(x)
|
||||||
|
#define IS_SEP_OR_NIL(x) QSE_ISPATHMBSEPORNIL(x)
|
||||||
|
#define IS_NIL(x) IS_NIL_MBS(x)
|
||||||
|
#define IS_WILD(x) IS_WILD_MBS(x)
|
||||||
|
#define str_t qse_mbs_t
|
||||||
|
#define str_open qse_mbs_open
|
||||||
|
#define str_close qse_mbs_close
|
||||||
|
#define str_init qse_mbs_init
|
||||||
|
#define str_fini qse_mbs_fini
|
||||||
|
#define str_cat qse_mbs_cat
|
||||||
|
#define str_ccat qse_mbs_ccat
|
||||||
|
#define str_ncat qse_mbs_ncat
|
||||||
|
#define str_setcapa qse_mbs_setcapa
|
||||||
|
#define str_setlen qse_mbs_setlen
|
||||||
|
#define STR_CAPA(x) QSE_MBS_CAPA(x)
|
||||||
|
#define STR_LEN(x) QSE_MBS_LEN(x)
|
||||||
|
#define STR_PTR(x) QSE_MBS_PTR(x)
|
||||||
|
#define STR_XSTR(x) QSE_MBS_XSTR(x)
|
||||||
|
#define STR_CPTR(x,y) QSE_MBS_CPTR(x,y)
|
||||||
|
#define strnfnmat qse_mbsnfnmat
|
||||||
|
#define DIR_CHAR_FLAGS QSE_DIR_MBSPATH
|
||||||
|
#define path_exists mbs_path_exists
|
||||||
|
#define search mbs_search
|
||||||
|
#define get_next_segment mbs_get_next_segment
|
||||||
|
#define handle_non_wild_segments mbs_handle_non_wild_segments
|
||||||
|
#define CHAR_IS_MCHAR
|
||||||
|
#undef DECLARE_MBUF
|
||||||
|
#include "glob.h"
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#undef glob
|
||||||
|
#undef cbimpl_t
|
||||||
|
#undef glob_t
|
||||||
|
#undef segment_t
|
||||||
|
#undef stack_node_t
|
||||||
|
#undef char_t
|
||||||
|
#undef cstr_t
|
||||||
|
#undef T
|
||||||
|
#undef IS_ESC
|
||||||
|
#undef IS_DRIVE
|
||||||
|
#undef IS_SEP
|
||||||
|
#undef IS_SEP_OR_NIL
|
||||||
|
#undef IS_NIL
|
||||||
|
#undef IS_WILD
|
||||||
|
#undef str_t
|
||||||
|
#undef str_open
|
||||||
|
#undef str_close
|
||||||
|
#undef str_init
|
||||||
|
#undef str_fini
|
||||||
|
#undef str_cat
|
||||||
|
#undef str_ccat
|
||||||
|
#undef str_ncat
|
||||||
|
#undef str_setcapa
|
||||||
|
#undef str_setlen
|
||||||
|
#undef STR_CAPA
|
||||||
|
#undef STR_LEN
|
||||||
|
#undef STR_PTR
|
||||||
|
#undef STR_XSTR
|
||||||
|
#undef STR_CPTR
|
||||||
|
#undef strnfnmat
|
||||||
|
#undef DIR_CHAR_FLAGS
|
||||||
|
#undef path_exists
|
||||||
|
#undef search
|
||||||
|
#undef get_next_segment
|
||||||
|
#undef handle_non_wild_segments
|
||||||
|
#undef CHAR_IS_MCHAR
|
||||||
|
#undef DECLARE_MBUF
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define glob qse_globwcs
|
||||||
|
#define cbimpl_t qse_glob_wcscbimpl_t
|
||||||
|
#define glob_t wcs_glob_t
|
||||||
|
#define segment_t wcs_segment_t
|
||||||
|
#define stack_node_t wcs_stack_node_t
|
||||||
|
#define char_t qse_wchar_t
|
||||||
|
#define cstr_t qse_wcstr_t
|
||||||
|
#define T(x) QSE_WT(x)
|
||||||
|
#define IS_ESC(x) IS_ESC_WCS(x)
|
||||||
|
#define IS_DRIVE(x) QSE_ISPATHWCDRIVE(x)
|
||||||
|
#define IS_SEP(x) QSE_ISPATHWCSEP(x)
|
||||||
|
#define IS_SEP_OR_NIL(x) QSE_ISPATHWCSEPORNIL(x)
|
||||||
|
#define IS_NIL(x) IS_NIL_WCS(x)
|
||||||
|
#define IS_WILD(x) IS_WILD_WCS(x)
|
||||||
|
#define str_t qse_wcs_t
|
||||||
|
#define str_open qse_wcs_open
|
||||||
|
#define str_close qse_wcs_close
|
||||||
|
#define str_init qse_wcs_init
|
||||||
|
#define str_fini qse_wcs_fini
|
||||||
|
#define str_cat qse_wcs_cat
|
||||||
|
#define str_ccat qse_wcs_ccat
|
||||||
|
#define str_ncat qse_wcs_ncat
|
||||||
|
#define str_setcapa qse_wcs_setcapa
|
||||||
|
#define str_setlen qse_wcs_setlen
|
||||||
|
#define STR_CAPA(x) QSE_WCS_CAPA(x)
|
||||||
|
#define STR_LEN(x) QSE_WCS_LEN(x)
|
||||||
|
#define STR_PTR(x) QSE_WCS_PTR(x)
|
||||||
|
#define STR_XSTR(x) QSE_WCS_XSTR(x)
|
||||||
|
#define STR_CPTR(x,y) QSE_WCS_CPTR(x,y)
|
||||||
|
|
||||||
|
#define strnfnmat qse_wcsnfnmat
|
||||||
|
#define DIR_CHAR_FLAGS QSE_DIR_WCSPATH
|
||||||
|
#define path_exists wcs_path_exists
|
||||||
|
#define search wcs_search
|
||||||
|
#define get_next_segment wcs_get_next_segment
|
||||||
|
#define handle_non_wild_segments wcs_handle_non_wild_segments
|
||||||
|
#undef CHAR_IS_MCHAR
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
# define DECLARE_MBUF 1
|
||||||
#endif
|
#endif
|
||||||
|
#include "glob.h"
|
||||||
struct glob_t
|
|
||||||
{
|
|
||||||
qse_glob_cbimpl_t cbimpl;
|
|
||||||
void* cbctx;
|
|
||||||
|
|
||||||
qse_mmgr_t* mmgr;
|
|
||||||
qse_cmgr_t* cmgr;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
qse_str_t path;
|
|
||||||
qse_str_t tbuf; /* temporary buffer */
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
|
||||||
/* nothing */
|
|
||||||
#else
|
|
||||||
qse_mbs_t mbuf;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int expanded;
|
|
||||||
int fnmat_flags;
|
|
||||||
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
stack_node_t* stack;
|
|
||||||
stack_node_t* free;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct glob_t glob_t;
|
|
||||||
|
|
||||||
static qse_mchar_t* wcs_to_mbuf (glob_t* g, const qse_wchar_t* wcs, qse_mbs_t* mbs)
|
|
||||||
{
|
|
||||||
qse_size_t ml, wl;
|
|
||||||
|
|
||||||
if (qse_wcstombswithcmgr (wcs, &wl, QSE_NULL, &ml, g->cmgr) <= -1 ||
|
|
||||||
qse_mbs_setlen (mbs, ml) == (qse_size_t)-1) return QSE_NULL;
|
|
||||||
|
|
||||||
qse_wcstombswithcmgr (wcs, &wl, QSE_MBS_PTR(mbs), &ml, g->cmgr);
|
|
||||||
return QSE_MBS_PTR(mbs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int path_exists (glob_t* g, const qse_char_t* name)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
#if !defined(INVALID_FILE_ATTRIBUTES)
|
|
||||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
|
||||||
#endif
|
|
||||||
return (GetFileAttributes(name) != INVALID_FILE_ATTRIBUTES)? 1: 0;
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#elif defined(__OS2__)
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
FILESTATUS3 fs;
|
|
||||||
APIRET rc;
|
|
||||||
const qse_mchar_t* mptr;
|
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
|
||||||
mptr = name;
|
|
||||||
#else
|
|
||||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
|
||||||
if (mptr == QSE_NULL) return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rc = DosQueryPathInfo (mptr, FIL_STANDARD, &fs, QSE_SIZEOF(fs));
|
|
||||||
|
|
||||||
return (rc == NO_ERROR)? 1:
|
|
||||||
(rc == ERROR_PATH_NOT_FOUND)? 0: -1;
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#elif defined(__DOS__)
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
unsigned int x, attr;
|
|
||||||
const qse_mchar_t* mptr;
|
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
|
||||||
mptr = name;
|
|
||||||
#else
|
|
||||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
|
||||||
if (mptr == QSE_NULL) return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
x = _dos_getfileattr (mptr, &attr);
|
|
||||||
return (x == 0)? 1:
|
|
||||||
(errno == ENOENT)? 0: -1;
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#elif defined(macintosh)
|
|
||||||
HFileInfo fpb;
|
|
||||||
const qse_mchar_t* mptr;
|
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
|
||||||
mptr = name;
|
|
||||||
#else
|
|
||||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
|
||||||
if (mptr == QSE_NULL) return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QSE_MEMSET (&fpb, 0, QSE_SIZEOF(fpb));
|
|
||||||
fpb.ioNamePtr = (unsigned char*)mptr;
|
|
||||||
|
|
||||||
return (PBGetCatInfoSync ((CInfoPBRec*)&fpb) == noErr)? 1: 0;
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
#if defined(HAVE_LSTAT)
|
|
||||||
qse_lstat_t st;
|
|
||||||
#else
|
|
||||||
qse_stat_t st;
|
|
||||||
#endif
|
|
||||||
const qse_mchar_t* mptr;
|
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
|
||||||
mptr = name;
|
|
||||||
#else
|
|
||||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
|
||||||
if (mptr == QSE_NULL) return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAVE_LSTAT)
|
|
||||||
return (QSE_LSTAT (mptr, &st) <= -1)? 0: 1;
|
|
||||||
#else
|
|
||||||
/* use stat() if no lstat() is available. */
|
|
||||||
return (QSE_STAT (mptr, &st) <= -1)? 0: 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
struct segment_t
|
|
||||||
{
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
ROOT,
|
|
||||||
NORMAL
|
|
||||||
} type;
|
|
||||||
|
|
||||||
const qse_char_t* ptr;
|
|
||||||
qse_size_t len;
|
|
||||||
|
|
||||||
qse_char_t sep; /* preceeding separator */
|
|
||||||
unsigned int wild: 1; /* indicate that it contains wildcards */
|
|
||||||
unsigned int esc: 1; /* indicate that it contains escaped letters */
|
|
||||||
unsigned int next: 1; /* indicate that it has the following segment */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct segment_t segment_t;
|
|
||||||
|
|
||||||
static int get_next_segment (glob_t* g, segment_t* seg)
|
|
||||||
{
|
|
||||||
if (seg->type == NONE)
|
|
||||||
{
|
|
||||||
/* seg->ptr must point to the beginning of the pattern
|
|
||||||
* and seg->len must be zero when seg->type is NONE. */
|
|
||||||
if (IS_NIL(seg->ptr[0]))
|
|
||||||
{
|
|
||||||
/* nothing to do */
|
|
||||||
}
|
|
||||||
else if (IS_SEP(seg->ptr[0]))
|
|
||||||
{
|
|
||||||
seg->type = ROOT;
|
|
||||||
seg->len = 1;
|
|
||||||
seg->next = IS_NIL(seg->ptr[1])? 0: 1;
|
|
||||||
seg->sep = QSE_T('\0');
|
|
||||||
seg->wild = 0;
|
|
||||||
seg->esc = 0;
|
|
||||||
}
|
|
||||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
|
||||||
else if (IS_DRIVE(seg->ptr))
|
|
||||||
{
|
|
||||||
seg->type = ROOT;
|
|
||||||
seg->len = 2;
|
|
||||||
if (IS_SEP(seg->ptr[2])) seg->len++;
|
|
||||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
|
||||||
seg->sep = QSE_T('\0');
|
|
||||||
seg->wild = 0;
|
|
||||||
seg->esc = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int escaped = 0;
|
|
||||||
seg->type = NORMAL;
|
|
||||||
seg->sep = QSE_T('\0');
|
|
||||||
seg->wild = 0;
|
|
||||||
seg->esc = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (escaped) escaped = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IS_ESC(seg->ptr[seg->len]))
|
|
||||||
{
|
|
||||||
escaped = 1;
|
|
||||||
seg->esc = 1;
|
|
||||||
}
|
|
||||||
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg->len++;
|
|
||||||
}
|
|
||||||
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]));
|
|
||||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (seg->type == ROOT)
|
|
||||||
{
|
|
||||||
int escaped = 0;
|
|
||||||
seg->type = NORMAL;
|
|
||||||
seg->ptr = &seg->ptr[seg->len];
|
|
||||||
seg->len = 0;
|
|
||||||
seg->sep = QSE_T('\0');
|
|
||||||
seg->wild = 0;
|
|
||||||
seg->esc = 0;
|
|
||||||
|
|
||||||
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]))
|
|
||||||
{
|
|
||||||
if (escaped) escaped = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IS_ESC(seg->ptr[seg->len]))
|
|
||||||
{
|
|
||||||
escaped = 1;
|
|
||||||
seg->esc = 1;
|
|
||||||
}
|
|
||||||
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
|
||||||
}
|
|
||||||
seg->len++;
|
|
||||||
}
|
|
||||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QSE_ASSERT (seg->type == NORMAL);
|
|
||||||
|
|
||||||
seg->ptr = &seg->ptr[seg->len + 1];
|
|
||||||
seg->len = 0;
|
|
||||||
seg->wild = 0;
|
|
||||||
seg->esc = 0;
|
|
||||||
if (IS_NIL(seg->ptr[-1]))
|
|
||||||
{
|
|
||||||
seg->type = NONE;
|
|
||||||
seg->next = 0;
|
|
||||||
seg->sep = QSE_T('\0');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int escaped = 0;
|
|
||||||
seg->sep = seg->ptr[-1];
|
|
||||||
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]))
|
|
||||||
{
|
|
||||||
if (escaped) escaped = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IS_ESC(seg->ptr[seg->len]))
|
|
||||||
{
|
|
||||||
escaped = 1;
|
|
||||||
seg->esc = 1;
|
|
||||||
}
|
|
||||||
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
|
||||||
}
|
|
||||||
seg->len++;
|
|
||||||
}
|
|
||||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return seg->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_non_wild_segments (glob_t* g, segment_t* seg)
|
|
||||||
{
|
|
||||||
while (get_next_segment(g, seg) != NONE && !seg->wild)
|
|
||||||
{
|
|
||||||
QSE_ASSERT (seg->type != NONE && !seg->wild);
|
|
||||||
|
|
||||||
if (seg->sep && qse_str_ccat (&g->path, seg->sep) == (qse_size_t)-1) return -1;
|
|
||||||
if (seg->esc)
|
|
||||||
{
|
|
||||||
/* if the segment contains escape sequences,
|
|
||||||
* strip the escape letters off the segment */
|
|
||||||
|
|
||||||
qse_cstr_t tmp;
|
|
||||||
qse_size_t i;
|
|
||||||
int escaped = 0;
|
|
||||||
|
|
||||||
if (QSE_STR_CAPA(&g->tbuf) < seg->len &&
|
|
||||||
qse_str_setcapa (&g->tbuf, seg->len) == (qse_size_t)-1) return -1;
|
|
||||||
|
|
||||||
tmp.ptr = QSE_STR_PTR(&g->tbuf);
|
|
||||||
tmp.len = 0;
|
|
||||||
|
|
||||||
/* the following loop drops the last character
|
|
||||||
* if it is the escape character */
|
|
||||||
for (i = 0; i < seg->len; i++)
|
|
||||||
{
|
|
||||||
if (escaped)
|
|
||||||
{
|
|
||||||
escaped = 0;
|
|
||||||
tmp.ptr[tmp.len++] = seg->ptr[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IS_ESC(seg->ptr[i]))
|
|
||||||
escaped = 1;
|
|
||||||
else
|
|
||||||
tmp.ptr[tmp.len++] = seg->ptr[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qse_str_ncat (&g->path, tmp.ptr, tmp.len) == (qse_size_t)-1) return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* if the segmetn doesn't contain escape sequences,
|
|
||||||
* append the segment to the path without special handling */
|
|
||||||
if (qse_str_ncat (&g->path, seg->ptr, seg->len) == (qse_size_t)-1) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!seg->next && path_exists(g, QSE_STR_PTR(&g->path)) > 0)
|
|
||||||
{
|
|
||||||
/* reached the last segment. match if the path exists */
|
|
||||||
if (g->cbimpl (QSE_STR_XSTR(&g->path), g->cbctx) <= -1) return -1;
|
|
||||||
g->expanded = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
struct stack_node_t
|
|
||||||
{
|
|
||||||
qse_size_t tmp;
|
|
||||||
qse_size_t tmp2;
|
|
||||||
qse_dir_t* dp;
|
|
||||||
segment_t seg;
|
|
||||||
|
|
||||||
stack_node_t* next;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int search (glob_t* g, segment_t* seg)
|
|
||||||
{
|
|
||||||
qse_dir_t* dp;
|
|
||||||
qse_size_t tmp, tmp2;
|
|
||||||
qse_dir_ent_t ent;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
stack_node_t* r;
|
|
||||||
|
|
||||||
entry:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dp = QSE_NULL;
|
|
||||||
|
|
||||||
if (handle_non_wild_segments (g, seg) <= -1) goto oops;
|
|
||||||
|
|
||||||
if (seg->wild)
|
|
||||||
{
|
|
||||||
int dir_flags = 0;
|
|
||||||
if (g->flags & QSE_GLOB_SKIPSPCDIR) dir_flags |= QSE_DIR_SKIPSPCDIR;
|
|
||||||
|
|
||||||
dp = qse_dir_open (
|
|
||||||
g->mmgr, 0, QSE_STR_PTR(&g->path),
|
|
||||||
dir_flags, QSE_NULL);
|
|
||||||
if (dp)
|
|
||||||
{
|
|
||||||
tmp = QSE_STR_LEN(&g->path);
|
|
||||||
|
|
||||||
if (seg->sep && qse_str_ccat (&g->path, seg->sep) == (qse_size_t)-1) goto oops;
|
|
||||||
tmp2 = QSE_STR_LEN(&g->path);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
qse_str_setlen (&g->path, tmp2);
|
|
||||||
|
|
||||||
x = qse_dir_read (dp, &ent);
|
|
||||||
if (x <= -1)
|
|
||||||
{
|
|
||||||
if (g->flags & QSE_GLOB_TOLERANT) break;
|
|
||||||
else goto oops;
|
|
||||||
}
|
|
||||||
if (x == 0) break;
|
|
||||||
|
|
||||||
if (qse_str_cat (&g->path, ent.name) == (qse_size_t)-1) goto oops;
|
|
||||||
|
|
||||||
if (qse_strnfnmat (QSE_STR_CPTR(&g->path,tmp2), seg->ptr, seg->len, g->fnmat_flags) > 0)
|
|
||||||
{
|
|
||||||
if (seg->next)
|
|
||||||
{
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
if (g->free)
|
|
||||||
{
|
|
||||||
r = g->free;
|
|
||||||
g->free = r->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r = QSE_MMGR_ALLOC (g->mmgr, QSE_SIZEOF(*r));
|
|
||||||
if (r == QSE_NULL) goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* push key variables that must be restored
|
|
||||||
* into the stack. */
|
|
||||||
r->tmp = tmp;
|
|
||||||
r->tmp2 = tmp2;
|
|
||||||
r->dp = dp;
|
|
||||||
r->seg = *seg;
|
|
||||||
|
|
||||||
r->next = g->stack;
|
|
||||||
g->stack = r;
|
|
||||||
|
|
||||||
/* move to the function entry point as if
|
|
||||||
* a recursive call has been made */
|
|
||||||
goto entry;
|
|
||||||
|
|
||||||
resume:
|
|
||||||
;
|
|
||||||
|
|
||||||
#else
|
|
||||||
segment_t save;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
save = *seg;
|
|
||||||
x = search (g, seg);
|
|
||||||
*seg = save;
|
|
||||||
if (x <= -1) goto oops;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (g->cbimpl (QSE_STR_XSTR(&g->path), g->cbctx) <= -1) goto oops;
|
|
||||||
g->expanded = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qse_str_setlen (&g->path, tmp);
|
|
||||||
qse_dir_close (dp); dp = QSE_NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_ASSERT (dp == QSE_NULL);
|
|
||||||
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
if (g->stack)
|
|
||||||
{
|
|
||||||
/* the stack is not empty. the emulated recusive call
|
|
||||||
* must have been made. restore the variables pushed
|
|
||||||
* and jump to the resumption point */
|
|
||||||
r = g->stack;
|
|
||||||
g->stack = r->next;
|
|
||||||
|
|
||||||
tmp = r->tmp;
|
|
||||||
tmp2 = r->tmp2;
|
|
||||||
dp = r->dp;
|
|
||||||
*seg = r->seg;
|
|
||||||
|
|
||||||
/* link the stack node to the free list
|
|
||||||
* instead of freeing it here */
|
|
||||||
r->next = g->free;
|
|
||||||
g->free = r;
|
|
||||||
|
|
||||||
goto resume;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (g->free)
|
|
||||||
{
|
|
||||||
/* destory the free list */
|
|
||||||
r = g->free;
|
|
||||||
g->free = r->next;
|
|
||||||
QSE_MMGR_FREE (g->mmgr, r);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
oops:
|
|
||||||
if (dp) qse_dir_close (dp);
|
|
||||||
|
|
||||||
#if defined(NO_RECURSION)
|
|
||||||
while (g->stack)
|
|
||||||
{
|
|
||||||
r = g->stack;
|
|
||||||
g->stack = r->next;
|
|
||||||
qse_dir_close (r->dp);
|
|
||||||
QSE_MMGR_FREE (g->mmgr, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (g->free)
|
|
||||||
{
|
|
||||||
r = g->stack;
|
|
||||||
g->free = r->next;
|
|
||||||
QSE_MMGR_FREE (g->mmgr, r);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int qse_glob (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr)
|
|
||||||
{
|
|
||||||
segment_t seg;
|
|
||||||
glob_t g;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
QSE_MEMSET (&g, 0, QSE_SIZEOF(g));
|
|
||||||
g.cbimpl = cbimpl;
|
|
||||||
g.cbctx = cbctx;
|
|
||||||
g.mmgr = mmgr;
|
|
||||||
g.cmgr = cmgr;
|
|
||||||
g.flags = flags;
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
|
||||||
g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
|
|
||||||
g.fnmat_flags |= QSE_STRFNMAT_NOESCAPE;
|
|
||||||
#else
|
|
||||||
if (flags & QSE_GLOB_IGNORECASE) g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
|
|
||||||
if (flags & QSE_GLOB_NOESCAPE) g.fnmat_flags |= QSE_STRFNMAT_NOESCAPE;
|
|
||||||
#endif
|
|
||||||
if (flags & QSE_GLOB_PERIOD) g.fnmat_flags |= QSE_STRFNMAT_PERIOD;
|
|
||||||
|
|
||||||
if (qse_str_init (&g.path, mmgr, 512) <= -1) return -1;
|
|
||||||
if (qse_str_init (&g.tbuf, mmgr, 256) <= -1)
|
|
||||||
{
|
|
||||||
qse_str_fini (&g.path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
|
||||||
/* nothing */
|
|
||||||
#else
|
|
||||||
if (qse_mbs_init (&g.mbuf, mmgr, 512) <= -1)
|
|
||||||
{
|
|
||||||
qse_str_fini (&g.path);
|
|
||||||
qse_str_fini (&g.path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QSE_MEMSET (&seg, 0, QSE_SIZEOF(seg));
|
|
||||||
seg.type = NONE;
|
|
||||||
seg.ptr = pattern;
|
|
||||||
seg.len = 0;
|
|
||||||
|
|
||||||
x = search (&g, &seg);
|
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
|
||||||
/* nothing */
|
|
||||||
#else
|
|
||||||
qse_mbs_fini (&g.mbuf);
|
|
||||||
#endif
|
|
||||||
qse_str_fini (&g.tbuf);
|
|
||||||
qse_str_fini (&g.path);
|
|
||||||
|
|
||||||
if (x <= -1) return -1;
|
|
||||||
return g.expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
590
qse/lib/cmn/glob.h
Normal file
590
qse/lib/cmn/glob.h
Normal file
@ -0,0 +1,590 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
typedef struct stack_node_t stack_node_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct glob_t
|
||||||
|
{
|
||||||
|
cbimpl_t cbimpl;
|
||||||
|
void* cbctx;
|
||||||
|
|
||||||
|
qse_mmgr_t* mmgr;
|
||||||
|
qse_cmgr_t* cmgr;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
str_t path;
|
||||||
|
str_t tbuf; /* temporary buffer */
|
||||||
|
|
||||||
|
#if defined(DECLARE_MBUF)
|
||||||
|
qse_mbs_t mbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int expanded;
|
||||||
|
int fnmat_flags;
|
||||||
|
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
stack_node_t* stack;
|
||||||
|
stack_node_t* free;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct glob_t glob_t;
|
||||||
|
|
||||||
|
struct segment_t
|
||||||
|
{
|
||||||
|
segment_type_t type;
|
||||||
|
|
||||||
|
const char_t* ptr;
|
||||||
|
qse_size_t len;
|
||||||
|
|
||||||
|
char_t sep; /* preceeding separator */
|
||||||
|
unsigned int wild: 1; /* indicate that it contains wildcards */
|
||||||
|
unsigned int esc: 1; /* indicate that it contains escaped letters */
|
||||||
|
unsigned int next: 1; /* indicate that it has the following segment */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct segment_t segment_t;
|
||||||
|
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
struct stack_node_t
|
||||||
|
{
|
||||||
|
qse_size_t tmp;
|
||||||
|
qse_size_t tmp2;
|
||||||
|
qse_dir_t* dp;
|
||||||
|
segment_t seg;
|
||||||
|
|
||||||
|
stack_node_t* next;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DECLARE_MBUF)
|
||||||
|
static qse_mchar_t* wcs_to_mbuf (glob_t* g, const qse_wchar_t* wcs, qse_mbs_t* mbs)
|
||||||
|
{
|
||||||
|
qse_size_t ml, wl;
|
||||||
|
|
||||||
|
if (qse_wcstombswithcmgr (wcs, &wl, QSE_NULL, &ml, g->cmgr) <= -1 ||
|
||||||
|
qse_mbs_setlen (mbs, ml) == (qse_size_t)-1) return QSE_NULL;
|
||||||
|
|
||||||
|
qse_wcstombswithcmgr (wcs, &wl, QSE_MBS_PTR(mbs), &ml, g->cmgr);
|
||||||
|
return QSE_MBS_PTR(mbs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int path_exists (glob_t* g, const char_t* name)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
#if !defined(INVALID_FILE_ATTRIBUTES)
|
||||||
|
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||||
|
#endif
|
||||||
|
#if defined(CHAR_IS_MCHAR)
|
||||||
|
return (GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES)? 1: 0;
|
||||||
|
#else
|
||||||
|
return (GetFileAttributesW(name) != INVALID_FILE_ATTRIBUTES)? 1: 0;
|
||||||
|
#endif
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#elif defined(__OS2__)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
FILESTATUS3 fs;
|
||||||
|
APIRET rc;
|
||||||
|
const qse_mchar_t* mptr;
|
||||||
|
|
||||||
|
#if defined(CHAR_IS_MCHAR)
|
||||||
|
mptr = name;
|
||||||
|
#else
|
||||||
|
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||||
|
if (mptr == QSE_NULL) return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = DosQueryPathInfo (mptr, FIL_STANDARD, &fs, QSE_SIZEOF(fs));
|
||||||
|
|
||||||
|
return (rc == NO_ERROR)? 1:
|
||||||
|
(rc == ERROR_PATH_NOT_FOUND)? 0: -1;
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#elif defined(__DOS__)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
unsigned int x, attr;
|
||||||
|
const qse_mchar_t* mptr;
|
||||||
|
|
||||||
|
#if defined(CHAR_IS_MCHAR)
|
||||||
|
mptr = name;
|
||||||
|
#else
|
||||||
|
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||||
|
if (mptr == QSE_NULL) return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
x = _dos_getfileattr (mptr, &attr);
|
||||||
|
return (x == 0)? 1:
|
||||||
|
(errno == ENOENT)? 0: -1;
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#elif defined(macintosh)
|
||||||
|
HFileInfo fpb;
|
||||||
|
const qse_mchar_t* mptr;
|
||||||
|
|
||||||
|
#if defined(CHAR_IS_MCHAR)
|
||||||
|
mptr = name;
|
||||||
|
#else
|
||||||
|
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||||
|
if (mptr == QSE_NULL) return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QSE_MEMSET (&fpb, 0, QSE_SIZEOF(fpb));
|
||||||
|
fpb.ioNamePtr = (unsigned char*)mptr;
|
||||||
|
|
||||||
|
return (PBGetCatInfoSync ((CInfoPBRec*)&fpb) == noErr)? 1: 0;
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
#if defined(HAVE_LSTAT)
|
||||||
|
qse_lstat_t st;
|
||||||
|
#else
|
||||||
|
qse_stat_t st;
|
||||||
|
#endif
|
||||||
|
const qse_mchar_t* mptr;
|
||||||
|
|
||||||
|
#if defined(CHAR_IS_MCHAR)
|
||||||
|
mptr = name;
|
||||||
|
#else
|
||||||
|
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||||
|
if (mptr == QSE_NULL) return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_LSTAT)
|
||||||
|
return (QSE_LSTAT (mptr, &st) <= -1)? 0: 1;
|
||||||
|
#else
|
||||||
|
/* use stat() if no lstat() is available. */
|
||||||
|
return (QSE_STAT (mptr, &st) <= -1)? 0: 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_next_segment (glob_t* g, segment_t* seg)
|
||||||
|
{
|
||||||
|
if (seg->type == NONE)
|
||||||
|
{
|
||||||
|
/* seg->ptr must point to the beginning of the pattern
|
||||||
|
* and seg->len must be zero when seg->type is NONE. */
|
||||||
|
if (IS_NIL(seg->ptr[0]))
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
}
|
||||||
|
else if (IS_SEP(seg->ptr[0]))
|
||||||
|
{
|
||||||
|
seg->type = ROOT;
|
||||||
|
seg->len = 1;
|
||||||
|
seg->next = IS_NIL(seg->ptr[1])? 0: 1;
|
||||||
|
seg->sep = T('\0');
|
||||||
|
seg->wild = 0;
|
||||||
|
seg->esc = 0;
|
||||||
|
}
|
||||||
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
|
else if (IS_DRIVE(seg->ptr))
|
||||||
|
{
|
||||||
|
seg->type = ROOT;
|
||||||
|
seg->len = 2;
|
||||||
|
if (IS_SEP(seg->ptr[2])) seg->len++;
|
||||||
|
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||||
|
seg->sep = T('\0');
|
||||||
|
seg->wild = 0;
|
||||||
|
seg->esc = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int escaped = 0;
|
||||||
|
seg->type = NORMAL;
|
||||||
|
seg->sep = T('\0');
|
||||||
|
seg->wild = 0;
|
||||||
|
seg->esc = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (escaped) escaped = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IS_ESC(seg->ptr[seg->len]))
|
||||||
|
{
|
||||||
|
escaped = 1;
|
||||||
|
seg->esc = 1;
|
||||||
|
}
|
||||||
|
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg->len++;
|
||||||
|
}
|
||||||
|
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]));
|
||||||
|
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (seg->type == ROOT)
|
||||||
|
{
|
||||||
|
int escaped = 0;
|
||||||
|
seg->type = NORMAL;
|
||||||
|
seg->ptr = &seg->ptr[seg->len];
|
||||||
|
seg->len = 0;
|
||||||
|
seg->sep = T('\0');
|
||||||
|
seg->wild = 0;
|
||||||
|
seg->esc = 0;
|
||||||
|
|
||||||
|
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]))
|
||||||
|
{
|
||||||
|
if (escaped) escaped = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IS_ESC(seg->ptr[seg->len]))
|
||||||
|
{
|
||||||
|
escaped = 1;
|
||||||
|
seg->esc = 1;
|
||||||
|
}
|
||||||
|
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
||||||
|
}
|
||||||
|
seg->len++;
|
||||||
|
}
|
||||||
|
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QSE_ASSERT (seg->type == NORMAL);
|
||||||
|
|
||||||
|
seg->ptr = &seg->ptr[seg->len + 1];
|
||||||
|
seg->len = 0;
|
||||||
|
seg->wild = 0;
|
||||||
|
seg->esc = 0;
|
||||||
|
if (IS_NIL(seg->ptr[-1]))
|
||||||
|
{
|
||||||
|
seg->type = NONE;
|
||||||
|
seg->next = 0;
|
||||||
|
seg->sep = T('\0');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int escaped = 0;
|
||||||
|
seg->sep = seg->ptr[-1];
|
||||||
|
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]))
|
||||||
|
{
|
||||||
|
if (escaped) escaped = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IS_ESC(seg->ptr[seg->len]))
|
||||||
|
{
|
||||||
|
escaped = 1;
|
||||||
|
seg->esc = 1;
|
||||||
|
}
|
||||||
|
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
||||||
|
}
|
||||||
|
seg->len++;
|
||||||
|
}
|
||||||
|
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return seg->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_non_wild_segments (glob_t* g, segment_t* seg)
|
||||||
|
{
|
||||||
|
while (get_next_segment(g, seg) != NONE && !seg->wild)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (seg->type != NONE && !seg->wild);
|
||||||
|
|
||||||
|
if (seg->sep && str_ccat (&g->path, seg->sep) == (qse_size_t)-1) return -1;
|
||||||
|
if (seg->esc)
|
||||||
|
{
|
||||||
|
/* if the segment contains escape sequences,
|
||||||
|
* strip the escape letters off the segment */
|
||||||
|
|
||||||
|
cstr_t tmp;
|
||||||
|
qse_size_t i;
|
||||||
|
int escaped = 0;
|
||||||
|
|
||||||
|
if (STR_CAPA(&g->tbuf) < seg->len &&
|
||||||
|
str_setcapa (&g->tbuf, seg->len) == (qse_size_t)-1) return -1;
|
||||||
|
|
||||||
|
tmp.ptr = STR_PTR(&g->tbuf);
|
||||||
|
tmp.len = 0;
|
||||||
|
|
||||||
|
/* the following loop drops the last character
|
||||||
|
* if it is the escape character */
|
||||||
|
for (i = 0; i < seg->len; i++)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
escaped = 0;
|
||||||
|
tmp.ptr[tmp.len++] = seg->ptr[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IS_ESC(seg->ptr[i]))
|
||||||
|
escaped = 1;
|
||||||
|
else
|
||||||
|
tmp.ptr[tmp.len++] = seg->ptr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_ncat (&g->path, tmp.ptr, tmp.len) == (qse_size_t)-1) return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if the segmetn doesn't contain escape sequences,
|
||||||
|
* append the segment to the path without special handling */
|
||||||
|
if (str_ncat (&g->path, seg->ptr, seg->len) == (qse_size_t)-1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seg->next && path_exists (g, STR_PTR(&g->path)) > 0)
|
||||||
|
{
|
||||||
|
/* reached the last segment. match if the path exists */
|
||||||
|
if (g->cbimpl (STR_XSTR(&g->path), g->cbctx) <= -1) return -1;
|
||||||
|
g->expanded = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int search (glob_t* g, segment_t* seg)
|
||||||
|
{
|
||||||
|
qse_dir_t* dp;
|
||||||
|
qse_size_t tmp, tmp2;
|
||||||
|
qse_dir_ent_t ent;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
stack_node_t* r;
|
||||||
|
|
||||||
|
entry:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dp = QSE_NULL;
|
||||||
|
|
||||||
|
if (handle_non_wild_segments (g, seg) <= -1) goto oops;
|
||||||
|
|
||||||
|
if (seg->wild)
|
||||||
|
{
|
||||||
|
int dir_flags = DIR_CHAR_FLAGS;
|
||||||
|
if (g->flags & QSE_GLOB_SKIPSPCDIR) dir_flags |= QSE_DIR_SKIPSPCDIR;
|
||||||
|
|
||||||
|
dp = qse_dir_open (
|
||||||
|
g->mmgr, 0, (const qse_char_t*)STR_PTR(&g->path),
|
||||||
|
dir_flags, QSE_NULL);
|
||||||
|
if (dp)
|
||||||
|
{
|
||||||
|
tmp = STR_LEN(&g->path);
|
||||||
|
|
||||||
|
if (seg->sep && str_ccat (&g->path, seg->sep) == (qse_size_t)-1) goto oops;
|
||||||
|
tmp2 = STR_LEN(&g->path);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
str_setlen (&g->path, tmp2);
|
||||||
|
|
||||||
|
x = qse_dir_read (dp, &ent);
|
||||||
|
if (x <= -1)
|
||||||
|
{
|
||||||
|
if (g->flags & QSE_GLOB_TOLERANT) break;
|
||||||
|
else goto oops;
|
||||||
|
}
|
||||||
|
if (x == 0) break;
|
||||||
|
|
||||||
|
if (str_cat (&g->path, (const char_t*)ent.name) == (qse_size_t)-1) goto oops;
|
||||||
|
|
||||||
|
if (strnfnmat (STR_CPTR(&g->path,tmp2), seg->ptr, seg->len, g->fnmat_flags) > 0)
|
||||||
|
{
|
||||||
|
if (seg->next)
|
||||||
|
{
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
if (g->free)
|
||||||
|
{
|
||||||
|
r = g->free;
|
||||||
|
g->free = r->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = QSE_MMGR_ALLOC (g->mmgr, QSE_SIZEOF(*r));
|
||||||
|
if (r == QSE_NULL) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push key variables that must be restored
|
||||||
|
* into the stack. */
|
||||||
|
r->tmp = tmp;
|
||||||
|
r->tmp2 = tmp2;
|
||||||
|
r->dp = dp;
|
||||||
|
r->seg = *seg;
|
||||||
|
|
||||||
|
r->next = g->stack;
|
||||||
|
g->stack = r;
|
||||||
|
|
||||||
|
/* move to the function entry point as if
|
||||||
|
* a recursive call has been made */
|
||||||
|
goto entry;
|
||||||
|
|
||||||
|
resume:
|
||||||
|
;
|
||||||
|
|
||||||
|
#else
|
||||||
|
segment_t save;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
save = *seg;
|
||||||
|
x = search (g, seg);
|
||||||
|
*seg = save;
|
||||||
|
if (x <= -1) goto oops;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (g->cbimpl (STR_XSTR(&g->path), g->cbctx) <= -1) goto oops;
|
||||||
|
g->expanded = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str_setlen (&g->path, tmp);
|
||||||
|
qse_dir_close (dp); dp = QSE_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_ASSERT (dp == QSE_NULL);
|
||||||
|
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
if (g->stack)
|
||||||
|
{
|
||||||
|
/* the stack is not empty. the emulated recusive call
|
||||||
|
* must have been made. restore the variables pushed
|
||||||
|
* and jump to the resumption point */
|
||||||
|
r = g->stack;
|
||||||
|
g->stack = r->next;
|
||||||
|
|
||||||
|
tmp = r->tmp;
|
||||||
|
tmp2 = r->tmp2;
|
||||||
|
dp = r->dp;
|
||||||
|
*seg = r->seg;
|
||||||
|
|
||||||
|
/* link the stack node to the free list
|
||||||
|
* instead of freeing it here */
|
||||||
|
r->next = g->free;
|
||||||
|
g->free = r;
|
||||||
|
|
||||||
|
goto resume;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g->free)
|
||||||
|
{
|
||||||
|
/* destory the free list */
|
||||||
|
r = g->free;
|
||||||
|
g->free = r->next;
|
||||||
|
QSE_MMGR_FREE (g->mmgr, r);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (dp) qse_dir_close (dp);
|
||||||
|
|
||||||
|
#if defined(NO_RECURSION)
|
||||||
|
while (g->stack)
|
||||||
|
{
|
||||||
|
r = g->stack;
|
||||||
|
g->stack = r->next;
|
||||||
|
qse_dir_close (r->dp);
|
||||||
|
QSE_MMGR_FREE (g->mmgr, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g->free)
|
||||||
|
{
|
||||||
|
r = g->stack;
|
||||||
|
g->free = r->next;
|
||||||
|
QSE_MMGR_FREE (g->mmgr, r);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int glob (const char_t* pattern, cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr)
|
||||||
|
{
|
||||||
|
segment_t seg;
|
||||||
|
glob_t g;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
QSE_MEMSET (&g, 0, QSE_SIZEOF(g));
|
||||||
|
g.cbimpl = cbimpl;
|
||||||
|
g.cbctx = cbctx;
|
||||||
|
g.mmgr = mmgr;
|
||||||
|
g.cmgr = cmgr;
|
||||||
|
g.flags = flags;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
|
g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
|
||||||
|
g.fnmat_flags |= QSE_STRFNMAT_NOESCAPE;
|
||||||
|
#else
|
||||||
|
if (flags & QSE_GLOB_IGNORECASE) g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
|
||||||
|
if (flags & QSE_GLOB_NOESCAPE) g.fnmat_flags |= QSE_STRFNMAT_NOESCAPE;
|
||||||
|
#endif
|
||||||
|
if (flags & QSE_GLOB_PERIOD) g.fnmat_flags |= QSE_STRFNMAT_PERIOD;
|
||||||
|
|
||||||
|
if (str_init (&g.path, mmgr, 512) <= -1) return -1;
|
||||||
|
if (str_init (&g.tbuf, mmgr, 256) <= -1)
|
||||||
|
{
|
||||||
|
str_fini (&g.path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(DECLARE_MBUF)
|
||||||
|
if (qse_mbs_init (&g.mbuf, mmgr, 512) <= -1)
|
||||||
|
{
|
||||||
|
str_fini (&g.path);
|
||||||
|
str_fini (&g.path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QSE_MEMSET (&seg, 0, QSE_SIZEOF(seg));
|
||||||
|
seg.type = NONE;
|
||||||
|
seg.ptr = pattern;
|
||||||
|
seg.len = 0;
|
||||||
|
|
||||||
|
x = search (&g, &seg);
|
||||||
|
|
||||||
|
#if defined(DECLARE_MBUF)
|
||||||
|
qse_mbs_fini (&g.mbuf);
|
||||||
|
#endif
|
||||||
|
str_fini (&g.tbuf);
|
||||||
|
str_fini (&g.path);
|
||||||
|
|
||||||
|
if (x <= -1) return -1;
|
||||||
|
return g.expanded;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user