Browse Source

A large update from Manuel Novoa III <mnovoa3@bellsouth.net>.

Eric Andersen 23 years ago
parent
commit
ae97a89e1a
62 changed files with 2763 additions and 495 deletions
  1. 2 2
      Makefile
  2. 1 1
      Rules.mak
  3. 48 0
      extra/Makefile
  4. 40 0
      extra/gcc-uClibc/Makefile
  5. 129 0
      extra/gcc-uClibc/gcc-uClibc.c
  6. 98 7
      include/getopt.h
  7. 5 9
      include/stdio.h
  8. 1 1
      include/sys/param.h
  9. 2 2
      libc/inet/Makefile
  10. 2 2
      libc/inet/resolv.c
  11. 2 2
      libc/inet/rpc/Makefile
  12. 1 1
      libc/misc/Makefile
  13. 2 2
      libc/misc/assert/Makefile
  14. 2 2
      libc/misc/fnmatch/Makefile
  15. 2 2
      libc/misc/glob/Makefile
  16. 2 2
      libc/misc/internals/Makefile
  17. 2 2
      libc/misc/lock/Makefile
  18. 2 2
      libc/misc/lsearch/Makefile
  19. 2 2
      libc/misc/mntent/Makefile
  20. 2 2
      libc/misc/regex/Makefile
  21. 2 2
      libc/misc/syslog/Makefile
  22. 2 2
      libc/misc/time/Makefile
  23. 2 2
      libc/pwd_grp/Makefile
  24. 2 2
      libc/signal/Makefile
  25. 5 4
      libc/stdio/Makefile
  26. 30 36
      libc/stdio/printf.c
  27. 62 133
      libc/stdio/stdio.c
  28. 3 3
      libc/stdlib/Makefile
  29. 24 58
      libc/stdlib/atexit.c
  30. 51 0
      libc/stdlib/malloc-930716/Makefile
  31. 40 0
      libc/stdlib/malloc-930716/README
  32. 25 0
      libc/stdlib/malloc-930716/calloc.c
  33. 156 0
      libc/stdlib/malloc-930716/free.c
  34. 254 0
      libc/stdlib/malloc-930716/malloc.c
  35. 107 0
      libc/stdlib/malloc-930716/malloc.h
  36. 61 0
      libc/stdlib/malloc-930716/memalign.c
  37. 28 0
      libc/stdlib/malloc-930716/morecore.c
  38. 131 0
      libc/stdlib/malloc-930716/realloc.c
  39. 62 0
      libc/stdlib/malloc-930716/valloc.c
  40. 2 2
      libc/stdlib/malloc-simple/Makefile
  41. 2 2
      libc/stdlib/malloc/Makefile
  42. 72 148
      libc/stdlib/qsort.c
  43. 2 0
      libc/stdlib/system.c
  44. 2 2
      libc/string/Makefile
  45. 35 8
      libc/string/strerror.c
  46. 50 23
      libc/string/strsignal.c
  47. 4 4
      libc/sysdeps/linux/arm/Makefile
  48. 21 5
      libc/sysdeps/linux/common/Makefile
  49. 35 0
      libc/sysdeps/linux/common/str_syscalls.sh
  50. 31 1
      libc/sysdeps/linux/common/syscalls.c
  51. 41 0
      libc/sysdeps/linux/common/unified_syscall_i386.h
  52. 8 5
      libc/sysdeps/linux/i386/Makefile
  53. 33 0
      libc/sysdeps/linux/i386/__init_brk.c
  54. 39 0
      libc/sysdeps/linux/i386/__uClibc_syscall.S
  55. 32 0
      libc/sysdeps/linux/i386/brk.c
  56. 35 0
      libc/sysdeps/linux/i386/sbrk.c
  57. 2 2
      libc/termios/Makefile
  58. 12 3
      libc/unistd/Makefile
  59. 12 4
      libc/unistd/getopt.c
  60. 2 1
      libc/unistd/getpass.c
  61. 873 0
      libc/unistd/gnu_getopt.c
  62. 24 0
      test/string/Makefile

+ 2 - 2
Makefile

@@ -28,7 +28,7 @@
 
 include Rules.mak
 
-DIRS = misc pwd_grp stdio string termios unistd net signal stdlib sysdeps
+DIRS = misc pwd_grp stdio string termios unistd net signal stdlib sysdeps extra
 
 all: libc.a
 
@@ -58,7 +58,7 @@ headers: dummy
 
 tags:
 	ctags -R
-	
+
 clean: subdirs_clean
 	rm -f libc.a
 	rm -f include/asm include/net include/linux include/bits

+ 1 - 1
Rules.mak

@@ -41,7 +41,7 @@ ifeq ($(DODEBUG),true)
     LDFLAGS = -nostdlib -Wl,-warn-common 
     STRIPTOOL = /bin/true -Since_we_are_debugging
 else
-    CFLAGS  += $(WARNINGS) #-fomit-frame-pointer
+    CFLAGS  += -DNDEBUG $(WARNINGS) #-fomit-frame-pointer
     LDFLAGS  = -s -nostdlib -Wl,-warn-common
 endif
 

+ 48 - 0
extra/Makefile

@@ -0,0 +1,48 @@
+# 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 Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library 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.mak
+LIBC=$(TOPDIR)libc.a
+
+
+DIRS = gcc-uClibc
+
+all: subdirs
+
+tags:
+	ctags -R
+
+clean: subdirs_clean
+	rm -f *.[oa] *~ core
+
+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
+

+ 40 - 0
extra/gcc-uClibc/Makefile

@@ -0,0 +1,40 @@
+
+TOPDIR = ../../
+include $(TOPDIR)Rules.mak
+
+UCLIBC_DIR = $(shell (cd ../.. ; /bin/pwd))
+GCC_BIN = $(CC)
+GCC_LIB = $(shell $(CC) -print-libgcc-file-name )
+#GCCINCDIR inherited from Rules.mak
+
+NATIVE_ARCH = $(shell uname -m | sed -e 's/i.86/i386/' -e 's/sparc.*/sparc/' -e 's/arm.*/arm/g')
+GCC_UCLIBC = gcc-uClibc-cross
+ifeq ($(TARGET_ARCH), $(NATIVE_ARCH))
+	GCC_UCLIBC = gcc-uClibc-native
+endif
+
+all: $(GCC_UCLIBC)
+
+clean:
+	rm -f gcc-uClibc.h gcc-uClibc-*
+
+gcc-uClibc.h: clean
+	echo "/* this file is created by make */" > gcc-uClibc.h
+	echo "#define UCLIBC_DIR " \"$(UCLIBC_DIR)/\" >> gcc-uClibc.h
+	echo "#define GCC_BIN " \"$(GCC_BIN)\" >> gcc-uClibc.h
+	echo "#define GCC_LIB " \"$(GCC_LIB)\" >> gcc-uClibc.h
+	echo "#define GCC_INCDIR " \"-I$(GCCINCDIR)/\" >> gcc-uClibc.h
+	echo "#define TARGET_ARCH " \"$(TARGET_ARCH)\" >> gcc-uClibc.h
+
+gcc-uClibc-native: gcc-uClibc.h gcc-uClibc.c
+	# uClibc built for native environment, so why not use it ;-)
+	$(CC) $(CFLAGS) -nostdinc -I$(UCLIBC_DIR)/include -I$(GCC_INC) \
+		-Wl,-static gcc-uClibc.c \
+		$(UCLIBC_DIR)/sysdeps/linux/$(TARGET_ARCH)/_start.o \
+		-nostdlib $(GCC_LIB) $(UCLIBC_DIR)/libc.a \
+		-s -o gcc-uClibc-$(TARGET_ARCH) #-DDEBUG
+
+gcc-uClibc-cross: gcc-uClibc.h gcc-uClibc.c
+	# don't use CFLAGS since may not be appropriate
+	gcc -s gcc-uClibc.c -o gcc-uClibc-$(TARGET_ARCH)
+

+ 129 - 0
extra/gcc-uClibc/gcc-uClibc.c

@@ -0,0 +1,129 @@
+
+/*
+ * Copyright (C) 2000 Manuel Novoa III
+ *
+ * This is a crude wrapper to use uClibc with gcc.
+ * It was originally written to work around ./configure for ext2fs-utils.
+ * It certainly can be improved, but it works for me in the normal cases.
+ *
+ * TODO:
+ * Check/modify gcc-specific environment variables?
+ */
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "gcc-uClibc.h"
+
+#define UCLIBC_START UCLIBC_DIR"sysdeps/linux/"TARGET_ARCH"/_start.o"
+#define UCLIBC_START_G UCLIBC_START
+#define UCLIBC_LIB UCLIBC_DIR"libc.a"
+#if 1
+#define UCLIBC_LIB_G UCLIBC_LIB
+#else
+#define UCLIBC_LIB_G UCLIBC_DIR"libc.a-debug"
+#endif
+#define UCLIBC_INC "-I"UCLIBC_DIR"include/"
+
+static char nostdinc[] = "-nostdinc";
+static char nostartfiles[] = "-nostartfiles";
+static char nodefaultlibs[] = "-nodefaultlibs";
+static char nostdlib[] = "-nostdlib";
+
+int main(int argc, char **argv)
+{
+	int debugging = 0, linking = 1;
+	int use_stdinc = 1, use_start = 1, use_stdlib = 1;
+	int i, j;
+	int source_count;
+	char ** gcc_argv;
+
+	source_count = 0;
+
+	for ( i = 1 ; i < argc ; i++ ) {
+		if (argv[i][0] == '-') { /* option */
+			switch (argv[i][1]) {
+				case 'c':
+				case 'S':
+				case 'E':
+				case 'r':
+					if (argv[i][2] == 0) linking = 0;
+					break;
+				case 'g':
+					if (argv[i][2] == 0) debugging = 1;
+					break;
+				case 'n':
+					if (strcmp(nostdinc,argv[i]) == 0) {
+						use_stdinc = 0;
+					} else if (strcmp(nostartfiles,argv[i]) == 0) {
+						use_start = 0;
+					} else if (strcmp(nodefaultlibs,argv[i]) == 0) {
+						use_stdlib = 0;
+					} else if (strcmp(nostdlib,argv[i]) == 0) {
+						use_start = 0;
+						use_stdlib = 0;
+					}
+
+			}
+		} else {				/* assume it is an existing source file */
+			++source_count;
+		}
+	}
+
+#if 1
+	gcc_argv = __builtin_alloca(sizeof(char*) * (argc + 20));
+#else
+	if (!(gcc_argv = malloc(sizeof(char) * (argc + 20)))) {
+		return EXIT_FAILURE;
+	}
+#endif
+
+	i = 0;
+	gcc_argv[i++] = GCC_BIN;
+	for ( j = 1 ; j < argc ; j++ ) {
+		gcc_argv[i++] = argv[j];
+	}
+	if (use_stdinc) {
+		gcc_argv[i++] = nostdinc;
+		gcc_argv[i++] = UCLIBC_INC;
+		gcc_argv[i++] = GCC_INCDIR;
+	}
+	if (linking && source_count) {
+		gcc_argv[i++] = "-static";
+		if (use_start) {
+			if (debugging) {
+				gcc_argv[i++] = UCLIBC_START_G;
+			} else {
+				gcc_argv[i++] = UCLIBC_START;
+			}
+		}
+		if (use_stdlib) {
+			gcc_argv[i++] = "-nostdlib";
+			if (debugging) {
+				gcc_argv[i++] = UCLIBC_LIB_G;
+			} else {
+				gcc_argv[i++] = UCLIBC_LIB;
+			}
+			gcc_argv[i++] = GCC_LIB;
+		}
+	}
+	gcc_argv[i++] = NULL;
+
+#ifdef DEBUG
+	for ( j = 0 ; gcc_argv[j] ; j++ ) {
+		printf("arg[%2i] = %s\n", j, gcc_argv[j]);
+	}
+	return EXIT_SUCCESS;
+#else
+	return execvp(GCC_BIN, gcc_argv);
+#endif
+}
+  
+
+  
+  

+ 98 - 7
include/getopt.h

@@ -1,18 +1,109 @@
-/* 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.
- */
+/* Declarations for getopt.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
 
-#ifndef __GETOPT_H
-#define __GETOPT_H
+This file is part of the GNU C Library.
+
+The GNU C 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.
+
+The GNU C 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
 
 #include <features.h>
 
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
 extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
 extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
 extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
 extern int optopt;
 
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+  const char *name;
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
 extern int getopt __P((int argc, char *const *argv, const char *shortopts));
+extern int getopt_long __P((int argc, char *const *argv, const char *shortopts,
+							const struct option *longopts, int *longind));
+extern int getopt_long_only __P((int argc, char *const *argv,
+								 const char *shortopts,
+								 const struct option *longopts, int *longind));
+
+#ifdef	__cplusplus
+}
+#endif
 
-#endif /* __GETOPT_H */
+#endif /* _GETOPT_H */

