Browse Source

New misc tree that actually has misc stuff in it.

Eric Andersen 23 years ago
parent
commit
1eb3e9989a

+ 46 - 0
libc/misc/Makefile

@@ -0,0 +1,46 @@
+# Makefile for uCLibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+
+DIRS = assert crypt ctype fnmatch glob lsearch
+
+all: libc.a
+
+libc.a: subdirs
+
+tags:
+	ctags -R
+	
+clean: subdirs_clean
+	rm -f libc.a
+
+subdirs: $(patsubst %, _dir_%, $(DIRS))
+subdirs_clean: $(patsubst %, _dirclean_%, $(DIRS))
+
+$(patsubst %, _dir_%, $(DIRS)) : dummy
+	$(MAKE) -C $(patsubst _dir_%, %, $@)
+
+$(patsubst %, _dirclean_%, $(DIRS)) : dummy
+	$(MAKE) -C $(patsubst _dirclean_%, %, $@) clean
+
+.PHONY: dummy
+

+ 33 - 0
libc/misc/assert/.indent.pro

@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space

+ 41 - 0
libc/misc/assert/Makefile

@@ -0,0 +1,41 @@
+# Makefile for uCLibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.make
+LIBC=$(TOPDIR)libc.a
+
+CSRC=__assert.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+OBJS=$(COBJS)
+
+all: $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(OBJS): Makefile
+
+clean:
+	rm -f *.[oa] *~ core

+ 31 - 0
libc/misc/assert/__assert.c

@@ -0,0 +1,31 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern char *itoa(int);
+
+static void errput(str)
+const char *str;
+{
+	write(2, str, strlen(str));
+}
+
+void __assert(assertion, filename, linenumber)
+const char *assertion;
+const char *filename;
+int linenumber;
+{
+	errput("Failed assertion '");
+	errput(assertion);
+	errput("' in file ");
+	errput(filename);
+	errput(" at line ");
+	errput(itoa(linenumber));
+	errput(".\n");
+	abort();
+}

+ 33 - 0
libc/misc/ctype/.indent.pro

@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space

+ 42 - 0
libc/misc/ctype/Makefile

@@ -0,0 +1,42 @@
+# Makefile for uCLibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.make
+LIBC=$(TOPDIR)libc.a
+
+CSRC=ctype.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+OBJS=$(COBJS)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(OBJS): Makefile
+
+clean:
+	rm -f *.[oa] *~ core
+

+ 67 - 0
libc/misc/ctype/ctype.c

@@ -0,0 +1,67 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/*
+ *  CTYPE.C	Character classification and conversion
+ */
+
+#include <ctype.h>
+
+#undef	toupper
+#undef	tolower
+
+unsigned char __ctype[128] = {
+	__CT_c, __CT_c, __CT_c, __CT_c,	/* 0x00..0x03 */
+	__CT_c, __CT_c, __CT_c, __CT_c,	/* 0x04..0x07 */
+	__CT_c, __CT_c | __CT_s, __CT_c | __CT_s, __CT_c | __CT_s,	/* 0x08..0x0B */
+	__CT_c | __CT_s, __CT_c | __CT_s, __CT_c, __CT_c,	/* 0x0C..0x0F */
+
+	__CT_c, __CT_c, __CT_c, __CT_c,	/* 0x10..0x13 */
+	__CT_c, __CT_c, __CT_c, __CT_c,	/* 0x14..0x17 */
+	__CT_c, __CT_c, __CT_c, __CT_c,	/* 0x18..0x1B */
+	__CT_c, __CT_c, __CT_c, __CT_c,	/* 0x1C..0x1F */
+
+	__CT_s, __CT_p, __CT_p, __CT_p,	/* 0x20..0x23 */
+	__CT_p, __CT_p, __CT_p, __CT_p,	/* 0x24..0x27 */
+	__CT_p, __CT_p, __CT_p, __CT_p,	/* 0x28..0x2B */
+	__CT_p, __CT_p, __CT_p, __CT_p,	/* 0x2C..0x2F */
+
+	__CT_d | __CT_x, __CT_d | __CT_x, __CT_d | __CT_x, __CT_d | __CT_x,	/* 0x30..0x33 */
+	__CT_d | __CT_x, __CT_d | __CT_x, __CT_d | __CT_x, __CT_d | __CT_x,	/* 0x34..0x37 */
+	__CT_d | __CT_x, __CT_d | __CT_x, __CT_p, __CT_p,	/* 0x38..0x3B */
+	__CT_p, __CT_p, __CT_p, __CT_p,	/* 0x3C..0x3F */
+
+	__CT_p, __CT_u | __CT_x, __CT_u | __CT_x, __CT_u | __CT_x,	/* 0x40..0x43 */
+	__CT_u | __CT_x, __CT_u | __CT_x, __CT_u | __CT_x, __CT_u,	/* 0x44..0x47 */
+	__CT_u, __CT_u, __CT_u, __CT_u,	/* 0x48..0x4B */
+	__CT_u, __CT_u, __CT_u, __CT_u,	/* 0x4C..0x4F */
+
+	__CT_u, __CT_u, __CT_u, __CT_u,	/* 0x50..0x53 */
+	__CT_u, __CT_u, __CT_u, __CT_u,	/* 0x54..0x57 */
+	__CT_u, __CT_u, __CT_u, __CT_p,	/* 0x58..0x5B */
+	__CT_p, __CT_p, __CT_p, __CT_p,	/* 0x5C..0x5F */
+
+	__CT_p, __CT_l | __CT_x, __CT_l | __CT_x, __CT_l | __CT_x,	/* 0x60..0x63 */
+	__CT_l | __CT_x, __CT_l | __CT_x, __CT_l | __CT_x, __CT_l,	/* 0x64..0x67 */
+	__CT_l, __CT_l, __CT_l, __CT_l,	/* 0x68..0x6B */
+	__CT_l, __CT_l, __CT_l, __CT_l,	/* 0x6C..0x6F */
+
+	__CT_l, __CT_l, __CT_l, __CT_l,	/* 0x70..0x73 */
+	__CT_l, __CT_l, __CT_l, __CT_l,	/* 0x74..0x77 */
+	__CT_l, __CT_l, __CT_l, __CT_p,	/* 0x78..0x7B */
+	__CT_p, __CT_p, __CT_p, __CT_c	/* 0x7C..0x7F */
+};
+
+int toupper(c)
+int c;
+{
+	return (islower(c) ? (c ^ 0x20) : (c));
+}
+
+int tolower(c)
+int c;
+{
+	return (isupper(c) ? (c ^ 0x20) : (c));
+}

