[Pkg-javascript-commits] [SCM] glob/fnmatch binding for NodeJS branch, master, updated. debian/2.0.9-1-3-ga067315

Jérémy Lal kapouer at melix.org
Fri Mar 16 21:56:47 UTC 2012


The following commit has been merged in the master branch:
commit 98d9eef08c2465cab993209a83b41e045f16f290
Author: Jérémy Lal <kapouer at melix.org>
Date:   Fri Mar 16 22:02:29 2012 +0100

    Imported Upstream version 3.1.6

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 73ee92d..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.lock-wscript
-build/
-test/core
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..2af4b71
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,2 @@
+.*.swp
+test/a/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..94cd7f6
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.7
diff --git a/LICENCE b/LICENCE
deleted file mode 100644
index ca677bf..0000000
--- a/LICENCE
+++ /dev/null
@@ -1,30 +0,0 @@
-
-Copyright (c) 2011 Isaac Z. Schlueter
-All rights reserved.
-
-The BSD License
-
-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 program includes software contributed to The NetBSD Foundation.
-See dep/bsdglob/LICENSE.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 30ad932..0000000
--- a/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-build:
-	node-waf configure build
-
-clean:
-	node-waf clean
-
-install:
-	npm install
-
-.PHONY: build clean install
diff --git a/README.md b/README.md
index 7955ee0..6e27df6 100644
--- a/README.md
+++ b/README.md
@@ -1,148 +1,233 @@
+# Glob
 
-node-glob - Globbing for Node
+This is a glob implementation in JavaScript.  It uses the `minimatch`
+library to do its matching.
 
-## One day, in <irc://irc.freenode.net#node.js>...
+## Attention: node-glob users!
 
-<code>[4:46pm] <a href="http://tinyclouds.org/">_ry</a>: it would be good to
-have a file system Glob functionality (to get an array of
-filenames)</code>
+The API has changed dramatically between 2.x and 3.x. This library is
+now 100% JavaScript, and the integer flags have been replaced with an
+options object.
 
-## // 9 months later...
+Also, there's an event emitter class, proper tests, and all the other
+things you've come to expect from node modules.
 
-    npm install glob
-
-(You can also install it by doing `node-waf configure build` and then
-linking or copying the folder into your project's `node_modules`
-directory.)
-
-## Wtf's a "glob"?
-
-A glob is a pattern-matching syntax that shells use.  Like when you do
-`rm *.js`, the `*.js` is a glob.
-
-You can do nifty things with them.
-
-## Supported Environments
-
-* Macintosh OS X (Darwin)
-* FreeBSD
-* NetBSD
-* Linux
-* Solaris
-
-If it doesn't work on one of those environments, please <a
-href="https://github.com/isaacs/node-glob/issues">post a bug</a>.
+And best of all, no compilation!
 
 ## Usage
 