+ 5 - 9
include/stdio.h

@@ -105,16 +105,12 @@ typedef struct __stdio_file FILE;
 #include <bits/stdio_lim.h>
 #undef __need_FOPEN_MAX
 
-
-/* Standard streams.  */
-extern FILE stdin[1];		/* Standard input stream.  */
-extern FILE stdout[1];		/* Standard output stream.  */
-extern FILE stderr[1];		/* Standard error output stream. */
+/* Standard streams (internal).  */
+extern FILE _stdio_streams[3];
 /* C89/C99 say they're macros.  Make them happy.  */
-#define stdin stdin
-#define stdout stdout
-#define stderr stderr
-
+#define stdin  (_stdio_streams)
+#define stdout (_stdio_streams+1)
+#define stderr (_stdio_streams+2)
 
 /* Remove file FILENAME.  */
 extern int remove __P ((__const char *__filename));

+ 1 - 1
include/sys/param.h

@@ -9,7 +9,7 @@
 #include <features.h>
 #include <limits.h>
 #include <linux/limits.h>
-#include <linux/param.h>
+#include <asm/param.h>
 
 #include <sys/types.h>
 

+ 2 - 2
libc/inet/Makefile

@@ -66,8 +66,8 @@ $(MOBJ3): $(MSRC3)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean: subdirs_clean

+ 2 - 2
libc/inet/resolv.c

@@ -455,6 +455,8 @@ int dns_lookup(const char *name, int type, int nscount, const char **nsip,
 	extern int searchdomains;
 	extern const char * searchdomain[MAX_SEARCH];
 
+	fd = -1;
+
 	if (!packet || !lookup || !nscount)
 	    goto fail;
 
@@ -462,8 +464,6 @@ int dns_lookup(const char *name, int type, int nscount, const char **nsip,
 
 	ns %= nscount;
 
-	fd = -1;
-
 	while (retries++ < MAX_RETRIES) {
 
 		if (fd != -1)

+ 2 - 2
libc/inet/rpc/Makefile

@@ -39,8 +39,8 @@ COBJS=$(patsubst %.c,%.o, $(CSRC))
 
 all: $(COBJS) $(LIBC)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(LIBC): $(COBJS)

+ 1 - 1
libc/misc/Makefile

@@ -39,7 +39,7 @@ libc.a: subdirs
 
 tags:
 	ctags -R
-	
+
 clean: subdirs_clean
 	rm -f *.[oa] *~ core
 

+ 2 - 2
libc/misc/assert/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/fnmatch/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/glob/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/internals/Makefile

@@ -39,8 +39,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/lock/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/lsearch/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/mntent/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/regex/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/syslog/Makefile

@@ -35,8 +35,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/misc/time/Makefile

@@ -43,8 +43,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/pwd_grp/Makefile

@@ -36,8 +36,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(OBJ): Makefile

+ 2 - 2
libc/signal/Makefile

@@ -37,8 +37,8 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 5 - 4
libc/stdio/Makefile

@@ -28,10 +28,11 @@ LIBC=$(TOPDIR)libc.a
 MSRC=stdio.c
 MOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o	\
      puts.o fread.o fwrite.o fopen.o fclose.o fseek.o rewind.o ftell.o	\
-     setbuffer.o setvbuf.o ungetc.o
+     setbuffer.o setvbuf.o ungetc.o _alloc_stdio_buffer.o _free_stdio_buffer.o
 
 MSRC2=printf.c
-MOBJ2=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o snprintf.o vsnprintf.o
+MOBJ2=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o snprintf.o \
+     vsnprintf.o _sprintf_fake_file.o vfnprintf.o
 
 MSRC3=scanf.c
 MOBJ3=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o
@@ -60,8 +61,8 @@ $(MOBJ3): $(MSRC3)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(OBJ): Makefile

+ 30 - 36
libc/stdio/printf.c

@@ -8,7 +8,7 @@
  *  "It's not reality that's important, but how you perceive things."
  */
 
-/* Altered to use stdarg, made the core function vfprintf.
+/* Altered to use stdarg, made the core function vfnprintf.
  * Hooked into the stdio package using 'inside information'
  * Altered sizeof() assumptions, now assumes all integers except chars
  * will be either
@@ -20,7 +20,7 @@
 /*
  *                    Manuel Novoa III   Dec 2000
  *
- * The previous vfprintf routine was almost completely rewritten with the
+ * The previous vfnprintf routine was almost completely rewritten with the
  * goal of fixing some shortcomings and reducing object size.
  *
  * The summary of changes:
@@ -52,6 +52,8 @@
  * Converted to use my (un)signed long (long) to string routines, which are
  * smaller than the previous functions and don't require static buffers.
  *
+ * Other Modifications:
+ *   Modified sprintf, snprintf, vsprintf, vsnprintf to share on fake-file.
  */
 
 /*****************************************************************************/
@@ -122,6 +124,14 @@
 extern int vfnprintf(FILE * op, size_t max_size,
 					 register __const char *fmt, register va_list ap);
 
+extern FILE __sprintf_fake_file[1];
+
+#ifdef L__sprintf_fake_file
+FILE __sprintf_fake_file[1] = {
+	{0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
+	 _IOFBF | __MODE_WRITE}
+};
+#endif
 
 #ifdef L_printf
 int printf(const char *fmt, ...)
@@ -139,19 +149,14 @@ int printf(const char *fmt, ...)
 #ifdef L_sprintf
 int sprintf(char *sp, const char *fmt, ...)
 {
-	static FILE string[1] = {
-		{0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
-		 _IOFBF | __MODE_WRITE}
-	};
-
 	va_list ptr;
 	int rv;
 
 	va_strt(ptr, fmt);
-	string->bufpos = sp;
-	rv = vfnprintf(string, -1, fmt, ptr);
+	__sprintf_fake_file->bufpos = sp;
+	rv = vfnprintf(__sprintf_fake_file, -1, fmt, ptr);
 	va_end(ptr);
-	*(string->bufpos) = 0;
+	*(__sprintf_fake_file->bufpos) = 0;
 	return rv;
 }
 #endif
@@ -160,19 +165,14 @@ int sprintf(char *sp, const char *fmt, ...)
 #ifdef L_snprintf
 int snprintf(char *sp, size_t size, const char *fmt, ...)
 {
-	static FILE string[1] = {
-		{0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
-		 _IOFBF | __MODE_WRITE}
-	};
-
 	va_list ptr;
 	int rv;
 
 	va_strt(ptr, fmt);
-	string->bufpos = sp;
-	rv = vfnprintf(string, size, fmt, ptr);
+	__sprintf_fake_file->bufpos = sp;
+	rv = vfnprintf(__sprintf_fake_file, size, fmt, ptr);
 	va_end(ptr);
-	*(string->bufpos) = 0;
+	*(__sprintf_fake_file->bufpos) = 0;
 	return rv;
 }
 #endif
@@ -200,38 +200,28 @@ int vprintf(const char *fmt, va_list ap)
 #ifdef L_vsprintf
 int vsprintf(char *sp, __const char *fmt, va_list ap)
 {
-	static FILE string[1] = {
-		{0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
-		 _IOFBF | __MODE_WRITE}
-	};
-
 	int rv;
 
-	string->bufpos = sp;
-	rv = vfnprintf(string, -1, fmt, ap);
-	*(string->bufpos) = 0;
+	__sprintf_fake_file->bufpos = sp;
+	rv = vfnprintf(__sprintf_fake_file, -1, fmt, ap);
+	*(__sprintf_fake_file->bufpos) = 0;
 	return rv;
 }
 #endif
 
-#ifdef L_vsprintf
+#ifdef L_vsnprintf
 int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap)
 {
-	static FILE string[1] = {
-		{0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
-		 _IOFBF | __MODE_WRITE}
-	};
-
 	int rv;
 
-	string->bufpos = sp;
-	rv = vfnprintf(string, size, fmt, ap);
-	*(string->bufpos) = 0;
+	__sprintf_fake_file->bufpos = sp;
+	rv = vfnprintf(__sprintf_fake_file, size, fmt, ap);
+	*(__sprintf_fake_file->bufpos) = 0;
 	return rv;
 }
 #endif
 
-#ifdef L_vfprintf
+#ifdef L_vfnprintf
 
 extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase);
 extern char *__ltostr(char *buf, long val, int base, int uppercase);
@@ -591,6 +581,10 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 	return (cnt);
 }
 
