From ae97a89e1a1a9833080dccc81f6cd26784e1b964 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 11 Jan 2001 11:42:17 +0000 Subject: A large update from Manuel Novoa III . --- Makefile | 4 +- Rules.mak | 2 +- extra/Makefile | 48 ++ extra/gcc-uClibc/Makefile | 40 ++ extra/gcc-uClibc/gcc-uClibc.c | 129 ++++ include/getopt.h | 105 ++- include/stdio.h | 14 +- include/sys/param.h | 2 +- libc/inet/Makefile | 4 +- libc/inet/resolv.c | 4 +- libc/inet/rpc/Makefile | 4 +- libc/misc/Makefile | 2 +- libc/misc/assert/Makefile | 4 +- libc/misc/fnmatch/Makefile | 4 +- libc/misc/glob/Makefile | 4 +- libc/misc/internals/Makefile | 4 +- libc/misc/lock/Makefile | 4 +- libc/misc/lsearch/Makefile | 4 +- libc/misc/mntent/Makefile | 4 +- libc/misc/regex/Makefile | 4 +- libc/misc/syslog/Makefile | 4 +- libc/misc/time/Makefile | 4 +- libc/pwd_grp/Makefile | 4 +- libc/signal/Makefile | 4 +- libc/stdio/Makefile | 9 +- libc/stdio/printf.c | 66 +- libc/stdio/stdio.c | 195 ++--- libc/stdlib/Makefile | 6 +- libc/stdlib/atexit.c | 82 +-- libc/stdlib/malloc-930716/Makefile | 51 ++ libc/stdlib/malloc-930716/README | 40 ++ libc/stdlib/malloc-930716/calloc.c | 25 + libc/stdlib/malloc-930716/free.c | 156 ++++ libc/stdlib/malloc-930716/malloc.c | 254 +++++++ libc/stdlib/malloc-930716/malloc.h | 107 +++ libc/stdlib/malloc-930716/memalign.c | 61 ++ libc/stdlib/malloc-930716/morecore.c | 28 + libc/stdlib/malloc-930716/realloc.c | 131 ++++ libc/stdlib/malloc-930716/valloc.c | 62 ++ libc/stdlib/malloc-simple/Makefile | 4 +- libc/stdlib/malloc/Makefile | 4 +- libc/stdlib/qsort.c | 220 ++---- libc/stdlib/system.c | 2 + libc/string/Makefile | 4 +- libc/string/strerror.c | 43 +- libc/string/strsignal.c | 73 +- libc/sysdeps/linux/arm/Makefile | 8 +- libc/sysdeps/linux/common/Makefile | 26 +- libc/sysdeps/linux/common/str_syscalls.sh | 35 + libc/sysdeps/linux/common/syscalls.c | 32 +- libc/sysdeps/linux/common/unified_syscall_i386.h | 41 ++ libc/sysdeps/linux/i386/Makefile | 13 +- libc/sysdeps/linux/i386/__init_brk.c | 33 + libc/sysdeps/linux/i386/__uClibc_syscall.S | 39 + libc/sysdeps/linux/i386/brk.c | 32 + libc/sysdeps/linux/i386/sbrk.c | 35 + libc/termios/Makefile | 4 +- libc/unistd/Makefile | 15 +- libc/unistd/getopt.c | 16 +- libc/unistd/getpass.c | 3 +- libc/unistd/gnu_getopt.c | 873 +++++++++++++++++++++++ test/string/Makefile | 24 + 62 files changed, 2763 insertions(+), 495 deletions(-) create mode 100644 extra/Makefile create mode 100644 extra/gcc-uClibc/Makefile create mode 100644 extra/gcc-uClibc/gcc-uClibc.c create mode 100644 libc/stdlib/malloc-930716/Makefile create mode 100644 libc/stdlib/malloc-930716/README create mode 100644 libc/stdlib/malloc-930716/calloc.c create mode 100644 libc/stdlib/malloc-930716/free.c create mode 100644 libc/stdlib/malloc-930716/malloc.c create mode 100644 libc/stdlib/malloc-930716/malloc.h create mode 100644 libc/stdlib/malloc-930716/memalign.c create mode 100644 libc/stdlib/malloc-930716/morecore.c create mode 100644 libc/stdlib/malloc-930716/realloc.c create mode 100644 libc/stdlib/malloc-930716/valloc.c create mode 100755 libc/sysdeps/linux/common/str_syscalls.sh create mode 100644 libc/sysdeps/linux/common/unified_syscall_i386.h create mode 100644 libc/sysdeps/linux/i386/__init_brk.c create mode 100644 libc/sysdeps/linux/i386/__uClibc_syscall.S create mode 100644 libc/sysdeps/linux/i386/brk.c create mode 100644 libc/sysdeps/linux/i386/sbrk.c create mode 100644 libc/unistd/gnu_getopt.c diff --git a/Makefile b/Makefile index d51c44ed5..d490a9f1f 100644 --- a/Makefile +++ b/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 diff --git a/Rules.mak b/Rules.mak index 280484aae..ab41e57c4 100644 --- a/Rules.mak +++ b/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 diff --git a/extra/Makefile b/extra/Makefile new file mode 100644 index 000000000..fa4b50b44 --- /dev/null +++ b/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 + diff --git a/extra/gcc-uClibc/Makefile b/extra/gcc-uClibc/Makefile new file mode 100644 index 000000000..af9f836a1 --- /dev/null +++ b/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) + diff --git a/extra/gcc-uClibc/gcc-uClibc.c b/extra/gcc-uClibc/gcc-uClibc.c new file mode 100644 index 000000000..f783cd7bd --- /dev/null +++ b/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 +#endif + +#include +#include +#include + +#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 +} + + + + diff --git a/include/getopt.h b/include/getopt.h index a4cb95496..725d9cbd4 100644 --- a/include/getopt.h +++ b/include/getopt.h @@ -1,18 +1,109 @@ -/* Copyright (C) 1996 Robert de Bath - * 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 +#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 */ diff --git a/include/stdio.h b/include/stdio.h index a7a468788..01f6667ef 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -105,16 +105,12 @@ typedef struct __stdio_file FILE; #include #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)); diff --git a/include/sys/param.h b/include/sys/param.h index 511c2ae1e..c59222cd4 100644 --- a/include/sys/param.h +++ b/include/sys/param.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include diff --git a/libc/inet/Makefile b/libc/inet/Makefile index de5d90d74..56e783ceb 100644 --- a/libc/inet/Makefile +++ b/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 diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 7abc9b506..18f366e87 100644 --- a/libc/inet/resolv.c +++ b/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) diff --git a/libc/inet/rpc/Makefile b/libc/inet/rpc/Makefile index 082c78a55..ade5d2422 100644 --- a/libc/inet/rpc/Makefile +++ b/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) diff --git a/libc/misc/Makefile b/libc/misc/Makefile index 6a3275903..3f84a5065 100644 --- a/libc/misc/Makefile +++ b/libc/misc/Makefile @@ -39,7 +39,7 @@ libc.a: subdirs tags: ctags -R - + clean: subdirs_clean rm -f *.[oa] *~ core diff --git a/libc/misc/assert/Makefile b/libc/misc/assert/Makefile index abc2261ba..d6023490f 100644 --- a/libc/misc/assert/Makefile +++ b/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: diff --git a/libc/misc/fnmatch/Makefile b/libc/misc/fnmatch/Makefile index 2a952881e..ce2ac2a47 100644 --- a/libc/misc/fnmatch/Makefile +++ b/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: diff --git a/libc/misc/glob/Makefile b/libc/misc/glob/Makefile index 557106488..8254381ea 100644 --- a/libc/misc/glob/Makefile +++ b/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: diff --git a/libc/misc/internals/Makefile b/libc/misc/internals/Makefile index be19bbf7b..da693ce51 100644 --- a/libc/misc/internals/Makefile +++ b/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: diff --git a/libc/misc/lock/Makefile b/libc/misc/lock/Makefile index 6a925b882..041ca5404 100644 --- a/libc/misc/lock/Makefile +++ b/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: diff --git a/libc/misc/lsearch/Makefile b/libc/misc/lsearch/Makefile index 82f70be97..5ea47e14d 100644 --- a/libc/misc/lsearch/Makefile +++ b/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: diff --git a/libc/misc/mntent/Makefile b/libc/misc/mntent/Makefile index fc8cfb33a..ee163c182 100644 --- a/libc/misc/mntent/Makefile +++ b/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: diff --git a/libc/misc/regex/Makefile b/libc/misc/regex/Makefile index 66a585a63..89912aa74 100644 --- a/libc/misc/regex/Makefile +++ b/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: diff --git a/libc/misc/syslog/Makefile b/libc/misc/syslog/Makefile index 6f4717f25..a52d413ed 100644 --- a/libc/misc/syslog/Makefile +++ b/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: diff --git a/libc/misc/time/Makefile b/libc/misc/time/Makefile index 27ebdad45..d225614cb 100644 --- a/libc/misc/time/Makefile +++ b/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: diff --git a/libc/pwd_grp/Makefile b/libc/pwd_grp/Makefile index 7ed905ad3..bdd3c9782 100644 --- a/libc/pwd_grp/Makefile +++ b/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 diff --git a/libc/signal/Makefile b/libc/signal/Makefile index 9dcdeab8b..e4fa6b7b4 100644 --- a/libc/signal/Makefile +++ b/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: diff --git a/libc/stdio/Makefile b/libc/stdio/Makefile index 49408c95a..5314af07b 100644 --- a/libc/stdio/Makefile +++ b/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 diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c index 634885e67..ffca106e4 100644 --- a/libc/stdio/printf.c +++ b/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)); diff --git a/libc/stdio/stdio.c b/libc/stdio/stdio.c index fbec9d5a9..32f4b925b 100644 --- a/libc/stdio/stdio.c +++ b/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; diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile index 5d7c9405a..52d00f876 100644 --- a/libc/stdlib/Makefile +++ b/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 diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c index 1c164ff86..20195fa96 100644 --- a/libc/stdlib/atexit.c +++ b/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 @@ -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 diff --git a/libc/stdlib/malloc-930716/Makefile b/libc/stdlib/malloc-930716/Makefile new file mode 100644 index 000000000..a4ae21798 --- /dev/null +++ b/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 + diff --git a/libc/stdlib/malloc-930716/README b/libc/stdlib/malloc-930716/README new file mode 100644 index 000000000..39c048312 --- /dev/null +++ b/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. diff --git a/libc/stdlib/malloc-930716/calloc.c b/libc/stdlib/malloc-930716/calloc.c new file mode 100644 index 000000000..152fe09c6 --- /dev/null +++ b/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 +#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; +} diff --git a/libc/stdlib/malloc-930716/free.c b/libc/stdlib/malloc-930716/free.c new file mode 100644 index 000000000..fbc98b714 --- /dev/null +++ b/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 +#include +#include +#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); +} diff --git a/libc/stdlib/malloc-930716/malloc.c b/libc/stdlib/malloc-930716/malloc.c new file mode 100644 index 000000000..e8f7c7004 --- /dev/null +++ b/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 +#include +#include +#include +#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; +} diff --git a/libc/stdlib/malloc-930716/malloc.h b/libc/stdlib/malloc-930716/malloc.h new file mode 100644 index 000000000..34458c062 --- /dev/null +++ b/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 + +/* 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); diff --git a/libc/stdlib/malloc-930716/memalign.c b/libc/stdlib/malloc-930716/memalign.c new file mode 100644 index 000000000..1098f5890 --- /dev/null +++ b/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 +#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; +} diff --git a/libc/stdlib/malloc-930716/morecore.c b/libc/stdlib/malloc-930716/morecore.c new file mode 100644 index 000000000..e2ad4464b --- /dev/null +++ b/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