-This is a binding to
-[glob(3)](http://www.daemon-systems.org/man/glob.3.html) and
-[fnmatch(3)](http://www.daemon-systems.org/man/fnmatch.3.html).  It includes
-a statically compiled port of the NetBSD glob and fnmatch
-programs, so it might not exactly match what `#include <fnmatch.h>`
-or `#include <glob.h>` implements on your system.
-
-To load the library:
-
-    var glob = require("glob")
-
-## Methods
-
-### glob
-
-Search through the filesystem asynchronously.
-
-#### Params
-
-* pattern: String
-* flags: int, Optional (see below)
-* cb: function
-
-#### Return
-
-NOTHING!
-
-#### Example
-
-    glob(pattern, flags, function (er, matches) {
-      // if an error occurred, it's in er.
-      // otherwise, "matches" is an array of filenames.
-      ...
-    })
-
-### globSync
-
-Search through the filesystem synchronously
-
-#### Params
-
-* pattern: String
-* flags: int, Optional (see below)
-
-#### Return
-
-Array of strings that match.
-
-#### Example
-
-    var matches = glob.globSync(pattern, flags) // throws on error
-
-### fnmatch
-
-Test if a string matches a pattern. (no i/o performed)
-
-#### Params
-
-* pattern: String
-* str: String to test
-* flags: int, Optional (see below)
-
-#### Example
-
-    var isMatch = glob.fnmatch(pattern, str, flags)
-
+```javascript
+var glob = require("glob")
 
-## Flags
+// options is optional
+glob("**/*.js", options, function (er, files) {
+  // files is an array of filenames.
+  // If the `nonull` option is set, and nothing
+  // was found, then files is ["**/*.js"]
+  // er is an error object or null.
+})
+```
 
-The behavior of glob and fnmatch are modified by several bitwise flags.
+## Features
 
-The flags are defined on the main glob object.  If you have an integer,
-and want to look up which flag it corresponds to, you can look it up on
-the glob/globSync functions if it is a glob flag, or on the fnmatch
-function if it is an fnmatch flag.
+Please see the [minimatch
+documentation](https://github.com/isaacs/minimatch) for more details.
 
-That is, `fnmatch[fnmatch.FNM_CASEFOLD] === 'FNM_CASEFOLD'`.
+Supports these glob features:
 
-* `GLOB_DEFAULT` Used if no flags are passed to `glob()` or
-  `globSync()`. Equivalent of
-  `GLOB_BRACE|GLOB_LIMIT|GLOB_STAR|GLOB_MARK|GLOB_TILDE`.
-* `FNM_DEFAULT` Used if no flags are passed to `fnmatch()`.  Equivalent
-  of `FNM_PATHNAME|FNM_PERIOD`.
-* `GLOB_MARK` Append / to matching directories.
-* `GLOB_NOCHECK` Return pattern itself if nothing matches.
-* `GLOB_NOSORT` Don't sort.
-* `GLOB_NOESCAPE` Disable backslash escaping.
-* `GLOB_NOSPACE` Malloc call failed.
-* `GLOB_ABORTED` Unignored error.
-* `GLOB_NOMATCH` No match, and GLOB_NOCHECK was not set.
-* `GLOB_NOSYS` Implementation does not support function.
-* `GLOB_BRACE` Expand braces ala csh.
-* `GLOB_NOMAGIC` GLOB_NOCHECK without magic chars (csh).
-* `GLOB_LIMIT` Limit memory used by matches to ARG_MAX
-* `GLOB_TILDE` Expand tilde names from the passwd file.
-* `GLOB_PERIOD` Allow metachars to match leading periods.
-* `GLOB_NO_DOTDIRS` Make . and .. vanish from wildcards.
-* `GLOB_STAR` Use glob `**` to recurse directories
-* `GLOB_QUOTE` source compatibility
-* `FNM_NOMATCH` Match failed.
-* `FNM_NOSYS` Function not implemented.
-* `FNM_NORES` Out of resources
-* `FNM_NOESCAPE` Disable backslash escaping.
-* `FNM_PATHNAME` Slash must be matched by slash.
-* `FNM_PERIOD` Period must be matched by period.
-* `FNM_CASEFOLD` Pattern is matched case-insensitive
-* `FNM_LEADING_DIR` Ignore /<tail> after Imatch.
+* Brace Expansion
+* Extended glob matching
+* "Globstar" `**` matching
 
-## Bugs
+See:
 
-See <https://github.com/isaacs/node-glob/issues>.
+* `man sh`
+* `man bash`
+* `man 3 fnmatch`
+* `man 5 gitignore`
+* [minimatch documentation](https://github.com/isaacs/minimatch)
+
+## glob(pattern, [options], cb)
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* `cb` {Function}
+  * `err` {Error | null}
+  * `matches` {Array<String>} filenames found matching the pattern
+
+Perform an asynchronous glob search.
+
+## glob.sync(pattern, [options]
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* return: {Array<String>} filenames found matching the pattern
+
+Perform a synchronous glob search.
+
+## Class: glob.Glob
+
+Create a Glob object by instanting the `glob.Glob` class.
+
+```javascript
+var Glob = require("glob").Glob
+var mg = new Glob(pattern, options, cb)
+```
+
+It's an EventEmitter, and starts walking the filesystem to find matches
+immediately.
+
+### new glob.Glob(pattern, [options], [cb])
+
+* `pattern` {String} pattern to search for
+* `options` {Object}
+* `cb` {Function} Called when an error occurs, or matches are found
+  * `err` {Error | null}
+  * `matches` {Array<String>} filenames found matching the pattern
+
+Note that if the `sync` flag is set in the options, then matches will
+be immediately available on the `g.found` member.
+
+### Properties
+
+* `minimatch` The minimatch object that the glob uses.
+* `options` The options object passed in.
+* `error` The error encountered.  When an error is encountered, the
+  glob object is in an undefined state, and should be discarded.
+* `aborted` Boolean which is set to true when calling `abort()`.  There
+  is no way at this time to continue a glob search after aborting, but
+  you can re-use the statCache to avoid having to duplicate syscalls.
+
+### Events
+
+* `end` When the matching is finished, this is emitted with all the
+  matches found.  If the `nonull` option is set, and no match was found,
+  then the `matches` list contains the original pattern.  The matches
+  are sorted, unless the `nosort` flag is set.
+* `match` Every time a match is found, this is emitted with the matched.
+* `error` Emitted when an unexpected error is encountered, or whenever
+  any fs error occurs if `options.strict` is set.
+* `abort` When `abort()` is called, this event is raised.
+
+### Methods
+
+* `abort` Stop the search.
+
+### Options
+
+All the options that can be passed to Minimatch can also be passed to
+Glob to change pattern matching behavior.  Also, some have been added,
+or have glob-specific ramifications.
+
+All options are false by default, unless otherwise noted.
+
+All options are added to the glob object, as well.
+
+* `cwd` The current working directory in which to search.  Defaults
+  to `process.cwd()`.
+* `root` The place where patterns starting with `/` will be mounted
+  onto.  Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
+  systems, and `C:\` or some such on Windows.)
+* `nomount` By default, a pattern starting with a forward-slash will be
+  "mounted" onto the root setting, so that a valid filesystem path is
+  returned.  Set this flag to disable that behavior.
+* `mark` Add a `/` character to directory matches.  Note that this
+  requires additional stat calls.
+* `nosort` Don't sort the results.
+* `stat` Set to true to stat *all* results.  This reduces performance
+  somewhat, and is completely unnecessary, unless `readdir` is presumed
+  to be an untrustworthy indicator of file existence.  It will cause
+  ELOOP to be triggered one level sooner in the case of cyclical
+  symbolic links.
+* `silent` When an unusual error is encountered
+  when attempting to read a directory, a warning will be printed to
+  stderr.  Set the `silent` option to true to suppress these warnings.
+* `strict` When an unusual error is encountered
+  when attempting to read a directory, the process will just continue on
+  in search of other matches.  Set the `strict` option to raise an error
+  in these cases.
+* `statCache` A cache of results of filesystem information, to prevent
+  unnecessary stat calls.  While it should not normally be necessary to
+  set this, you may pass the statCache from one glob() call to the
+  options object of another, if you know that the filesystem will not
+  change between calls.  (See "Race Conditions" below.)
+* `sync` Perform a synchronous glob search.
+* `nounique` In some cases, brace-expanded patterns can result in the
+  same file showing up multiple times in the result set.  By default,
+  this implementation prevents duplicates in the result set.
+  Set this flag to disable that behavior.
+* `nonull` Set to never return an empty set, instead returning a set
+  containing the pattern itself.  This is the default in glob(3).
+* `nocase` Perform a case-insensitive match.  Note that case-insensitive
+  filesystems will sometimes result in glob returning results that are
+  case-insensitively matched anyway, since readdir and stat will not
+  raise an error.
+* `debug` Set to enable debug logging in minimatch and glob.
+* `globDebug` Set to enable debug logging in glob, but not minimatch.
+
+## Comparisons to other fnmatch/glob implementations
+
+While strict compliance with the existing standards is a worthwhile
+goal, some discrepancies exist between node-glob and other
+implementations, and are intentional.
+
+If the pattern starts with a `!` character, then it is negated.  Set the
+`nonegate` flag to suppress this behavior, and treat leading `!`
+characters normally.  This is perhaps relevant if you wish to start the
+pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
+characters at the start of a pattern will negate the pattern multiple
+times.
+
+If a pattern starts with `#`, then it is treated as a comment, and
+will not match anything.  Use `\#` to match a literal `#` at the
+start of a line, or set the `nocomment` flag to suppress this behavior.
+
+The double-star character `**` is supported by default, unless the
+`noglobstar` flag is set.  This is supported in the manner of bsdglob
+and bash 4.1, where `**` only has special significance if it is the only
+thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
+`a/**b` will not.  **Note that this is different from the way that `**` is
+handled by ruby's `Dir` class.**
+
+If an escaped pattern has no matches, and the `nonull` flag is set,
+then glob returns the pattern as-provided, rather than
+interpreting the character escapes.  For example,
+`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
+`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
+that it does not resolve escaped pattern characters.
+
+If brace expansion is not disabled, then it is performed before any
+other interpretation of the glob pattern.  Thus, a pattern like
+`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
+**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
+checked for validity.  Since those two are valid, matching proceeds.
+
+## Windows
+
+**Please only use forward-slashes in glob expressions.**
+
+Though windows uses either `/` or `\` as its path separator, only `/`
+characters are used by this glob implementation.  You must use
+forward-slashes **only** in glob expressions.  Back-slashes will always
+be interpreted as escape characters, not path separators.
+
+Results from absolute patterns such as `/foo/*` are mounted onto the
+root setting using `path.join`.  On windows, this will by default result
+in `/foo/*` matching `C:\foo\bar.txt`.
+
+## Race Conditions
+
+Glob searching, by its very nature, is susceptible to race conditions,
+since it relies on directory walking and such.
+
+As a result, it is possible that a file that exists when glob looks for
+it may have been deleted or modified by the time it returns the result.
+
+As part of its internal implementation, this program caches all stat
+and readdir calls that it makes, in order to cut down on system
+overhead.  However, this also makes it even more susceptible to races,
+especially if the statCache object is reused between glob calls.
+
+Users are thus advised not to use a glob result as a
+guarantee of filesystem state in the face of rapid changes.
+For the vast majority of operations, this is never a problem.
diff --git a/deps/fnmatch/LICENSE b/deps/fnmatch/LICENSE
deleted file mode 100644
index bf33ae5..0000000
--- a/deps/fnmatch/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2008 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation.
-
-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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
diff --git a/deps/fnmatch/fnmatch.c b/deps/fnmatch/fnmatch.c
deleted file mode 100644
index 8bfbecd..0000000
--- a/deps/fnmatch/fnmatch.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*	$NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $	*/
-
-/*
- * Copyright (c) 1989, 1993, 1994
- *	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.
- */
-
-/* isaacs */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)fnmatch.c	8.2 (Berkeley) 4/16/94";
-#else
-__RCSID("$NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-/* isaacs */
-#ifndef __UNCONST
-# define __UNCONST(a)    ((void *)(unsigned long)(const void *)(a))
-#endif
-
-/* isaacs */
-#ifndef _DIAGASSERT
-# ifdef DEBUG
-#  define _DIAGASSERT(a) assert(a)
-# else
-#  define _DIAGASSERT(a)
-# endif
-#endif
-
-/*
- * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- * Compares a filename or pathname to a pattern.
- */
-
-#include <fnmatch.h>
-#include <assert.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef __weak_alias
-__weak_alias(fnmatch,_fnmatch)
-#endif
-
-#define	EOS	'\0'
-
-static inline int
-foldcase(int ch, int flags)
-{
-
-	if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))
-		return tolower(ch);
-	return ch;
-}
-
-#define	FOLDCASE(ch, flags)	foldcase((unsigned char)(ch), (flags))
-
-static const char *
-rangematch(const char *pattern, int test, int flags)
-{
-	int negate, ok;
-	char c, c2;
-
-	_DIAGASSERT(pattern != NULL);
-
-	/*
-	 * A bracket expression starting with an unquoted circumflex
-	 * character produces unspecified results (IEEE 1003.2-1992,
-	 * 3.13.2).  This implementation treats it like '!', for
-	 * consistency with the regular expression syntax.
-	 * J.T. Conklin (conklin at ngai.kaleida.com)
-	 */
-	if ((negate = (*pattern == '!' || *pattern == '^')) != 0)
-		++pattern;
-	
-	for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) {
-		if (c == '\\' && !(flags & FNM_NOESCAPE))
-			c = FOLDCASE(*pattern++, flags);
-		if (c == EOS)
-			return NULL;
-		if (*pattern == '-' 
-		    && (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS &&
-		        c2 != ']') {
-			pattern += 2;
-			if (c2 == '\\' && !(flags & FNM_NOESCAPE))
-				c2 = FOLDCASE(*pattern++, flags);
-			if (c2 == EOS)
-				return NULL;
-			if (c <= test && test <= c2)
-				ok = 1;
-		} else if (c == test)
-			ok = 1;
-	}
-	return ok == negate ? NULL : pattern;
-}
-
-
-static int
-fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)
-{
-	const char *stringstart;
-	char c, test;
-
-	_DIAGASSERT(pattern != NULL);
-	_DIAGASSERT(string != NULL);
-
-	if (recursion-- == 0)
-		return FNM_NORES;
-
-	for (stringstart = string;;) {
-		switch (c = FOLDCASE(*pattern++, flags)) {
-		case EOS:
-			if ((flags & FNM_LEADING_DIR) && *string == '/')
-				return 0;
-			return *string == EOS ? 0 : FNM_NOMATCH;
-		case '?':
-			if (*string == EOS)
-				return FNM_NOMATCH;
-			if (*string == '/' && (flags & FNM_PATHNAME))
-				return FNM_NOMATCH;
-			if (*string == '.' && (flags & FNM_PERIOD) &&
-			    (string == stringstart ||
-			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
-				return FNM_NOMATCH;
-			++string;
-			break;
-		case '*':
-			c = FOLDCASE(*pattern, flags);
-			/* Collapse multiple stars. */
-			while (c == '*')
-				c = FOLDCASE(*++pattern, flags);
-
-			if (*string == '.' && (flags & FNM_PERIOD) &&
-			    (string == stringstart ||
-			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
-				return FNM_NOMATCH;
-
-			/* Optimize for pattern with * at end or before /. */
-			if (c == EOS) {
-				if (flags & FNM_PATHNAME)
-					return (flags & FNM_LEADING_DIR) ||
-					    strchr(string, '/') == NULL ?
-					    0 : FNM_NOMATCH;
-				else
-					return 0;
-			} else if (c == '/' && flags & FNM_PATHNAME) {
-				if ((string = strchr(string, '/')) == NULL)
-					return FNM_NOMATCH;
-				break;
-			}
-
-			/* General case, use recursion. */
-			while ((test = FOLDCASE(*string, flags)) != EOS) {
-				int e;
-				switch ((e = fnmatchx(pattern, string,
-				    flags & ~FNM_PERIOD, recursion))) {
-				case FNM_NOMATCH:
-					break;
-				default:
-					return e;
-				}
-				if (test == '/' && flags & FNM_PATHNAME)
-					break;
-				++string;
-			}
-			return FNM_NOMATCH;
-		case '[':
-			if (*string == EOS)
-				return FNM_NOMATCH;
-			if (*string == '/' && flags & FNM_PATHNAME)
-				return FNM_NOMATCH;
-			if ((pattern = rangematch(pattern,
-			    FOLDCASE(*string, flags), flags)) == NULL)
-				return FNM_NOMATCH;
-			++string;
-			break;
-		case '\\':
-			if (!(flags & FNM_NOESCAPE)) {
-				if ((c = FOLDCASE(*pattern++, flags)) == EOS) {
-					c = '\\';
-					--pattern;
-				}
-			}
-			/* FALLTHROUGH */
-		default:
-			if (c != FOLDCASE(*string++, flags))
-				return FNM_NOMATCH;
-			break;
-		}
-	}
-	/* NOTREACHED */
-}
-
-int
-fnmatch(const char *pattern, const char *string, int flags)
-{
-	return fnmatchx(pattern, string, flags, 64);
-}
-
-/* isaacs */
-#ifdef __cplusplus
-}
-#endif
diff --git a/deps/fnmatch/fnmatch.h b/deps/fnmatch/fnmatch.h
deleted file mode 100644
index d4c3129..0000000
--- a/deps/fnmatch/fnmatch.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*	$NetBSD: fnmatch.h,v 1.13 2011/01/31 04:49:46 christos Exp $	*/
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  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.
- * 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.
- *
- *	@(#)fnmatch.h	8.1 (Berkeley) 6/2/93
- */
-
-#ifndef	_FNMATCH_H_
-#define	_FNMATCH_H_
-
-#define	FNM_NOMATCH	1	/* Match failed. */
-#define	FNM_NOSYS	2	/* Function not implemented. */
-#define	FNM_NORES	3	/* Out of resources */
-
-#define	FNM_NOESCAPE	0x01	/* Disable backslash escaping. */
-#define	FNM_PATHNAME	0x02	/* Slash must be matched by slash. */
-#define	FNM_PERIOD	0x04	/* Period must be matched by period. */
-#define	FNM_CASEFOLD	0x08	/* Pattern is matched case-insensitive */
-#define	FNM_LEADING_DIR	0x10	/* Ignore /<tail> after Imatch. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int	 fnmatch(const char *, const char *, int);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_FNMATCH_H_ */
diff --git a/deps/glob/LICENSE b/deps/glob/LICENSE
deleted file mode 100644
index bf33ae5..0000000
--- a/deps/glob/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2008 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation.
-
-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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
diff --git a/deps/glob/glob.c b/deps/glob/glob.c
deleted file mode 100644
index b5feb1a..0000000
--- a/deps/glob/glob.c
+++ /dev/null
@@ -1,1256 +0,0 @@
-/*  $NetBSD: glob.c,v 1.27 2010/09/06 14:40:25 christos Exp $  */
-
-/*
- * 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.
- */
-
-/* isaacs */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)glob.c  8.3 (Berkeley) 10/13/93";
-#else
-__RCSID("$NetBSD: glob.c,v 1.27 2010/09/06 14:40:25 christos Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-/* isaacs */
-#ifndef __UNCONST
-# define __UNCONST(a)    ((void *)(unsigned long)(const void *)(a))
-#endif
-
-/*
- * 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_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 
- * GLOB_PERIOD:
- *  allow metacharacters to match leading dots in filenames.
- * GLOB_NO_DOTDIRS:
- *  . and .. are hidden from wildcards, even if GLOB_PERIOD is set.
- * gl_matchc:
- *  Number of matches in the current invocation of glob.
- */
-
-/* isaacs #include "namespace.h" */
-#include <assert.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <glob.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#ifndef __P
-# if __STDC__ || defined(__cplusplus)
-#  define __P(protos) protos    /* full-blown ANSI C */
-# else
-#  define __P(protos) ()
-# endif
-#endif
-
-#ifdef HAVE_NBTOOL_CONFIG_H
-#define NO_GETPW_R
-#endif
-
-
-/* isaacs - added strlcpy implementation for systems that lack it. */
-#ifndef strlcpy
-/*  $NetBSD: strlcpy.c,v 1.1 2010/12/05 03:15:43 christos Exp $  */
-/*  from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp   */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
- * 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.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``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.
- */
-
-/*
- * Copy src to string dst of size siz.  At most siz-1 characters
- * will be copied.  Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
-  register char *d = dst;
-  register const char *s = src;
-  register size_t n = siz;
-
-  /* Copy as many bytes as will fit */
-  if (n != 0 && --n != 0) {
-    do {
-      if ((*d++ = *s++) == 0)
-        break;
-    } while (--n != 0);
-  }
-
-  /* Not enough room in dst, add NUL and traverse rest of src */
-  if (n == 0) {
-    if (siz != 0)
-      *d = '\0';    /* NUL-terminate dst */
-    while (*s++)
-      ;
-  }
-
-  return(s - src - 1);  /* count does not include NUL */
-}
-#endif
-
-#define  GLOB_LIMIT_MALLOC  65536
-#define  GLOB_LIMIT_STAT    128
-#define  GLOB_LIMIT_READDIR  16384
-
-#define  GLOB_INDEX_MALLOC  0
-#define  GLOB_INDEX_STAT    1
-#define  GLOB_INDEX_READDIR  2
-
-#ifndef _DIAGASSERT
-# ifdef DEBUG
-#  define _DIAGASSERT(a) assert(a)
-# else
-#  define _DIAGASSERT(a)
-# endif
-#endif
-
-#define  DOLLAR    '$'
-#define  DOT    '.'
-#define  EOS    '\0'
-#define  LBRACKET  '['
-#define  NOT    '!'
-#define  QUESTION  '?'
-#define  QUOTE    '\\'
-#define  RANGE    '-'
-#define  RBRACKET  ']'
-#define  SEP    '/'
-#define  STAR    '*'
-#define  TILDE    '~'
-#define  UNDERSCORE  '_'
-#define  LBRACE    '{'
-#define  RBRACE    '}'
-#define  SLASH    '/'
-#define  COMMA    ','
-
-#ifndef USE_8BIT_CHARS
-
-#define  M_QUOTE    0x8000
-#define  M_PROTECT  0x4000
-#define  M_MASK    0xffff
-#define  M_ASCII    0x00ff
-
-typedef u_short Char;
-
-#else
-
-#define  M_QUOTE    (Char)0x80
-#define  M_PROTECT  (Char)0x40
-#define  M_MASK    (Char)0xff
-#define  M_ASCII    (Char)0x7f
-
-typedef char Char;
-
-#endif
-
-
-#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   g_Ctoc(const Char *, char *, size_t);
-static int   g_lstat(Char *, __gl_stat_t  *, glob_t *);
-static DIR  *g_opendir(Char *, glob_t *);
-static Char  *g_strchr(const Char *, int);
-static int   g_stat(Char *, __gl_stat_t *, glob_t *);
-static int   glob0(const Char *, glob_t *, size_t *);
-static int   glob1(Char *, glob_t *, size_t *);
-static int   glob2(Char *, Char *, Char *, const Char *, glob_t *,
-    size_t *);
-static int   glob3(Char *, Char *, Char *, const Char *, const Char *,
-    const 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 *, size_t *);
-static int   globexp2(const Char *, const Char *, glob_t *, int *,
-    size_t *);
-static int   match(const Char *, const Char *, const Char *);
-#ifdef DEBUG
-static void   qprintf(const char *, Char *);
-#else
-#define qprintf(a,b)
-#endif
-
-int
-myglob(const char *pattern, int flags, int (*errfunc)(const char *, int),
-    glob_t *pglob)
-{
-  const u_char *patnext;
-  int c;
-  Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
-  /* 0 = malloc(), 1 = stat(), 2 = readdir() */
-  size_t limit[] = { 0, 0, 0 };
-
-  _DIAGASSERT(pattern != NULL);
-
-  patnext = (const u_char *) pattern;
-  if (!(flags & GLOB_APPEND)) {
-    pglob->gl_pathc = 0;
-    pglob->gl_pathv = NULL;
-    if (!(flags & GLOB_DOOFFS))
-      pglob->gl_offs = 0;
-  }
-  pglob->gl_flags = flags & ~GLOB_MAGCHAR;
-  pglob->gl_errfunc = errfunc;
-  pglob->gl_matchc = 0;
-
-  bufnext = patbuf;
-  bufend = bufnext + MAXPATHLEN;
-  if (flags & GLOB_NOESCAPE) {
-    while (bufnext < bufend && (c = *patnext++) != EOS) 
-      *bufnext++ = c;
-  } else {
-    /* Protect the quoted characters. */
-    while (bufnext < bufend && (c = *patnext++) != EOS) 
-      if (c == QUOTE) {
-        if ((c = *patnext++) == EOS) {
-          c = QUOTE;
-          --patnext;
-        }
-        *bufnext++ = c | M_PROTECT;
-      }
-      else
-        *bufnext++ = c;
-  }
-  *bufnext = EOS;
-
-  if (flags & GLOB_BRACE)
-      return globexp1(patbuf, pglob, limit);
-  else
-      return glob0(patbuf, pglob, limit);
-}
-
-/*
- * 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 int
-globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
-{
-  const Char* ptr = pattern;
-  int rv;
-
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  /* Protect a single {}, for find(1), like csh */
-  if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
-    return glob0(pattern, pglob, limit);
-
-  while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
-    if (!globexp2(ptr, pattern, pglob, &rv, limit))
-      return rv;
-
-  return glob0(pattern, pglob, limit);
-}
-
-
-/*
- * 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 int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
-    size_t *limit)
-{
-  int     i;
-  Char   *lm, *ls;
-  const Char *pe, *pm, *pl;
-  Char    patbuf[MAXPATHLEN + 1];
-
-  _DIAGASSERT(ptr != NULL);
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(pglob != NULL);
-  _DIAGASSERT(rv != NULL);
-
-  /* copy part up to the brace */
-  for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
-    continue;
-  ls = lm;
-
-  /* Find the balanced brace */
-  for (i = 0, pe = ++ptr; *pe; pe++)
-    if (*pe == LBRACKET) {
-      /* Ignore everything between [] */
-      for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
-        continue;
-      if (*pe == EOS) {
-        /* 
-         * We could not find a matching RBRACKET.
-         * Ignore and just look for RBRACE
-         */
-        pe = pm;
-      }
-    }
-    else if (*pe == LBRACE)
-      i++;
-    else if (*pe == RBRACE) {
-      if (i == 0)
-        break;
-      i--;
-    }
-
-  /* Non matching braces; just glob the pattern */
-  if (i != 0 || *pe == EOS) {
-    /*
-     * we use `pattern', not `patbuf' here so that that
-     * unbalanced braces are passed to the match
-     */
-    *rv = glob0(pattern, pglob, limit);
-    return 0;
-  }
-
-  for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
-    switch (*pm) {
-    case LBRACKET:
-      /* Ignore everything between [] */
-      for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
-        continue;
-      if (*pm == EOS) {
-        /* 
-         * We could not find a matching RBRACKET.
-         * Ignore and just look for RBRACE
-         */
-        pm = pl;
-      }
-      break;
-
-    case LBRACE:
-      i++;
-      break;
-
-    case RBRACE:
-      if (i) {
-        i--;
-        break;
-      }
-      /* FALLTHROUGH */
-    case COMMA:
-      if (i && *pm == COMMA)
-        break;
-      else {
-        /* Append the current string */
-        for (lm = ls; (pl < pm); *lm++ = *pl++)
-          continue;
-        /* 
-         * Append the rest of the pattern after the
-         * closing brace
-         */
-        for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
-          continue;
-
-        /* Expand the current pattern */
-        qprintf("globexp2", patbuf);
-        *rv = globexp1(patbuf, pglob, limit);
-
-        /* move after the comma, to the next string */
-        pl = pm + 1;
-      }
-      break;
-
-    default:
-      break;
-    }
-  }
-  *rv = 0;
-  return 0;
-}
-
-
-
-/*
- * expand tilde from the passwd file.
- */
-static const Char *
-globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
-{
-  struct passwd *pwd;
-  const char *h;
-  const Char *p;
-  Char *b;
-  char *d;
-  Char *pend = &patbuf[patsize / sizeof(Char)];
-#ifndef NO_GETPW_R
-  struct passwd pwres;
-  char pwbuf[1024];
-#endif
-
-  pend--;
-
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(patbuf != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
-    return pattern;
-
-  /* Copy up to the end of the string or / */
-  for (p = pattern + 1, d = (char *)(void *)patbuf; 
-       d < (char *)(void *)pend && *p && *p != SLASH; 
-       *d++ = *p++)
-    continue;
-
-  if (d == (char *)(void *)pend)
-    return NULL;
-
-  *d = EOS;
-  d = (char *)(void *)patbuf;
-
-  if (*d == EOS) {
-    /* 
-     * handle a plain ~ or ~/ by expanding $HOME 
-     * first and then trying the password file
-     */
-    if ((h = getenv("HOME")) == NULL) {
-#ifdef NO_GETPW_R
-      if ((pwd = getpwuid(getuid())) == NULL)
-#else
-      if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
-          &pwd) != 0 || pwd == NULL)
-#endif
-        return pattern;
-      else
-        h = pwd->pw_dir;
-    }
-  }
-  else {
-    /*
-     * Expand a ~user
-     */
-#ifdef NO_GETPW_R
-    if ((pwd = getpwnam(d)) == NULL)
-#else
-    if (getpwnam_r(d, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
-        pwd == NULL)
-#endif
-      return pattern;
-    else
-      h = pwd->pw_dir;
-  }
-
-  /* Copy the home directory */
-  for (b = patbuf; b < pend && *h; *b++ = *h++)
-    continue;
-
-  if (b == pend)
-    return NULL;
-  
-  /* Append the rest of the pattern */
-  while (b < pend && (*b++ = *p++) != EOS)
-    continue;
-
-  if (b == pend)
-    return NULL;
-
-  return patbuf;
-}
-  
-
-/*
- * The main glob() routine: compiles the pattern (optionally processing
- * quotes), calls glob1() to do the real pattern matching, and finally
- * sorts the list (unless unsorted operation is requested).  Returns 0
- * if things went well, nonzero if errors occurred.  It is not an error
- * to find no matches.
- */
-static int
-glob0(const Char *pattern, glob_t *pglob, size_t *limit)
-{
-  const Char *qpatnext;
-  int c, error;
-  __gl_size_t oldpathc;
-  Char *bufnext, patbuf[MAXPATHLEN+1];
-
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf),
-      pglob)) == NULL)
-    return GLOB_ABEND;
-  oldpathc = pglob->gl_pathc;
-  bufnext = patbuf;
-
-  /* We don't need to check for buffer overflow any more. */
-  while ((c = *qpatnext++) != EOS) {
-    switch (c) {
-    case LBRACKET:
-      c = *qpatnext;
-      if (c == NOT)
-        ++qpatnext;
-      if (*qpatnext == EOS ||
-          g_strchr(qpatnext+1, RBRACKET) == NULL) {
-        *bufnext++ = LBRACKET;
-        if (c == NOT)
-          --qpatnext;
-        break;
-      }
-      *bufnext++ = M_SET;
-      if (c == NOT)
-        *bufnext++ = M_NOT;
-      c = *qpatnext++;
-      do {
-        *bufnext++ = CHAR(c);
-        if (*qpatnext == RANGE &&
-            (c = qpatnext[1]) != RBRACKET) {
-          *bufnext++ = M_RNG;
-          *bufnext++ = CHAR(c);
-          qpatnext += 2;
-        }
-      } while ((c = *qpatnext++) != RBRACKET);
-      pglob->gl_flags |= GLOB_MAGCHAR;
-      *bufnext++ = M_END;
-      break;
-    case QUESTION:
-      pglob->gl_flags |= GLOB_MAGCHAR;
-      *bufnext++ = M_ONE;
-      break;
-    case STAR:
-      pglob->gl_flags |= GLOB_MAGCHAR;
-      /* collapse adjacent stars to one [or three if globstar]
-       * to avoid exponential behavior
-       */
-      if (bufnext == patbuf || bufnext[-1] != M_ALL ||
-          ((pglob->gl_flags & GLOB_STAR) != 0 && 
-          (bufnext - 1 == patbuf || bufnext[-2] != M_ALL ||
-          bufnext - 2 == patbuf || bufnext[-3] != M_ALL)))
-        *bufnext++ = M_ALL;
-      break;
-    default:
-      *bufnext++ = CHAR(c);
-      break;
-    }
-  }
-  *bufnext = EOS;
-  qprintf("glob0", patbuf);
-
-  if ((error = glob1(patbuf, pglob, limit)) != 0)
-    return error;
-
-  if (pglob->gl_pathc == oldpathc) {  
-    /*
-     * If there was no match we are going to append the pattern 
-     * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was
-     * specified and the pattern did not contain any magic
-     * characters GLOB_NOMAGIC is there just for compatibility
-     * with csh.
-     */
-    if ((pglob->gl_flags & GLOB_NOCHECK) ||
-        ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
-         == GLOB_NOMAGIC)) {
-      return globextend(pattern, pglob, limit);
-    } else {
-      return GLOB_NOMATCH;
-    }
-  } else if (!(pglob->gl_flags & GLOB_NOSORT)) {
-    qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
-        (size_t)pglob->gl_pathc - oldpathc, sizeof(char *),
-        compare);
-  }
-
-  return 0;
-}
-
-static int
-compare(const void *p, const void *q)
-{
-
-  _DIAGASSERT(p != NULL);
-  _DIAGASSERT(q != NULL);
-
-  return strcoll(*(const char * const *)p, *(const char * const *)q);
-}
-
-static int
-glob1(Char *pattern, glob_t *pglob, size_t *limit)
-{
-  Char pathbuf[MAXPATHLEN+1];
-
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
-  if (*pattern == EOS)
-    return 0;
-  /*
-   * we save one character so that we can use ptr >= limit,
-   * in the general case when we are appending non nul chars only.
-   */
-  return glob2(pathbuf, pathbuf,
-      pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern,
-      pglob, limit);
-}
-
-/*
- * The functions glob2 and glob3 are mutually recursive; there is one level
- * of recursion for each segment in the pattern that contains one or more
- * meta characters.
- */
-static int
-glob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
-    glob_t *pglob, size_t *limit)
-{
-  __gl_stat_t sb;
-  const Char *p;
-  Char *q;
-  int anymeta;
-  Char *pend;
-  ptrdiff_t diff;
-
-  _DIAGASSERT(pathbuf != NULL);
-  _DIAGASSERT(pathend != NULL);
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  qprintf("glob2", pathbuf);
-  /*
-   * Loop over pattern segments until end of pattern or until
-   * segment with meta character found.
-   */
-  for (anymeta = 0;;) {
-    if (*pattern == EOS) {    /* End of pattern? */
-      *pathend = EOS;
-      if (g_lstat(pathbuf, &sb, pglob))
-        return 0;
-    
-      if ((pglob->gl_flags & GLOB_LIMIT) &&
-          limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) {
-        errno = 0;
-        *pathend++ = SEP;
-        *pathend = EOS;
-        return GLOB_NOSPACE;
-      }
-      if (((pglob->gl_flags & GLOB_MARK) &&
-          pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
-          (S_ISLNK(sb.st_mode) &&
-          (g_stat(pathbuf, &sb, pglob) == 0) &&
-          S_ISDIR(sb.st_mode)))) {
-        if (pathend >= pathlim)
-          return GLOB_ABORTED;
-        *pathend++ = SEP;
-        *pathend = EOS;
-      }
-      ++pglob->gl_matchc;
-      return globextend(pathbuf, pglob, limit);
-    }
-
-    /* Find end of next segment, copy tentatively to pathend. */
-    q = pathend;
-    p = pattern;
-    while (*p != EOS && *p != SEP) {
-      if (ismeta(*p))
-        anymeta = 1;
-      if (q >= pathlim)
-        return GLOB_ABORTED;
-      *q++ = *p++;
-    }
-
-    /*
-     * No expansion, or path ends in slash-dot shash-dot-dot,
-     * do next segment.
-     */
-    if (pglob->gl_flags & GLOB_PERIOD) {
-      for (pend = pathend; pend > pathbuf && pend[-1] == '/';
-          pend--)
-        continue;
-      diff = pend - pathbuf;
-    } else {
-      /* XXX: GCC */
-      diff = 0;
-      pend = pathend;
-    }
-      
-    if ((!anymeta) ||
-        ((pglob->gl_flags & GLOB_PERIOD) &&
-         (diff >= 1 && pend[-1] == DOT) &&
-         (diff >= 2 && (pend[-2] == SLASH || pend[-2] == DOT)) &&
-         (diff < 3 || pend[-3] == SLASH))) {
-      pathend = q;
-      pattern = p;
-      while (*pattern == SEP) {
-        if (pathend >= pathlim)
-          return GLOB_ABORTED;
-        *pathend++ = *pattern++;
-      }
-    } else      /* Need expansion, recurse. */
-      return glob3(pathbuf, pathend, pathlim, pattern, p,
-          pattern, pglob, limit);
-  }
-  /* NOTREACHED */
-}
-
-static int
-glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
-    const Char *restpattern, const Char *pglobstar, glob_t *pglob,
-    size_t *limit)
-{
-  struct dirent *dp;
-  DIR *dirp;
-  __gl_stat_t sbuf;
-  int error;
-  char buf[MAXPATHLEN];
-  int globstar = 0;
-  int chase_symlinks = 0;
-  const Char *termstar = NULL;
-
-  /*
-   * The readdirfunc declaration can't be prototyped, because it is
-   * assigned, below, to two functions which are prototyped in glob.h
-   * and dirent.h as taking pointers to differently typed opaque
-   * structures.
-   */
-  struct dirent *(*readdirfunc)(void *);
-
-  _DIAGASSERT(pathbuf != NULL);
-  _DIAGASSERT(pathend != NULL);
-  _DIAGASSERT(pattern != NULL);
-  _DIAGASSERT(restpattern != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  *pathend = EOS;
-  errno = 0;
-      
-  while (pglobstar < restpattern) {
-    if ((pglobstar[0] & M_MASK) == M_ALL &&
-        (pglobstar[1] & M_MASK) == M_ALL) {
-      globstar = 1;
-      chase_symlinks = (pglobstar[2] & M_MASK) == M_ALL;
-      termstar = pglobstar + (2 + chase_symlinks);
-      break;
-    }
-    pglobstar++;
-  } 
-
-  if (globstar) {
-    error = pglobstar == pattern && termstar == restpattern ?
-        *restpattern == EOS ?
-        glob2(pathbuf, pathend, pathlim, restpattern - 1, pglob,
-        limit) :
-        glob2(pathbuf, pathend, pathlim, restpattern + 1, pglob,
-        limit) :
-        glob3(pathbuf, pathend, pathlim, pattern, restpattern,
-        termstar, pglob, limit);
-    if (error)
-      return error;
-    *pathend = EOS;
-  }
-
-  if (*pathbuf && (g_lstat(pathbuf, &sbuf, pglob) ||
-      !S_ISDIR(sbuf.st_mode)
-#ifdef S_IFLINK
-       && ((globstar && !chase_symlinks) || !S_ISLNK(sbuf.st_mode))
-#endif
-      ))
-    return 0;
-
-  if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
-    if (pglob->gl_errfunc) {
-      if (g_Ctoc(pathbuf, buf, sizeof(buf)))
-        return GLOB_ABORTED;
-      if (pglob->gl_errfunc(buf, errno) ||
-          pglob->gl_flags & GLOB_ERR)
-        return GLOB_ABORTED;
-    }
-    /*
-     * Posix/XOpen: glob should return when it encounters a
-     * directory that it cannot open or read
-     * XXX: Should we ignore ENOTDIR and ENOENT though?
-     * I think that Posix had in mind EPERM...
-     */
-    if (pglob->gl_flags & GLOB_ERR)
-      return GLOB_ABORTED;
-
-    return 0;
-  }
-
-  error = 0;
-
-  /* Search directory for matching names. */
-  if (pglob->gl_flags & GLOB_ALTDIRFUNC)
-    readdirfunc = pglob->gl_readdir;
-  else
-    readdirfunc = (struct dirent *(*)__P((void *))) readdir;
-  while ((dp = (*readdirfunc)(dirp)) != NULL) {
-    u_char *sc;
-    Char *dc;
-
-    if ((pglob->gl_flags & GLOB_LIMIT) &&
-        limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) {
-      errno = 0;
-      *pathend++ = SEP;
-      *pathend = EOS;
-      return GLOB_NOSPACE;
-    }
-
-    /*
-     * Initial DOT must be matched literally, unless we have
-     * GLOB_PERIOD set.
-     */
-    if ((pglob->gl_flags & GLOB_PERIOD) == 0)
-      if (dp->d_name[0] == DOT && *pattern != DOT)
-        continue;
-    /*
-     * If GLOB_NO_DOTDIRS is set, . and .. vanish.
-     */
-    if ((pglob->gl_flags & GLOB_NO_DOTDIRS) &&
-        (dp->d_name[0] == DOT) &&
-        ((dp->d_name[1] == EOS) ||
-         ((dp->d_name[1] == DOT) && (dp->d_name[2] == EOS))))
-      continue;
-    /*
-     * The resulting string contains EOS, so we can
-     * use the pathlim character, if it is the nul
-     */
-    for (sc = (u_char *) dp->d_name, dc = pathend; 
-         dc <= pathlim && (*dc++ = *sc++) != EOS;)
-      continue;
-
-    /*
-     * Have we filled the buffer without seeing EOS?
-     */
-    if (dc > pathlim && *pathlim != EOS) {
-      /*
-       * Abort when requested by caller, otherwise
-       * reset pathend back to last SEP and continue
-       * with next dir entry.
-       */
-      if (pglob->gl_flags & GLOB_ERR) {
-        error = GLOB_ABORTED;
-        break;
-      }
-      else {
-        *pathend = EOS;
-        continue;
-      }
-    }
-
-    if (globstar) {
-#ifdef S_IFLNK
-      if (!chase_symlinks &&
-          (g_lstat(pathbuf, &sbuf, pglob) ||
-          S_ISLNK(sbuf.st_mode)))
-        continue;
-#endif
-
-      if (!match(pathend, pattern, termstar))
-        continue;
-      
-      if (--dc < pathlim - 2)
-        *dc++ = SEP;
-      *dc = EOS;
-      error = glob2(pathbuf, dc, pathlim, pglobstar,
-          pglob, limit);
-      if (error)
-        break;
-      *pathend = EOS;
-    } else {
-      if (!match(pathend, pattern, restpattern)) {
-        *pathend = EOS;
-        continue;
-      }
-      error = glob2(pathbuf, --dc, pathlim, restpattern,
-          pglob, limit);
-      if (error)
-        break;
-    }
-  }
-  if (pglob->gl_flags & GLOB_ALTDIRFUNC)
-    (*pglob->gl_closedir)(dirp);
-  else
-    closedir(dirp);
-
-  /*
-   * Again Posix X/Open issue with regards to error handling.
-   */
-  if ((error || errno) && (pglob->gl_flags & GLOB_ERR))
-    return GLOB_ABORTED;
-
-  return error;
-}
-
-
-/*
- * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
- * add the new item, and update gl_pathc.
- *
- * This assumes the BSD realloc, which only copies the block when its size
- * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
- * behavior.
- *
- * Return 0 if new item added, error code if memory couldn't be allocated.
- *
- * Invariant of the glob_t structure:
- *  Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
- *  gl_pathv points to (gl_offs + gl_pathc + 1) items.
- */
-static int
-globextend(const Char *path, glob_t *pglob, size_t *limit)
-{
-  char **pathv;
-  size_t i, newsize, len;
-  char *copy;
-  const Char *p;
-
-  _DIAGASSERT(path != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
-  /* isaacs - added explicit cast */
-  pathv = (char**) (pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) :
-      malloc(newsize));
-  if (pathv == NULL)
-    return GLOB_NOSPACE;
-
-  if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
-    /* first time around -- clear initial gl_offs items */
-    pathv += pglob->gl_offs;
-    for (i = pglob->gl_offs + 1; --i > 0; )
-      *--pathv = NULL;
-  }
-  pglob->gl_pathv = pathv;
-
-  for (p = path; *p++;)
-    continue;
-  len = (size_t)(p - path);
-  limit[GLOB_INDEX_MALLOC] += len;
-  /* isaacs - added explicit cast */
-  if ((copy = (char*)malloc(len)) != NULL) {
-    if (g_Ctoc(path, copy, len)) {
-      free(copy);
-      return GLOB_ABORTED;
-    }
-    pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
-  }
-  pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
-  if ((pglob->gl_flags & GLOB_LIMIT) &&
-      (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) {
-    errno = 0;
-    return GLOB_NOSPACE;
-  }
-
-  return copy == NULL ? GLOB_NOSPACE : 0;
-}
-
-
-/*
- * pattern matching function for filenames.  Each occurrence of the *
- * pattern causes a recursion level.
- */
-static int
-match(const Char *name, const Char *pat, const Char *patend)
-{
-  int ok, negate_range;
-  Char c, k;
-
-  _DIAGASSERT(name != NULL);
-  _DIAGASSERT(pat != NULL);
-  _DIAGASSERT(patend != NULL);
-
-  while (pat < patend) {
-    c = *pat++;
-    switch (c & M_MASK) {
-    case M_ALL:
-      while (pat < patend && (*pat & M_MASK) == M_ALL)
-        pat++;  /* eat consecutive '*' */
-      if (pat == patend)
-        return 1;
-      for (; !match(name, pat, patend); name++)
-        if (*name == EOS)
-          return 0;
-      return 1;
-    case M_ONE:
-      if (*name++ == EOS)
-        return 0;
-      break;
-    case M_SET:
-      ok = 0;
-      if ((k = *name++) == EOS)
-        return 0;
-      if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
-        ++pat;
-      while (((c = *pat++) & M_MASK) != M_END)
-        if ((*pat & M_MASK) == M_RNG) {
-          if (c <= k && k <= pat[1])
-            ok = 1;
-          pat += 2;
-        } else if (c == k)
-          ok = 1;
-      if (ok == negate_range)
-        return 0;
-      break;
-    default:
-      if (*name++ != c)
-        return 0;
-      break;
-    }
-  }
-  return *name == EOS;
-}
-
-/* Free allocated data belonging to a glob_t structure. */
-void
-myglobfree(glob_t *pglob)
-{
-  size_t i;
-  char **pp;
-
-  _DIAGASSERT(pglob != NULL);
-
-  if (pglob->gl_pathv != NULL) {
-    pp = pglob->gl_pathv + pglob->gl_offs;
-    for (i = pglob->gl_pathc; i--; ++pp)
-      if (*pp)
-        free(*pp);
-    free(pglob->gl_pathv);
-    pglob->gl_pathv = NULL;
-    pglob->gl_pathc = 0;
-  }
-}
-
-int
-myglob_pattern_p(const char *pattern, int quote)
-{
-  int range = 0;
-
-  for (; *pattern; pattern++)
-    switch (*pattern) {
-    case QUESTION:
-    case STAR:
-      return 1;
-
-    case QUOTE:
-      if (quote && pattern[1] != EOS)
-            ++pattern;
-      break;
-
-    case LBRACKET:
-      range = 1;
-      break;
-
-    case RBRACKET:
-      if (range)
-            return 1;
-      break;
-    default:
-      break;
-    }
-
-    return 0;
-}
-
-static DIR *
-g_opendir(Char *str, glob_t *pglob)
-{
-  char buf[MAXPATHLEN];
-
-  _DIAGASSERT(str != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  if (!*str)
-    (void)strlcpy(buf, ".", sizeof(buf));
-  else {
-    if (g_Ctoc(str, buf, sizeof(buf)))
-      return NULL;
-  }
-
-  /* isaacs - added explicit cast */
-  if (pglob->gl_flags & GLOB_ALTDIRFUNC)
-    return (DIR *)(*pglob->gl_opendir)(buf);
-
-  /* isaacs - added explicit cast */
-  return (DIR *)opendir(buf);
-}
-
-static int
-g_lstat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
-{
-  char buf[MAXPATHLEN];
-
-  _DIAGASSERT(fn != NULL);
-  _DIAGASSERT(sb != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  if (g_Ctoc(fn, buf, sizeof(buf)))
-    return -1;
-  if (pglob->gl_flags & GLOB_ALTDIRFUNC)
-    return (*pglob->gl_lstat)(buf, sb);
-  return lstat(buf, sb);
-}
-
-static int
-g_stat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
-{
-  char buf[MAXPATHLEN];
-
-  _DIAGASSERT(fn != NULL);
-  _DIAGASSERT(sb != NULL);
-  _DIAGASSERT(pglob != NULL);
-
-  if (g_Ctoc(fn, buf, sizeof(buf)))
-    return -1;
-  if (pglob->gl_flags & GLOB_ALTDIRFUNC)
-    return (*pglob->gl_stat)(buf, sb);
-  return stat(buf, sb);
-}
-
-static Char *
-g_strchr(const Char *str, int ch)
-{
-
-  _DIAGASSERT(str != NULL);
-
-  do {
-    if (*str == ch)
-      /* isaacs - added explicit cast */
-      return (Char *)__UNCONST(str);
-  } while (*str++);
-  return NULL;
-}
-
-static int
-g_Ctoc(const Char *str, char *buf, size_t len)
-{
-  char *dc;
-
-  _DIAGASSERT(str != NULL);
-  _DIAGASSERT(buf != NULL);
-
-  if (len == 0)
-    return 1;
-
-  for (dc = buf; len && (*dc++ = *str++) != EOS; len--)
-    continue;
-
-  return len == 0;
-}
-
-#ifdef DEBUG
-static void 
-qprintf(const char *str, Char *s)
-{
-  Char *p;
-
-  _DIAGASSERT(str != NULL);
-  _DIAGASSERT(s != NULL);
-
-  (void)printf("%s:\n", str);
-  for (p = s; *p; p++)
-    (void)printf("%c", CHAR(*p));
-  (void)printf("\n");
-  for (p = s; *p; p++)
-    (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
-  (void)printf("\n");
-  for (p = s; *p; p++)
-    (void)printf("%c", ismeta(*p) ? '_' : ' ');
-  (void)printf("\n");
-}
-#endif
-
-#ifdef GLOB_STANDALONE
-int main (int argc, char **argv) {
-  glob_t g;
-  int i;
-
-  g.gl_offs = 2;
-  myglob("**", GLOB_DOOFFS|GLOB_STAR, NULL, &g);
-
-  for (i = 0; i < g.gl_pathc; i ++) {
-    fprintf(stderr, "glob found:%s\n", g.gl_pathv[i]);
-  }
-}
-#endif
-
-/* isaacs */
-#ifdef __cplusplus
-}
-#endif
diff --git a/deps/glob/glob.h b/deps/glob/glob.h
deleted file mode 100644
index bf7ac19..0000000
--- a/deps/glob/glob.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*	$NetBSD: glob.h,v 1.25.2.1 2010/10/22 07:11:52 uebayasi Exp $	*/
-
-/*
- * 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.
- *
- *	@(#)glob.h	8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _GLOB_H_
-#define	_GLOB_H_
-
-/*
-#include <sys/cdefs.h>
-//#include <sys/featuretest.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-*/
-#include <stdlib.h>
-#include <stddef.h>
-
-#ifndef __gl_size_t
-#define __gl_size_t	size_t
-#endif
-#ifndef __gl_stat_t
-#define __gl_stat_t	struct stat
-#endif
-
-typedef struct {
-	__gl_size_t gl_pathc;	/* Count of total paths so far. */
-	__gl_size_t gl_matchc;	/* Count of paths matching pattern. */
-	__gl_size_t gl_offs;	/* Reserved at beginning of gl_pathv. */
-	int gl_flags;		/* Copy of flags parameter to glob. */
-	char **gl_pathv;	/* List of paths matching pattern. */
-				/* Copy of errfunc parameter to glob. */
-	int (*gl_errfunc)(const char *, int);
-
-	/*
-	 * Alternate filesystem access methods for glob; replacement
-	 * versions of closedir(3), readdir(3), opendir(3), stat(2)
-	 * and lstat(2).
-	 */
-	void (*gl_closedir)(void *);
-	struct dirent *(*gl_readdir)(void *);	
-	void *(*gl_opendir)(const char *);
-	int (*gl_lstat)(const char *, __gl_stat_t *);
-	int (*gl_stat)(const char *, __gl_stat_t *);
-} glob_t;
-
-#define	GLOB_APPEND	0x0001	/* Append to output from previous call. */
-#define	GLOB_DOOFFS	0x0002	/* Use gl_offs. */
-#define	GLOB_ERR	0x0004	/* Return on error. */
-#define	GLOB_MARK	0x0008	/* Append / to matching directories. */
-#define	GLOB_NOCHECK	0x0010	/* Return pattern itself if nothing matches. */
-#define	GLOB_NOSORT	0x0020	/* Don't sort. */
-#define	GLOB_NOESCAPE	0x1000	/* Disable backslash escaping. */
-
-#define	GLOB_NOSPACE	(-1)	/* Malloc call failed. */
-#define	GLOB_ABORTED	(-2)	/* Unignored error. */
-#define	GLOB_NOMATCH	(-3)	/* No match, and GLOB_NOCHECK was not set. */
-#define	GLOB_NOSYS	(-4)	/* Implementation does not support function. */
-
-#define	GLOB_ALTDIRFUNC	0x0040	/* Use alternately specified directory funcs. */
-#define	GLOB_BRACE	0x0080	/* Expand braces ala csh. */
-#define	GLOB_MAGCHAR	0x0100	/* Pattern had globbing characters. */
-#define	GLOB_NOMAGIC	0x0200	/* GLOB_NOCHECK without magic chars (csh). */
-#define	GLOB_LIMIT	0x0400	/* Limit memory used by matches to ARG_MAX */
-#define	GLOB_TILDE	0x0800	/* Expand tilde names from the passwd file. */
-/*	GLOB_NOESCAPE	0x1000	above */
-#define	GLOB_PERIOD	0x2000	/* Allow metachars to match leading periods. */
-#define	GLOB_NO_DOTDIRS	0x4000	/* Make . and .. vanish from wildcards. */
-#define	GLOB_STAR	0x8000	/* Use glob ** to recurse directories */
-#define	GLOB_QUOTE	0	/* source compatibility */
-
-#define	GLOB_ABEND	GLOB_ABORTED	/* source compatibility */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int	myglob(const char * __restrict, int,
-    int (*)(const char *, int), glob_t * __restrict);
-void	myglobfree(glob_t *);
-int	myglob_pattern_p(const char *, int);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_GLOB_H_ */
diff --git a/examples/g.js b/examples/g.js
new file mode 100644
index 0000000..be122df
--- /dev/null
+++ b/examples/g.js
@@ -0,0 +1,9 @@
+var Glob = require("../").Glob
+
+var pattern = "test/a/**/[cg]/../[cg]"
+console.log(pattern)
+
+var mg = new Glob(pattern, {mark: true, sync:true}, function (er, matches) {
+  console.log("matches", matches)
+})
+console.log("after")
diff --git a/examples/usr-local.js b/examples/usr-local.js
new file mode 100644
index 0000000..327a425
--- /dev/null
+++ b/examples/usr-local.js
@@ -0,0 +1,9 @@
+var Glob = require("../").Glob
+
+var pattern = "{./*/*,/*,/usr/local/*}"
+console.log(pattern)
+
+var mg = new Glob(pattern, {mark: true}, function (er, matches) {
+  console.log("matches", matches)
+})
+console.log("after")
diff --git a/glob.js b/glob.js
new file mode 100644
index 0000000..48262b5
--- /dev/null
+++ b/glob.js
@@ -0,0 +1,542 @@
+// Approach:
+//
+// 1. Get the minimatch set
+// 2. For each pattern in the set, PROCESS(pattern)
+// 3. Store matches per-set, then uniq them
+//
+// PROCESS(pattern)
+// Get the first [n] items from pattern that are all strings
+// Join these together.  This is PREFIX.
+//   If there is no more remaining, then stat(PREFIX) and
+//   add to matches if it succeeds.  END.
+// readdir(PREFIX) as ENTRIES
+//   If fails, END
+//   If pattern[n] is GLOBSTAR
+//     // handle the case where the globstar match is empty
+//     // by pruning it out, and testing the resulting pattern
+//     PROCESS(pattern[0..n] + pattern[n+1 .. $])
+//     // handle other cases.
+//     for ENTRY in ENTRIES (not dotfiles)
+//       // attach globstar + tail onto the entry
+//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $])
+//
+//   else // not globstar
+//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
+//       Test ENTRY against pattern[n+1]
+//       If fails, continue
+//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
+//
+// Caveat:
+//   Cache all stats and readdirs results to minimize syscall.  Since all
+//   we ever care about is existence and directory-ness, we can just keep
+//   `true` for files, and [children,...] for directories, or `false` for
+//   things that don't exist.
+
+
+
+module.exports = glob
+
+var fs = require("graceful-fs")
+, minimatch = require("minimatch")
+, Minimatch = minimatch.Minimatch
+, inherits = require("inherits")
+, EE = require("events").EventEmitter
+, path = require("path")
+, isDir = {}
+, assert = require("assert").ok
+
+function glob (pattern, options, cb) {
+  if (typeof options === "function") cb = options, options = {}
+  if (!options) options = {}
+
+  if (typeof options === "number") {
+    deprecated()
+    return
+  }
+
+  var g = new Glob(pattern, options, cb)
+  return g.sync ? g.found : g
+}
+
+glob.fnmatch = deprecated
+
+function deprecated () {
+  throw new Error("glob's interface has changed. Please see the docs.")
+}
+
+glob.sync = globSync
+function globSync (pattern, options) {
+  if (typeof options === "number") {
+    deprecated()
+    return
+  }
+
+  options = options || {}
+  options.sync = true
+  return glob(pattern, options)
+}
+
+
+glob.Glob = Glob
+inherits(Glob, EE)
+function Glob (pattern, options, cb) {
+  if (!(this instanceof Glob)) {
+    return new Glob(pattern, options, cb)
+  }
+
+  if (typeof cb === "function") {
+    this.on("error", cb)
+    this.on("end", function (matches) {
+      // console.error("cb with matches", matches)
+      cb(null, matches)
+    })
+  }
+
+  options = options || {}
+
+  this.maxDepth = options.maxDepth || 1000
+  this.maxLength = options.maxLength || Infinity
+  this.statCache = options.statCache || {}
+
+  this.changedCwd = false
+  var cwd = process.cwd()
+  if (!options.hasOwnProperty("cwd")) this.cwd = cwd
+  else {
+    this.cwd = options.cwd
+    this.changedCwd = path.resolve(options.cwd) !== cwd
+  }
+
+  this.root = options.root || path.resolve(this.cwd, "/")
+  this.root = path.resolve(this.root)
+
+  this.nomount = !!options.nomount
+
+  if (!pattern) {
+    throw new Error("must provide pattern")
+  }
+
+  // base-matching: just use globstar for that.
+  if (options.matchBase && -1 === pattern.indexOf("/")) {
+    if (options.noglobstar) {
+      throw new Error("base matching requires globstar")
+    }
+    pattern = "**/" + pattern
+  }
+
+  this.dot = !!options.dot
+  this.mark = !!options.mark
+  this.sync = !!options.sync
+  this.nounique = !!options.nounique
+  this.nonull = !!options.nonull
+  this.nosort = !!options.nosort
+  this.nocase = !!options.nocase
+  this.stat = !!options.stat
+  this.debug = !!options.debug || !!options.globDebug
+  this.silent = !!options.silent
+
+  var mm = this.minimatch = new Minimatch(pattern, options)
+  this.options = mm.options
+  pattern = this.pattern = mm.pattern
+
+  this.error = null
+  this.aborted = false
+
+  EE.call(this)
+
+  // process each pattern in the minimatch set
+  var n = this.minimatch.set.length
+
+  // The matches are stored as {<filename>: true,...} so that
+  // duplicates are automagically pruned.
+  // Later, we do an Object.keys() on these.
+  // Keep them as a list so we can fill in when nonull is set.
+  this.matches = new Array(n)
+
+  this.minimatch.set.forEach(iterator.bind(this))
+  function iterator (pattern, i, set) {
+    this._process(pattern, 0, i, function (er) {
+      if (er) this.emit("error", er)
+      if (-- n <= 0) this._finish()
+    }.bind(this))
+  }
+}
+
+Glob.prototype._finish = function () {
+  assert(this instanceof Glob)
+
+  var nou = this.nounique
+  , all = nou ? [] : {}
+
+  for (var i = 0, l = this.matches.length; i < l; i ++) {
+    var matches = this.matches[i]
+    if (this.debug) console.error("matches[%d] =", i, matches)
+    // do like the shell, and spit out the literal glob
+    if (!matches) {
+      if (this.nonull) {
+        var literal = this.minimatch.globSet[i]
+        if (nou) all.push(literal)
+        else nou[literal] = true
+      }
+    } else {
+      // had matches
+      var m = Object.keys(matches)
+      if (nou) all.push.apply(all, m)
+      else m.forEach(function (m) {
+        all[m] = true
+      })
+    }
+  }
+
+  if (!nou) all = Object.keys(all)
+
+  if (!this.nosort) {
+    all = all.sort(this.nocase ? alphasorti : alphasort)
+  }
+
+  if (this.mark) {
+    // at *some* point we statted all of these
+    all = all.map(function (m) {
+      var sc = this.statCache[m]
+      if (!sc) return m
+      if (m.slice(-1) !== "/" && (Array.isArray(sc) || sc === 2)) {
+        return m + "/"
+      }
+      if (m.slice(-1) === "/") {
+        return m.replace(/\/$/, "")
+      }
+      return m
+    })
+  }
+
+  if (this.debug) console.error("emitting end", all)
+
+  this.found = all
+  this.emit("end", all)
+}
+
+function alphasorti (a, b) {
+  a = a.toLowerCase()
+  b = b.toLowerCase()
+  return alphasort(a, b)
+}
+
+function alphasort (a, b) {
+  return a > b ? 1 : a < b ? -1 : 0
+}
+
+Glob.prototype.abort = function () {
+  this.aborted = true
+  this.emit("abort")
+}
+
+
+Glob.prototype._process = function (pattern, depth, index, cb) {
+  assert(this instanceof Glob)
+  cb = cb.bind(this)
+  if (this.aborted) return cb()
+
+  if (depth > this.maxDepth) return cb()
+
+  // Get the first [n] parts of pattern that are all strings.
+  var n = 0
+  while (typeof pattern[n] === "string") {
+    n ++
+  }
+  // now n is the index of the first one that is *not* a string.
+
+  // see if there's anything else
+  var prefix
+  switch (n) {
+    // if not, then this is rather simple
+    case pattern.length:
+      prefix = pattern.join("/")
+      this._stat(prefix, function (exists, isDir) {
+        // either it's there, or it isn't.
+        // nothing more to do, either way.
+        if (exists) {
+          if (prefix.charAt(0) === "/" && !this.nomount) {
+            prefix = path.join(this.root, prefix)
+          }
+          this.matches[index] = this.matches[index] || {}
+          this.matches[index][prefix] = true
+          this.emit("match", prefix)
+        }
+        return cb()
+      })
+      return
+
+    case 0:
+      // pattern *starts* with some non-trivial item.
+      // going to readdir(cwd), but not include the prefix in matches.
+      prefix = null
+      break
+
+    default:
+      // pattern has some string bits in the front.
+      // whatever it starts with, whether that's "absolute" like /foo/bar,
+      // or "relative" like "../baz"
+      prefix = pattern.slice(0, n)
+      prefix = prefix.join("/")
+      break
+  }
+
+  // get the list of entries.
+  var read
+  if (prefix === null) read = "."
+  else if (isAbsolute(prefix)) {
+    read = prefix = path.join("/", prefix)
+    if (this.debug) console.error('absolute: ', prefix, this.root, pattern)
+  } else read = prefix
+
+  if (this.debug) console.error('readdir(%j)', read, this.cwd, this.root)
+  return this._readdir(read, function (er, entries) {
+    if (er) {
+      // not a directory!
+      // this means that, whatever else comes after this, it can never match
+      return cb()
+    }
+
+    // globstar is special
+    if (pattern[n] === minimatch.GLOBSTAR) {
+      // test without the globstar, and with every child both below
+      // and replacing the globstar.
+      var s = [ pattern.slice(0, n).concat(pattern.slice(n + 1)) ]
+      entries.forEach(function (e) {
+        if (e.charAt(0) === "." && !this.dot) return
+        // instead of the globstar
+        s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1)))
+        // below the globstar
+        s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n)))
+      }, this)
+
+      // now asyncForEach over this
+      var l = s.length
+      , errState = null
+      s.forEach(function (gsPattern) {
+        this._process(gsPattern, depth + 1, index, function (er) {
+          if (errState) return
+          if (er) return cb(errState = er)
+          if (--l <= 0) return cb()
+        })
+      }, this)
+
+      return
+    }
+
+    // not a globstar
+    // It will only match dot entries if it starts with a dot, or if
+    // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
+    var pn = pattern[n]
+    if (typeof pn === "string") {
+      var found = entries.indexOf(pn) !== -1
+      entries = found ? entries[pn] : []
+    } else {
+      var rawGlob = pattern[n]._glob
+      , dotOk = this.dot || rawGlob.charAt(0) === "."
+
+      entries = entries.filter(function (e) {
+        return (e.charAt(0) !== "." || dotOk) &&
+               (typeof pattern[n] === "string" && e === pattern[n] ||
+                e.match(pattern[n]))
+      })
+    }
+
+    // If n === pattern.length - 1, then there's no need for the extra stat
+    // *unless* the user has specified "mark" or "stat" explicitly.
+    // We know that they exist, since the readdir returned them.
+    if (n === pattern.length - 1 &&
+        !this.mark &&
+        !this.stat) {
+      entries.forEach(function (e) {
+        if (prefix) {
+          if (prefix !== "/") e = prefix + "/" + e
+          else e = prefix + e
+        }
+        if (e.charAt(0) === "/" && !this.nomount) {
+          e = path.join(this.root, e)
+        }
+
+        this.matches[index] = this.matches[index] || {}
+        this.matches[index][e] = true
+        this.emit("match", e)
+      }, this)
+      return cb.call(this)
+    }
+
+
+    // now test all the remaining entries as stand-ins for that part
+    // of the pattern.
+    var l = entries.length
+    , errState = null
+    if (l === 0) return cb() // no matches possible
+    entries.forEach(function (e) {
+      var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))
+      this._process(p, depth + 1, index, function (er) {
+        if (errState) return
+        if (er) return cb(errState = er)
+        if (--l === 0) return cb.call(this)
+      }.bind(this))
+    }, this)
+  })
+
+}
+
+Glob.prototype._stat = function (f, cb) {
+  assert(this instanceof Glob)
+  var abs = f
+  if (f.charAt(0) === "/") {
+    abs = path.join(this.root, f)
+  } else if (this.changedCwd) {
+    abs = path.resolve(this.cwd, f)
+  }
+  if (this.debug) console.error('stat', [this.cwd, f, '=', abs])
+  if (f.length > this.maxLength) {
+    var er = new Error("Path name too long")
+    er.code = "ENAMETOOLONG"
+    er.path = f
+    return this._afterStat(f, abs, cb, er)
+  }
+
+  if (this.statCache.hasOwnProperty(f)) {
+    var exists = this.statCache[f]
+    , isDir = exists && (Array.isArray(exists) || exists === 2)
+    if (this.sync) return cb.call(this, !!exists, isDir)
+    return process.nextTick(cb.bind(this, !!exists, isDir))
+  }
+
+  if (this.sync) {
+    var er, stat
+    try {
+      stat = fs.statSync(abs)
+    } catch (e) {
+      er = e
+    }
+    this._afterStat(f, abs, cb, er, stat)
+  } else {
+    fs.stat(abs, this._afterStat.bind(this, f, abs, cb))
+  }
+}
+
+Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
+  assert(this instanceof Glob)
+  if (er || !stat) {
+    exists = false
+  } else {
+    exists = stat.isDirectory() ? 2 : 1
+  }
+  this.statCache[f] = this.statCache[f] || exists
+  cb.call(this, !!exists, exists === 2)
+}
+
+Glob.prototype._readdir = function (f, cb) {
+  assert(this instanceof Glob)
+  var abs = f
+  if (f.charAt(0) === "/") {
+    abs = path.join(this.root, f)
+  } else if (isAbsolute(f)) {
+    abs = f
+  } else if (this.changedCwd) {
+    abs = path.resolve(this.cwd, f)
+  }
+
+  if (this.debug) console.error('readdir', [this.cwd, f, abs])
+  if (f.length > this.maxLength) {
+    var er = new Error("Path name too long")
+    er.code = "ENAMETOOLONG"
+    er.path = f
+    return this._afterReaddir(f, abs, cb, er)
+  }
+
+  if (this.statCache.hasOwnProperty(f)) {
+    var c = this.statCache[f]
+    if (Array.isArray(c)) {
+      if (this.sync) return cb.call(this, null, c)
+      return process.nextTick(cb.bind(this, null, c))
+    }
+
+    if (!c || c === 1) {
+      // either ENOENT or ENOTDIR
+      var code = c ? "ENOTDIR" : "ENOENT"
+      , er = new Error((c ? "Not a directory" : "Not found") + ": " + f)
+      er.path = f
+      er.code = code
+      if (this.debug) console.error(f, er)
+      if (this.sync) return cb.call(this, er)
+      return process.nextTick(cb.bind(this, er))
+    }
+
+    // at this point, c === 2, meaning it's a dir, but we haven't
+    // had to read it yet, or c === true, meaning it's *something*
+    // but we don't have any idea what.  Need to read it, either way.
+  }
+
+  if (this.sync) {
+    var er, entries
+    try {
+      entries = fs.readdirSync(abs)
+    } catch (e) {
+      er = e
+    }
+    return this._afterReaddir(f, abs, cb, er, entries)
+  }
+
+  fs.readdir(abs, this._afterReaddir.bind(this, f, abs, cb))
+}
+
+Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) {
+  assert(this instanceof Glob)
+  if (entries && !er) {
+    this.statCache[f] = entries
+    // if we haven't asked to stat everything for suresies, then just
+    // assume that everything in there exists, so we can avoid
+    // having to stat it a second time.  This also gets us one step
+    // further into ELOOP territory.
+    if (!this.mark && !this.stat) {
+      entries.forEach(function (e) {
+        if (f === "/") e = f + e
+        else e = f + "/" + e
+        this.statCache[e] = true
+      }, this)
+    }
+
+    return cb.call(this, er, entries)
+  }
+
+  // now handle errors, and cache the information
+  if (er) switch (er.code) {
+    case "ENOTDIR": // totally normal. means it *does* exist.
+      this.statCache[f] = 1
+      return cb.call(this, er)
+    case "ENOENT": // not terribly unusual
+    case "ELOOP":
+    case "ENAMETOOLONG":
+    case "UNKNOWN":
+      this.statCache[f] = false
+      return cb.call(this, er)
+    default: // some unusual error.  Treat as failure.
+      this.statCache[f] = false
+      if (this.strict) this.emit("error", er)
+      if (!this.silent) console.error("glob error", er)
+      return cb.call(this, er)
+  }
+}
+
+var isAbsolute = process.platform === "win32" ? absWin : absUnix
+
+function absWin (p) {
+  if (absUnix(p)) return true
+  // pull off the device/UNC bit from a windows path.
+  // from node's lib/path.js
+  var splitDeviceRe =
+        /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
+    , result = splitDeviceRe.exec(p)
+    , device = result[1] || ''
+    , isUnc = device && device.charAt(1) !== ':'
+    , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
+
+  return isAbsolute
+}
+
+function absUnix (p) {
+  return p.charAt(0) === "/" || p === ""
+}
diff --git a/lib/glob.js b/lib/glob.js
deleted file mode 100644
index 07de722..0000000
--- a/lib/glob.js
+++ /dev/null
@@ -1,81 +0,0 @@
-// the nice wrapper around the raw C++ binding.
-
-var binding = require(process.env.GLOB_DEBUG != undefined
-                     ? "../build/default/glob_g"
-                     : "../build/default/glob")
-
-module.exports = glob
-glob.glob = glob
-glob.globSync = glob.sync = globSync
-glob.fnmatch = fnmatch
-
-Object.keys(binding)
-  .filter(function (k) { return k.match(/^GLOB_/) })
-  .forEach(function (k) {
-    glob[k] = globSync[k] = binding[k]
-    globSync[binding[k]] = glob[binding[k]] = k
-  })
-
-Object.keys(binding)
-  .filter(function (k) { return k.match(/^FNM_/) })
-  .forEach(function (k) {
-    fnmatch[k] = glob[k] = binding[k]
-    fnmatch[binding[k]] = k
-  })
-
-// sane defaults.
-glob.FNM_DEFAULT = binding.FNM_PATHNAME | binding.FNM_PERIOD
-fnmatch.FNM_DEFAULT = glob.FNM_DEFAULT
-fnmatch[fnmatch.FNM_DEFAULT] = "FNM_DEFAULT"
-
-glob.GLOB_DEFAULT = binding.GLOB_BRACE
-                  | binding.GLOB_STAR
-                  | binding.GLOB_MARK
-                  | binding.GLOB_TILDE
-globSync.GLOB_DEFAULT = glob.GLOB_DEFAULT
-glob[glob.GLOB_DEFAULT] = globSync[glob.GLOB_DEFAULT] = "GLOB_DEFAULT"
-
-function glob (pattern, flags, cb) {
-  // console.log("glob", pattern, flags, cb)
-  if (typeof cb !== "function") cb = flags, flags = null
-  if (typeof cb !== "function") throw new Error(
-    "usage: glob(pattern, [flags,] cb)")
-
-  if (!flags) flags = glob.GLOB_DEFAULT
-
-  // console.log("glob", pattern, flags, cb)
-  return binding.glob(pattern, flags, function (er, matches) {
-    // console.log("back from binding", er, matches)
-    // swallow this error, since it's really not such a big deal.
-    if (er && er.message === "GLOB_NOMATCH") matches = [], er = null
-    if (er && glob.hasOwnProperty(er.message)) {
-      er.errno = glob[er.message]
-    }
-    cb(er, matches)
-  })
-}
-
-function globSync (pattern, flags) {
-  if (!flags) flags = glob.GLOB_DEFAULT
-  if (typeof pattern !== "string") throw new Error(
-    "usage: globSync(pattern [, flags])")
-  try {
-    return binding.globSync(pattern, flags)
-  } catch (er) {
-    if (er.message === "GLOB_NOMATCH") return []
-    if (glob.hasOwnProperty(er.message)) {
-      er.errno = glob[er.message]
-    }
-    throw er
-  }
-}
-
-function fnmatch (pattern, str, flags) {
-  if (typeof flags !== "number") {
-    flags = glob.FNM_DEFAULT
-  }
-  var res = binding.fnmatch(pattern, str, flags)
-  if (res === 0) return true
-  if (res === binding.FNM_NOMATCH) return false
-  throw new Error("fnmatch error "+res)
-}
diff --git a/package.json b/package.json
index 2f44041..349644d 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,27 @@
-{ "name" : "glob"
-, "description" : "glob/fnmatch binding for node"
-, "author" : "Isaac Z. Schlueter <i at izs.me> (http://blog.izs.me/)"
-, "version" : "2.0.9"
-, "main" : "./lib/glob"
-, "repository" : "git://github.com/isaacs/node-glob.git"
-, "homepage" : "https://github.com/isaacs/node-glob"
-, "keywords" : ["glob", "pattern", "match", "filesystem", "posix", "fnmatch"]
-, "bugs" : { "web" : "https://github.com/isaacs/node-glob/issues" }
-, "engines": { "node": "0.4" }
+{
+  "author": "Isaac Z. Schlueter <i at izs.me> (http://blog.izs.me/)",
+  "name": "glob",
+  "description": "a little globber",
+  "version": "3.1.6",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/node-glob.git"
+  },
+  "main": "glob.js",
+  "engines": {
+    "node": "*"
+  },
+  "dependencies": {
+    "minimatch": "0.2",
+    "graceful-fs": "~1.1.2",
+    "inherits": "1"
+  },
+  "devDependencies": {
+    "tap": "~0.2.3",
+    "mkdirp":"0",
+    "rimraf":"1"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  }
 }