+#endif
+
+#ifdef L_vfprintf
+
 int vfprintf(FILE * op, register __const char *fmt, register va_list ap)
 {
 	return (vfnprintf(op, -1, fmt, ap));

+ 62 - 133
libc/stdio/stdio.c

@@ -28,8 +28,6 @@
 
 #undef STUB_FWRITE
 
-void __init_stdio(void);
-
 extern FILE *__IO_list;			/* For fflush at exit */
 
 #define FIXED_BUFFERS 2
@@ -38,47 +36,72 @@ struct fixed_buffer {
 	int used;
 };
 
-extern struct fixed_buffer _fixed_buffers[2];
+extern struct fixed_buffer _fixed_buffers[FIXED_BUFFERS];
 
-#ifdef L__stdio_init
+extern unsigned char *_alloc_stdio_buffer(size_t size);
+extern void _free_stdio_buffer(unsigned char *buf);
 
-#define buferr (stderr->unbuf)		/* Stderr is unbuffered */
+#ifdef L__alloc_stdio_buffer
 
-FILE *__IO_list = 0;			/* For fflush at exit */
+unsigned char *_alloc_stdio_buffer(size_t size)
+{
+	if (size == BUFSIZ) {
+		int i;
 
-static char *bufin;
-static char *bufout;
-#ifndef buferr
-static char *buferr;
+		for (i = 0; i < FIXED_BUFFERS; i++)
+			if (!_fixed_buffers[i].used) {
+				_fixed_buffers[i].used = 1;
+				return _fixed_buffers[i].data;
+			}
+	}
+	return malloc(size);
+}
 #endif
 
-FILE stdin[1] = {
-#if 0
-	{bufin, bufin, bufin, bufin, bufin + BUFSIZ,
-#else
-	{0, 0, 0, 0, 0,
+#ifdef L__free_stdio_buffer
+
+void _free_stdio_buffer(unsigned char *buf)
+{
+	int i;
+
+	for (i = 0; i < FIXED_BUFFERS; i++) {
+		if (buf == _fixed_buffers[i].data) {
+			_fixed_buffers[i].used = 0;
+			return;
+		}
+	}
+	free(buf);
+}
 #endif
-	 0, _IOFBF | __MODE_READ | __MODE_IOTRAN}
-};
 
-FILE stdout[1] = {
-#if 0
-	{bufout, bufout, bufout, bufout, bufout + BUFSIZ,
-#else
-	{0, 0, 0, 0, 0,
+#ifdef L__stdio_init
+
+#if FIXED_BUFFERS < 2
+#error FIXED_BUFFERS must be >= 2
 #endif
-	 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN}
-};
 
-FILE stderr[1] = {
-#if 0
+#define bufin (_fixed_buffers[0].data)
+#define bufout (_fixed_buffers[1].data)
+#define buferr (_stdio_streams[3].unbuf)		/* Stderr is unbuffered */
+
+struct fixed_buffer _fixed_buffers[FIXED_BUFFERS];
+
+FILE _stdio_streams[3] = {
+	{bufin, bufin, bufin, bufin, bufin + BUFSIZ,
+	 0, _IOFBF | __MODE_READ | __MODE_IOTRAN | __MODE_FREEBUF},
+	{bufout, bufout, bufout, bufout, bufout + BUFSIZ,
+	 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN | __MODE_FREEBUF},
 	{buferr, buferr, buferr, buferr, buferr + sizeof(buferr),
-#else
-	{0, 0, 0, 0, 0,
-#endif
 	 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN}
 };
 
+/*
+ * Note: the following forces lining of the __init_stdio function if
+ * any of the stdio functions are used (except perror) since they all
+ * call fflush directly or indirectly.
+ */
+FILE *__IO_list = 0;			/* For fflush at exit */
+
 /* Call the stdio initiliser; it's main job it to call atexit */
 
 void __stdio_close_all(void)
@@ -96,52 +119,17 @@ void __stdio_close_all(void)
 	}
 }
 
-static int first_time = 0;
-
-struct fixed_buffer _fixed_buffers[2];
-
-
 void __init_stdio(void)
 {
-	if (first_time)
-		return;
-	first_time = 1;
-
-	stdin->bufpos = bufin = _fixed_buffers[0].data; /*(char *)malloc(BUFSIZ) */ ;
-	stdin->bufread = bufin;
-	stdin->bufwrite = bufin;
-	stdin->bufstart = bufin;
-	stdin->bufend = bufin + sizeof(_fixed_buffers[0].data);
-	stdin->fd = 0;
-	stdin->mode = _IOFBF | __MODE_READ | __MODE_IOTRAN | __MODE_FREEBUF;
-
 	_fixed_buffers[0].used = 1;
-
-	stdout->bufpos = bufout = _fixed_buffers[1].data;	/*(char *)malloc(BUFSIZ); */
-	stdout->bufread = bufout;
-	stdout->bufwrite = bufout;
-	stdout->bufstart = bufout;
-	stdout->bufend = bufout + sizeof(_fixed_buffers[1].data);
-	stdout->fd = 1;
-	stdout->mode = _IOFBF | __MODE_WRITE | __MODE_IOTRAN | __MODE_FREEBUF;
-
 	_fixed_buffers[1].used = 1;
 
-#if 0
-	stderr->bufpos = buferr = (char *) malloc(BUFSIZ);
-#else
-	stderr->bufpos = buferr;
-#endif
-	stderr->bufread = buferr;
-	stderr->bufwrite = buferr;
-	stderr->bufstart = buferr;
-	stderr->bufend = buferr + sizeof(buferr);
-	stderr->fd = 2;
-	stderr->mode = _IONBF | __MODE_WRITE | __MODE_IOTRAN;
-
 	if (isatty(1))
 		stdout->mode |= _IOLBF;
+#if 0
+	/* taken care of in _start.c and exit.c now*/
 	atexit(__stdio_close_all);
+#endif
 }
 #endif
 
@@ -152,8 +140,6 @@ FILE *fp;
 {
 	register int v;
 
-	__init_stdio();
-
 	v = fp->mode;
 	/* If last op was a read ... */
 	if ((v & __MODE_READING) && fflush(fp))
@@ -199,8 +185,6 @@ FILE *fp;
 {
 	int ch;
 
-	__init_stdio();
-
 	if (fp->mode & __MODE_WRITING)
 		fflush(fp);
 
@@ -243,8 +227,6 @@ FILE *fp;
 	int len, cc, rv = 0;
 	char *bstart;
 
-	__init_stdio();
-
 	if (fp == NULL) {			/* On NULL flush the lot. */
 		if (fflush(stdin))
 			return EOF;
@@ -406,8 +388,6 @@ FILE *fp;
 	int len, v;
 	unsigned bytes, got = 0;
 
-	__init_stdio();
-
 	v = fp->mode;
 
 	/* Want to do this to bring the file pointer up to date */
@@ -611,8 +591,6 @@ const char *mode;
 	int fopen_mode = 0;
 	FILE *nfp = 0;
 
-	__init_stdio();
-
 	/* If we've got an fp close the old one (freopen) */
 	if (fp) {
 		/* Careful, don't de-allocate it */
@@ -684,8 +662,6 @@ const char *mode;
 
 	/* If this isn't freopen create a (FILE) and buffer for it */
 	if (fp == 0) {
-		int i;
-
 		fp = nfp;
 		fp->next = __IO_list;
 		__IO_list = fp;
@@ -700,15 +676,7 @@ const char *mode;
 		} else
 			fp->mode |= _IOFBF;
 
-		for (i = 0; i < FIXED_BUFFERS; i++)
-			if (!_fixed_buffers[i].used) {
-				fp->bufstart = _fixed_buffers[i].data;
-				_fixed_buffers[i].used = 1;
-				break;
-			}
-
-		if (i == FIXED_BUFFERS)
-			fp->bufstart = malloc(BUFSIZ);
+		fp->bufstart = _alloc_stdio_buffer(BUFSIZ);
 
 		if (fp->bufstart == 0) {	/* Oops, no mem *//* Humm, full buffering with a two(!) byte
 									   * buffer. */
@@ -733,8 +701,6 @@ FILE *fp;
 {
 	int rv = 0;
 
-	__init_stdio();
-
 	if (fp == 0) {
 		errno = EINVAL;
 		return EOF;
@@ -747,15 +713,7 @@ FILE *fp;
 	fp->fd = -1;
 
 	if (fp->mode & __MODE_FREEBUF) {
-		int i;
-
-		for (i = 0; i < FIXED_BUFFERS; i++)
-			if (fp->bufstart == _fixed_buffers[i].data) {
-				_fixed_buffers[i].used = 0;
-				break;
-			}
-		if (i == FIXED_BUFFERS)
-			free(fp->bufstart);
+		_free_stdio_buffer(fp->bufstart);
 		fp->mode &= ~__MODE_FREEBUF;
 		fp->bufstart = fp->bufend = 0;
 	}
@@ -793,15 +751,7 @@ size_t size;
 		return;
 
 	if (fp->mode & __MODE_FREEBUF) {
-		int i;
-
-		for (i = 0; i < FIXED_BUFFERS; i++)
-			if (fp->bufstart == _fixed_buffers[i].data) {
-				_fixed_buffers[i].used = 0;
-				break;
-			}
-		if (i == FIXED_BUFFERS)
-			free(fp->bufstart);
+		_free_stdio_buffer(fp->bufstart);
 	}
 	fp->mode &= ~(__MODE_FREEBUF | __MODE_BUF);
 
@@ -827,15 +777,7 @@ size_t size;
 {
 	fflush(fp);
 	if (fp->mode & __MODE_FREEBUF) {
-		int i;
-
-		for (i = 0; i < FIXED_BUFFERS; i++)
-			if (fp->bufstart == _fixed_buffers[i].data) {
-				_fixed_buffers[i].used = 0;
-				break;
-			}
-		if (i == FIXED_BUFFERS)
-			free(fp->bufstart);
+		_free_stdio_buffer(fp->bufstart);
 	}
 	fp->mode &= ~(__MODE_FREEBUF | __MODE_BUF);
 	fp->bufstart = fp->unbuf;
@@ -847,23 +789,10 @@ size_t size;
 			size = BUFSIZ;
 		}
 		if (buf == 0) {
-			if (size == BUFSIZ) {
-				int i;
-
-				for (i = 0; i < FIXED_BUFFERS; i++)
-					if (!_fixed_buffers[i].used) {
-						_fixed_buffers[i].used = 1;
-						buf = _fixed_buffers[i].data;
-						break;
-					}
-				if (i == FIXED_BUFFERS)
-					buf = malloc(size);
-			} else {
-				buf = malloc(size);
-			}
+			buf = _alloc_stdio_buffer(size);
+			if (buf == 0)
+				return EOF;
 		}
-		if (buf == 0)
-			return EOF;
 
 		fp->bufstart = buf;
 		fp->bufend = buf + size;

+ 3 - 3
libc/stdlib/Makefile

@@ -33,7 +33,7 @@ MSRC1=strto_ll.c
 MOBJ1=strtoll.o strtoull.o strto_ll.o
 
 MSRC2=atexit.c
-MOBJ2=on_exit.o atexit.o __do_exit.o exit.o
+MOBJ2=atexit.o exit.o
 
 
 CSRC =	abort.c getenv.c mktemp.c qsort.c realpath.c abs.c bsearch.c \
@@ -65,8 +65,8 @@ $(MOBJ2): $(MSRC2)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(OBJ): Makefile

+ 24 - 58
libc/stdlib/atexit.c

@@ -4,11 +4,12 @@
  */
 
 /*
- * This deals with both the atexit and on_exit function calls
- * 
- * Note calls installed with atexit are called with the same args as on_exit
- * fuctions; the void* is given the NULL value.
- * 
+ * Manuel Novoa III       Dec 2000
+ *
+ * Modifications:
+ *   Made atexit handling conform to standards... i.e. no args.
+ *   Removed on_exit since it did not match gnu libc definition.
+ *   Combined atexit and __do_exit into one object file.
  */
 
 #include <errno.h>
@@ -16,93 +17,58 @@
 /* ATEXIT.H */
 #define MAXONEXIT 20			/* AIUI Posix requires 10 */
 
-typedef void (*vfuncp) ();
+typedef void (*vfuncp) (void);
 
 extern vfuncp __cleanup;
 extern void __do_exit();
 extern void _exit __P((int __status)) __attribute__ ((__noreturn__));
 
-extern struct exit_table {
-	vfuncp called;
-	void *argument;
-} __on_exit_table[MAXONEXIT];
-
-extern int __on_exit_count;
+extern vfuncp __atexit_table[MAXONEXIT];
+extern int __atexit_count;
 
 /* End ATEXIT.H */
 
 #ifdef L_atexit
-vfuncp __cleanup;
-
-int atexit(ptr)
-vfuncp ptr;
+int atexit(vfuncp ptr)
 {
-	if (__on_exit_count < 0 || __on_exit_count >= MAXONEXIT) {
+	if ((__atexit_count < 0) || (__atexit_count >= MAXONEXIT)) {
 		errno = ENOMEM;
 		return -1;
 	}
-	__cleanup = __do_exit;
 	if (ptr) {
-		__on_exit_table[__on_exit_count].called = ptr;
-		__on_exit_table[__on_exit_count].argument = 0;
-		__on_exit_count++;
+		__cleanup = __do_exit;
+		__atexit_table[__atexit_count++] = ptr;
 	}
 	return 0;
 }
 
-#endif
+vfuncp __atexit_table[MAXONEXIT];
+int __atexit_count = 0;
 
-#ifdef L_on_exit
-int on_exit(ptr, arg)
-vfuncp ptr;
-void *arg;
+void __do_exit(int rv)
 {
-	if (__on_exit_count < 0 || __on_exit_count >= MAXONEXIT) {
-		errno = ENOMEM;
-		return -1;
-	}
-	__cleanup = __do_exit;
-	if (ptr) {
-		__on_exit_table[__on_exit_count].called = ptr;
-		__on_exit_table[__on_exit_count].argument = arg;
-		__on_exit_count++;
-	}
-	return 0;
-}
+	int count = __atexit_count - 1;
 
-#endif
-
-#ifdef L___do_exit
-
-int __on_exit_count = 0;
-struct exit_table __on_exit_table[MAXONEXIT];
-
-void __do_exit(rv)
-int rv;
-{
-	register int count = __on_exit_count - 1;
-	register vfuncp ptr;
-
-	__on_exit_count = -1;		/* ensure no more will be added */
+	__atexit_count = -1;		/* ensure no more will be added */
 	__cleanup = 0;				/* Calling exit won't re-do this */
 
 	/* In reverse order */
 	for (; count >= 0; count--) {
-		ptr = __on_exit_table[count].called;
-		(*ptr) (rv, __on_exit_table[count].argument);
+		(*__atexit_table[count])();
 	}
 }
-
 #endif
 
 #ifdef L_exit
+void __stdio_close_all(void);	/* note: see _start.S - could be faked */
 
-void exit(rv)
-int rv;
+vfuncp __cleanup = 0;
+
+void exit(int rv)
 {
 	if (__cleanup)
 		__cleanup();
+	__stdio_close_all();
 	_exit(rv);
 }
-
 #endif

+ 51 - 0
libc/stdlib/malloc-930716/Makefile

@@ -0,0 +1,51 @@
+# 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 Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library 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.mak
+LIBC=$(TOPDIR)libc.a
+
+CSRC=calloc.c free.c malloc.c memalign.c morecore.c realloc.c valloc.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+
+MSRC=../malloc/alloc.c
+MOBJ=malloc_dbg.o free_dbg.o calloc_dbg.o
+OBJS=$(COBJS) $(MOBJ)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(MOBJ): $(MSRC)
+	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+clean:
+	rm -f *.[oa] *~ core
+

+ 40 - 0
libc/stdlib/malloc-930716/README

@@ -0,0 +1,40 @@
+This is a fast malloc implementation that I wrote several years ago.
+I later used it as the basis of GNU malloc.  My version differs from
+the GNU version in that it does not support debugging hooks, and does
+not record statistics.  Therefore it is slightly faster.
+
+In order to safely link programs using this malloc with a C library
+that provides a different malloc, you need to make sure that
+malloc(), free(), and realloc() are defined in a single object file.
+Otherwise when linking you might get a combination of this malloc()
+with the library's free().  The Makefile builds such an object file,
+alloc.o.
+
+If you are using this malloc as the allocator for a C library of your
+own, and are not linking with another C library, then you don't need
+alloc.o.  If you are building a C library, you should also write a
+replacement for the file "morecore.c" that doesn't pollute the name
+space.
+
+The header file "malloc.h" in this directory is NOT intended to be a
+public header file; it is for internal use by malloc and its
+friends.  Don't install malloc.h in a public include directory!
+
+When porting this allocator to a new machine or operating system, you
+should inspect the definition of BLOCKSIZE in malloc.h to make sure
+it is greater than or equal to your target machine's virtual memory
+page size; otherwise valloc() won't work properly.  (If you don't
+care about valloc() then BLOCKSIZE doesn't matter.)
+
+You will also need to provide a machine-dependent _default_morecore()
+function; see morecore.c for a sample version that works on Unix.
+Your morecore function should return a pointer to a newly allocated
+region of the given size, aligned on the most pessimistic alignment
+boundary for the machine.  Subsequent calls to morecore should return
+contiguous memory, and calls to morecore with a negative argument
+should return memory to the system.  If no memory is available
+morecore should return NULL.
+
+Bug reports to Mike Haertel, mike@cs.uoregon.edu.
+This version is dated March 26, 1993; include this
+date with your bug report.

+ 25 - 0
libc/stdlib/malloc-930716/calloc.c

@@ -0,0 +1,25 @@
+/* calloc.c - C standard library routine.
+   Copyright (c) 1989, 1993  Michael J. Haertel
+   You may redistribute this library under the terms of the
+   GNU Library General Public License (version 2 or any later
+   version) as published by the Free Software Foundation.
+   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR
+   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */
+
+#include <string.h>
+#include "malloc.h"
+
+/* Allocate space for the given number of elements of the given
+   size, initializing the whole region to binary zeroes. */
+void *
+calloc(size_t nelem, size_t size)
+{
+    void *result;
+
+    result = malloc(size * nelem);
+    if (result)
+	memset(result, 0, nelem * size);
+    return result;
+}

+ 156 - 0
libc/stdlib/malloc-930716/free.c

@@ -0,0 +1,156 @@
+/* free.c - C standard library routine.
+   Copyright (c) 1989, 1993  Michael J. Haertel
+   You may redistribute this library under the terms of the
+   GNU Library General Public License (version 2 or any later
+   version) as published by the Free Software Foundation.
+   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR
+   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "malloc.h"
+
+/* Return memory to the heap. */
+void
+_free_internal (void *ptr)
+{
+    int block, blocks, i, type;
+    struct list *prev, *next;
+
+    if (!ptr)
+	return;
+
+    block = BLOCK(ptr);
+
+    switch (type = _heapinfo[block].busy.type) {
+    case 0:
+	/* Find the free cluster previous to this one in the free list.
+	   Start searching at the last block referenced; this may benefit
+	   programs with locality of allocation. */
+	i = _heapindex;
+	if (i > block)
+	    while (i > block)
+		i = _heapinfo[i].free.prev;
+	else {
+	    do
+		i = _heapinfo[i].free.next;
+	    while (i > 0 && i < block);
+	    i = _heapinfo[i].free.prev;
+	}
+
+	/* Determine how to link this block into the free list. */
+	if (block == i + _heapinfo[i].free.size) {
+	    /* Coalesce this block with its predecessor. */
+	    _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+	    block = i;
+	} else {
+	    /* Really link this block back into the free list. */
+	    _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+	    _heapinfo[block].free.next = _heapinfo[i].free.next;
+	    _heapinfo[block].free.prev = i;
+	    _heapinfo[i].free.next = block;
+	    _heapinfo[_heapinfo[block].free.next].free.prev = block;
+	}
+
+	/* Now that the block is linked in, see if we can coalesce it
+	   with its successor (by deleting its successor from the list
+	   and adding in its size). */
+	if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) {
+	    _heapinfo[block].free.size
+		+= _heapinfo[_heapinfo[block].free.next].free.size;
+	    _heapinfo[block].free.next
+		= _heapinfo[_heapinfo[block].free.next].free.next;
+	    _heapinfo[_heapinfo[block].free.next].free.prev = block;
+	}
+
+	/* Now see if we can return stuff to the system. */
+	blocks = _heapinfo[block].free.size;
+	if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+	    && (*__morecore)(0) == ADDRESS(block + blocks)) {
+	    _heaplimit -= blocks;
+	    (*__morecore)(-blocks * BLOCKSIZE);
+	    _heapinfo[_heapinfo[block].free.prev].free.next
+		= _heapinfo[block].free.next;
+	    _heapinfo[_heapinfo[block].free.next].free.prev
+		= _heapinfo[block].free.prev;
+	    block = _heapinfo[block].free.prev;
+	}
+
+	/* Set the next search to begin at this block. */
+	_heapindex = block;
+	break;
+
+    default:
+	/* Get the address of the first free fragment in this block. */
+	prev = (struct list *) ((char *) ADDRESS(block)
+				+ (_heapinfo[block].busy.info.frag.first
+				   << type));
+
+	if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1
+	&& _fragblocks[type] > 1) {
+	    /* If all fragments of this block are free, remove them
+	       from the fragment list and free the whole block. */
+	    --_fragblocks[type];
+	    for (next = prev, i = 1; i < BLOCKSIZE >> type; ++i)
+		next = next->next;
+	    prev->prev->next = next;
+	    if (next)
+		next->prev = prev->prev;
+	    _heapinfo[block].busy.type = 0;
+	    _heapinfo[block].busy.info.size = 1;
+	    free(ADDRESS(block));
+	} else if (_heapinfo[block].busy.info.frag.nfree) {
+	    /* If some fragments of this block are free, link this fragment
+	       into the fragment list after the first free fragment of
+	       this block. */
+	    next = ptr;
+	    next->next = prev->next;
+	    next->prev = prev;
+	    prev->next = next;
+	    if (next->next)
+		next->next->prev = next;
+	    ++_heapinfo[block].busy.info.frag.nfree;
+	} else {
+	    /* No fragments of this block are free, so link this fragment
+	       into the fragment list and announce that it is the first
+	       free fragment of this block. */
+	    prev = (struct list *) ptr;
+	    _heapinfo[block].busy.info.frag.nfree = 1;
+	    _heapinfo[block].busy.info.frag.first
+		= (unsigned int) ((char *) ptr - (char *) NULL) % BLOCKSIZE
+		  >> type;
+	    prev->next = _fraghead[type].next;
+	    prev->prev = &_fraghead[type];
+	    prev->prev->next = prev;
+	    if (prev->next)
+		prev->next->prev = prev;
+	}
+	break;
+    }
+}
+
+struct alignlist *_aligned_blocks = NULL;
+
+void
+free (void *ptr)
+{
+  register struct alignlist *l;
+  
+  if (ptr == NULL)
+    return;
+	 
+  for (l = _aligned_blocks; l != NULL; l = l->next)
+  {
+    if (l->aligned == ptr)
+    {
+      l->aligned = NULL;	/* Mark the slot in the list as free.  */
+      ptr = l->exact;
+      break;
+    }
+  }
+
+  _free_internal (ptr);
+}

+ 254 - 0
libc/stdlib/malloc-930716/malloc.c

@@ -0,0 +1,254 @@
+/* malloc.c - C standard library routine.
+   Copyright (c) 1989, 1993  Michael J. Haertel
+   You may redistribute this library under the terms of the
+   GNU Library General Public License (version 2 or any later
+   version) as published by the Free Software Foundation.
+   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR
+   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "malloc.h"
+
+/* How to really get more memory. */
+void *(*__morecore)(long) = __default_morecore_init;
+
+/* Pointer to the base of the first block. */
+char *_heapbase;
+
+/* Block information table. */
+union info *_heapinfo;
+
+/* Number of info entries. */
+static int heapsize;
+
+/* Search index in the info table. */
+int _heapindex;
+
+/* Limit of valid info table indices. */
+int _heaplimit;
+
+/* Count of large blocks allocated for each fragment size. */
+int _fragblocks[BLOCKLOG];
+
+/* Free lists for each fragment size. */
+struct list _fraghead[BLOCKLOG];
+
+/* Are we experienced? */
+static int initialized;
+
+/* Aligned allocation. */
+static void *
+align(size_t size)
+{
+    void *result;
+    unsigned int adj;
+
+    result = (*__morecore)(size);
+    adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE;
+    if (adj != 0) {
+	(*__morecore)(adj = BLOCKSIZE - adj);
+	result = (char *) result + adj;
+    }
+    return result;
+}
+
+/* Set everything up and remember that we have. */
+static int
+initialize(void)
+{
+    heapsize = HEAP / BLOCKSIZE;
+    _heapinfo = align(heapsize * sizeof (union info));
+    if (!_heapinfo)
+	return 0;
+    memset(_heapinfo, 0, heapsize * sizeof (union info));
+    _heapinfo[0].free.size = 0;
+    _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+    _heapindex = 0;
+    _heapbase = (char *) _heapinfo;
+    initialized = 1;
+    return 1;
+}
+
+/* Get neatly aligned memory, initializing or growing the
+   heap info table as necessary. */
+static void *
+morecore(size_t size)
+{
+    void *result;
+    union info *newinfo, *oldinfo;
+    int newsize;
+
+    result = align(size);
+    if (!result)
+	return NULL;
+
+    /* Check if we need to grow the info table. */
+    if (BLOCK((char *) result + size) > heapsize) {
+	newsize = heapsize;
+	while (BLOCK((char *) result + size) > newsize)
+	    newsize *= 2;
+	newinfo = align(newsize * sizeof (union info));
+	if (!newinfo) {
+	    (*__morecore)(-size);
+	    return NULL;
+	}
+	memset(newinfo, 0, newsize * sizeof (union info));
+	memcpy(newinfo, _heapinfo, heapsize * sizeof (union info));
+	oldinfo = _heapinfo;
+	newinfo[BLOCK(oldinfo)].busy.type = 0;
+	newinfo[BLOCK(oldinfo)].busy.info.size
+	    = BLOCKIFY(heapsize * sizeof (union info));
+	_heapinfo = newinfo;
+#if 0
+	free(oldinfo);
+#else
+	_free_internal (oldinfo);
+#endif
+	heapsize = newsize;
+    }
+
+    _heaplimit = BLOCK((char *) result + size);
+    return result;
+}
+
+/* Allocate memory from the heap. */
+void *
+malloc (size_t size)
+{
+    void *result;
+    int log, block, blocks, i, lastblocks, start;
+    struct list *next;
+
+    if (!initialized && !initialize())
+	return NULL;
+
+    /* Some programs will call malloc (0). We let them pass. */
+#if 0
+    if (size == 0)
+	return NULL;
+#endif
+
+    if (size < sizeof (struct list))
+	size = sizeof (struct list);
+
+    /* Determine the allocation policy based on the request size. */
+    if (size <= BLOCKSIZE / 2) {
+	/* Small allocation to receive a fragment of a block. Determine
+	   the logarithm to base two of the fragment size. */
+	--size;
+	for (log = 1; (size >>= 1) != 0; ++log)
+	    ;
+
+	/* Look in the fragment lists for a free fragment of the
+	   desired size. */
+	if ((next = _fraghead[log].next) != 0) {
+	    /* There are free fragments of this size.  Pop a fragment
+	       out of the fragment list and return it.  Update the block's
+	       nfree and first counters. */
+	    result = next;
+	    next->prev->next = next->next;
+	    if (next->next)
+		next->next->prev = next->prev;
+	    block = BLOCK(result);
+	    if (--_heapinfo[block].busy.info.frag.nfree)
+		_heapinfo[block].busy.info.frag.first
+		    = (unsigned int) ((char *) next->next - (char *) NULL)
+		      % BLOCKSIZE >> log;
+	} else {
+	    /* No free fragments of the desired size, so get a new block
+	       and break it into fragments, returning the first. */
+	    result = malloc(BLOCKSIZE);
+	    if (!result)
+		return NULL;
+	    ++_fragblocks[log];
+
+	    /* Link all fragments but the first into the free list. */
+	    next = (struct list *) ((char *) result + (1 << log));
+	    next->next = 0;
+	    next->prev = &_fraghead[log];
+	    _fraghead[log].next = next;
+
+	    for (i = 2; i < BLOCKSIZE >> log; ++i) {
+		next = (struct list *) ((char *) result + (i << log));
+		next->next = _fraghead[log].next;
+		next->prev = &_fraghead[log];
+		next->prev->next = next;
+		next->next->prev = next;
+	    }
+
+	    /* Initialize the nfree and first counters for this block. */
+	    block = BLOCK(result);
+	    _heapinfo[block].busy.type = log;
+	    _heapinfo[block].busy.info.frag.nfree = i - 1;
+	    _heapinfo[block].busy.info.frag.first = i - 1;
+	}
+    } else {
+	/* Large allocation to receive one or more blocks.  Search
+	   the free list in a circle starting at the last place visited.
+	   If we loop completely around without finding a large enough
+	   space we will have to get more memory from the system. */
+	blocks = BLOCKIFY(size);
+	start = block = _heapindex;
+	while (_heapinfo[block].free.size < blocks) {
+	    block = _heapinfo[block].free.next;
+	    if (block == start) {
+		/* Need to get more from the system.  Check to see if
+		   the new core will be contiguous with the final free
+		   block; if so we don't need to get as much. */
+		block = _heapinfo[0].free.prev;
+		lastblocks = _heapinfo[block].free.size;
+		if (_heaplimit && block + lastblocks == _heaplimit
+		    && (*__morecore)(0) == ADDRESS(block + lastblocks)
+		    && morecore((blocks - lastblocks) * BLOCKSIZE)) {
+		    /* Note that morecore() can change the location of
+		       the final block if it moves the info table and the
+		       old one gets coalesced into the final block. */
+		    block = _heapinfo[0].free.prev;
+		    _heapinfo[block].free.size += blocks - lastblocks;
+		    continue;
+		}
+		result = morecore(blocks * BLOCKSIZE);
+		if (!result)
+		    return NULL;
+		block = BLOCK(result);
+		_heapinfo[block].busy.type = 0;
+		_heapinfo[block].busy.info.size = blocks;
+		return result;
+	    }
+	}
+
+	/* At this point we have found a suitable free list entry.
+	   Figure out how to remove what we need from the list. */
+	result = ADDRESS(block);
+	if (_heapinfo[block].free.size > blocks) {
+	    /* The block we found has a bit left over, so relink the
+	       tail end back into the free list. */
+	    _heapinfo[block + blocks].free.size
+		= _heapinfo[block].free.size - blocks;
+	    _heapinfo[block + blocks].free.next
+		= _heapinfo[block].free.next;
+	    _heapinfo[block + blocks].free.prev
+		= _heapinfo[block].free.prev;
+	    _heapinfo[_heapinfo[block].free.prev].free.next
+		= _heapinfo[_heapinfo[block].free.next].free.prev
+		    = _heapindex = block + blocks;
+	} else {
+	    /* The block exactly matches our requirements, so
+	       just remove it from the list. */
+	    _heapinfo[_heapinfo[block].free.next].free.prev
+		= _heapinfo[block].free.prev;
+	    _heapinfo[_heapinfo[block].free.prev].free.next
+		= _heapindex = _heapinfo[block].free.next;
+	}
+
+	_heapinfo[block].busy.type = 0;
+	_heapinfo[block].busy.info.size = blocks;
+    }
+
+    return result;
+}

+ 107 - 0
libc/stdlib/malloc-930716/malloc.h

@@ -0,0 +1,107 @@
+/* malloc.h - declarations for the allocator.
+   Copyright (c) 1989, 1993  Michael J. Haertel
+   You may redistribute this library under the terms of the
+   GNU Library General Public License (version 2 or any later
+   version) as published by the Free Software Foundation.
+   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR
+   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */
+
+#include <sys/cdefs.h>
+
+/* Underlying allocation function; successive calls should return
+   contiguous pieces of memory. */
+extern void *(*__morecore)(long);
+
+/* Default value of previous. */
+extern void *__default_morecore_init(long);
+extern void *__default_morecore(long);
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.
+   WARNING: BLOCKSIZE must be set greater than or equal to the
+   machine's page size for valloc() to work correctly.  The default
+   definition here is 4096 bytes. */
+#define INT_BIT (CHAR_BIT * sizeof (int))
+#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit). */
+#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system. */
+#define FINAL_FREE_BLOCKS 8
+
+/* Data structure giving per-block information. */
+union info {
+    struct {
+	int type;		/* Zero for a large block, or positive
+				   giving the logarithm to the base two
+				   of the fragment size. */
+	union {
+	    struct {
+		int nfree;	/* Free fragments in a fragmented block. */
+		int first;	/* First free fragment of the block. */
+	    } frag;
+	    int size;		/* Size (in blocks) of a large cluster. */
+	} info;
+    } busy;
+    struct {
+	int size;		/* Size (in blocks) of a free cluster. */
+	int next;		/* Index of next free cluster. */
+	int prev;		/* Index of previous free cluster. */
+    } free;
+};
+
+/* Pointer to first block of the heap. */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information. */
+extern union info *_heapinfo;
+
+/* Address to block number and vice versa. */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table. */
+extern int _heapindex;
+
+/* Limit of valid info table indices. */
+extern int _heaplimit;
+
+/* Doubly linked lists of free fragments. */
+struct list {
+    struct list *next;
+    struct list *prev;
+};
+
+/* Count of blocks for each fragment size. */
+extern int _fragblocks[];
+
+/* Free list headers for each fragment size. */
+extern struct list _fraghead[];
+
+/* List of blocks allocated with `memalign' (or `valloc').  */
+struct alignlist
+{ 
+  struct alignlist *next;
+  __ptr_t aligned;	/* The address that memaligned returned.  */
+  __ptr_t exact;	/* The address that malloc returned.  */
+};
+extern struct alignlist *_aligned_blocks;
+
+extern void _free_internal __P ((__ptr_t __ptr));
+
+extern void free (void *);
+extern void * malloc (size_t);
+extern void * calloc (size_t, size_t);
+extern void * valloc (size_t);
+extern void * memalign (size_t, size_t);
+extern void * realloc (void *, size_t);

+ 61 - 0
libc/stdlib/malloc-930716/memalign.c

@@ -0,0 +1,61 @@
+/* Copyright (C) 1991, 1992 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.  */
+
+#include <stdlib.h>
+#include "malloc.h"
+
+__ptr_t
+memalign (alignment, size)
+     size_t alignment;
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  result = malloc (size + alignment - 1);
+  if (result == NULL)
+    return NULL;
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+						(char *) NULL)) % alignment;
+  if (adj != 0)
+    {
+      struct alignlist *l;
+      for (l = _aligned_blocks; l != NULL; l = l->next)
+	if (l->aligned == NULL)
+	  /* This slot is free.  Use it.  */
+	  break;
+      if (l == NULL)
+	{
+	  l = (struct alignlist *) malloc (sizeof (struct alignlist));
+	  if (l == NULL)
+	    {
+#if 1
+	      free (result);
+#else
+	      _free_internal (result);
+#endif
+	      return NULL;
+	    }
+	  l->next = _aligned_blocks;
+	  _aligned_blocks = l;
+	}
+      l->exact = result;
+      result = l->aligned = (char *) result + alignment - adj;
+    }
+
+  return result;
+}

+ 28 - 0
libc/stdlib/malloc-930716/morecore.c

@@ -0,0 +1,28 @@
+/* morecore.c - C library support routine for UNIX.
+   Copyright (c) 1989, 1993  Michael J. Haertel
+   You may redistribute this library under the terms of the
+   GNU Library General Public License (version 2 or any later
+   version) as published by the Free Software Foundation.
+   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR
+   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */
+
+#include <limits.h>
+#include <stddef.h>
+#include "malloc.h"
+
+extern void *sbrk(int);
+
+/* Note that morecore has to take a signed argument so
+   that negative values can return memory to the system. */
+void *
+__default_morecore_init(long size)
+{
+    void *result;
+
+    result = sbrk(size);
+    if (result == (void *) -1)
+	return NULL;
+    return result;
+}

+ 131 - 0
libc/stdlib/malloc-930716/realloc.c

@@ -0,0 +1,131 @@
+/* realloc.c - C standard library routine.
+   Copyright (c) 1989, 1993  Michael J. Haertel
+   You may redistribute this library under the terms of the
+   GNU Library General Public License (version 2 or any later
+   version) as published by the Free Software Foundation.
+   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR
+   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "malloc.h"
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+/* Resize the given region to the new size, returning a pointer
+   to the (possibly moved) region.  This is optimized for speed;
+   some benchmarks seem to indicate that greater compactness is
+   achieved by unconditionally allocating and copying to a
+   new region. */
+void *
+realloc (void *ptr, size_t size)
+{
+    void *result, *previous;
+    int block, blocks, type;
+    int oldlimit;
+
+    if (!ptr)
+	return malloc(size);
+    if (!size) {
+	free(ptr);
+	return malloc(0);
+    }
+
+    block = BLOCK(ptr);
+
+    switch (type = _heapinfo[block].busy.type) {
+    case 0:
+	/* Maybe reallocate a large block to a small fragment. */
+	if (size <= BLOCKSIZE / 2) {
+	    if ((result = malloc(size)) != NULL) {
+	    	memcpy(result, ptr, size);
+#if 1
+	    	free(ptr);
+#else
+	    	_free_internal(ptr);
+#endif
+
+	    }
+	    return result;
+	}
+
+	/* The new size is a large allocation as well; see if
+	   we can hold it in place. */
+	blocks = BLOCKIFY(size);
+	if (blocks < _heapinfo[block].busy.info.size) {
+	    /* The new size is smaller; return excess memory
+	       to the free list. */
+	    _heapinfo[block + blocks].busy.type = 0;
+	    _heapinfo[block + blocks].busy.info.size
+		= _heapinfo[block].busy.info.size - blocks;
+	    _heapinfo[block].busy.info.size = blocks;
+#if 1
+	    free(ADDRESS(block + blocks));
+#else
+	    _free_internal(ADDRESS(block + blocks));
+#endif
+	    return ptr;
+	} else if (blocks == _heapinfo[block].busy.info.size)
+	    /* No size change necessary. */
+	    return ptr;
+	else {
+	    /* Won't fit, so allocate a new region that will.  Free
+	       the old region first in case there is sufficient adjacent
+	       free space to grow without moving. */
+	    blocks = _heapinfo[block].busy.info.size;
+	    /* Prevent free from actually returning memory to the system. */
+	    oldlimit = _heaplimit;
+	    _heaplimit = 0;
+#if 1
+	    free(ptr);
+#else
+	    _free_internal(ptr);
+#endif
+	    _heaplimit = oldlimit;
+	    result = malloc(size);
+	    if (!result) {
+		/* Now we're really in trouble.  We have to unfree
+		   the thing we just freed.  Unfortunately it might
+		   have been coalesced with its neighbors. */
+		if (_heapindex == block)
+		    malloc(blocks * BLOCKSIZE);
+		else {
+		    previous = malloc((block - _heapindex) * BLOCKSIZE);
+		    malloc(blocks * BLOCKSIZE);
+#if 1
+		    free(previous);
+#else
+		    _free_internal(previous);
+#endif
+		}	    
+		return NULL;
+	    }
+	    if (ptr != result)
+		memmove(result, ptr, blocks * BLOCKSIZE);
+	    return result;
+	}
+	break;
+
+    default:
+	/* Old size is a fragment; type is logarithm to base two of
+	   the fragment size. */
+	if ((size > 1 << (type - 1)) && (size <= 1 << type))
+	    /* New size is the same kind of fragment. */
+	    return ptr;
+	else {
+	    /* New size is different; allocate a new space, and copy
+	       the lesser of the new size and the old. */
+	    result = malloc(size);
+	    if (!result)
+		return NULL;
+	    memcpy(result, ptr, MIN(size, 1 << type));
+	    free(ptr);
+	    return result;
+	}
+	break;
+    }
+}

+ 62 - 0
libc/stdlib/malloc-930716/valloc.c

@@ -0,0 +1,62 @@
+/* Allocate memory on a page boundary.
+   Copyright (C) 1991, 1992 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.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#include <stdlib.h>
+#include "malloc.h"
+
+#ifdef	 emacs
+#include "config.h"
+#endif
+
+#ifdef	__GNU_LIBRARY__
+extern size_t __getpagesize __P ((void));
+#else
+#ifndef	USG
+extern size_t getpagesize __P ((void));
+#define	__getpagesize()	getpagesize()
+#else
+#include <sys/param.h>
+#ifdef	EXEC_PAGESIZE
+#define	__getpagesize()	EXEC_PAGESIZE
+#else /* No EXEC_PAGESIZE.  */
+#ifdef	NBPG
+#ifndef	CLSIZE
+#define	CLSIZE	1
+#endif /* No CLSIZE.  */
+#define	__getpagesize()	(NBPG * CLSIZE)
+#else /* No NBPG.  */
+#define	__getpagesize()	NBPC
+#endif /* NBPG.  */
+#endif /* EXEC_PAGESIZE.  */
+#endif /* USG.  */
+#endif
+
+static size_t pagesize;
+
+__ptr_t
+valloc (size)
+     size_t size;
+{
+  if (pagesize == 0)
+    pagesize = __getpagesize ();
+
+  return memalign (pagesize, size);
+}

+ 2 - 2
libc/stdlib/malloc-simple/Makefile

@@ -40,8 +40,8 @@ $(MOBJ): $(MSRC)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 2 - 2
libc/stdlib/malloc/Makefile

@@ -42,8 +42,8 @@ $(MOBJ): $(MSRC)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 72 - 148
libc/stdlib/qsort.c

@@ -1,148 +1,72 @@
-/*
- * 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 <string.h>
-
-char *_qbuf = 0;				/* pointer to storage for qsort() */
-
-#define	PIVOT			((i+j)>>1)
-#define moveitem(dst,src,size)	if(dst != src) memcpy(dst, src, size)
-
-static void _wqsort(base, lo, hi, cmp)
-register int *base;
-register int lo;
-register int hi;
-register int (*cmp) ();
-{
-	int k;
-	register int i, j, t;
-	register int *p = &k;
-
-	while (hi > lo) {
-		i = lo;
-		j = hi;
-		t = PIVOT;
-		*p = base[t];
-		base[t] = base[i];
-		base[i] = *p;
-		while (i < j) {
-			while (((*cmp) ((base + j), p)) > 0)
-				--j;
-			base[i] = base[j];
-			while ((i < j) && (((*cmp) ((base + i), p)) <= 0))
-				++i;
-			base[j] = base[i];
-		}
-		base[i] = *p;
-		if ((i - lo) < (hi - i)) {
-			_wqsort(base, lo, (i - 1), cmp);
-			lo = i + 1;
-		} else {
-			_wqsort(base, (i + 1), hi, cmp);
-			hi = i - 1;
-		}
-	}
-}
-
-static void _lqsort(base, lo, hi, cmp)
-register long *base;
-register int lo;
-register int hi;
-register int (*cmp) ();
-{
-	long k;
-	register int i, j, t;
-	register long *p = &k;
-
-	while (hi > lo) {
-		i = lo;
-		j = hi;
-		t = PIVOT;
-		*p = base[t];
-		base[t] = base[i];
-		base[i] = *p;
-		while (i < j) {
-			while (((*cmp) ((base + j), p)) > 0)
-				--j;
-			base[i] = base[j];
-			while ((i < j) && (((*cmp) ((base + i), p)) <= 0))
-				++i;
-			base[j] = base[i];
-		}
-		base[i] = *p;
-		if ((i - lo) < (hi - i)) {
-			_lqsort(base, lo, (i - 1), cmp);
-			lo = i + 1;
-		} else {
-			_lqsort(base, (i + 1), hi, cmp);
-			hi = i - 1;
-		}
-	}
-}
-
-static void _nqsort(base, lo, hi, size, cmp)
-register char *base;
-register int lo;
-register int hi;
-register int size;
-register int (*cmp) ();
-{
-	register int i, j;
-	register char *p = _qbuf;
-
-	while (hi > lo) {
-		i = lo;
-		j = hi;
-		p = (base + size * PIVOT);
-		moveitem(_qbuf, p, size);
-		moveitem(p, (base + size * i), size);
-		moveitem((base + size * i), _qbuf, size);
-		p = _qbuf;
-		while (i < j) {
-			while (((*cmp) ((base + size * j), p)) > 0)
-				--j;
-			moveitem((base + size * i), (base + size * j), size);
-			while ((i < j) && (((*cmp) ((base + size * i), p)) <= 0))
-				++i;
-			moveitem((base + size * j), (base + size * i), size);
-		}
-		moveitem((base + size * i), p, size);
-		if ((i - lo) < (hi - i)) {
-			_nqsort(base, lo, (i - 1), size, cmp);
-			lo = i + 1;
-		} else {
-			_nqsort(base, (i + 1), hi, size, cmp);
-			hi = i - 1;
-		}
-	}
-}
-
-extern int qsort(base, num, size, cmp)
-char *base;
-int num;
-int size;
-int (*cmp) ();
-{
-	char _qtemp[128];
-
-	if (_qbuf == 0) {
-		if (size > sizeof(_qtemp))	/* records too large! */
-			return 1;
-		_qbuf = _qtemp;
-	}
-	if (size == 2)
-		_wqsort(base, 0, num - 1, cmp);
-	else if (size == 4)
-		_lqsort(base, 0, num - 1, cmp);
-	else
-		_nqsort(base, 0, num - 1, size, cmp);
-	if (_qbuf == _qtemp)
-		_qbuf = 0;
-	return 0;
-}
+/* +++Date last modified: 05-Jul-1997 */
+
+/*
+**  ssort()  --  Fast, small, qsort()-compatible Shell sort
+**
+**  by Ray Gardner,  public domain   5/90
+*/
+
+/*
+ * Manuel Novoa III       Dec 2000
+ *
+ * There were several problems with the qsort code contained in uClibc.
+ * It assumed sizeof(int) was 2 and sizeof(long) was 4.  It then had three
+ * seperate quiicksort routines based on the width of the data passed: 2, 4,
+ * or anything else <= 128.  If the width was > 128, it returned -1 (although
+ * qsort should not return a value) and did no sorting.  On i386 with
+ * -Os -fomit-frame-pointer -ffunction-sections, the text segment of qsort.o
+ * was 1358 bytes, with an additional 4 bytes in bss.
+ *
+ * I decided to completely replace the existing code with a small
+ * implementation of a shell sort.  It is a drop-in replacement for the
+ * standard qsort and, with the same gcc flags as above, the text segment
+ * size on i386 is only 183 bytes.
+ *
+ * Grabbed original file rg_ssort.c from snippets.org.
+ * Modified original code to avoid possible overflow in wgap calculation.
+ * Modified wgap calculation in loop and eliminated variables gap and wnel.
+ */
+
+
+#include <stdlib.h>
+
+void qsort (void  *base,
+            size_t nel,
+            size_t width,
+            int (*comp)(const void *, const void *))
+{
+	size_t wgap, i, j, k;
+	char *a, *b, tmp;
+
+#if 0
+	/* Note: still conceivable that nel * width could overflow! */
+	assert(width > 0);
+#endif
+
+	if (nel > 1) {
+		for (wgap = 0; ++wgap < (nel-1)/3 ; wgap *= 3) {}
+		wgap *= width;
+		nel *= width;			/* convert nel to 'wnel' */
+		do {
+			for (i = wgap; i < nel; i += width) {
+				for (j = i - wgap; ;j -= wgap) {
+					a = j + ((char *)base);
+					b = a + wgap;
+					if ( (*comp)(a, b) <= 0 ) {
+						break;
+					}
+					k = width;
+					do {
+						tmp = *a;
+						*a++ = *b;
+						*b++ = tmp;
+					} while ( --k );
+					if (j < wgap) {
+						break;
+					}
+				}
+			}
+			wgap = (wgap - width)/3;
+		} while (wgap);
+	}
+}

+ 2 - 0
libc/stdlib/system.c

@@ -35,7 +35,9 @@ char *command;
 	signal(SIGQUIT, SIG_IGN);
 	signal(SIGINT, SIG_IGN);
 
+#if 0
 	printf("Waiting for child %d\n", pid);
+#endif
 
 	if (wait4(pid, &wait_val, 0, 0) == -1)
 		wait_val = -1;

+ 2 - 2
libc/string/Makefile

@@ -53,8 +53,8 @@ $(MOBJ1): $(MSRC1)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 35 - 8
libc/string/strerror.c

@@ -23,13 +23,19 @@ Cambridge, MA 02139, USA.  */
  * are smaller than the previous functions and don't require static buffers.
  * Removed dependence on strcat in the process.
  *
- * Also appended a test routine ( -DSTRERROR_TEST ) to allow a quick check
+ * Also appended a test routine ( -DCHECK_BUF ) to allow a quick check
  * on the buffer length when the sys_errorlist is modified.
+ *
+ * Added the option WANT_ERRORLIST for low-memory applications to omit the
+ * error message strings and only output the error number.
  */
 
+#define WANT_ERRORLIST     1
+
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
+
 #include <limits.h>
 
 #if (INT_MAX >> 31)
@@ -39,7 +45,11 @@ Cambridge, MA 02139, USA.  */
 
 extern char *__ltostr(char *buf, long uval, int base, int uppercase);
 
+#if WANT_ERRORLIST
+static char retbuf[48];
+#else
 static char retbuf[33];			/* 33 is sufficient for 32 bit ints */
+#endif
 static const char unknown_error[] = "Unknown Error: errno"; /* = */
 
 /* Return a string descibing the errno code in ERRNUM.
@@ -49,10 +59,12 @@ char *strerror(int err)
 {
 	char *pos;
 
+#if WANT_ERRORLIST
 	if ((err >= 0) && (err < sys_nerr)) {
 		strcpy(retbuf, sys_errlist[err]);
 		return retbuf;
 	}
+#endif
 
 	/* unknown error */
 	pos = __ltostr(retbuf + sizeof(retbuf) + 1, err, 10, 0)
@@ -62,24 +74,39 @@ char *strerror(int err)
 	return pos;
 }
 
-#if STRERROR_TEST
-/* quick way to check for sufficient buffer length */
+#ifdef CHECK_BUF
+/* quick way to check buffer length */
 #include <stdio.h>
 #include <stdlib.h>
 int main(void)
 {
 	int max = 0;
-	int i, j;
+	int j, retcode;
 	char *p;
+#if WANT_ERRORLIST
+	int i;
+#endif
+
+	retcode = EXIT_SUCCESS;
+
+#if WANT_ERRORLIST
 	for ( i=0 ; i < sys_nerr ; i++ ) {
 		j = strlen(sys_errlist[i])+1;
 		if (j > max) max = j;
 	}
-	printf("max len = %i\n", j);
+#endif
 
 	p = strerror(INT_MIN);
-	printf("<%s>  %d\n", p, strlen(p)+1);
-	printf("current buffer length is %d\n", sizeof(retbuf));
-	return EXIT_SUCCESS;
+	j = strlen(p)+1;
+	if (j > max) max = j;
+	printf("strerror.c - Test of INT_MIN: <%s>  %d\n", p, j);
+
+	if (sizeof(retbuf) != max) {
+		printf("Error: strerror.c - dimension of retbuf should be = %d\n", max);
+		retcode = EXIT_FAILURE;
+	}
+	printf("strerror.c - dimension of retbuf correct at %d\n", max);
+
+	return retcode;
 }
 #endif

+ 50 - 23
libc/string/strsignal.c

@@ -14,16 +14,31 @@
  * Also fixed a bug in the signal name lookup code.  While the table is
  * declared with dimension > 60, there are currently on 32 signals listed.
  *
- * Also appended a test routine ( -DSTRSIGNAL_TEST ) to allow a quick check
- * on the buffer length when the sys_errorlist is modified.
+ * Also appended a test routine ( -DCHECK_BUF ) to allow a quick check
+ * on the buffer length and the number of known signals when the sys_errorlist
+ * is modified.
+ *
+ * Added the option WANT_SIGLIST for low-memory applications to omit the
+ * signal message strings and only output the signal number.
  */
 
+#define WANT_SIGLIST       1
+
 #include <string.h>
 #include <malloc.h>
 #include <signal.h>
 
+#include <limits.h>
+
+#if (INT_MAX >> 31)
+/* We're set up for 32 bit ints */
+#error need to check size allocation for static buffer 'retbuf'
+#endif
+
 extern char *__ltostr(char *buf, long uval, int base, int uppercase);
 
+#if WANT_SIGLIST
+
 const char *const sys_siglist[] = {
 	"Unknown signal",
 	"Hangup",
@@ -60,26 +75,27 @@ const char *const sys_siglist[] = {
 	NULL
 };
 
-#include <limits.h>
-
-#if (INT_MAX >> 31)
-/* We're set up for 32 bit ints */
-#error need to check size allocation for static buffer 'retbuf'
 #endif
 
+#define NUM_KNOWN_SIGNALS    32
+
 /********************** Function strsignal ************************************/
 
+static char retbuf[28];			/* 28 is sufficient for 32 bit ints */
+static const char unknown_signal[] = "Unknown Signal:";
+
 char *strsignal(int sig)
 {
-	static char retbuf[28];		/* 28 is sufficient for 32 bit ints */
-	static const char unknown_signal[] = "Unknown Signal:";
 	char *pos;
 
+#ifdef WANT_SIGLIST
 	/* if ((sig >= 0) && (sig < _NSIG)) { */
-	if ((sig >= 0) && (sig < 32)) { /* WARNING!!! NOT ALL _NSIG DEFINED!!! */
+	/* WARNING!!! NOT ALL _NSIG DEFINED!!! */
+	if ((sig >= 0) && (sig < NUM_KNOWN_SIGNALS)) {
 		strcpy(retbuf, sys_siglist[sig]);
 		return retbuf;
 	}
+#endif
 
 	pos = __ltostr(retbuf + sizeof(unknown_signal) + 1, sig, 10, 0)
 		- sizeof(unknown_signal);
@@ -90,33 +106,44 @@ char *strsignal(int sig)
 
 /********************** THE END ********************************************/
 
-#if STRSIGNAL_TEST
+#ifdef CHECK_BUF
 /* quick way to check for sufficient buffer length */
 #include <stdio.h>
 #include <stdlib.h>
 int main(void)
 {
 	int max = 0;
-	int i, j;
+	int j, retcode;
+
 	const char *p;
+#if WANT_SIGLIST
+	int i;
+#endif
+	retcode = EXIT_SUCCESS;
 
+#if WANT_SIGLIST
 	printf("_NSIG = %d  from headers\n", _NSIG);
-	for ( i=0 ; i < _NSIG ; i++ ) {
-		p = sys_siglist[i];
-		if (!p) {
-			printf("Warning! I only count %d signals!\n", i);
-			break;
-		}
+	for ( i=0 ; sys_siglist[i] ; i++ ) {
 		j = strlen(sys_siglist[i])+1;
 		if (j > max) max = j;
 	}
-	printf("max len = %i\n", j);
+	if (i != NUM_KNOWN_SIGNALS) {
+		printf("Error: strsignal.c - NUM_KNOWN_SIGNALS should be %d\n", i);
+		retcode = EXIT_FAILURE;
+	}
+#endif
 
 	p = strsignal(INT_MIN);
-	printf("<%s>  %d\n", p, strlen(p)+1);
+	j = strlen(p)+1;
+	if (j > max) max = j;
+	printf("strsignal.c - Test of INT_MIN: <%s>  %d\n", p, j);
+
+	if (sizeof(retbuf) != max) {
+		printf("Error: strsignal.c - dimension of retbuf should be = %d\n", max);
+		retcode = EXIT_FAILURE;
+	}
+	printf("strsignal.c - dimension of retbuf correct at %d\n", max);
 
-	p = strsignal(i-1);
-	printf("last signal %d is %s\n", i-1, p);
-	return EXIT_SUCCESS;
+	return retcode;
 }
 #endif

+ 4 - 4
libc/sysdeps/linux/arm/Makefile

@@ -41,12 +41,12 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(SOBJS):
-	$(CC) $(CFLAGS) $< -c $*.S -o $*.o
+$(SOBJS): %.o : %.S
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 21 - 5
libc/sysdeps/linux/common/Makefile

@@ -25,7 +25,6 @@ TOPDIR=../../../
 include $(TOPDIR)Rules.mak
 LIBC=$(TOPDIR)libc.a
 
-
 CSRC =closedir.c dirfd.c getdents.c getdnnm.c gethstnm.c getpagesize.c \
 	isatty.c kernel_version.c mkfifo.c opendir.c readdir.c rewinddir.c \
 	seekdir.c setegid.c seteuid.c setpgrp.c statfix.c tell.c telldir.c \
@@ -40,7 +39,16 @@ MOBJ=$(shell ./list_syscalls.sh)
 
 OBJ=$(COBJS) $(NIOBJS) $(MOBJ)
 
-all: $(OBJ) $(LIBC)
+UNIFIED_SYSCALL_HEADER = /dev/null
+STR_SYSCALLS =
+ifeq ($(UNIFIED_SYSCALL),true)
+	ifeq ($(TARGET_ARCH), i386)
+		UNIFIED_SYSCALL_HEADER = unified_syscall_i386.h
+		STR_SYSCALLS = str_syscalls
+	endif
+endif
+
+all: $(STR_SYSCALLS) unified_syscall.h $(OBJ) $(LIBC)
 
 $(LIBC): ar-target
 
@@ -51,14 +59,22 @@ $(MOBJ): $(MSRC)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(NIOBJS):
 	$(CC) $(CFLAGS) $< -c $*.c -o $*.o -fno-inline
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
+str_syscalls:
+	./str_syscalls.sh > str_syscalls.c
+	gcc str_syscalls.c -o str_syscalls
+	./str_syscalls > str_syscalls.h
+
+unified_syscall.h:
+	cat $(UNIFIED_SYSCALL_HEADER) > unified_syscall.h
+
 clean:
-	rm -f *.[oa] *~ core
+	rm -f *.[oa] *~ core unified_syscall.h str_syscalls.[ch] str_syscalls
 

+ 35 - 0
libc/sysdeps/linux/common/str_syscalls.sh

@@ -0,0 +1,35 @@
+#!/bin/sh
+
+echo "#include <stdio.h>"
+echo "#include <stdlib.h>"
+echo "#include \"../include/asm/unistd.h\""
+echo
+echo "int main(void) {"
+echo
+echo "#define __NR__exit __NR_exit"
+echo "#define __NR___open __NR_open"
+echo "#define __NR__ioctl __NR_ioctl"
+echo "#define __NR__fcntl __NR_fcntl"
+echo "#define __NR__reboot __NR_reboot"
+echo "#define __NR__mmap __NR_mmap"
+echo "#define __NR__syslog __NR_syslog"
+echo "#define __NR__stat __NR_stat"
+echo "#define __NR__lstat __NR_lstat"
+echo "#define __NR__fstat __NR_fstat"
+echo "#define __NR__getdents __NR_getdents"
+echo
+sed -ne 's/^.*_syscall[0-9].*([^,]*, *\([^,)]*\).*/printf("#define __STR_NR_\1 \\\"%d\\\"\\n", __NR_\1);/gp' syscalls.c
+echo
+echo "printf(\"#define __STR_NR_exit     __STR_NR__exit\n\");"
+echo "printf(\"#define __STR_NR_open    __STR_NR___open\n\");"
+echo "printf(\"#define __STR_NR_ioctl    __STR_NR__ioctl\n\");"
+echo "printf(\"#define __STR_NR_fcntl    __STR_NR__fcntl\n\");"
+echo "printf(\"#define __STR_NR_reboot   __STR_NR__reboot\n\");"
+echo "printf(\"#define __STR_NR_mmap     __STR_NR__mmap\n\");"
+echo "printf(\"#define __STR_NR_syslog   __STR_NR__syslog\n\");"
+echo "printf(\"#define __STR_NR_stat     __STR_NR__stat\n\");"
+echo "printf(\"#define __STR_NR_lstat    __STR_NR__lstat\n\");"
+echo "printf(\"#define __STR_NR_fstat    __STR_NR__fstat\n\");"
+echo "printf(\"#define __STR_NR_getdents __STR_NR__getdents\n\");"
+echo
+echo "return EXIT_SUCCESS; }"

+ 31 - 1
libc/sysdeps/linux/common/syscalls.c

@@ -26,13 +26,18 @@
 #include <sys/types.h>
 #include <sys/syscall.h>
 
+#define uClibc_syscall_exit(void, _exit, int, status) \
+_syscall1(void, _exit, int, status)
+
+
+#include "unified_syscall.h"
 
 //#define __NR_exit             1
 #ifdef L__exit
 /* Do not include unistd.h, so gcc doesn't whine about 
  * _exit returning.  It really doesn't return... */
 #define __NR__exit __NR_exit
-_syscall1(void, _exit, int, status);
+uClibc_syscall_exit(void, _exit, int, status);
 #endif
 
 //#define __NR_fork             2
@@ -347,6 +352,9 @@ _syscall2(int, umount2, const char *, special_file, int, flags);
 #include <stdarg.h>
 #include <sys/ioctl.h>
 #define __NR__ioctl __NR_ioctl
+
+extern int _ioctl(int fd, int request, void *arg);
+
 _syscall3(int, _ioctl, int, fd, int, request, void *, arg);
 
 int ioctl(int fd, unsigned long int request, ...)
@@ -368,6 +376,9 @@ int ioctl(int fd, unsigned long int request, ...)
 #include <stdarg.h>
 #include <fcntl.h>
 #define __NR__fcntl __NR_fcntl
+
+extern int _fcntl(int fd, int cmd, long arg);
+
 _syscall3(int, _fcntl, int, fd, int, cmd, long, arg);
 
 int fcntl(int fd, int command, ...)
@@ -558,6 +569,9 @@ _syscall2(int, swapon, const char *, path, int, swapflags);
 //#define __NR_reboot           88
 #ifdef L__reboot
 #define __NR__reboot __NR_reboot
+
+extern int _reboot(int magic, int magic2, int flag);
+
 _syscall3(int, _reboot, int, magic, int, magic2, int, flag);
 
 int reboot(int flag)
@@ -574,6 +588,8 @@ int reboot(int flag)
 #include <unistd.h>
 #include <sys/mman.h>
 
+extern __ptr_t _mmap(unsigned long *buffer);
+
 _syscall1(__ptr_t, _mmap, unsigned long *, buffer);
 
 __ptr_t mmap(__ptr_t addr, size_t len, int prot,
@@ -667,6 +683,9 @@ _syscall2(int, socketcall, int, call, unsigned long *, args);
 #ifdef L__syslog
 #include <unistd.h>
 #define __NR__syslog		__NR_syslog
+
+extern int _syslog(int type, char *buf, int len);
+
 _syscall3(int, _syslog, int, type, char *, buf, int, len);
 
 int klogctl(int type, char *buf, int len)
@@ -694,6 +713,8 @@ _syscall2(int, getitimer, enum __itimer_which, which, struct itimerval *, value)
 #define __NR__stat __NR_stat
 #include <unistd.h>
 #include "statfix.h"
+extern int _stat(const char *file_name, struct kernel_stat *buf);
+
 _syscall2(int, _stat, const char *, file_name, struct kernel_stat *, buf);
 
 int stat(const char * file_name, struct libc_stat * cstat)
@@ -713,6 +734,8 @@ int stat(const char * file_name, struct libc_stat * cstat)
 #define __NR__lstat __NR_lstat
 #include <unistd.h>
 #include "statfix.h"
+extern int _lstat(const char *file_name, struct kernel_stat *buf);
+
 _syscall2(int, _lstat, const char *, file_name, struct kernel_stat *, buf);
 
 int lstat(const char * file_name, struct libc_stat * cstat)
@@ -732,6 +755,8 @@ int lstat(const char * file_name, struct libc_stat * cstat)
 #define __NR__fstat __NR_fstat
 #include <unistd.h>
 #include "statfix.h"
+extern int _fstat(int filedes, struct kernel_stat *buf);
+
 _syscall2(int, _fstat, int, filedes, struct kernel_stat *, buf);
 
 int fstat(int fd, struct libc_stat *cstat) 
@@ -878,6 +903,8 @@ SYSCALL__(setfsuid, 1)
 #endif
 //#define __NR__llseek          140
 #ifdef L__llseek
+extern int _llseek(int fd, off_t hoff, off_t loff, loff_t *res, int whence);
+
 _syscall5(int, _llseek, int, fd, off_t, hoff, off_t, loff, loff_t *, res,
 		  int, whence);
 
@@ -904,6 +931,9 @@ _syscall3(int, _getdents, int, fd, char *, dirp, size_t, count);
 //#define __NR__newselect       142
 #ifdef L__newselect
 #include <unistd.h>
+extern int _newselect(int n, fd_set *readfds, fd_set *writefds,
+					  fd_set *exceptfds, struct timeval *timeout);
+
 _syscall5(int, _newselect, int, n, fd_set *, readfds, fd_set *, writefds,
 		  fd_set *, exceptfds, struct timeval *, timeout);
 

+ 41 - 0
libc/sysdeps/linux/common/unified_syscall_i386.h

@@ -0,0 +1,41 @@
+#undef _syscall0
+#undef _syscall1
+#undef _syscall2
+#undef _syscall3
+#undef _syscall4
+#undef _syscall5
+
+#include "str_syscalls.h"
+
+#undef uClibc_syscall_exit
+#define uClibc_syscall_exit(type,name,type1,arg1) \
+__asm__ ( \
+".text\n.align 4\n.global "###name"\n"#name":;\npushl %ebp;\n" \
+"movl %esp,%ebp;\nsubl $4,%esp;\npushl %ebx;\nmovl 8(%ebp),%ebx;\n" \
+"jmp _start_exit" \
+)
+
+#define unified_syscall_body(name) \
+__asm__ ( \
+".text\n.align 4\n.global "###name"\n"#name":\nmovb $"__STR_NR_##name \
+",%al;\n jmp __uClibc_syscall" \
+)
+
+#define _syscall0(type,name) \
+unified_syscall_body(name)
+
+#define _syscall1(type,name,type1,arg1) \
+unified_syscall_body(name)
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+unified_syscall_body(name)
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+unified_syscall_body(name)
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+unified_syscall_body(name)
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+unified_syscall_body(name)
+

+ 8 - 5
libc/sysdeps/linux/i386/Makefile

@@ -26,9 +26,12 @@ LIBC=$(TOPDIR)libc.a
 ASFLAGS=$(CFLAGS)
 
 SSRC=_start.S longjmp.S setjmp.S #_start.S #clone.S
+ifeq ($(UNIFIED_SYSCALL),true)
+	SSRC += __uClibc_syscall.S
+endif
 SOBJS=$(patsubst %.S,%.o, $(SSRC))
 
-CSRC=fork.c vfork.c
+CSRC=fork.c vfork.c __init_brk.c brk.c sbrk.c
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 
 OBJS=$(SOBJS) $(COBJS)
@@ -41,12 +44,12 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(SOBJS): 
-	$(CC) $(CFLAGS) $< -c $*.S -o $*.o
+$(SOBJS): %.o : %.S
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 33 - 0
libc/sysdeps/linux/i386/__init_brk.c

@@ -0,0 +1,33 @@
+/* From libc-5.3.12 */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+void * ___brk_addr = 0;
+
+int
+__init_brk ()
+{
+    if (___brk_addr == 0)
+    {
+#if defined(__PIC__) || defined (__pic__)
+	__asm__ volatile ("pushl %%ebx\n\t"
+			  "movl $0,%%ebx\n\t"
+			  "int $0x80\n\t"
+			  "popl %%ebx"
+		:"=a" (___brk_addr)
+		:"0" (SYS_brk));
+#else
+	__asm__ volatile ("int $0x80"
+		:"=a" (___brk_addr)
+		:"0" (SYS_brk),"b" (0));
+#endif
+	if (___brk_addr == 0)
+	{
+	  errno = ENOMEM;
+	  return -1;
+	}
+    }
+    return 0;
+}

+ 39 - 0
libc/sysdeps/linux/i386/__uClibc_syscall.S

@@ -0,0 +1,39 @@
+.globl __uClibc_syscall
+
+.text
+	.align 4
+__uClibc_syscall:
+	pushl %ebp
+	movl %esp,%ebp
+	subl $8,%esp
+	pushl %edi
+	pushl %esi
+	pushl %ebx
+	/* movl $21,%eax */
+	and $0xff,%eax
+	movl 8(%ebp),%ebx
+	movl 12(%ebp),%ecx
+	movl 16(%ebp),%edx
+	movl 20(%ebp),%esi
+	movl 24(%ebp),%edi
+#APP
+	int $0x80
+#NO_APP
+	movl %eax,-4(%ebp)
+	.p2align 4,,7
+	cmpl $-126,-4(%ebp)
+	jbe .L5
+	movl -4(%ebp),%eax
+	negl %eax
+	movl %eax,errno
+	movl $-1,-4(%ebp)
+.L5:
+	movl -4(%ebp),%edx
+	movl %edx,-8(%ebp)
+	movl -8(%ebp),%eax
+	leal -20(%ebp),%esp
+	popl %ebx
+	popl %esi
+	popl %edi
+	leave
+	ret

+ 32 - 0
libc/sysdeps/linux/i386/brk.c

@@ -0,0 +1,32 @@
+/* From libc-5.3.12 */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+extern void * ___brk_addr;
+
+extern int __init_brk ();
+
+int brk(void * end_data_seg)
+{
+    if (__init_brk () == 0)
+    {
+#if defined(__PIC__) || defined (__pic__)
+	__asm__ volatile ("pushl %%ebx\n\t"
+			  "movl %%ecx,%%ebx\n\t"
+			  "int $0x80\n\t"
+			  "popl %%ebx"
+		:"=a" (___brk_addr)
+		:"0" (SYS_brk),"c" (end_data_seg));
+#else
+	__asm__ volatile ("int $0x80"
+		:"=a" (___brk_addr)
+		:"0" (SYS_brk),"b" (end_data_seg));
+#endif
+	if (___brk_addr == end_data_seg)
+		return 0;
+	errno = ENOMEM;
+    }
+    return -1;
+}

+ 35 - 0
libc/sysdeps/linux/i386/sbrk.c

@@ -0,0 +1,35 @@
+/* From libc-5.3.12 */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+extern void * ___brk_addr;
+
+extern int __init_brk (void);
+
+void *
+sbrk(ptrdiff_t increment)
+{
+    if (__init_brk () == 0)
+    {
+	void * tmp = ___brk_addr+increment;
+#if defined(__PIC__) || defined (__pic__)
+	__asm__ volatile ("pushl %%ebx\n\t"
+			  "movl %%ecx,%%ebx\n\t"
+                          "int $0x80\n\t"
+                          "popl %%ebx"
+		:"=a" (___brk_addr)
+		:"0" (SYS_brk),"c" (tmp));
+#else
+	__asm__ volatile ("int $0x80"
+		:"=a" (___brk_addr)
+		:"0" (SYS_brk),"b" (tmp));
+#endif
+	if (___brk_addr == tmp)
+		return tmp-increment;
+	errno = ENOMEM;
+	return ((void *) -1);
+    }
+    return ((void *) -1);
+}

+ 2 - 2
libc/termios/Makefile

@@ -45,8 +45,8 @@ $(MOBJ): $(MSRC)
 	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:

+ 12 - 3
libc/unistd/Makefile

@@ -28,8 +28,13 @@ LIBC=$(TOPDIR)libc.a
 CSRC=execl.c execlp.c execv.c execvep.c execvp.c getcwd.c getopt.c \
 	sleep.c sysconf.c getpass.c
 COBJS=$(patsubst %.c,%.o, $(CSRC))
-OBJS=$(COBJS)
 
+MSRC=gnu_getopt.c
+MOBJ=_gnu_getopt_internal.o gnu_getopt_long.o gnu_getopt_long_only.o
+
+# WARNING! MOBJ _must_ come after COBJS for link to pick getopt 
+# over gnu_getopt when appropriate.
+OBJS=$(COBJS) $(MOBJ)
 
 all: $(OBJS) $(LIBC)
 
@@ -38,8 +43,12 @@ $(LIBC): ar-target subdirs
 ar-target: $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(MOBJ): $(MSRC)
+	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(OBJ): Makefile

+ 12 - 4
libc/unistd/getopt.c

@@ -13,13 +13,18 @@
  * and ommision of whitespace between option and arg.
  */
 
+/*
+ * Modified by Manuel Novoa III on 1/5/01 to use weak symbols.
+ * Programs needing long options will link gnu_getopt instead.
+ */
+
 #include <stdio.h>
 #include <string.h>
 
-int opterr = 1;					/* error => print message */
-int optind = 1;					/* next argv[] index */
-int optopt = 1;					/* Set for unknown arguments */
-char *optarg = NULL;			/* option parameter if any */
+int opterr __attribute__ ((__weak__)) = 1; /* error => print message */
+int optind __attribute__ ((__weak__)) = 1; /* next argv[] index */
+int optopt __attribute__ ((__weak__)) = 1; /* Set for unknown arguments */
+char *optarg __attribute__ ((__weak__)) = NULL;	/* option parameter if any */
 
 static int Err(name, mess, c) /* returns '?' */
 char *name;						/* program name argv[0] */
@@ -34,6 +39,9 @@ int c;							/* defective option letter */
 	return '?';					/* erroneous-option marker */
 }
 
+extern int getopt (int argc, char *const *argv, const char *optstring)
+	 __attribute__ ((__weak__));
+
 int getopt (int argc, char *const *argv, const char *optstring)
 {
 	static int sp = 1;			/* position within argument */

+ 2 - 1
libc/unistd/getpass.c

@@ -17,6 +17,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <stdio.h>
+#include <string.h>
 #include <termios.h>
 #include <unistd.h>
 #include <string.h>
@@ -72,9 +73,9 @@ getpass (prompt)
 
   /* Read the password.  */
   fgets (buf, PWD_BUFFER_SIZE-1, in);
-  nread = strlen(buf);
   if (buf != NULL)
     {
+      nread = strlen(buf);
       if (nread < 0)
 	buf[0] = '\0';
       else if (buf[nread - 1] == '\n')

+ 873 - 0
libc/unistd/gnu_getopt.c

@@ -0,0 +1,873 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+   	Free Software Foundation, 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, 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Modified for uClibc by Manuel Novoa III on 1/5/01.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include <getopt.h>
+
+extern int _getopt_internal (int argc, char *const *argv, 
+							 const char *optstring,
+							 const struct option *longopts,
+							 int *longind, int long_only);
+
+
+#ifdef L__gnu_getopt_internal
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#include <string.h>
+#define	my_index	strchr
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (optstring)
+     const char *optstring;
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind = 1;
+
+  nextchar = NULL;
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (getenv ("POSIXLY_CORRECT") != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+  return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+#if NLS
+#include "nl_types.h"
+#endif
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  optarg = NULL;
+
+#if NLS
+  libc_nls_init();
+#endif
+
+  if (optind == 0)
+    optstring = _getopt_initialize (optstring);
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc
+		 && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return EOF;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return EOF;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+	  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, nextchar, nameend - nextchar))
+	  {
+	    if (nameend - nextchar == strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (opterr)
+#if NLS
+	    fprintf (stderr,
+		     catgets(_libc_cat, GetoptSet, GetoptAmbiguous,
+			     "%s: option `%s' is ambiguous\n"),
+		     argv[0], argv[optind]);
+#else
+	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
+		     argv[0], argv[optind]);
+#endif
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = nameend + 1;
+	      else
+		{
+		  if (opterr)
+		    {
+		      if (argv[optind - 1][1] == '-')
+			/* --option */
+#if NLS
+			fprintf (stderr,
+				 catgets(_libc_cat, GetoptSet, GetoptNoArgumentsAllowed1,
+				 "%s: option `--%s' doesn't allow an argument\n"),
+				 argv[0], pfound->name);
+#else
+			fprintf (stderr,
+				 "%s: option `--%s' doesn't allow an argument\n",
+				 argv[0], pfound->name);
+#endif
+		      else
+			/* +option or -option */
+#if NLS
+			fprintf (stderr,
+			     catgets(_libc_cat, GetoptSet, GetoptNoArgumentsAllowed2,
+			     "%s: option `%c%s' doesn't allow an argument\n"),
+			     argv[0], argv[optind - 1][0], pfound->name);
+#else
+			fprintf (stderr,
+			     "%s: option `%c%s' doesn't allow an argument\n",
+			     argv[0], argv[optind - 1][0], pfound->name);
+#endif
+		    }
+		  nextchar += strlen (nextchar);
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (opterr)
+#if NLS
+		    fprintf (stderr,
+			     catgets(_libc_cat, GetoptSet, GetoptRequiresArgument1,
+		             "%s: option `%s' requires an argument\n"),
+			     argv[0], argv[optind - 1]);
+#else
+		    fprintf (stderr, "%s: option `%s' requires an argument\n",
+			     argv[0], argv[optind - 1]);
+#endif
+		  nextchar += strlen (nextchar);
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (opterr)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+#if NLS
+		fprintf (stderr,
+			 catgets(_libc_cat, GetoptSet, GetoptUnrecognized1,
+			 "%s: unrecognized option `--%s'\n"),
+			 argv[0], nextchar);
+#else
+		fprintf (stderr, "%s: unrecognized option `--%s'\n",
+			 argv[0], nextchar);
+#endif
+	      else
+		/* +option or -option */
+#if NLS
+		fprintf (stderr,
+			 catgets(_libc_cat, GetoptSet, GetoptUnrecognized2,
+			 "%s: unrecognized option `%c%s'\n"),
+			 argv[0], argv[optind][0], nextchar);
+#else
+		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+			 argv[0], argv[optind][0], nextchar);
+#endif
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (opterr)
+	  {
+	    /* 1003.2 specifies the format of this message.  */
+#if NLS
+	    fprintf (stderr,
+		catgets(_libc_cat, GetoptSet, GetoptIllegal,
+		"%s: illegal option -- %c\n"),
+		argv[0], c);
+#else
+	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+	  }
+	optopt = c;
+	return '?';
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = NULL;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (opterr)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+#if NLS
+		    fprintf (stderr,
+			catgets(_libc_cat, GetoptSet,
+			GetoptRequiresArgument2,
+			"%s: option requires an argument -- %c\n"),
+			argv[0], c);
+#else
+		    fprintf (stderr, "%s: option requires an argument -- %c\n",
+			     argv[0], c);
+#endif
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif /* L__gnu_getopt_internal */
+
+#ifdef L_gnu_getopt_long
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+#endif /*  L_gnu_getopt_long */
+
+#ifdef L_gnu_getopt_long_only
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+#endif /* L_gnu_getopt_long_only */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+  exit (0);
+}
+
+#endif /* TEST */
+
+  /* getopt_long testing */
+#ifdef TEST_LONG
+
+/* Compile with -DTEST_LONG to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST_LONG */

+ 24 - 0
test/string/Makefile

@@ -22,6 +22,7 @@ YLDFLAGS = -s --static
 
 TARGETS=string string_glibc
 TARGETS+=testcopy testcopy_glibc
+TARGETS+=strerror strsignal
 
 all: $(TARGETS)
 
@@ -78,6 +79,29 @@ testcopy_diff: testcopy testcopy_glibc
 	-@ echo " "
 
 
+strerror: ../../string/strerror.c
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs uClibc: "
+	-@ echo " "
+	$(CC) $(XCFLAGS) -DCHECK_BUF -c $< -o $@.o
+	$(CC) $(XLDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
+	$(STRIPTOOL) -x -R .note -R .comment $@
+	-./$@
+	-@ echo " "
+
+strsignal: ../../string/strsignal.c
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs uClibc: "
+	-@ echo " "
+	$(CC) $(XCFLAGS) -DCHECK_BUF -c $< -o $@.o
+	$(CC) $(XLDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
+	$(STRIPTOOL) -x -R .note -R .comment $@
+	-./$@
+	-@ echo " "
+
+
 clean:
 	rm -f *.[oa] *~ core $(TARGETS) testcopy.gnu.out testcopy.out