+ 33 - 0
libc/misc/fnmatch/.indent.pro

@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space

+ 42 - 0
libc/misc/fnmatch/Makefile

@@ -0,0 +1,42 @@
+# Makefile for uCLibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.make
+LIBC=$(TOPDIR)libc.a
+
+CSRC=fnmatch.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+OBJS=$(COBJS)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(OBJS): Makefile
+
+clean:
+	rm -f *.[oa] *~ core
+

+ 232 - 0
libc/misc/fnmatch/fnmatch.c

@@ -0,0 +1,232 @@
+/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+# if defined (STDC_HEADERS) || !defined (isascii)
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+
+
+# ifndef errno
+extern int errno;
+# endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+int fnmatch(pattern, string, flags)
+const char *pattern;
+const char *string;
+int flags;
+{
+	register const char *p = pattern, *n = string;
+	register char c;
+
+/* Note that this evaluates C many times.  */
+# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+
+	while ((c = *p++) != '\0') {
+		c = FOLD(c);
+
+		switch (c) {
+		case '?':
+			if (*n == '\0')
+				return FNM_NOMATCH;
+			else if ((flags & FNM_FILE_NAME) && *n == '/')
+				return FNM_NOMATCH;
+			else if ((flags & FNM_PERIOD) && *n == '.' &&
+					 (n == string
+					  || ((flags & FNM_FILE_NAME)
+						  && n[-1] == '/'))) return FNM_NOMATCH;
+			break;
+
+		case '\\':
+			if (!(flags & FNM_NOESCAPE)) {
+				c = *p++;
+				if (c == '\0')
+					/* Trailing \ loses.  */
+					return FNM_NOMATCH;
+				c = FOLD(c);
+			}
+			if (FOLD(*n) != c)
+				return FNM_NOMATCH;
+			break;
+
+		case '*':
+			if ((flags & FNM_PERIOD) && *n == '.' &&
+				(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+				return FNM_NOMATCH;
+
+			for (c = *p++; c == '?' || c == '*'; c = *p++) {
+				if ((flags & FNM_FILE_NAME) && *n == '/')
+					/* A slash does not match a wildcard under FNM_FILE_NAME.  */
+					return FNM_NOMATCH;
+				else if (c == '?') {
+					/* A ? needs to match one character.  */
+					if (*n == '\0')
+						/* There isn't another character; no match.  */
+						return FNM_NOMATCH;
+					else
+						/* One character of the string is consumed in matching
+						   this ? wildcard, so *??? won't match if there are
+						   less than three characters.  */
+						++n;
+				}
+			}
+
+			if (c == '\0')
+				return 0;
+
+			{
+				char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+
+				c1 = FOLD(c1);
+				for (--p; *n != '\0'; ++n)
+					if ((c == '[' || FOLD(*n) == c1) &&
+						fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
+						return 0;
+				return FNM_NOMATCH;
+			}
+
+		case '[':
+		{
+			/* Nonzero if the sense of the character class is inverted.  */
+			register int not;
+
+			if (*n == '\0')
+				return FNM_NOMATCH;
+
+			if ((flags & FNM_PERIOD) && *n == '.' &&
+				(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+				return FNM_NOMATCH;
+
+			not = (*p == '!' || *p == '^');
+			if (not)
+				++p;
+
+			c = *p++;
+			for (;;) {
+				register char cstart = c, cend = c;
+
+				if (!(flags & FNM_NOESCAPE) && c == '\\') {
+					if (*p == '\0')
+						return FNM_NOMATCH;
+					cstart = cend = *p++;
+				}
+
+				cstart = cend = FOLD(cstart);
+
+				if (c == '\0')
+					/* [ (unterminated) loses.  */
+					return FNM_NOMATCH;
+
+				c = *p++;
+				c = FOLD(c);
+
+				if ((flags & FNM_FILE_NAME) && c == '/')
+					/* [/] can never match.  */
+					return FNM_NOMATCH;
+
+				if (c == '-' && *p != ']') {
+					cend = *p++;
+					if (!(flags & FNM_NOESCAPE) && cend == '\\')
+						cend = *p++;
+					if (cend == '\0')
+						return FNM_NOMATCH;
+					cend = FOLD(cend);
+
+					c = *p++;
+				}
+
+				if (FOLD(*n) >= cstart && FOLD(*n) <= cend)
+					goto matched;
+
+				if (c == ']')
+					break;
+			}
+			if (!not)
+				return FNM_NOMATCH;
+			break;
+
+		  matched:;
+			/* Skip the rest of the [...] that already matched.  */
+			while (c != ']') {
+				if (c == '\0')
+					/* [... (unterminated) loses.  */
+					return FNM_NOMATCH;
+
+				c = *p++;
+				if (!(flags & FNM_NOESCAPE) && c == '\\') {
+					if (*p == '\0')
+						return FNM_NOMATCH;
+					/* XXX 1003.2d11 is unclear if this is right.  */
+					++p;
+				}
+			}
+			if (not)
+				return FNM_NOMATCH;
+		}
+			break;
+
+		default:
+			if (c != FOLD(*n))
+				return FNM_NOMATCH;
+		}
+
+		++n;
+	}
+
+	if (*n == '\0')
+		return 0;
+
+	if ((flags & FNM_LEADING_DIR) && *n == '/')
+		/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+		return 0;
+
+	return FNM_NOMATCH;
+
+# undef FOLD
+}
+
+#endif							/* _LIBC or not __GNU_LIBRARY__.  */

+ 33 - 0
libc/misc/glob/.indent.pro

@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space

+ 42 - 0
libc/misc/glob/Makefile

@@ -0,0 +1,42 @@
+# Makefile for uCLibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.make
+LIBC=$(TOPDIR)libc.a
+
+CSRC=glob.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+OBJS=$(COBJS)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(OBJS): Makefile
+
+clean:
+	rm -f *.[oa] *~ core
+

+ 1028 - 0
libc/misc/glob/glob.c

@@ -0,0 +1,1028 @@
+/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* AIX requires this to be the first thing in the file.  */
+#if defined _AIX && !defined __GNUC__
+#pragma alloca
+#endif
+
+#ifdef	HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define HAVE_DIRENT_H
+
+/* Enable GNU extensions in glob.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* Outcomment the following line for production quality code.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+#include <stdio.h>				/* Needed on stupid SunOS for assert.  */
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GLOB_INTERFACE_VERSION 1
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stddef.h>
+#endif
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+# ifndef POSIX
+#  ifdef _POSIX_VERSION
+#   define POSIX
+#  endif
+# endif
+#endif
+
+#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
+# include <pwd.h>
+#endif
+
+#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#ifndef	NULL
+# define NULL	0
+#endif
+
+
+#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+# ifdef HAVE_VMSDIR_H
+#  include "vmsdir.h"
+# endif							/* HAVE_VMSDIR_H */
+#endif
+
+
+/* In GNU systems, <dirent.h> defines this macro for us.  */
+#ifdef _D_NAMLEN
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+   if the `d_type' member for `struct dirent' is available.  */
+#ifdef _DIRENT_HAVE_D_TYPE
+# define HAVE_D_TYPE	1
+#endif
+
+
+#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+# define REAL_DIR_ENTRY(dp) 1
+#else
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif							/* POSIX */
+
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stdlib.h>
+# include <string.h>
+# define	ANSI_STRING
+#else							/* No standard headers.  */
+
+extern char *getenv();
+
+# ifdef HAVE_STRING_H
+#  include <string.h>
+#  define ANSI_STRING
+# else
+#  include <strings.h>
+# endif
+# ifdef	HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+
+extern char *malloc(), *realloc();
+extern void free();
+
+extern void qsort();
+extern void abort(), exit();
+
+#endif							/* Standard headers.  */
+
+#ifndef	ANSI_STRING
+
+# ifndef bzero
+extern void bzero();
+# endif
+# ifndef bcopy
+extern void bcopy();
+# endif
+
+# define memcpy(d, s, n)	bcopy ((s), (d), (n))
+# define strrchr	rindex
+/* memset is only used for zero here, but let's be paranoid.  */
+# define memset(s, better_be_zero, n) \
+  ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
+#endif							/* Not ANSI_STRING.  */
+
+#if !defined HAVE_STRCOLL && !defined _LIBC
+# define strcoll	strcmp
+#endif
+
+#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
+# define HAVE_MEMPCPY	1
+# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
+#endif
+
+
+#ifndef	__GNU_LIBRARY__
+# ifdef	__GNUC__
+__inline
+# endif
+# ifndef __SASC
+#  ifdef WINDOWS32
+static void *
+#  else
+static char *
+# endif
+my_realloc(p, n)
+char *p;
+unsigned int n;
+{
+	/* These casts are the for sake of the broken Ultrix compiler,
+	   which warns of illegal pointer combinations otherwise.  */
+	if (p == NULL)
+		return (char *) malloc(n);
+	return (char *) realloc(p, n);
+}
+
+# define	realloc	my_realloc
+# endif							/* __SASC */
+#endif							/* __GNU_LIBRARY__ */
+
+
+#if !defined __alloca && !defined __GNU_LIBRARY__
+
+# ifdef	__GNUC__
+#  undef alloca
+#  define alloca(n)	__builtin_alloca (n)
+# else							/* Not GCC.  */
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else							/* Not HAVE_ALLOCA_H.  */
+#   ifndef _AIX
+#    ifdef WINDOWS32
+#     include <malloc.h>
+#    else
+extern char *alloca();
+#    endif						/* WINDOWS32 */
+#   endif						/* Not _AIX.  */
+#  endif						/* sparc or HAVE_ALLOCA_H.  */
+# endif							/* GCC.  */
+
+# define __alloca	alloca
+
+#endif
+
+#ifndef __GNU_LIBRARY__
+# define __stat stat
+# ifdef STAT_MACROS_BROKEN
+#  undef S_ISDIR
+# endif
+# ifndef S_ISDIR
+#  define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+# endif
+#endif
+
+#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
+# undef	size_t
+# define size_t	unsigned int
+#endif
+
+/* Some system header files erroneously define these.
+   We want our own definitions from <fnmatch.h> to take precedence.  */
+#undef	FNM_PATHNAME
+#undef	FNM_NOESCAPE
+#undef	FNM_PERIOD
+#include <fnmatch.h>
+
+/* Some system header files erroneously define these.
+   We want our own definitions from <glob.h> to take precedence.  */
+#undef	GLOB_ERR
+#undef	GLOB_MARK
+#undef	GLOB_NOSORT
+#undef	GLOB_DOOFFS
+#undef	GLOB_NOCHECK
+#undef	GLOB_APPEND
+#undef	GLOB_NOESCAPE
+#undef	GLOB_PERIOD
+#include <glob.h>
+
+static
+#if __GNUC__ - 0 >= 2
+/*inline*/
+#endif
+const char *next_brace_sub __P((const char *begin));
+static int glob_in_dir __P((const char *pattern, const char *directory,
+							int flags,
+							int (*errfunc) __P((const char *, int)),
+							glob_t * pglob));
+static int prefix_array __P((const char *prefix, char **array, size_t n));
+static int collated_compare __P((const __ptr_t, const __ptr_t));
+
+
+/* Find the end of the sub-pattern in a brace expression.  We define
+   this as an inline function if the compiler permits.  */
+static
+#if __GNUC__ - 0 >= 2
+/*inline*/
+#endif
+const char *next_brace_sub(begin)
+const char *begin;
+{
+	unsigned int depth = 0;
+	const char *cp = begin;
+
+	while (1) {
+		if (depth == 0) {
+			if (*cp != ',' && *cp != '}' && *cp != '\0') {
+				if (*cp == '{')
+					++depth;
+				++cp;
+				continue;
+			}
+		} else {
+			while (*cp != '\0' && (*cp != '}' || depth > 0)) {
+				if (*cp == '}')
+					--depth;
+				++cp;
+			}
+			if (*cp == '\0')
+				/* An incorrectly terminated brace expression.  */
+				return NULL;
+
+			continue;
+		}
+		break;
+	}
+
+	return cp;
+}
+
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
+int __glob_pattern_p(pattern, quote)
+const char *pattern;
+int quote;
+{
+	register const char *p;
+	int open = 0;
+
+	for (p = pattern; *p != '\0'; ++p)
+		switch (*p) {
+		case '?':
+		case '*':
+			return 1;
+
+		case '\\':
+			if (quote && p[1] != '\0')
+				++p;
+			break;
+
+		case '[':
+			open = 1;
+			break;
+
+		case ']':
+			if (open)
+				return 1;
+			break;
+		}
+
+	return 0;
+}
+
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+   The bits defined above may be set in FLAGS.
+   If a directory cannot be opened or read and ERRFUNC is not nil,
+   it is called with the pathname that caused the error, and the
+   `errno' value from the failing call; if it returns non-zero
+   `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
+   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+   Otherwise, `glob' returns zero.  */
+int glob(pattern, flags, errfunc, pglob)
+const char *pattern;
+int flags;
+int (*errfunc) __P((const char *, int));
+glob_t *pglob;
+{
+	const char *filename;
+	char *dirname;
+	size_t dirlen;
+	int status;
+	int oldcount;
+
+	if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) {
+		__set_errno(EINVAL);
+		return -1;
+	}
+
+	if (flags & GLOB_BRACE) {
+		const char *begin = strchr(pattern, '{');
+
+		if (begin != NULL) {
+			/* Allocate working buffer large enough for our work.  Note that
+			   we have at least an opening and closing brace.  */
+			int firstc;
+			char *alt_start;
+			const char *p;
+			const char *next;
+			const char *rest;
+			size_t rest_len;
+
+#ifdef __GNUC__
+			char onealt[strlen(pattern) - 1];
+#else
+			char *onealt = (char *) malloc(strlen(pattern) - 1);
+
+			if (onealt == NULL) {
+				if (!(flags & GLOB_APPEND))
+					globfree(pglob);
+				return GLOB_NOSPACE;
+			}
+#endif
+
+			/* We know the prefix for all sub-patterns.  */
+#ifdef HAVE_MEMPCPY
+			alt_start = mempcpy(onealt, pattern, begin - pattern);
+#else
+			memcpy(onealt, pattern, begin - pattern);
+			alt_start = &onealt[begin - pattern];
+#endif
+
+			/* Find the first sub-pattern and at the same time find the
+			   rest after the closing brace.  */
+			next = next_brace_sub(begin + 1);
+			if (next == NULL) {
+				/* It is an illegal expression.  */
+#ifndef __GNUC__
+				free(onealt);
+#endif
+				return glob(pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+			}
+
+			/* Now find the end of the whole brace expression.  */
+			rest = next;
+			while (*rest != '}') {
+				rest = next_brace_sub(rest + 1);
+				if (rest == NULL) {
+					/* It is an illegal expression.  */
+#ifndef __GNUC__
+					free(onealt);
+#endif
+					return glob(pattern, flags & ~GLOB_BRACE, errfunc,
+								pglob);
+				}
+			}
+			/* Please note that we now can be sure the brace expression
+			   is well-formed.  */
+			rest_len = strlen(++rest) + 1;
+
+			/* We have a brace expression.  BEGIN points to the opening {,
+			   NEXT points past the terminator of the first element, and END
+			   points past the final }.  We will accumulate result names from
+			   recursive runs for each brace alternative in the buffer using
+			   GLOB_APPEND.  */
+
+			if (!(flags & GLOB_APPEND)) {
+				/* This call is to set a new vector, so clear out the
+				   vector so we can append to it.  */
+				pglob->gl_pathc = 0;
+				pglob->gl_pathv = NULL;
+			}
+			firstc = pglob->gl_pathc;
+
+			p = begin + 1;
+			while (1) {
+				int result;
+
+				/* Construct the new glob expression.  */
+#ifdef HAVE_MEMPCPY
+				mempcpy(mempcpy(alt_start, p, next - p), rest, rest_len);
+#else
+				memcpy(alt_start, p, next - p);
+				memcpy(&alt_start[next - p], rest, rest_len);
+#endif
+
+				result = glob(onealt,
+							  ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+							   | GLOB_APPEND), errfunc, pglob);
+
+				/* If we got an error, return it.  */
+				if (result && result != GLOB_NOMATCH) {
+#ifndef __GNUC__
+					free(onealt);
+#endif
+					if (!(flags & GLOB_APPEND))
+						globfree(pglob);
+					return result;
+				}
+
+				if (*next == '}')
+					/* We saw the last entry.  */
+					break;
+
+				p = next + 1;
+				next = next_brace_sub(p);
+				assert(next != NULL);
+			}
+
+#ifndef __GNUC__
+			free(onealt);
+#endif
+
+			if (pglob->gl_pathc != firstc)
+				/* We found some entries.  */
+				return 0;
+			else if (!(flags & (GLOB_NOCHECK | GLOB_NOMAGIC)))
+				return GLOB_NOMATCH;
+		}
+	}
+
+	/* Find the filename.  */
+	filename = strrchr(pattern, '/');
+	if (filename == NULL) {
+		filename = pattern;
+#ifdef _AMIGA
+		dirname = (char *) "";
+#else
+		dirname = (char *) ".";
+#endif
+		dirlen = 0;
+	} else if (filename == pattern) {
+		/* "/pattern".  */
+		dirname = (char *) "/";
+		dirlen = 1;
+		++filename;
+	} else {
+		dirlen = filename - pattern;
+		dirname = (char *) __alloca(dirlen + 1);
+#ifdef HAVE_MEMPCPY
+		*((char *) mempcpy(dirname, pattern, dirlen)) = '\0';
+#else
+		memcpy(dirname, pattern, dirlen);
+		dirname[dirlen] = '\0';
+#endif
+		++filename;
+	}
+
+	if (filename[0] == '\0' && dirlen > 1)
+		/* "pattern/".  Expand "pattern", appending slashes.  */
+	{
+		int val = glob(dirname, flags | GLOB_MARK, errfunc, pglob);
+
+		if (val == 0)
+			pglob->gl_flags =
+				(pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
+		return val;
+	}
+
+	if (!(flags & GLOB_APPEND)) {
+		pglob->gl_pathc = 0;
+		pglob->gl_pathv = NULL;
+	}
+
+	oldcount = pglob->gl_pathc;
+
+#ifndef VMS
+	if ((flags & GLOB_TILDE) && dirname[0] == '~') {
+		if (dirname[1] == '\0' || dirname[1] == '/') {
+			/* Look up home directory.  */
+			char *home_dir = getenv("HOME");
+
+			if (home_dir == NULL || home_dir[0] == '\0')
+				home_dir = (char *) "~";	/* No luck.  */
+
+			/* Now construct the full directory.  */
+			if (dirname[1] == '\0')
+				dirname = home_dir;
+			else {
+				char *newp;
+				size_t home_len = strlen(home_dir);
+
+				newp = (char *) __alloca(home_len + dirlen);
+# ifdef HAVE_MEMPCPY
+				mempcpy(mempcpy(newp, home_dir, home_len),
+						&dirname[1], dirlen);
+# else
+				memcpy(newp, home_dir, home_len);
+				memcpy(&newp[home_len], &dirname[1], dirlen);
+# endif
+				dirname = newp;
+			}
+		}
+# if !defined _AMIGA && !defined WINDOWS32
+		else {
+			char *end_name = strchr(dirname, '/');
+			char *user_name;
+			char *home_dir;
+
+			if (end_name == NULL)
+				user_name = dirname + 1;
+			else {
+				user_name = (char *) __alloca(end_name - dirname);
+# ifdef HAVE_MEMPCPY
+				*((char *)
+				  mempcpy(user_name, dirname + 1, end_name - dirname)) =
+					'\0';
+# else
+				memcpy(user_name, dirname + 1, end_name - dirname);
+				user_name[end_name - dirname - 1] = '\0';
+# endif
+			}
+
+			/* Look up specific user's home directory.  */
+			{
+//#  if defined HAVE_GETPWNAM_R || defined _LIBC
+#  if 0
+				size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+				char *pwtmpbuf = (char *) __alloca(buflen);
+				struct passwd pwbuf, *p;
+
+				if (__getpwnam_r(user_name, &pwbuf, pwtmpbuf, buflen, &p)
+					>= 0)
+					home_dir = p->pw_dir;
+				else
+					home_dir = NULL;
+#  else
+				struct passwd *p = getpwnam(user_name);
+
+				if (p != NULL)
+					home_dir = p->pw_dir;
+				else
+					home_dir = NULL;
+#  endif
+			}
+			/* If we found a home directory use this.  */
+			if (home_dir != NULL) {
+				char *newp;
+				size_t home_len = strlen(home_dir);
+				size_t rest_len = end_name == NULL ? 0 : strlen(end_name);
+
+				newp = (char *) __alloca(home_len + rest_len + 1);
+#  ifdef HAVE_MEMPCPY
+				*((char *) mempcpy(mempcpy(newp, home_dir, home_len),
+								   end_name, rest_len)) = '\0';
+#  else
+				memcpy(newp, home_dir, home_len);
+				memcpy(&newp[home_len], end_name, rest_len);
+				newp[home_len + rest_len] = '\0';
+#  endif
+				dirname = newp;
+			}
+		}
+# endif							/* Not Amiga && not WINDOWS32.  */
+	}
+#endif							/* Not VMS.  */
+
+	if (__glob_pattern_p(dirname, !(flags & GLOB_NOESCAPE))) {
+		/* The directory name contains metacharacters, so we
+		   have to glob for the directory, and then glob for
+		   the pattern in each directory found.  */
+		glob_t dirs;
+		register int i;
+
+		status = glob(dirname,
+					  ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
+					   | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs);
+		if (status != 0)
+			return status;
+
+		/* We have successfully globbed the preceding directory name.
+		   For each name we found, call glob_in_dir on it and FILENAME,
+		   appending the results to PGLOB.  */
+		for (i = 0; i < dirs.gl_pathc; ++i) {
+			int oldcount;
+
+#ifdef	SHELL
+			{
+				/* Make globbing interruptible in the bash shell. */
+				extern int interrupt_state;
+
+				if (interrupt_state) {
+					globfree(&dirs);
+					globfree(&files);
+					return GLOB_ABORTED;
+				}
+			}
+#endif							/* SHELL.  */
+
+			oldcount = pglob->gl_pathc;
+			status = glob_in_dir(filename, dirs.gl_pathv[i],
+								 ((flags | GLOB_APPEND)
+								  & ~(GLOB_NOCHECK | GLOB_ERR)),
+								 errfunc, pglob);
+			if (status == GLOB_NOMATCH)
+				/* No matches in this directory.  Try the next.  */
+				continue;
+
+			if (status != 0) {
+				globfree(&dirs);
+				globfree(pglob);
+				return status;
+			}
+
+			/* Stick the directory on the front of each name.  */
+			if (prefix_array(dirs.gl_pathv[i],
+							 &pglob->gl_pathv[oldcount],
+							 pglob->gl_pathc - oldcount)) {
+				globfree(&dirs);
+				globfree(pglob);
+				return GLOB_NOSPACE;
+			}
+		}
+
+		flags |= GLOB_MAGCHAR;
+
+		if (pglob->gl_pathc == oldcount) {
+			/* No matches.  */
+			if (flags & GLOB_NOCHECK) {
+				size_t len = strlen(pattern) + 1;
+				char *patcopy = (char *) malloc(len);
+
+				if (patcopy == NULL)
+					return GLOB_NOSPACE;
+				memcpy(patcopy, pattern, len);
+
+				pglob->gl_pathv
+					= (char **) realloc(pglob->gl_pathv,
+										(pglob->gl_pathc +
+										 ((flags & GLOB_DOOFFS) ?
+										  pglob->gl_offs : 0) +
+										 1 + 1) * sizeof(char *));
+
+				if (pglob->gl_pathv == NULL) {
+					free(patcopy);
+					return GLOB_NOSPACE;
+				}
+
+				if (flags & GLOB_DOOFFS)
+					while (pglob->gl_pathc < pglob->gl_offs)
+						pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+				pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
+				pglob->gl_pathv[pglob->gl_pathc] = NULL;
+				pglob->gl_flags = flags;
+			} else
+				return GLOB_NOMATCH;
+		}
+	} else {
+		status = glob_in_dir(filename, dirname, flags, errfunc, pglob);
+		if (status != 0)
+			return status;
+
+		if (dirlen > 0) {
+			/* Stick the directory on the front of each name.  */
+			if (prefix_array(dirname,
+							 &pglob->gl_pathv[oldcount],
+							 pglob->gl_pathc - oldcount)) {
+				globfree(pglob);
+				return GLOB_NOSPACE;
+			}
+		}
+	}
+
+	if (flags & GLOB_MARK) {
+		/* Append slashes to directory names.  */
+		int i;
+		struct stat st;
+
+		for (i = oldcount; i < pglob->gl_pathc; ++i)
+			if (((flags & GLOB_ALTDIRFUNC) ?
+				 (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
+				 __stat(pglob->gl_pathv[i], &st)) == 0 &&
+				S_ISDIR(st.st_mode)) {
+				size_t len = strlen(pglob->gl_pathv[i]) + 2;
+				char *new = realloc(pglob->gl_pathv[i], len);
+
+				if (new == NULL) {
+					globfree(pglob);
+					return GLOB_NOSPACE;
+				}
+				strcpy(&new[len - 2], "/");
+				pglob->gl_pathv[i] = new;
+			}
+	}
+
+	if (!(flags & GLOB_NOSORT))
+		/* Sort the vector.  */
+		qsort((__ptr_t) & pglob->gl_pathv[oldcount],
+			  pglob->gl_pathc - oldcount,
+
+			  sizeof(char *), collated_compare);
+
+	return 0;
+}
+
+
+/* Free storage allocated in PGLOB by a previous `glob' call.  */
+void globfree(pglob)
+register glob_t *pglob;
+{
+	if (pglob->gl_pathv != NULL) {
+		register int i;
+
+		for (i = 0; i < pglob->gl_pathc; ++i)
+			if (pglob->gl_pathv[i] != NULL)
+				free((__ptr_t) pglob->gl_pathv[i]);
+		free((__ptr_t) pglob->gl_pathv);
+	}
+}
+
+
+/* Do a collated comparison of A and B.  */
+static int collated_compare(a, b)
+const __ptr_t a;
+const __ptr_t b;
+{
+	const char *const s1 = *(const char *const *const) a;
+	const char *const s2 = *(const char *const *const) b;
+
+	if (s1 == s2)
+		return 0;
+	if (s1 == NULL)
+		return 1;
+	if (s2 == NULL)
+		return -1;
+	return strcoll(s1, s2);
+}
+
+
+/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
+   elements in place.  Return nonzero if out of memory, zero if successful.
+   A slash is inserted between DIRNAME and each elt of ARRAY,
+   unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
+static int prefix_array(dirname, array, n)
+const char *dirname;
+char **array;
+size_t n;
+{
+	register size_t i;
+	size_t dirlen = strlen(dirname);
+
+	if (dirlen == 1 && dirname[0] == '/')
+		/* DIRNAME is just "/", so normal prepending would get us "//foo".
+		   We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
+		dirlen = 0;
+
+	for (i = 0; i < n; ++i) {
+		size_t eltlen = strlen(array[i]) + 1;
+		char *new = (char *) malloc(dirlen + 1 + eltlen);
+
+		if (new == NULL) {
+			while (i > 0)
+				free((__ptr_t) array[--i]);
+			return 1;
+		}
+#ifdef HAVE_MEMPCPY
+		{
+			char *endp = (char *) mempcpy(new, dirname, dirlen);
+
+			*endp++ = '/';
+			mempcpy(endp, array[i], eltlen);
+		}
+#else
+		memcpy(new, dirname, dirlen);
+		new[dirlen] = '/';
+		memcpy(&new[dirlen + 1], array[i], eltlen);
+#endif
+		free((__ptr_t) array[i]);
+		array[i] = new;
+	}
+
+	return 0;
+}
+
+
+
+/* Like `glob', but PATTERN is a final pathname component,
+   and matches are searched for in DIRECTORY.
+   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
+   The GLOB_APPEND flag is assumed to be set (always appends).  */
+static int glob_in_dir(pattern, directory, flags, errfunc, pglob)
+const char *pattern;
+const char *directory;
+int flags;
+int (*errfunc) __P((const char *, int));
+glob_t *pglob;
+{
+	__ptr_t stream;
+
+	struct globlink {
+		struct globlink *next;
+		char *name;
+	};
+	struct globlink *names = NULL;
+	size_t nfound;
+	int meta;
+	int save;
+
+	stream = ((flags & GLOB_ALTDIRFUNC) ?
+			  (*pglob->gl_opendir) (directory) :
+			  (__ptr_t) opendir(directory));
+	if (stream == NULL) {
+		if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
+			(flags & GLOB_ERR)) return GLOB_ABORTED;
+		nfound = 0;
+		meta = 0;
+	} else if (pattern[0] == '\0') {
+		/* This is a special case for matching directories like in
+		   "*a/".  */
+		names = (struct globlink *) __alloca(sizeof(struct globlink));
+
+		names->name = (char *) malloc(1);
+		if (names->name == NULL)
+			goto memory_error;
+		names->name[0] = '\0';
+		names->next = NULL;
+		nfound = 1;
+		meta = 0;
+	} else {
+		nfound = 0;
+		meta = __glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE));
+		if (meta)
+			flags |= GLOB_MAGCHAR;
+
+		while (1) {
+			const char *name;
+			size_t len;
+			struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
+								(*pglob->gl_readdir) (stream) :
+								readdir((DIR *) stream));
+
+			if (d == NULL)
+				break;
+			if (!REAL_DIR_ENTRY(d))
+				continue;
+
+#ifdef HAVE_D_TYPE
+			/* If we shall match only directories use the information
+			   provided by the dirent call if possible.  */
+			if ((flags & GLOB_ONLYDIR)
+				&& d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
+				continue;
+#endif
+
+			name = d->d_name;
+
+			if ((!meta && strcmp(pattern, name) == 0)
+				|| fnmatch(pattern, name,
+						   (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
+						   ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+#ifdef _AMIGA
+						   | FNM_CASEFOLD
+#endif
+				) == 0) {
+				struct globlink *new
+
+					=
+					(struct globlink *) __alloca(sizeof(struct globlink));
+				len = NAMLEN(d);
+				new->name = (char *) malloc(len + 1);
+				if (new->name == NULL)
+					goto memory_error;
+#ifdef HAVE_MEMPCPY
+				*((char *) mempcpy((__ptr_t) new->name, name, len)) = '\0';
+#else
+				memcpy((__ptr_t) new->name, name, len);
+				new->name[len] = '\0';
+#endif
+				new->next = names;
+				names = new;
+				++nfound;
+				if (!meta)
+					break;
+			}
+		}
+	}
+
+	if (nfound == 0 && (flags & GLOB_NOMAGIC) && !meta)
+		flags |= GLOB_NOCHECK;
+
+	if (nfound == 0 && (flags & GLOB_NOCHECK)) {
+		size_t len = strlen(pattern);
+
+		nfound = 1;
+		names = (struct globlink *) __alloca(sizeof(struct globlink));
+
+		names->next = NULL;
+		names->name = (char *) malloc(len + 1);
+		if (names->name == NULL)
+			goto memory_error;
+#ifdef HAVE_MEMPCPY
+		*((char *) mempcpy(names->name, pattern, len)) = '\0';
+#else
+		memcpy(names->name, pattern, len);
+		names->name[len] = '\0';
+#endif
+	}
+
+	if (nfound != 0) {
+		pglob->gl_pathv
+			= (char **) realloc(pglob->gl_pathv,
+								(pglob->gl_pathc +
+								 ((flags & GLOB_DOOFFS) ? pglob->
+								  gl_offs : 0) + nfound +
+
+								 1) * sizeof(char *));
+		if (pglob->gl_pathv == NULL)
+			goto memory_error;
+
+		if (flags & GLOB_DOOFFS)
+			while (pglob->gl_pathc < pglob->gl_offs)
+				pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+		for (; names != NULL; names = names->next)
+			pglob->gl_pathv[pglob->gl_pathc++] = names->name;
+		pglob->gl_pathv[pglob->gl_pathc] = NULL;
+
+		pglob->gl_flags = flags;
+	}
+
+	save = errno;
+	if (flags & GLOB_ALTDIRFUNC)
+		(*pglob->gl_closedir) (stream);
+	else
+		closedir((DIR *) stream);
+	__set_errno(save);
+
+	return nfound == 0 ? GLOB_NOMATCH : 0;
+
+  memory_error:
+	{
+		int save = errno;
+
+		if (flags & GLOB_ALTDIRFUNC)
+			(*pglob->gl_closedir) (stream);
+		else
+			closedir((DIR *) stream);
+		__set_errno(save);
+	}
+	while (names != NULL) {
+		if (names->name != NULL)
+			free((__ptr_t) names->name);
+		names = names->next;
+	}
+	return GLOB_NOSPACE;
+}
+
+#endif							/* Not ELIDE_CODE.  */

+ 33 - 0
libc/misc/lsearch/.indent.pro

@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space

+ 42 - 0
libc/misc/lsearch/Makefile

@@ -0,0 +1,42 @@
+# Makefile for uCLibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.make
+LIBC=$(TOPDIR)libc.a
+
+CSRC=lsearch.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+OBJS=$(COBJS)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(OBJS): Makefile
+
+clean:
+	rm -f *.[oa] *~ core
+

+ 43 - 0
libc/misc/lsearch/lsearch.c

@@ -0,0 +1,43 @@
+/*
+ * This file lifted in toto from 'Dlibs' on the atari ST  (RdeBath)
+ *
+ * 
+ *    Dale Schumacher                         399 Beacon Ave.
+ *    (alias: Dalnefre')                      St. Paul, MN  55104
+ *    dal@syntel.UUCP                         United States of America
+ *  "It's not reality that's important, but how you perceive things."
+ */
+
+#include <stdio.h>
+
+char *lfind(key, base, num, size, cmp)
+register char *key, *base;
+unsigned int *num;
+register unsigned int size;
+register int (*cmp) ();
+{
+	register int n = *num;
+
+	while (n--) {
+		if ((*cmp) (base, key) == 0)
+			return (base);
+		base += size;
+	}
+	return (NULL);
+}
+
+char *lsearch(key, base, num, size, cmp)
+char *key, *base;
+register unsigned int *num;
+register unsigned int size;
+int (*cmp) ();
+{
+	register char *p;
+	char *memcpy();
+
+	if ((p = lfind(key, base, num, size, cmp)) == NULL) {
+		p = memcpy((base + (size * (*num))), key, size);
+		++(*num);
+	}
+	return (p);
+}