diff --git a/src/glob.cc b/src/glob.cc
deleted file mode 100644
index 17ba568..0000000
--- a/src/glob.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// exposes the glob function to node.
-
-// int
-// myglob(const char *restrict pattern, int flags,
-//     int (*errfunc)(const char *epath, int errno), glob_t *restrict pglob);
-
-#include "glob_constants.h"
-#include <glob.h>
-#include <v8.h>
-#include <node.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-using namespace std;
-using namespace node;
-using namespace v8;
-
-#ifdef DEBUG
-# define debug_p(a,b) ((NULL != (void *)b) ? fprintf(stderr, a, b) : fprintf(stderr, a, ""))
-# define ASSERT(x) assert(x)
-#else
-# define debug_p(a,b)
-# define ASSERT(x)
-#endif
-
-
-static Handle<String>
-GlobError (int er) {
-  switch (er) {
-    case GLOB_ABORTED: return String::New("GLOB_ABORTED"); break;
-    case GLOB_NOMATCH: return String::New("GLOB_NOMATCH"); break;
-    case GLOB_NOSPACE: return String::New("GLOB_NOSPACE"); break;
-  }
-
-  return String::New("undefined glob error");
-}
-
-
-static Handle<Value> Throw (int);
-static Handle<Value> Throw (const char*);
-static Handle<Value> Throw (Handle<String>);
-
-static Handle<Value>
-Throw (int msg) {
-  return Throw(GlobError(msg));
-}
-static Handle<Value>
-Throw (const char* msg) {
-  return Throw(String::New(msg));
-}
-static Handle<Value>
-Throw (Handle<String> msg) {
-  ThrowException(Exception::Error(msg));
-}
-
-
-// binding to fnmatch
-// Not really glob-specific, but useful if you're doing globbing.
-// int fnmatch(const char *pattern, const char *string, int flags);
-static Handle<Value> FNMatch (const Arguments& args) {
-  if (args.Length() != 3) return Throw(
-    "usage: fnmatch(pattern, string, flags)");
-
-  String::Utf8Value pattern(args[0]);
-  String::Utf8Value str(args[1]);
-  int flags = args[2]->Int32Value();
-
-  int res = fnmatch(*pattern, *str, flags);
-
-  return Integer::New(res);
-}
-
-
-// async EIO globbing
-struct glob_request {
-  Persistent<Function> cb;
-  glob_t *g;
-  int retval;
-  int flags;
-  char pattern[1];
-};
-static int EIO_Glob (eio_req *req) {
-  glob_request *gr = (glob_request *)req->data;
-  debug_p("EIO_Glob pattern=%s\n", gr->pattern);
-  gr->retval = myglob(gr->pattern, gr->flags, NULL, gr->g);
-  debug_p("EIO_Glob retval=%i\n", gr->retval);
-  return 0;
-}
-static int EIO_GlobAfter (eio_req *req) {
-  HandleScope scope;
-  ev_unref(EV_DEFAULT_UC);
-  glob_request *gr = (glob_request *)req->data;
-  glob_t *g = gr->g;
-
-  Local<Value> argv[2];
-  debug_p("EIO_GlobAfter pattern=%s\n", gr->pattern);
-  if (gr->retval != 0) {
-    argv[0] = Exception::Error(GlobError(gr->retval));
-    argv[1] = String::New(gr->pattern);
-    debug_p("EIO_GlobAfter error=%i\n", gr->retval);
-  } else {
-    Local<Array> pathv = Array::New(g->gl_pathc);
-    for (int i = 0; i < g->gl_pathc; i ++) {
-      debug_p("EIO_GlobAfter path=%s\n", g->gl_pathv[i]);
-      pathv->Set(Integer::New(i), String::New(g->gl_pathv[i]));
-    }
-    argv[0] = Local<Value>::New(Null());
-    argv[1] = pathv;
-  }
-
-  TryCatch try_catch;
-  debug_p("EIO_GlobAfter calling cb%s\n", "");
-  gr->cb->Call(Context::GetCurrent()->Global(), 2, argv);
-  if (try_catch.HasCaught()) {
-    debug_p("EIO_GlobAfter cb threw%s\n", "");
-    FatalException(try_catch);
-  }
-  gr->cb.Dispose();
-  debug_p("EIO_GlobAfter globfreeing %i\n", g);
-  myglobfree(g);
-  debug_p("EIO_GlobAfter freeing %i\n", gr);
-  free(gr);
-  return 0;
-}
-static Handle<Value> GlobAsync (const Arguments& args) {
-  HandleScope scope;
-  const char *usage = "usage: glob(pattern, flags, cb)";
-
-  if (args.Length() != 3) {
-    Throw(usage);
-  }
-
-  String::Utf8Value pattern(args[0]);
-
-  int flags = args[1]->Int32Value();
-  Local<Function> cb = Local<Function>::Cast(args[2]);
-
-  glob_request *gr = (glob_request *)
-    calloc(1, sizeof(struct glob_request) + pattern.length() + 1);
-
-  debug_p("GlobAsync gr=%i\n", gr);
-
-  ASSERT(gr != NULL);
-
-  gr->cb = Persistent<Function>::New(cb);
-  strncpy(gr->pattern, *pattern, pattern.length() + 1);
-  gr->flags = flags;
-  gr->g = new glob_t;
-  eio_req* eioret = eio_custom(EIO_Glob, EIO_PRI_DEFAULT, EIO_GlobAfter, gr);
-  debug_p("GlobAsync eioret=%i\n", eioret);
-  ev_ref(EV_DEFAULT_UC);
-
-  return Undefined();
-}
-
-// synchronous globbing.
-static Handle<Value> GlobSync (const Arguments& args) {
-  HandleScope scope;
-  const char * usage = "usage: globSync(pattern, flags)";
-  if (args.Length() != 2) {
-    return Throw(usage);
-  }
-
-  String::Utf8Value pattern(args[0]);
-
-  int flags = args[1]->Int32Value();
-
-  debug_p("GlobSync pattern=%s\n", *pattern);
-  debug_p("GlobSync flags=%i\n", flags);
-  glob_t g;
-  int retval = myglob(*pattern, flags, NULL, &g);
-
-  if (retval != 0) {
-    debug_p("GlobSync fail: %i", retval);
-    if (retval != GLOB_NOSPACE) myglobfree(&g);
-    return Throw(retval);
-  }
-
-  // create a JS array
-  // loop through the g.gl_pathv adding JS strings to the JS array.
-  // then return the JS array.
-  Handle<Array> pathv = Array::New(g.gl_pathc);
-  for (int i = 0; i < g.gl_pathc; i ++) {
-    debug_p("GlobSync path=%s\n", g.gl_pathv[i]);
-    pathv->Set(Integer::New(i), String::New(g.gl_pathv[i]));
-  }
-
-  debug_p("GlobSync freeing%s\n", "");
-  myglobfree(&g);
-  return scope.Close(pathv);
-}
-
-
-extern "C" void
-init (Handle<Object> target)
-{
-  HandleScope scope;
-  GlobConstants(target);
-  NODE_SET_METHOD(target, "glob", GlobAsync);
-  NODE_SET_METHOD(target, "globSync", GlobSync);
-  NODE_SET_METHOD(target, "fnmatch", FNMatch);
-}
-
diff --git a/src/glob_constants.h b/src/glob_constants.h
deleted file mode 100644
index 71ef667..0000000
--- a/src/glob_constants.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <glob.h>
-#include <fnmatch.h>
-#include <v8.h>
-#include <node.h>
-
-using namespace node;
-using namespace v8;
-
-void
-GlobConstants (Handle<Object> target) {
-  // flags
-  // These are defined in deps/fnmatch/fnmatch.h and deps/glob/glob.h
-
-// these are actually useless, because the glob_t object isn't exposed
-// to the javascript layer.  Since it's so trivial to concatenate
-// arrays in JS anyway, it's a bit silly to even bother with this.
-// NODE_DEFINE_CONSTANT(target, GLOB_APPEND);
-// NODE_DEFINE_CONSTANT(target, GLOB_DOOFFS);
-
-// this is useless as well, because there is no way to supply the errfunc
-// function to glob().  It's just handled like the rest of node, passing
-// an Error() obj to the cb.
-// NODE_DEFINE_CONSTANT(target, GLOB_ERR);
-
-// Not supported, since the glob_t object isn't exposed directly.
-// NODE_DEFINE_CONSTANT(target, GLOB_ALTDIRFUNC);
-
-NODE_DEFINE_CONSTANT(target, GLOB_MARK);
-NODE_DEFINE_CONSTANT(target, GLOB_NOCHECK);
-NODE_DEFINE_CONSTANT(target, GLOB_NOSORT);
-NODE_DEFINE_CONSTANT(target, GLOB_NOESCAPE);
-
-NODE_DEFINE_CONSTANT(target, GLOB_NOSPACE);
-NODE_DEFINE_CONSTANT(target, GLOB_ABORTED);
-NODE_DEFINE_CONSTANT(target, GLOB_NOMATCH);
-NODE_DEFINE_CONSTANT(target, GLOB_NOSYS);
-
-NODE_DEFINE_CONSTANT(target, GLOB_BRACE);
-NODE_DEFINE_CONSTANT(target, GLOB_MAGCHAR);
-NODE_DEFINE_CONSTANT(target, GLOB_NOMAGIC);
-NODE_DEFINE_CONSTANT(target, GLOB_LIMIT);
-NODE_DEFINE_CONSTANT(target, GLOB_TILDE);
-
-NODE_DEFINE_CONSTANT(target, GLOB_PERIOD);
-NODE_DEFINE_CONSTANT(target, GLOB_NO_DOTDIRS);
-NODE_DEFINE_CONSTANT(target, GLOB_STAR);
-NODE_DEFINE_CONSTANT(target, GLOB_QUOTE);
-NODE_DEFINE_CONSTANT(target, GLOB_ABEND);
-
-// the fnmatch stuff
-NODE_DEFINE_CONSTANT(target, FNM_NOMATCH);
-NODE_DEFINE_CONSTANT(target, FNM_NOSYS);
-NODE_DEFINE_CONSTANT(target, FNM_NORES);
-NODE_DEFINE_CONSTANT(target, FNM_NOESCAPE);
-NODE_DEFINE_CONSTANT(target, FNM_PATHNAME);
-NODE_DEFINE_CONSTANT(target, FNM_PERIOD);
-NODE_DEFINE_CONSTANT(target, FNM_CASEFOLD);
-NODE_DEFINE_CONSTANT(target, FNM_LEADING_DIR);
-
-}
diff --git a/test/00-setup.js b/test/00-setup.js
new file mode 100644
index 0000000..2b60643
--- /dev/null
+++ b/test/00-setup.js
@@ -0,0 +1,61 @@
+// just a little pre-run script to set up the fixtures.
+// zz-finish cleans it up
+
+var mkdirp = require("mkdirp")
+var path = require("path")
+var i = 0
+var tap = require("tap")
+var fs = require("fs")
+var rimraf = require("rimraf")
+
+var files =
+[ "a/.abcdef/x/y/z/a"
+, "a/abcdef/g/h"
+, "a/abcfed/g/h"
+, "a/b/c/d"
+, "a/bc/e/f"
+, "a/c/d/c/b"
+, "a/cb/e/f"
+]
+
+var symlinkTo = path.resolve(__dirname, "a/symlink/a/b/c")
+var symlinkFrom = "../.."
+
+files = files.map(function (f) {
+  return path.resolve(__dirname, f)
+})
+
+tap.test("remove fixtures", function (t) {
+  rimraf(path.resolve(__dirname, "a"), function (er) {
+    t.ifError(er, "remove fixtures")
+    t.end()
+  })
+})
+
+files.forEach(function (f) {
+  tap.test(f, function (t) {
+    var d = path.dirname(f)
+    mkdirp(d, 0755, function (er) {
+      if (er) {
+        t.fail(er)
+        return t.bailout()
+      }
+      fs.writeFile(f, "i like tests", function (er) {
+        t.ifError(er, "make file")
+        t.end()
+      })
+    })
+  })
+})
+
+tap.test("symlinky", function (t) {
+  var d = path.dirname(symlinkTo)
+  console.error("mkdirp", d)
+  mkdirp(d, 0755, function (er) {
+    t.ifError(er)
+    fs.symlink(symlinkFrom, symlinkTo, function (er) {
+      t.ifError(er, "make symlink")
+      t.end()
+    })
+  })
+})
diff --git a/test/bash-comparison.js b/test/bash-comparison.js
new file mode 100644
index 0000000..86a3d8b
--- /dev/null
+++ b/test/bash-comparison.js
@@ -0,0 +1,119 @@
+// basic test
+// show that it does the same thing by default as the shell.
+var tap = require("tap")
+, child_process = require("child_process")
+
+// put more patterns here.
+, globs =
+  [
+  "test/a/*/+(c|g)/./d"
+  ,"test/a/**/[cg]/../[cg]"
+  ,"test/a/{b,c,d,e,f}/**/g"
+  ,"test/a/b/**"
+  ,"test/**/g"
+  ,"test/a/abc{fed,def}/g/h"
+  ,"test/a/abc{fed/g,def}/**/"
+  ,"test/a/abc{fed/g,def}/**///**/"
+  ,"test/**/a/**/"
+  ,"test/+(a|b|c)/a{/,bc*}/**"
+  ,"test/*/*/*/f"
+  ,"test/**/f"
+  ,"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**"
+  ,"{./*/*,/usr/local/*}"
+  ,"{/*,*}" // evil owl face!  how you taunt me!
+  ]
+, glob = require("../")
+, path = require("path")
+
+// run from the root of the project
+// this is usually where you're at anyway, but be sure.
+process.chdir(path.resolve(__dirname, ".."))
+
+function alphasort (a, b) {
+  a = a.toLowerCase()
+  b = b.toLowerCase()
+  return a > b ? 1 : a < b ? -1 : 0
+}
+
+globs.forEach(function (pattern) {
+  var echoOutput
+  tap.test(pattern, function (t) {
+    var bashPattern = pattern //.replace(/(\(|\||\))/g, "\\$1")
+    , cmd = "shopt -s globstar && " +
+            "shopt -s extglob && " +
+            "shopt -s nullglob && " +
+            // "shopt >&2; " +
+            "eval \'for i in " + bashPattern + "; do echo $i; done\'"
+    , cp = child_process.spawn("bash", ["-c",cmd])
+    , out = []
+    , globResult
+    cp.stdout.on("data", function (c) {
+      out.push(c)
+    })
+    cp.stderr.on("data", function (c) {
+      process.stderr.write(c)
+    })
+    cp.on("exit", function () {
+      echoOutput = flatten(out)
+      if (!echoOutput) echoOutput = []
+      else {
+        echoOutput = echoOutput.split(/\r*\n/).map(function (m) {
+          // Bash is a oddly inconsistent with slashes in the
+          // the results.  This implementation is a bit more
+          // normalized.  Account for this in the test results.
+          return m.replace(/\/+/g, "/").replace(/\/$/, "")
+        }).sort(alphasort).reduce(function (set, f) {
+          if (f !== set[set.length - 1]) set.push(f)
+          return set
+        }, []).sort(alphasort)
+      }
+      next()
+    })
+
+    glob(pattern, function (er, matches) {
+      // sort and unpark, just to match the shell results
+      matches = matches.map(function (m) {
+        return m.replace(/\/+/g, "/").replace(/\/$/, "")
+      }).sort(alphasort).reduce(function (set, f) {
+        if (f !== set[set.length - 1]) set.push(f)
+        return set
+      }, []).sort(alphasort)
+
+      t.ifError(er, pattern + " should not error")
+      globResult = matches
+      next()
+    })
+
+    function next () {
+      if (!echoOutput || !globResult) return
+
+      t.deepEqual(globResult, echoOutput, "should match shell")
+      t.end()
+    }
+  })
+
+  tap.test(pattern + " sync", function (t) {
+    var matches = glob.sync(pattern).map(function (m) {
+        return m.replace(/\/+/g, "/").replace(/\/$/, "")
+      }).sort(alphasort).reduce(function (set, f) {
+        if (f !== set[set.length - 1]) set.push(f)
+        return set
+      }, []).sort(alphasort)
+
+    t.deepEqual(matches, echoOutput, "should match shell")
+    t.end()
+  })
+})
+
+function flatten (chunks) {
+  var s = 0
+  chunks.forEach(function (c) { s += c.length })
+  var out = new Buffer(s)
+  s = 0
+  chunks.forEach(function (c) {
+    c.copy(out, s)
+    s += c.length
+  })
+
+  return out.toString().trim()
+}
diff --git a/test/cwd-test.js b/test/cwd-test.js
new file mode 100644
index 0000000..352c27e
--- /dev/null
+++ b/test/cwd-test.js
@@ -0,0 +1,55 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing cwd and searching for **/d", function (t) {
+  var glob = require('../')
+  var path = require('path')
+  t.test('.', function (t) {
+    glob('**/d', function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('a', function (t) {
+    glob('**/d', {cwd:path.resolve('a')}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'b/c/d', 'c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('a/b', function (t) {
+    glob('**/d', {cwd:path.resolve('a/b')}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('a/b/', function (t) {
+    glob('**/d', {cwd:path.resolve('a/b/')}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('.', function (t) {
+    glob('**/d', {cwd: process.cwd()}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('cd -', function (t) {
+    process.chdir(origCwd)
+    t.end()
+  })
+
+  t.end()
+})
diff --git a/test/foo/bar b/test/foo/bar
deleted file mode 100644
index e69de29..0000000
diff --git a/test/foo/baz/bar b/test/foo/baz/bar
deleted file mode 100644
index e69de29..0000000
diff --git a/test/foo/baz/quux/bar b/test/foo/baz/quux/bar
deleted file mode 100644
index e69de29..0000000
diff --git a/test/root-nomount.js b/test/root-nomount.js
new file mode 100644
index 0000000..3ac5979
--- /dev/null
+++ b/test/root-nomount.js
@@ -0,0 +1,39 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing root and searching for /b*/**", function (t) {
+  var glob = require('../')
+  var path = require('path')
+  t.test('.', function (t) {
+    glob('/b*/**', { globDebug: true, root: '.', nomount: true }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [])
+      t.end()
+    })
+  })
+
+  t.test('a', function (t) {
+    glob('/b*/**', { globDebug: true, root: path.resolve('a'), nomount: true }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
+      t.end()
+    })
+  })
+
+  t.test('root=a, cwd=a/b', function (t) {
+    glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b'), nomount: true }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
+      t.end()
+    })
+  })
+
+  t.test('cd -', function (t) {
+    process.chdir(origCwd)
+    t.end()
+  })
+
+  t.end()
+})
diff --git a/test/root.js b/test/root.js
new file mode 100644
index 0000000..5ccdd0e
--- /dev/null
+++ b/test/root.js
@@ -0,0 +1,43 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing root and searching for /b*/**", function (t) {
+  var glob = require('../')
+  var path = require('path')
+  t.test('.', function (t) {
+    glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [])
+      t.end()
+    })
+  })
+
+  t.test('a', function (t) {
+    glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
+        return path.join(path.resolve('a'), m)
+      }))
+      t.end()
+    })
+  })
+
+  t.test('root=a, cwd=a/b', function (t) {
+    glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
+        return path.join(path.resolve('a'), m)
+      }))
+      t.end()
+    })
+  })
+
+  t.test('cd -', function (t) {
+    process.chdir(origCwd)
+    t.end()
+  })
+
+  t.end()
+})
diff --git a/test/test.js b/test/test.js
deleted file mode 100644
index a39470b..0000000
--- a/test/test.js
+++ /dev/null
@@ -1,83 +0,0 @@
-var g = require("../lib/glob")
-
-process.chdir(__dirname)
-
-var failures = 0
-
-function testSync(pattern, flags) {
-  console.error("testing: %j %j", pattern, flags)
-  console.error(g.globSync(pattern, flags))
-}
-try {
-  testSync("*", 0)
-  testSync("*/*.js", 0)
-  testSync("lib/*", 0)
-  testSync("~/*", g.GLOB_TILDE)
-  testSync("foo/**/bar")
-} catch (ex) {
-  console.error(ex.stack)
-  failures ++
-}
-
-function testAsync (pattern, flags, cb) {
-  if (!cb) cb = flags, flags = undefined
-  console.error("testing async: %j %j", pattern, flags)
-  g.glob(pattern, flags, function (er, m) {
-    if (er) {
-      console.error(" FAIL: "+(er.stack||er.message))
-      failures ++
-    } else console.error("  %j", m)
-    cb()
-  })
-}
-
-function testAsyncList (list, cb) {
-  next()
-  function next (er, m) {
-    var test = list.shift()
-    if (!test) return cb()
-    test.push(cb)
-    testAsync.apply(null, test)
-  }
-}
-
-testAsyncList
-  ([["*", 0]
-   ,["../*/*.js", 0]
-   ,["../lib/*", 0]
-   ,["~/*", g.GLOB_DEFAULT | g.GLOB_TILDE]
-   ,["foo/**/bar"]
-   ]
-  ,testFnmatch)
-
-function f (pattern, str, flags, expect) {
-  if (arguments.length === 3) expect = flags, flags = undefined
-  var actual = g.fnmatch(pattern, str, flags)
-  if (actual !== expect) {
-    console.error("Fail: "+JSON.stringify([pattern,str,flags]) + " expected "+expect + " actual "+actual)
-    failures ++
-  }
-  console.error("%s, %s, %s => %j", pattern, str, flags, expect)
-}
-
-function testFnmatch () {
-  f("*", "foo", true)
-  f(".*", "foo", false)
-  f("*", ".foo", false)
-  f("*", "foo/bar", false)
-  f("*/*", "foo/bar", true)
-  f("*", ".foo", g.FNM_DEFAULT & ~g.FNM_PERIOD, true)
-  f("*/*", "foo/bar", g.FNM_DEFAULT & ~g.FNM_PATHNAME, true)
-  f("**/bar", "foo/bar", true)
-  f("**/bar", "foo/baz/bar", true)
-  f("foo/**/bar", "foo/bar/baz/quux/bar", true)
-  done()
-}
-
-function done () {
-  if (failures === 0) console.log("ok")
-  else {
-    console.error("Failures: %j", failures)
-    process.exit(failures)
-  }
-}
diff --git a/test/zz-cleanup.js b/test/zz-cleanup.js
new file mode 100644
index 0000000..e085f0f
--- /dev/null
+++ b/test/zz-cleanup.js
@@ -0,0 +1,11 @@
+// remove the fixtures
+var tap = require("tap")
+, rimraf = require("rimraf")
+, path = require("path")
+
+tap.test("cleanup fixtures", function (t) {
+  rimraf(path.resolve(__dirname, "a"), function (er) {
+    t.ifError(er, "removed")
+    t.end()
+  })
+})
diff --git a/wscript b/wscript
deleted file mode 100644
index 0d46a3a..0000000
--- a/wscript
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-srcdir = "."
-blddir = "build"
-VERSION = "0.0.1"
-
-def set_options(opt):
-  opt.tool_options("compiler_cxx")
-
-def configure(conf):
-  conf.check_tool("compiler_cxx")
-  conf.check_tool("node_addon")
-
-def build(bld):
-  ### bsd_glob
-  bsd_glob = bld.new_task_gen("cxx")
-  bsd_glob.source = "deps/glob/glob.c"
-  bsd_glob.includes = "deps/glob/"
-  bsd_glob.name = "bsd_glob"
-  bsd_glob.target = "bsd_glob"
-  bsd_glob.install_path = None
-  bsd_glob.cxxflags = ["-fPIC"]
-
-  ### bsd_fnmatch
-  bsd_fnmatch = bld.new_task_gen("cxx")
-  bsd_fnmatch.source = "deps/fnmatch/fnmatch.c"
-  bsd_fnmatch.includes = "deps/fnmatch/"
-  bsd_fnmatch.name = "bsd_fnmatch"
-  bsd_fnmatch.target = "bsd_fnmatch"
-  bsd_fnmatch.install_path = None
-  bsd_fnmatch.cxxflags = ["-fPIC"]
-
-  obj = bld.new_task_gen("cxx", "shlib", "node_addon")
-  obj.add_objects = "bsd_glob bsd_fnmatch"
-  obj.includes = """
-    src/
-    deps/glob/
-    deps/fnmatch/
-  """
-  obj.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"]
-  obj.target = "glob"
-  obj.source = "src/glob.cc"
-
-  ### debug versions
-  bsd_glob_debug = bld.new_task_gen("cxx")
-  bsd_glob_debug.source = bsd_glob.source
-  bsd_glob_debug.includes = bsd_glob.includes
-  bsd_glob_debug.name = "bsd_glob_debug"
-  bsd_glob_debug.target = "bsd_glob_debug"
-  bsd_glob_debug.install_path = None
-  bsd_glob_debug.cxxflags = ["-fPIC", "-DDEBUG"]
-
-  bsd_fnmatch_debug = bld.new_task_gen("cxx")
-  bsd_fnmatch_debug.source = bsd_fnmatch.source
-  bsd_fnmatch_debug.includes = bsd_fnmatch.includes
-  bsd_fnmatch_debug.name = "bsd_fnmatch_debug"
-  bsd_fnmatch_debug.target = "bsd_fnmatch_debug"
-  bsd_fnmatch_debug.install_path = None
-  bsd_fnmatch_debug.cxxflags = ["-fPIC", "-DDEBUG"]
-
-  obj_debug = bld.new_task_gen("cxx", "shlib", "node_addon")
-  obj_debug.add_objects = "bsd_glob_debug bsd_fnmatch_debug"
-  obj_debug.includes = obj.includes
-  obj_debug.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-DDEBUG"]
-  obj_debug.target = "glob_g"
-  obj_debug.source = obj.source

-- 
glob/fnmatch binding for NodeJS



More information about the Pkg-javascript-commits mailing list