⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bsd_glob.c

📁 source of perl for linux application,
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Guido van Rossum. * * 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. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";/* most changes between the version above and the one below have been ported:static char sscsid[]=  "$OpenBSD: glob.c,v 1.8.10.1 2001/04/10 jason Exp $"; */#endif /* LIBC_SCCS and not lint *//* * glob(3) -- a superset of the one defined in POSIX 1003.2. * * The [!...] convention to negate a range is supported (SysV, Posix, ksh). * * Optional extra services, controlled by flags not defined by POSIX: * * GLOB_QUOTE: *	Escaping convention: \ inhibits any special meaning the following *	character might have (except \ at end of string is retained). * GLOB_MAGCHAR: *	Set in gl_flags if pattern contained a globbing character. * GLOB_NOMAGIC: *	Same as GLOB_NOCHECK, but it will only append pattern if it did *	not contain any magic characters.  [Used in csh style globbing] * GLOB_ALTDIRFUNC: *	Use alternately specified directory access functions. * GLOB_TILDE: *	expand ~user/foo to the /home/dir/of/user/foo * GLOB_BRACE: *	expand {1,2}{a,b} to 1a 1b 2a 2b * gl_matchc: *	Number of matches in the current invocation of glob. * GLOB_ALPHASORT: *	sort alphabetically like csh (case doesn't matter) instead of in ASCII *	order */#include <EXTERN.h>#include <perl.h>#include <XSUB.h>#include "bsd_glob.h"#ifdef I_PWD#	include <pwd.h>#else#if defined(HAS_PASSWD) && !defined(VMS)	struct passwd *getpwnam(char *);	struct passwd *getpwuid(Uid_t);#endif#endif#ifndef MAXPATHLEN#  ifdef PATH_MAX#    define	MAXPATHLEN	PATH_MAX#    ifdef MACOS_TRADITIONAL#      define	MAXPATHLEN	255#    else#      define	MAXPATHLEN	1024#    endif#  endif#endif#ifdef I_LIMITS#include <limits.h>#endif#ifndef ARG_MAX#  ifdef MACOS_TRADITIONAL#    define		ARG_MAX		65536	/* Mac OS is actually unlimited */#  else#    ifdef _SC_ARG_MAX#      define		ARG_MAX		(sysconf(_SC_ARG_MAX))#    else#      ifdef _POSIX_ARG_MAX#        define		ARG_MAX		_POSIX_ARG_MAX#      else#        ifdef WIN32#          define	ARG_MAX		14500	/* from VC's limits.h */#        else#          define	ARG_MAX		4096	/* from POSIX, be conservative */#        endif#      endif#    endif#  endif#endif#define	BG_DOLLAR	'$'#define	BG_DOT		'.'#define	BG_EOS		'\0'#define	BG_LBRACKET	'['#define	BG_NOT		'!'#define	BG_QUESTION	'?'#define	BG_QUOTE	'\\'#define	BG_RANGE	'-'#define	BG_RBRACKET	']'#ifdef MACOS_TRADITIONAL#  define	BG_SEP	':'#else#  define	BG_SEP	'/'#endif#ifdef DOSISH#define BG_SEP2		'\\'#endif#define	BG_STAR		'*'#define	BG_TILDE	'~'#define	BG_UNDERSCORE	'_'#define	BG_LBRACE	'{'#define	BG_RBRACE	'}'#define	BG_SLASH	'/'#define	BG_COMMA	','#ifndef GLOB_DEBUG#define	M_QUOTE		0x8000#define	M_PROTECT	0x4000#define	M_MASK		0xffff#define	M_ASCII		0x00fftypedef U16 Char;#else#define	M_QUOTE		0x80#define	M_PROTECT	0x40#define	M_MASK		0xff#define	M_ASCII		0x7ftypedef U8 Char;#endif /* !GLOB_DEBUG */#define	CHAR(c)		((Char)((c)&M_ASCII))#define	META(c)		((Char)((c)|M_QUOTE))#define	M_ALL		META('*')#define	M_END		META(']')#define	M_NOT		META('!')#define	M_ONE		META('?')#define	M_RNG		META('-')#define	M_SET		META('[')#define	ismeta(c)	(((c)&M_QUOTE) != 0)static int	 compare(const void *, const void *);static int	 ci_compare(const void *, const void *);static int	 g_Ctoc(const Char *, char *, STRLEN);static int	 g_lstat(Char *, Stat_t *, glob_t *);static DIR	*g_opendir(Char *, glob_t *);static Char	*g_strchr(Char *, int);static int	 g_stat(Char *, Stat_t *, glob_t *);static int	 glob0(const Char *, glob_t *);static int	 glob1(Char *, Char *, glob_t *, size_t *);static int	 glob2(Char *, Char *, Char *, Char *, Char *, Char *,		       glob_t *, size_t *);static int	 glob3(Char *, Char *, Char *, Char *, Char *, Char *,		       Char *, Char *, glob_t *, size_t *);static int	 globextend(const Char *, glob_t *, size_t *);static const Char *		 globtilde(const Char *, Char *, size_t, glob_t *);static int	 globexp1(const Char *, glob_t *);static int	 globexp2(const Char *, const Char *, glob_t *, int *);static int	 match(Char *, Char *, Char *, int);#ifdef GLOB_DEBUGstatic void	 qprintf(const char *, Char *);#endif /* GLOB_DEBUG */#ifdef PERL_IMPLICIT_CONTEXTstatic Direntry_t *	my_readdir(DIR*);static Direntry_t *my_readdir(DIR *d){#ifndef NETWARE    return PerlDir_read(d);#else    return (DIR *)PerlDir_read(d);#endif}#else/* ReliantUNIX (OS formerly known as SINIX) defines readdir * in LFS-mode to be a 64-bit version of readdir.  */#   ifdef sinixstatic Direntry_t *    my_readdir(DIR*);static Direntry_t *my_readdir(DIR *d){    return readdir(d);}#   else#       define	my_readdir	readdir#   endif#endif#ifdef MACOS_TRADITIONAL#include <Files.h>#include <Types.h>#include <string.h>#define NO_UPDIR_ERR 1	/* updir resolving failed */static Boolean g_matchVol; /* global variable */static short updir(char *path);static short resolve_updirs(char *new_pattern);static void remove_trColon(char *path);static short glob_mark_Mac(Char *pathbuf, Char *pathend, Char *pathend_last);static OSErr GetVolInfo(short volume, Boolean indexed, FSSpec *spec);static void name_f_FSSpec(StrFileName volname, FSSpec *spec);#endifintbsd_glob(const char *pattern, int flags,	 int (*errfunc)(const char *, int), glob_t *pglob){	const U8 *patnext;	int c;	Char *bufnext, *bufend, patbuf[MAXPATHLEN];#ifdef MACOS_TRADITIONAL	char *new_pat, *p, *np;	int err;	size_t len;#endif#ifndef MACOS_TRADITIONAL	patnext = (U8 *) pattern;#endif	/* TODO: GLOB_APPEND / GLOB_DOOFFS aren't supported yet */#if 0	if (!(flags & GLOB_APPEND)) {		pglob->gl_pathc = 0;		pglob->gl_pathv = NULL;		if (!(flags & GLOB_DOOFFS))			pglob->gl_offs = 0;	}#else	pglob->gl_pathc = 0;	pglob->gl_pathv = NULL;	pglob->gl_offs = 0;#endif	pglob->gl_flags = flags & ~GLOB_MAGCHAR;	pglob->gl_errfunc = errfunc;	pglob->gl_matchc = 0;	bufnext = patbuf;	bufend = bufnext + MAXPATHLEN - 1;#ifdef DOSISH	/* Nasty hack to treat patterns like "C:*" correctly. In this	 * case, the * should match any file in the current directory	 * on the C: drive. However, the glob code does not treat the	 * colon specially, so it looks for files beginning "C:" in	 * the current directory. To fix this, change the pattern to	 * add an explicit "./" at the start (just after the drive	 * letter and colon - ie change to "C:./").	 */	if (isalpha(pattern[0]) && pattern[1] == ':' &&	    pattern[2] != BG_SEP && pattern[2] != BG_SEP2 &&	    bufend - bufnext > 4) {		*bufnext++ = pattern[0];		*bufnext++ = ':';		*bufnext++ = '.';		*bufnext++ = BG_SEP;		patnext += 2;	}#endif#ifdef MACOS_TRADITIONAL	/* Check if we need to match a volume name (e.g. '*HD:*') */	g_matchVol = false;	p = (char *) pattern;	if (*p != BG_SEP) {	    p++;	    while (*p != BG_EOS) {		if (*p == BG_SEP) {		    g_matchVol = true;		    break;		}		p++;	    }	}	/* Transform the pattern:	 * (a) Resolve updirs, e.g.	 *     '*:t*p::'       -> '*:'	 *	   ':a*:tmp::::'   -> '::'	 *	   ':base::t*p:::' -> '::'	 *     '*HD::'         -> return 0 (error, quit silently)	 *	 * (b) Remove a single trailing ':', unless it's a "match volume only"	 *     pattern like '*HD:'; e.g.	 *     '*:tmp:' -> '*:tmp'  but	 *     '*HD:'   -> '*HD:'	 *     (If we don't do that, even filenames will have a trailing ':' in	 *     the result.)	 */	/* We operate on a copy of the pattern */	len = strlen(pattern);	Newx(new_pat, len + 1, char);	if (new_pat == NULL)	    return (GLOB_NOSPACE);	p = (char *) pattern;	np = new_pat;	while (*np++ = *p++) ;	/* Resolve updirs ... */	err = resolve_updirs(new_pat);	if (err) {	    Safefree(new_pat);	    /* The pattern is incorrect: tried to move	       up above the volume root, see above.	       We quit silently. */	    return 0;	}	/* remove trailing colon ... */	remove_trColon(new_pat);	patnext = (U8 *) new_pat;#endif /* MACOS_TRADITIONAL */	if (flags & GLOB_QUOTE) {		/* Protect the quoted characters. */		while (bufnext < bufend && (c = *patnext++) != BG_EOS)			if (c == BG_QUOTE) {#ifdef DOSISH				    /* To avoid backslashitis on Win32,				     * we only treat \ as a quoting character				     * if it precedes one of the				     * metacharacters []-{}~\				     */				if ((c = *patnext++) != '[' && c != ']' &&				    c != '-' && c != '{' && c != '}' &&				    c != '~' && c != '\\') {#else				if ((c = *patnext++) == BG_EOS) {#endif					c = BG_QUOTE;					--patnext;				}				*bufnext++ = c | M_PROTECT;			} else				*bufnext++ = c;	} else		while (bufnext < bufend && (c = *patnext++) != BG_EOS)			*bufnext++ = c;	*bufnext = BG_EOS;#ifdef MACOS_TRADITIONAL	if (flags & GLOB_BRACE)	    err = globexp1(patbuf, pglob);	else	    err = glob0(patbuf, pglob);	Safefree(new_pat);	return err;#else	if (flags & GLOB_BRACE)	    return globexp1(patbuf, pglob);	else	    return glob0(patbuf, pglob);#endif}/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */static intglobexp1(const Char *pattern, glob_t *pglob){	const Char* ptr = pattern;	int rv;	/* Protect a single {}, for find(1), like csh */	if (pattern[0] == BG_LBRACE && pattern[1] == BG_RBRACE && pattern[2] == BG_EOS)		return glob0(pattern, pglob);	while ((ptr = (const Char *) g_strchr((Char *) ptr, BG_LBRACE)) != NULL)		if (!globexp2(ptr, pattern, pglob, &rv))			return rv;	return glob0(pattern, pglob);}/* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */static intglobexp2(const Char *ptr, const Char *pattern,	 glob_t *pglob, int *rv){	int     i;	Char   *lm, *ls;	const Char *pe, *pm, *pm1, *pl;	Char    patbuf[MAXPATHLEN];	/* copy part up to the brace */	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)		;	*lm = BG_EOS;	ls = lm;	/* Find the balanced brace */	for (i = 0, pe = ++ptr; *pe; pe++)		if (*pe == BG_LBRACKET) {			/* Ignore everything between [] */			for (pm = pe++; *pe != BG_RBRACKET && *pe != BG_EOS; pe++)				;			if (*pe == BG_EOS) {				/*				 * We could not find a matching BG_RBRACKET.				 * Ignore and just look for BG_RBRACE				 */				pe = pm;			}		} else if (*pe == BG_LBRACE)			i++;		else if (*pe == BG_RBRACE) {			if (i == 0)				break;			i--;		}	/* Non matching braces; just glob the pattern */	if (i != 0 || *pe == BG_EOS) {		*rv = glob0(patbuf, pglob);		return 0;	}	for (i = 0, pl = pm = ptr; pm <= pe; pm++) {		switch (*pm) {		case BG_LBRACKET:			/* Ignore everything between [] */			for (pm1 = pm++; *pm != BG_RBRACKET && *pm != BG_EOS; pm++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -