diff options
Diffstat (limited to 'lib')
105 files changed, 5474 insertions, 5476 deletions
diff --git a/lib/glob/ChangeLog b/lib/glob/ChangeLog deleted file mode 100644 index 377f0c1..0000000 --- a/lib/glob/ChangeLog +++ /dev/null @@ -1,13 +0,0 @@ -Thu Oct 29 08:58:12 1992 Brian Fox (bfox@cubit) - - * glob.c (glob_filename): Fix tiny memory leak. Rework some - comments. - -Mon Jul 20 10:57:36 1992 Brian Fox (bfox@cubit) - - * glob.c: (glob_filename) Change use of rindex () to strrchr (). - -Thu Jul 9 10:02:47 1992 Brian Fox (bfox@cubit) - - * fnmatch.c: (fnmatch) Only process `[' as the start of a bracket - expression if there is a closing `]' present in the string. diff --git a/lib/glob/Makefile.in b/lib/glob/Makefile.in index 234e8e1..a229f99 100644 --- a/lib/glob/Makefile.in +++ b/lib/glob/Makefile.in @@ -62,12 +62,12 @@ CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS LIBRARY_NAME = libglob.a # The C code source files for this library. -CSOURCES = $(srcdir)/glob.c $(srcdir)/fnmatch.c +CSOURCES = $(srcdir)/glob.c $(srcdir)/strmatch.c # The header files for this library. -HSOURCES = $(srcdir)/fnmatch.h +HSOURCES = $(srcdir)/strmatch.h -OBJECTS = glob.o fnmatch.o +OBJECTS = glob.o strmatch.o # The texinfo files which document this library. DOCSOURCE = doc/glob.texi @@ -121,14 +121,15 @@ mostlyclean: clean # # ###################################################################### -fnmatch.o: fnmatch.h -fnmatch.o: $(BUILD_DIR)/config.h +strmatch.o: strmatch.h +strmatch.o: $(BUILD_DIR)/config.h +strmatch.o: $(BASHINCDIR)/chartypes.h glob.o: $(BUILD_DIR)/config.h glob.o: $(topdir)/bashtypes.h $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h glob.o: $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/memalloc.h -glob.o: fnmatch.h +glob.o: strmatch.h # Rules for deficient makes, like SunOS and Solaris -fnmatch.o: fnmatch.c +strmatch.o: strmatch.c glob.o: glob.c diff --git a/lib/glob/collsyms.h b/lib/glob/collsyms.h index 7ef0906..1dbca3c 100644 --- a/lib/glob/collsyms.h +++ b/lib/glob/collsyms.h @@ -34,96 +34,108 @@ typedef struct _collsym { static COLLSYM posix_collsyms[] = { - "NUL", '\0', - "SOH", '\001', - "STX", '\002', - "ETX", '\003', - "EOT", '\004', - "ENQ", '\005', - "ACK", '\006', + { "NUL", '\0' }, + { "SOH", '\001' }, + { "STX", '\002' }, + { "ETX", '\003' }, + { "EOT", '\004' }, + { "ENQ", '\005' }, + { "ACK", '\006' }, #ifdef __STDC__ - "alert", '\a', + { "alert", '\a' }, #else - "alert", '\007', + { "alert", '\007' }, #endif - "backspace", '\b', - "tab", '\t', - "newline", '\n', - "vertical-tab", '\v', - "form-feed", '\f', - "carriage-return", '\r', - "SO", '\016', - "SI", '\017', - "DLE", '\020', - "DC1", '\021', - "DC2", '\022', - "DC3", '\023', - "DC4", '\024', - "NAK", '\025', - "SYN", '\026', - "ETB", '\027', - "CAN", '\030', - "EM", '\031', - "SUB", '\032', - "ESC", '\033', - "IS4", '\034', - "IS3", '\035', - "IS2", '\036', - "IS1", '\037', - "space", ' ', - "exclamation-mark", '!', - "quotation-mark", '"', - "number-sign", '#', - "dollar-sign", '$', - "percent-sign", '%', - "ampersand", '&', - "apostrophe", '\'', - "left-parenthesis", '(', - "right-parenthesis", ')', - "asterisk", '*', - "plus-sign", '+', - "comma", ',', - "hyphen", '-', - "minus", '-', /* extension from POSIX.2 */ - "dash", '-', /* extension from POSIX.2 */ - "period", '.', - "slash", '/', - "solidus", '/', /* extension from POSIX.2 */ - "zero", '0', - "one", '1', - "two", '2', - "three", '3', - "four", '4', - "five", '5', - "six", '6', - "seven", '7', - "eight", '8', - "nine", '9', - "colon", ':', - "semicolon", ';', - "less-than-sign", '<', - "equals-sign", '=', - "greater-than-sign", '>', - "question-mark", '?', - "commercial-at", '@', - /* upper-case letters omitted */ - "left-square-bracket",'[', - "backslash", '\\', - "reverse-solidus", '\\', - "right-square-bracket", ']', - "circumflex", '^', - "circumflex-accent", '^', /* extension from POSIX.2 */ - "underscore", '_', - "grave-accent", '`', - /* lower-case letters omitted */ - "left-brace", '{', /* extension from POSIX.2 */ - "left-curly-bracket", '{', - "vertical-line", '|', - "right-brace", '}', /* extension from POSIX.2 */ - "right-curly-bracket", '}', - "tilde", '~', - "DEL", '\177', - 0, 0, + { "BS", '\010' }, + { "backspace", '\b' }, + { "HT", '\011' }, + { "tab", '\t' }, + { "LF", '\012' }, + { "newline", '\n' }, + { "VT", '\013' }, + { "vertical-tab", '\v' }, + { "FF", '\014' }, + { "form-feed", '\f' }, + { "CR", '\015' }, + { "carriage-return", '\r' }, + { "SO", '\016' }, + { "SI", '\017' }, + { "DLE", '\020' }, + { "DC1", '\021' }, + { "DC2", '\022' }, + { "DC3", '\023' }, + { "DC4", '\024' }, + { "NAK", '\025' }, + { "SYN", '\026' }, + { "ETB", '\027' }, + { "CAN", '\030' }, + { "EM", '\031' }, + { "SUB", '\032' }, + { "ESC", '\033' }, + { "IS4", '\034' }, + { "FS", '\034' }, + { "IS3", '\035' }, + { "GS", '\035' }, + { "IS2", '\036' }, + { "RS", '\036' }, + { "IS1", '\037' }, + { "US", '\037' }, + { "space", ' ' }, + { "exclamation-mark", '!' }, + { "quotation-mark", '"' }, + { "number-sign", '#' }, + { "dollar-sign", '$' }, + { "percent-sign", '%' }, + { "ampersand", '&' }, + { "apostrophe", '\'' }, + { "left-parenthesis", '(' }, + { "right-parenthesis", ')' }, + { "asterisk", '*' }, + { "plus-sign", '+' }, + { "comma", ',' }, + { "hyphen", '-' }, + { "hyphen-minus", '-' }, + { "minus", '-' }, /* extension from POSIX.2 */ + { "dash", '-' }, /* extension from POSIX.2 */ + { "period", '.' }, + { "full-stop", '.' }, + { "slash", '/' }, + { "solidus", '/' }, /* extension from POSIX.2 */ + { "zero", '0' }, + { "one", '1' }, + { "two", '2' }, + { "three", '3' }, + { "four", '4' }, + { "five", '5' }, + { "six", '6' }, + { "seven", '7' }, + { "eight", '8' }, + { "nine", '9' }, + { "colon", ':' }, + { "semicolon", ';' }, + { "less-than-sign", '<' }, + { "equals-sign", '=' }, + { "greater-than-sign", '>' }, + { "question-mark", '?' }, + { "commercial-at", '@' }, + /* upper-case letters omitted */ + { "left-square-bracket",'[' }, + { "backslash", '\\' }, + { "reverse-solidus", '\\' }, + { "right-square-bracket",']' }, + { "circumflex", '^' }, + { "circumflex-accent", '^' }, /* extension from POSIX.2 */ + { "underscore", '_' }, + { "grave-accent", '`' }, + /* lower-case letters omitted */ + { "left-brace", '{' }, /* extension from POSIX.2 */ + { "left-curly-bracket",'{' }, + { "vertical-line", '|' }, + { "right-brace", '}' }, /* extension from POSIX.2 */ + { "right-curly-bracket",'}' }, + { "tilde", '~' }, + { "DEL", '\177' }, + { 0, 0 }, }; #endif diff --git a/lib/glob/glob.c b/lib/glob/glob.c index 69d0e54..22f2931 100644 --- a/lib/glob/glob.c +++ b/lib/glob/glob.c @@ -67,7 +67,7 @@ # endif #endif /* !HAVE_DIRENT_H */ -#if defined (_POSIX_SOURCE) && !defined (STRUCT_DIRENT_HAS_D_INO) +#if defined (_POSIX_SOURCE) && !defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO) /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 @@ -94,7 +94,7 @@ # include "memalloc.h" #endif -#include "fnmatch.h" +#include "strmatch.h" #if !defined (HAVE_STDLIB_H) && !defined (SHELL) extern char *malloc (), *realloc (); @@ -131,9 +131,9 @@ char *glob_error_return; /* Return nonzero if PATTERN has any special globbing chars in it. */ int glob_pattern_p (pattern) - char *pattern; + const char *pattern; { - register char *p; + register const char *p; register char c; int bopen; @@ -256,7 +256,7 @@ glob_vector (pat, dir) int lose, skip; register char **name_vector; register unsigned int i; - int flags; /* Flags passed to fnmatch (). */ + int flags; /* Flags passed to strmatch (). */ lastlink = 0; count = lose = skip = 0; @@ -342,7 +342,7 @@ glob_vector (pat, dir) if (d == NULL) return ((char **) &glob_error_return); - /* Compute the flags that will be passed to fnmatch(). We don't + /* Compute the flags that will be passed to strmatch(). We don't need to do this every time through the loop. */ flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME; @@ -394,7 +394,7 @@ glob_vector (pat, dir) (pat[0] != '\\' || pat[1] != '.')) continue; - if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH) + if (strmatch (pat, dp->d_name, flags) != FNM_NOMATCH) { nextlink = (struct globval *) alloca (sizeof (struct globval)); nextlink->next = lastlink; diff --git a/lib/glob/glob.h b/lib/glob/glob.h index 41ad726..fbfa9f7 100644 --- a/lib/glob/glob.h +++ b/lib/glob/glob.h @@ -20,7 +20,7 @@ #include "stdc.h" -extern int glob_pattern_p __P((char *)); +extern int glob_pattern_p __P((const char *)); extern char **glob_vector __P((char *, char *)); extern char **glob_filename __P((char *)); diff --git a/lib/glob/fnmatch.c b/lib/glob/strmatch.c index 2860ee5..c0645ad 100644 --- a/lib/glob/fnmatch.c +++ b/lib/glob/strmatch.c @@ -1,4 +1,4 @@ -/* fnmatch.c -- ksh-like extended pattern matching for the shell and filename +/* strmatch.c -- ksh-like extended pattern matching for the shell and filename globbing. */ /* Copyright (C) 1991, 1997 Free Software Foundation, Inc. @@ -23,9 +23,9 @@ #include <stdio.h> /* for debugging */ -#include "fnmatch.h" +#include "strmatch.h" #include "collsyms.h" -#include <ctype.h> +#include <chartypes.h> #if defined (HAVE_STRING_H) # include <string.h> @@ -40,27 +40,13 @@ static int extmatch (); static char *patscan (); #endif -#if !defined (isascii) +#if !defined (isascii) && !defined (HAVE_ISASCII) # define isascii(c) ((unsigned int)(c) <= 0177) #endif -/* Note that these evaluate C many times. */ - -#ifndef isblank -# define isblank(c) ((c) == ' ' || (c) == '\t') -#endif - -#ifndef isgraph -# define isgraph(c) ((c) != ' ' && isprint((c))) -#endif - -#ifndef isxdigit -# define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - /* The result of FOLD is an `unsigned char' */ -# define FOLD(c) ((flags & FNM_CASEFOLD) && isupper ((unsigned char)c) \ - ? tolower ((unsigned char)c) \ +# define FOLD(c) ((flags & FNM_CASEFOLD) \ + ? TOLOWER ((unsigned char)c) \ : ((unsigned char)c)) #ifndef STREQ @@ -127,8 +113,23 @@ collsym (s, len) return -1; } +#ifdef HAVE_LIBC_FNM_EXTMATCH +int +strmatch (pattern, string, flags) + char *pattern; + char *string; + int flags; +{ + char *se, *pe; + + if (string == 0 || pattern == 0) + return FNM_NOMATCH; + + return (fnmatch (pattern, string, flags)); +} +#else /* !HAVE_LIBC_FNM_EXTMATCH */ int -fnmatch (pattern, string, flags) +strmatch (pattern, string, flags) char *pattern; char *string; int flags; @@ -143,6 +144,7 @@ fnmatch (pattern, string, flags) return (gmatch (string, se, pattern, pe, flags)); } +#endif /* !HAVE_LIBC_FNM_EXTMATCH */ /* Match STRING against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ @@ -231,7 +233,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); we are matching a pathname. */ return FNM_NOMATCH; - /* Collapse multiple consecutive, `*' and `?', but make sure that + /* Collapse multiple consecutive `*' and `?', but make sure that one character of the string is consumed for each `?'. */ for (c = *p++; (c == '?' || c == '*'); c = *p++) { @@ -267,7 +269,8 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); We need to skip the glob pattern and see if we match the rest of the string. */ newn = patscan (p + 1, pe, 0); - p = newn; + /* If NEWN is 0, we have an ill-formed pattern. */ + p = newn ? newn : pe; } #endif if (p == pe) @@ -288,7 +291,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); c1 = FOLD (c1); for (--p; n < se; ++n) { - /* Only call fnmatch if the first character indicates a + /* Only call strmatch if the first character indicates a possible match. We can check the first character if we're not doing an extended glob match. */ if ((flags & FNM_EXTMATCH) == 0 && c != '[' && FOLD (*n) != c1) /*]*/ @@ -426,29 +429,29 @@ brackmatch (p, test, flags) { pc = 0; /* make sure invalid char classes don't match. */ if (STREQN (p+1, "alnum:]", 7)) - { pc = isalnum (test); p += 8; } + { pc = ISALNUM (test); p += 8; } else if (STREQN (p+1, "alpha:]", 7)) - { pc = isalpha (test); p += 8; } + { pc = ISALPHA (test); p += 8; } else if (STREQN (p+1, "blank:]", 7)) - { pc = isblank (test); p += 8; } + { pc = ISBLANK (test); p += 8; } else if (STREQN (p+1, "cntrl:]", 7)) - { pc = iscntrl (test); p += 8; } + { pc = ISCNTRL (test); p += 8; } else if (STREQN (p+1, "digit:]", 7)) - { pc = isdigit (test); p += 8; } + { pc = ISDIGIT (test); p += 8; } else if (STREQN (p+1, "graph:]", 7)) - { pc = isgraph (test); p += 8; } + { pc = ISGRAPH (test); p += 8; } else if (STREQN (p+1, "lower:]", 7)) - { pc = islower (test); p += 8; } + { pc = ISLOWER (test); p += 8; } else if (STREQN (p+1, "print:]", 7)) - { pc = isprint (test); p += 8; } + { pc = ISPRINT (test); p += 8; } else if (STREQN (p+1, "punct:]", 7)) - { pc = ispunct (test); p += 8; } + { pc = ISPUNCT (test); p += 8; } else if (STREQN (p+1, "space:]", 7)) - { pc = isspace (test); p += 8; } + { pc = ISSPACE (test); p += 8; } else if (STREQN (p+1, "upper:]", 7)) - { pc = isupper (test); p += 8; } + { pc = ISUPPER (test); p += 8; } else if (STREQN (p+1, "xdigit:]", 8)) - { pc = isxdigit (test); p += 9; } + { pc = ISXDIGIT (test); p += 9; } else if (STREQN (p+1, "ascii:]", 7)) { pc = isascii (test); p += 8; } if (pc) @@ -828,7 +831,7 @@ main (c, v) string = v[1]; pat = v[2]; - if (fnmatch (pat, string, 0) == 0) + if (strmatch (pat, string, 0) == 0) { printf ("%s matches %s\n", string, pat); exit (0); diff --git a/lib/glob/fnmatch.h b/lib/glob/strmatch.h index c690891..d31e592 100644 --- a/lib/glob/fnmatch.h +++ b/lib/glob/strmatch.h @@ -16,8 +16,14 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#ifndef _FNMATCH_H -#define _FNMATCH_H 1 +#ifndef _STRMATCH_H +#define _STRMATCH_H 1 + +#ifdef HAVE_LIBC_FNM_EXTMATCH + +#include <fnmatch.h> + +#else /* !HAVE_LIBC_FNM_EXTMATCH */ #include "stdc.h" @@ -27,22 +33,32 @@ not, write to the Free Software Foundation, Inc., #undef FNM_NOESCAPE #undef FNM_PERIOD -/* Bits set in the FLAGS argument to `fnmatch'. */ -/* standard flags */ +/* Bits set in the FLAGS argument to `strmatch'. */ + +/* standard flags are like fnmatch(3). */ #define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ #define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ #define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ -/* extended flags */ +/* extended flags not available in most libc fnmatch versions, but we undef + them to avoid any possible warnings. */ +#undef FNM_LEADING_DIR +#undef FNM_CASEFOLD +#undef FNM_EXTMATCH + #define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ #define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ #define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ -/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +/* Value returned by `strmatch' if STRING does not match PATTERN. */ +#undef FNM_NOMATCH + #define FNM_NOMATCH 1 /* Match STRING against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ -extern int fnmatch __P((char *, char *, int)); +extern int strmatch __P((char *, char *, int)); + +#endif /* !HAVE_LIBC_FNM_EXTMATCH */ -#endif /* _FNMATCH_H */ +#endif /* _STRMATCH_H */ diff --git a/lib/malloc/Makefile.in b/lib/malloc/Makefile.in index 9e8f022..cbc6dbf 100644 --- a/lib/malloc/Makefile.in +++ b/lib/malloc/Makefile.in @@ -60,8 +60,6 @@ CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \ $(CC) $(CCFLAGS) -c $< MALLOC_SOURCE = malloc.c -GMALLOC_SOURCE = gmalloc.c -NMALLOC_SOURCE = nmalloc.c STUB_SOURCE = stub.c ALLOCA_SOURCE = alloca.c @@ -71,14 +69,10 @@ MALLOC_SRC = @MALLOC_SRC@ MALLOC = @MALLOC@ ALLOCA = @ALLOCA@ -MALLOC_OBJS = malloc.o $(ALLOCA) stub.o -GMALLOC_OBJS = gmalloc.o $(ALLOCA) stub.o -NMALLOC_OBJS = nmalloc.o $(ALLOCA) stub.o -NMALLOC2_OBJS = nmalloc2.o $(ALLOCA) stub.o -NGMALLOC_OBJS = ngmalloc.o $(ALLOCA) stub.o +MALLOC_OBJS = malloc.o $(ALLOCA) trace.o stats.o table.o STUB_OBJS = $(ALLOCA) stub.o -.PHONY: malloc gmalloc stubmalloc nmalloc ngmalloc nmalloc2 +.PHONY: malloc stubmalloc all: malloc @@ -87,29 +81,14 @@ malloc: ${MALLOC_OBJS} ${AR} ${ARFLAGS} libmalloc.a ${MALLOC_OBJS} -test -n "$(RANLIB)" && $(RANLIB) libmalloc.a -nmalloc: ${NMALLOC_OBJS} - ${RM} libmalloc.a - ${AR} ${ARFLAGS} libmalloc.a ${NMALLOC_OBJS} - -test -n "$(RANLIB)" && $(RANLIB) libmalloc.a - -nmalloc2: ${NMALLOC2_OBJS} - ${RM} libmalloc.a - ${AR} ${ARFLAGS} libmalloc.a ${NMALLOC2_OBJS} - -test -n "$(RANLIB)" && $(RANLIB) libmalloc.a - -gmalloc: ${GMALLOC_OBJS} - ${RM} libmalloc.a - ${AR} ${ARFLAGS} libmalloc.a ${GMALLOC_OBJS} - -test -n "$(RANLIB)" && $(RANLIB) libmalloc.a - -ngmalloc: ${NGMALLOC_OBJS} +stubmalloc: ${STUB_OBJS} ${RM} libmalloc.a - ${AR} ${ARFLAGS} libmalloc.a ${NGMALLOC_OBJS} + ${AR} ${ARFLAGS} libmalloc.a ${STUB_OBJS} -test -n "$(RANLIB)" && $(RANLIB) libmalloc.a -stubmalloc: ${STUB_OBJS} +alloca: ${ALLOCA} ${RM} libmalloc.a - ${AR} ${ARFLAGS} libmalloc.a ${STUB_OBJS} + ${AR} ${ARFLAGS} libmalloc.a ${ALLOCA} -test -n "$(RANLIB)" && $(RANLIB) libmalloc.a alloca.o: $(srcdir)/$(ALLOCA_SOURCE) @@ -126,12 +105,18 @@ distclean realclean maintainer-clean: clean alloca.o: $(BUILD_DIR)/config.h malloc.o: $(BUILD_DIR)/config.h $(topdir)/bashtypes.h getpagesize.h -nmalloc.o: $(BUILD_DIR)/config.h $(topdir)/bashtypes.h getpagesize.h -nmalloc2.o: $(BUILD_DIR)/config.h $(topdir)/bashtypes.h getpagesize.h xmalloc.o: $(BUILD_DIR)/config.h $(BASHINCDIR)/ansi_stdlib.h -gmalloc.o: $(BUILD_DIR)/config.h +trace.o: ${BUILD_DIR}/config.h +table.o: ${BUILD_DIR}/config.h + +malloc.o: ${srcdir}/imalloc.h ${srcdir}/mstats.h +stats.o: ${srcdir}/imalloc.h ${srcdir}/mstats.h +trace.o: ${srcdir}/imalloc.h +table.o: ${srcdir}/imalloc.h ${srcdir}/table.h # Rules for deficient makes, like SunOS and Solaris stub.o: stub.c malloc.o: malloc.c -gmalloc.o: gmalloc.c +table.o: table.c +trace.o: trace.c +stats.o: stats.c diff --git a/lib/malloc/alloca.c b/lib/malloc/alloca.c index 567ea1b..26319c2 100644 --- a/lib/malloc/alloca.c +++ b/lib/malloc/alloca.c @@ -28,6 +28,8 @@ /* If compiling with GCC 2, this file's not needed. */ #if !defined (__GNUC__) || __GNUC__ < 2 +#include <bashtypes.h> /* for size_t */ + /* If alloca is defined somewhere, this file is not needed. */ #ifndef alloca @@ -155,7 +157,7 @@ static header *last_alloca_header = NULL; /* -> last alloca header. */ pointer alloca (size) - unsigned size; + size_t size; { auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); diff --git a/lib/malloc/gmalloc.c b/lib/malloc/gmalloc.c deleted file mode 100644 index c21d447..0000000 --- a/lib/malloc/gmalloc.c +++ /dev/null @@ -1,1486 +0,0 @@ -/* The malloc headers and source files from the C library follow here. */ - -/* Declarations for `malloc' and friends. - Copyright 1990, 91, 92, 93, 95, 96 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - -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 -ot, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 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. */ - -/* XXX NOTES: - 1. Augment the mstats struct so we can see how many blocks for fragments - and how many blocks for large requests were allocated. -*/ - -/* CHANGES: - 1. Reorganized the source for my benefit. - 2. Integrated the range-checking code by default. - 3. free(0) no longer dumps core. - 4. Extended the statistics. - 5. Fixed a couple of places where the stats were not kept correctly. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if defined (HAVE_STRING_H) -# include <string.h> -#else -# include <strings.h> -#endif - -#if defined (HAVE_LIMITS_H) -# include <limits.h> -#endif - -#if defined (HAVE_UNISTD_H) -# ifdef _MINIX -# include <sys/types.h> -# endif -# include <unistd.h> -#endif - -#if defined (HAVE_STDDEF_H) -# include <stddef.h> -#endif -#include <errno.h> - -#if defined (RCHECK) && !defined (botch) -# include <stdio.h> -# define STDIO_H_INCLUDED -#endif - -#include "stdc.h" - -#ifndef errno -extern int errno; -#endif - -/* Need an autoconf test for this. */ -#if __STDC__ -# undef genptr_t -# define genptr_t void * -#else -# undef genptr_t -# define genptr_t char * -#endif /* !__STDC__ */ - -#if !defined (HAVE_MEMSET) -# define memset(s, zero, n) bzero ((s), (n)) -#endif -#if !defined (HAVE_MEMCPY) -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -#endif - -/* Cope with systems lacking `memmove'. */ -#if !defined (HAVE_MEMMOVE) && !defined (memmove) -static void malloc_safe_bcopy __P ((genptr_t, genptr_t, size_t)); -# define memmove(to, from, size) malloc_safe_bcopy ((from), (to), (size)) -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef min -#define min(A, B) ((A) < (B) ? (A) : (B)) -#endif - -/* Return values for `mprobe': these are the kinds of inconsistencies that - `mcheck' enables detection of. */ -enum mcheck_status - { - MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ - MCHECK_OK, /* Block is fine. */ - MCHECK_FREE, /* Block freed twice. */ - MCHECK_HEAD, /* Memory before the block was clobbered. */ - MCHECK_TAIL /* Memory after the block was clobbered. */ - }; - -/* Statistics available to the user. */ -struct mstats - { - size_t bytes_total; /* Total size of the heap. */ - size_t chunks_used; /* Chunks allocated by the user. */ - size_t bytes_used; /* Byte total of user-allocated chunks. */ - size_t chunks_free; /* Chunks in the free list. */ - size_t bytes_free; /* Byte total of chunks in the free list. */ - int nmalloc; /* Total number of calls to malloc. */ - int nfree; /* Total number of calls to free. */ - int nrealloc; /* Total number of calls to realloc. */ - int nsbrk; /* Total number of calls to sbrk. */ - size_t tsbrk; /* Total number of bytes allocated via sbrk. */ - int negsbrk; /* Total number of calls to sbrk with a negative arg */ - size_t tnegsbrk; /* Total number of bytes returned to the kernel. */ - }; - -#ifdef RCHECK -/* Arbitrary magical numbers. */ -#define MAGICWORD 0xfedabeeb -#define MAGICFREE 0xd8675309 -#define MAGICBYTE ((char) 0xd7) -#define MALLOCFLOOD ((char) 0x93) -#define FREEFLOOD ((char) 0x95) - -struct hdr - { - size_t size; /* Exact size requested by user. */ - u_bits32_t magic; /* Magic number to check header integrity. */ - }; -#endif /* RCHECK */ - -/* Functions exported by this library. */ -/* Allocate SIZE bytes of memory. */ -extern genptr_t malloc __P ((size_t __size)); - -/* Re-allocate the previously allocated block - in genptr_t, making the new block SIZE bytes long. */ -extern genptr_t realloc __P ((genptr_t __ptr, size_t __size)); - -/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ -extern genptr_t calloc __P ((size_t __nmemb, size_t __size)); - -/* Free a block allocated by `malloc', `realloc' or `calloc'. */ -extern void free __P ((genptr_t __ptr)); - -/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ -extern genptr_t memalign __P ((size_t __alignment, size_t __size)); - -/* Pick up the current statistics. */ -extern struct mstats mstats __P ((void)); - -#ifdef RCHECK -extern enum mcheck_status mprobe __P((genptr_t ptr)); -#endif - -/* End of exported functions. */ - -/* 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. */ -#define BLOCKLOG 12 -#define BLOCKSIZE 4096 /* 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 4194304 /* 1 << 22 */ - -/* 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. */ -typedef union - { - /* Heap information for a busy block. */ - struct - { - /* Zero for a large (multiblock) object, or positive giving the - logarithm to the base two of the fragment size. */ - int type; - union - { - struct - { - size_t nfree; /* Free frags in a fragmented block. */ - size_t first; /* First free fragment of the block. */ - } frag; - /* For a large object, in its first block, this has the number - of blocks in the object. In the other blocks, this has a - negative number which says how far back the first block is. */ - ptrdiff_t size; - } info; - } busy; - /* Heap information for a free block (that may be the first of a - free cluster). */ - struct - { - size_t size; /* Size (in blocks) of a free cluster. */ - size_t next; /* Index of next free cluster. */ - size_t prev; /* Index of previous free cluster. */ - } free; - } malloc_info; - -/* Pointer to first block of the heap. */ -static char *_heapbase; - -/* Table indexed by block number giving per-block information. */ -static malloc_info *_heapinfo; - -/* Address to block number and vice versa. */ -#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) -#define ADDRESS(B) ((genptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) - -/* Number of info entries. */ -static size_t heapsize; - -/* Current search index for the heap table. */ -static size_t _heapindex; - -/* Limit of valid info table indices. */ -static size_t _heaplimit; - -/* Doubly linked lists of free fragments. */ -struct list - { - struct list *next; - struct list *prev; - }; - -/* Free list headers for each fragment size. */ -static struct list _fraghead[BLOCKLOG]; - -/* List of blocks allocated with `memalign'. */ -struct alignlist - { - struct alignlist *next; - genptr_t aligned; /* The address that memaligned returned. */ - genptr_t exact; /* The address that malloc returned. */ - }; - -/* List of blocks allocated by memalign. */ -static struct alignlist *_aligned_blocks = NULL; - -/* Internal versions of `malloc', `realloc', and `free' - used when these functions need to call each other. */ -static genptr_t imalloc __P ((size_t __size)); -static genptr_t irealloc __P ((genptr_t __ptr, size_t __size)); -static void ifree __P ((genptr_t __ptr)); - -/* Given an address in the middle of a malloc'd object, - return the address of the beginning of the object. */ -static genptr_t malloc_find_object_address __P ((genptr_t __ptr)); - -/* Underlying allocation function; successive calls should - return contiguous pieces of memory. */ -static genptr_t default_morecore __P ((ptrdiff_t __size)); - -/* Number of extra blocks to get each time we ask for more core. - This reduces the frequency of calling `default_morecore'. */ -static size_t malloc_extra_blocks; - -/* Nonzero if `malloc' has been called and done its initialization. */ -static int malloc_initialized; -/* Function called to initialize malloc data structures. */ -static int malloc_initialize __P ((void)); - -#ifdef RCHECK -static void zmemset __P((genptr_t, int, size_t)); -static enum mcheck_status checkhdr __P((const struct hdr *)); -static void mabort __P((enum mcheck_status)); -#endif - -/* Instrumentation. */ -static size_t chunks_used; -static size_t bytes_used; -static size_t chunks_free; -static size_t bytes_free; -static int nmalloc, nfree, nrealloc; -static int nsbrk; -static size_t tsbrk; -static int negsbrk; -static size_t tnegsbrk; - -/* Aligned allocation. */ -static genptr_t -align (size) - size_t size; -{ - genptr_t result; - unsigned long int adj; - - result = default_morecore (size); - adj = (unsigned long int) ((unsigned long int) ((char *) result - - (char *) NULL)) % BLOCKSIZE; - if (adj != 0) - { - genptr_t new; - adj = BLOCKSIZE - adj; - new = default_morecore (adj); - result = (char *) result + adj; - } - - return result; -} - -/* Get SIZE bytes, if we can get them starting at END. - Return the address of the space we got. - If we cannot get space at END, fail and return -1. */ -static genptr_t -get_contiguous_space (size, position) - ptrdiff_t size; - genptr_t position; -{ - genptr_t before; - genptr_t after; - - before = default_morecore (0); - /* If we can tell in advance that the break is at the wrong place, - fail now. */ - if (before != position) - return 0; - - /* Allocate SIZE bytes and get the address of them. */ - after = default_morecore (size); - if (!after) - return 0; - - /* It was not contiguous--reject it. */ - if (after != position) - { - default_morecore (- size); - return 0; - } - - return after; -} - -/* This is called when `_heapinfo' and `heapsize' have just - been set to describe a new info table. Set up the table - to describe itself and account for it in the statistics. */ -inline static void -register_heapinfo () -{ - size_t block, blocks; - - block = BLOCK (_heapinfo); - blocks = BLOCKIFY (heapsize * sizeof (malloc_info)); - - /* Account for the _heapinfo block itself in the statistics. */ - bytes_used += blocks * BLOCKSIZE; - ++chunks_used; - - /* Describe the heapinfo block itself in the heapinfo. */ - _heapinfo[block].busy.type = 0; - _heapinfo[block].busy.info.size = blocks; - /* Leave back-pointers for malloc_find_address. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; -} - -/* Set everything up and remember that we have. */ -static int -malloc_initialize () -{ - if (malloc_initialized) - return 0; - - heapsize = HEAP / BLOCKSIZE; - _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); - if (_heapinfo == NULL) - return 0; - memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); - _heapinfo[0].free.size = 0; - _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; - _heapindex = 0; - _heapbase = (char *) _heapinfo; - _heaplimit = BLOCK (_heapbase + heapsize * sizeof (malloc_info)); - - register_heapinfo (); - - malloc_initialized = 1; - return 1; -} - -/* Allocate INCREMENT more bytes of data space, - and return the start of data space, or NULL on errors. - If INCREMENT is negative, shrink data space. */ -static genptr_t -default_morecore (increment) - ptrdiff_t increment; -{ - genptr_t result; - - nsbrk++; - tsbrk += increment; - if (increment < 0) - { - negsbrk++; - tnegsbrk += -increment; - } - result = (genptr_t) sbrk (increment); - if ((long)result == -1L) - return NULL; - return result; -} - -static int morecore_recursing; - -/* Get neatly aligned memory, initializing or - growing the heap info table as necessary. */ -static genptr_t -morecore (size) - size_t size; -{ - genptr_t result; - malloc_info *newinfo, *oldinfo; - size_t newsize; - - if (morecore_recursing) - /* Avoid recursion. The caller will know how to handle a null return. */ - return NULL; - - result = align (size); - if (result == NULL) - return NULL; - - /* Check if we need to grow the info table. */ - if ((size_t) BLOCK ((char *) result + size) > heapsize) - { - /* Calculate the new _heapinfo table size. We do not account for the - added blocks in the table itself, as we hope to place them in - existing free space, which is already covered by part of the - existing table. */ - newsize = heapsize; - do - newsize <<= 1; - while ((size_t) BLOCK ((char *) result + size) > newsize); - - /* We must not reuse existing core for the new info table when called - from realloc in the case of growing a large block, because the - block being grown is momentarily marked as free. In this case - _heaplimit is zero so we know not to reuse space for internal - allocation. */ - if (_heaplimit != 0) - { - /* First try to allocate the new info table in core we already - have, in the usual way using realloc. If realloc cannot - extend it in place or relocate it to existing sufficient core, - we will get called again, and the code above will notice the - `morecore_recursing' flag and return null. */ - int save = errno; /* Don't want to clobber errno with ENOMEM. */ - morecore_recursing = 1; - newinfo = (malloc_info *) irealloc (_heapinfo, newsize * sizeof (malloc_info)); - morecore_recursing = 0; - if (newinfo == NULL) - errno = save; - else - { - /* We found some space in core, and realloc has put the old - table's blocks on the free list. Now zero the new part - of the table and install the new table location. */ - memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info)); - _heapinfo = newinfo; - heapsize = newsize; - goto got_heap; - } - } - - /* Allocate new space for the malloc info table. */ - while (1) - { - newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); - - /* Did it fail? */ - if (newinfo == NULL) - { - default_morecore (-size); - return NULL; - } - - /* Is it big enough to record status for its own space? - If so, we win. */ - if ((size_t) BLOCK ((char *) newinfo + newsize * sizeof (malloc_info)) < newsize) - break; - - /* Must try again. First give back most of what we just got. */ - default_morecore (- newsize * sizeof (malloc_info)); - newsize *= 2; - } - - /* Copy the old table to the beginning of the new, - and zero the rest of the new table. */ - memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); - memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info)); - oldinfo = _heapinfo; - _heapinfo = newinfo; - heapsize = newsize; - - register_heapinfo (); - - /* Reset _heaplimit so ifree never decides - it can relocate or resize the info table. */ - _heaplimit = 0; - ifree (oldinfo); - - /* The new heap limit includes the new table just allocated. */ - _heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info)); - return result; - } - - got_heap: - _heaplimit = BLOCK ((char *) result + size); - return result; -} - -/* Allocate memory from the heap. */ -static genptr_t -imalloc (size) - size_t size; -{ - genptr_t result; - size_t block, blocks, lastblocks, start; - register size_t i; - struct list *next; - - /* ANSI C allows `malloc (0)' to either return NULL, or to return a - valid address you can realloc and free (though not dereference). - - It turns out that some extant code (sunrpc, at least Ultrix's version) - expects `malloc (0)' to return non-NULL and breaks otherwise. - Be compatible. */ - -#if 0 - if (size == 0) - return NULL; -#endif - - if (size < sizeof (struct list)) - size = sizeof (struct list); - -#ifdef SUNOS_LOCALTIME_BUG - if (size < 16) - size = 16; -#endif - - /* 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. */ - register size_t log = 1; - --size; - while ((size /= 2) != 0) - ++log; - - /* Look in the fragment lists for a - free fragment of the desired size. */ - next = _fraghead[log].next; - if (next != NULL) - { - /* 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 = (genptr_t) next; - next->prev->next = next->next; - if (next->next != NULL) - next->next->prev = next->prev; - block = BLOCK (result); - if (--_heapinfo[block].busy.info.frag.nfree != 0) - _heapinfo[block].busy.info.frag.first = (unsigned long int) - ((unsigned long int) ((char *) next->next - (char *) NULL) - % BLOCKSIZE) >> log; - - /* Update the statistics. */ - ++chunks_used; - bytes_used += 1 << log; - --chunks_free; - bytes_free -= 1 << log; - } - else - { - /* No free fragments of the desired size, so get a new block - and break it into fragments, returning the first. */ - result = imalloc (BLOCKSIZE); - if (result == NULL) - return NULL; - - /* Link all fragments but the first into the free list. */ - next = (struct list *) ((char *) result + (1 << log)); - next->next = NULL; - next->prev = &_fraghead[log]; - _fraghead[log].next = next; - - for (i = 2; i < (size_t) (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; - - chunks_free += (BLOCKSIZE >> log) - 1; - bytes_free += BLOCKSIZE - (1 << log); - bytes_used -= BLOCKSIZE - (1 << log); - } - } - 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. Get a little extra. */ - size_t wantblocks = blocks + malloc_extra_blocks; - block = _heapinfo[0].free.prev; - lastblocks = _heapinfo[block].free.size; - /* 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. */ - if (_heaplimit != 0 && block + lastblocks == _heaplimit && - /* We can't do this if we will have to make the heap info - table bigger to accomodate the new space. */ - block + wantblocks <= heapsize && - get_contiguous_space ((wantblocks - lastblocks) * BLOCKSIZE, - ADDRESS (block + lastblocks))) - { - /* We got it contiguously. Which block we are extending - (the `final free block' referred to above) might have - changed, if it got combined with a freed info table. */ - block = _heapinfo[0].free.prev; - _heapinfo[block].free.size += (wantblocks - lastblocks); - bytes_free += (wantblocks - lastblocks) * BLOCKSIZE; - _heaplimit += wantblocks - lastblocks; - continue; - } - result = morecore (wantblocks * BLOCKSIZE); - if (result == NULL) - return NULL; - block = BLOCK (result); - /* Put the new block at the end of the free list. */ - _heapinfo[block].free.size = wantblocks; - _heapinfo[block].free.prev = _heapinfo[0].free.prev; - _heapinfo[block].free.next = 0; - _heapinfo[0].free.prev = block; - _heapinfo[_heapinfo[block].free.prev].free.next = block; - ++chunks_free; - bytes_free += wantblocks * BLOCKSIZE; - /* Now loop to use some of that block for this allocation. */ - } - } - - /* 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; - --chunks_free; - } - - _heapinfo[block].busy.type = 0; - _heapinfo[block].busy.info.size = blocks; - ++chunks_used; - bytes_used += blocks * BLOCKSIZE; - bytes_free -= blocks * BLOCKSIZE; - - /* Mark all the blocks of the object just allocated except for the - first with a negative number so you can find the first block by - adding that adjustment. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; - } - - return result; -} - -genptr_t -malloc (size) - size_t size; -{ -#ifdef RCHECK - struct hdr *hdr; -#endif - - nmalloc++; - - if (malloc_initialized == 0 && malloc_initialize () == 0) - return NULL; - -#ifdef RCHECK - hdr = (struct hdr *) imalloc (sizeof (struct hdr) + size + 1); - if (hdr == NULL) - return NULL; - - hdr->size = size; - hdr->magic = MAGICWORD; - ((char *) &hdr[1])[size] = MAGICBYTE; - zmemset ((genptr_t) (hdr + 1), MALLOCFLOOD, size); - return (genptr_t) (hdr + 1); -#else - return (imalloc (size)); -#endif -} - -/* Free a block of memory allocated by `malloc'. */ - -/* Return memory to the heap. */ -static void -ifree (ptr) - genptr_t ptr; -{ - int type; - size_t block, blocks; - register size_t i; - struct list *prev, *next; - genptr_t curbrk; - size_t lesscore_threshold; - register struct alignlist *l; - - if (ptr == NULL) - return; - - /* Threshold of free space at which we will return some to the system. */ - lesscore_threshold = FINAL_FREE_BLOCKS + 2 * malloc_extra_blocks; - - 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; - } - - block = BLOCK (ptr); - - type = _heapinfo[block].busy.type; - switch (type) - { - case 0: - /* Get as many statistics as early as we can. */ - --chunks_used; - bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; - bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; - - /* 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; - ++chunks_free; - } - - /* 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; - --chunks_free; - } - - /* How many trailing free blocks are there now? */ - blocks = _heapinfo[block].free.size; - - /* Where is the current end of accessible core? */ - curbrk = default_morecore (0); - - if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit)) - { - /* The end of the malloc heap is at the end of accessible core. - It's possible that moving _heapinfo will allow us to - return some space to the system. */ - - size_t info_block = BLOCK (_heapinfo); - size_t info_blocks = _heapinfo[info_block].busy.info.size; - size_t prev_block = _heapinfo[block].free.prev; - size_t prev_blocks = _heapinfo[prev_block].free.size; - size_t next_block = _heapinfo[block].free.next; - size_t next_blocks = _heapinfo[next_block].free.size; - - if (/* Win if this block being freed is last in core, the info table - is just before it, the previous free block is just before the - info table, and the two free blocks together form a useful - amount to return to the system. */ - (block + blocks == _heaplimit && - info_block + info_blocks == block && - prev_block != 0 && prev_block + prev_blocks == info_block && - blocks + prev_blocks >= lesscore_threshold) || - /* Nope, not the case. We can also win if this block being - freed is just before the info table, and the table extends - to the end of core or is followed only by a free block, - and the total free space is worth returning to the system. */ - (block + blocks == info_block && - ((info_block + info_blocks == _heaplimit && - blocks >= lesscore_threshold) || - (info_block + info_blocks == next_block && - next_block + next_blocks == _heaplimit && - blocks + next_blocks >= lesscore_threshold))) - ) - { - malloc_info *newinfo; - size_t oldlimit = _heaplimit; - - /* Free the old info table, clearing _heaplimit to avoid - recursion into this code. We don't want to return the - table's blocks to the system before we have copied them to - the new location. */ - _heaplimit = 0; - ifree (_heapinfo); - _heaplimit = oldlimit; - - /* Tell malloc to search from the beginning of the heap for - free blocks, so it doesn't reuse the ones just freed. */ - _heapindex = 0; - - /* Allocate new space for the info table and move its data. */ - newinfo = (malloc_info *) imalloc (info_blocks - * BLOCKSIZE); - memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE); - _heapinfo = newinfo; - - /* We should now have coalesced the free block with the - blocks freed from the old info table. Examine the entire - trailing free block to decide below whether to return some - to the system. */ - block = _heapinfo[0].free.prev; - blocks = _heapinfo[block].free.size; - } - - /* Now see if we can return stuff to the system. */ - if (block + blocks == _heaplimit && blocks >= lesscore_threshold) - { - register size_t bytes = blocks * BLOCKSIZE; - _heaplimit -= blocks; - default_morecore (-bytes); - _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; - --chunks_free; - bytes_free -= bytes; - } - } - - /* Set the next search to begin at this block. */ - _heapindex = block; - break; - - default: - /* Do some of the statistics. */ - --chunks_used; - bytes_used -= 1 << type; - ++chunks_free; - bytes_free += 1 << type; - - /* 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) - { - /* If all fragments of this block are free, remove them - from the fragment list and free the whole block. */ - next = prev; - for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) - next = next->next; - prev->prev->next = next; - if (next != NULL) - next->prev = prev->prev; - _heapinfo[block].busy.type = 0; - _heapinfo[block].busy.info.size = 1; - - /* Keep the statistics accurate. */ - ++chunks_used; - bytes_used += BLOCKSIZE; - chunks_free -= BLOCKSIZE >> type; - bytes_free -= BLOCKSIZE; - - ifree (ADDRESS (block)); - } - else if (_heapinfo[block].busy.info.frag.nfree != 0) - { - /* If some fragments of this block are free, link this - fragment into the fragment list after the first free - fragment of this block. */ - next = (struct list *) ptr; - next->next = prev->next; - next->prev = prev; - prev->next = next; - if (next->next != NULL) - 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 long int) - ((unsigned long int) ((char *) ptr - (char *) NULL) - % BLOCKSIZE >> type); - prev->next = _fraghead[type].next; - prev->prev = &_fraghead[type]; - prev->prev->next = prev; - if (prev->next != NULL) - prev->next->prev = prev; - } - break; - } -} - -/* Return memory to the heap. */ -void -free (ptr) - genptr_t ptr; -{ -#ifdef RCHECK - struct hdr *hdr; -#endif - - nfree++; - - if (ptr == 0) - return; - -#ifdef RCHECK - hdr = ((struct hdr *) ptr) - 1; - checkhdr (hdr); - hdr->magic = MAGICFREE; - zmemset (ptr, FREEFLOOD, hdr->size); - ifree (hdr); -#else - ifree (ptr); -#endif -} - -/* Change the size of a block allocated by `malloc'. */ - -#ifndef HAVE_MEMMOVE -/* Snarfed directly from Emacs src/dispnew.c: - XXX Should use system bcopy if it handles overlap. */ - -/* Like bcopy except never gets confused by overlap. */ - -static void -malloc_safe_bcopy (afrom, ato, size) - genptr_t afrom; - genptr_t ato; - size_t size; -{ - char *from, *to; - - from = afrom; - to = ato; - if (size <= 0 || from == to) - return; - - /* If the source and destination don't overlap, then bcopy can - handle it. If they do overlap, but the destination is lower in - memory than the source, we'll assume bcopy can handle that. */ - if (to < from || from + size <= to) - bcopy (from, to, size); - - /* Otherwise, we'll copy from the end. */ - else - { - register char *endf = from + size; - register char *endt = to + size; - - /* If TO - FROM is large, then we should break the copy into - nonoverlapping chunks of TO - FROM bytes each. However, if - TO - FROM is small, then the bcopy function call overhead - makes this not worth it. The crossover point could be about - anywhere. Since I don't think the obvious copy loop is too - bad, I'm trying to err in its favor. */ - if (to - from < 64) - { - do - *--endt = *--endf; - while (endf != from); - } - else - { - for (;;) - { - endt -= (to - from); - endf -= (to - from); - - if (endt < to) - break; - - bcopy (endf, endt, to - from); - } - - /* If SIZE wasn't a multiple of TO - FROM, there will be a - little left over. The amount left over is - (endt + (to - from)) - to, which is endt - from. */ - bcopy (from, to, endt - from); - } - } -} -#endif /* !HAVE_MEMMOVE */ - -/* 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. This module has incestuous knowledge of the - internals of both free and malloc. */ -static genptr_t -irealloc (ptr, size) - genptr_t ptr; - size_t size; -{ - genptr_t result; - int type; - size_t block, blocks, oldlimit; - - if (size == 0) - { - ifree (ptr); - return imalloc (0); - } - else if (ptr == NULL) - return imalloc (size); - - block = BLOCK (ptr); - - type = _heapinfo[block].busy.type; - switch (type) - { - case 0: - /* Maybe reallocate a large block to a small fragment. */ - if (size <= BLOCKSIZE / 2) - { - result = imalloc (size); - if (result != NULL) - { - memcpy (result, ptr, size); - ifree (ptr); - 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; - /* We have just created a new chunk by splitting a chunk in two. - Now we will free this chunk; increment the statistics counter - so it doesn't become wrong when ifree decrements it. */ - ++chunks_used; - ifree (ADDRESS (block + blocks)); - result = ptr; - } - else if (blocks == _heapinfo[block].busy.info.size) - /* No size change necessary. */ - result = 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; - ifree (ptr); - result = imalloc (size); - if (_heaplimit == 0) - _heaplimit = oldlimit; - if (result == NULL) - { - /* 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) - (void) imalloc (blocks * BLOCKSIZE); - else - { - genptr_t previous; - previous = imalloc ((block - _heapindex) * BLOCKSIZE); - (void) imalloc (blocks * BLOCKSIZE); - ifree (previous); - } - return NULL; - } - if (ptr != result) - memmove (result, ptr, blocks * BLOCKSIZE); - } - break; - - default: - /* Old size is a fragment; type is logarithm - to base two of the fragment size. */ - if (size > (size_t) (1 << (type - 1)) && - size <= (size_t) (1 << type)) - /* The new size is the same kind of fragment. */ - result = ptr; - else - { - /* The new size is different; allocate a new space, - and copy the lesser of the new size and the old. */ - result = imalloc (size); - if (result == NULL) - return NULL; - memcpy (result, ptr, min (size, (size_t) 1 << type)); - ifree (ptr); - } - break; - } - - return result; -} - -genptr_t -realloc (ptr, size) - genptr_t ptr; - size_t size; -{ -#ifdef RCHECK - struct hdr *hdr; - size_t osize; -#endif - - if (malloc_initialized == 0 && malloc_initialize () == 0) - return NULL; - - nrealloc++; - -#ifdef RCHECK - hdr = ((struct hdr *) ptr) - 1; - osize = hdr->size; - - checkhdr (hdr); - if (size < osize) - zmemset ((char *) ptr + size, FREEFLOOD, osize - size); - hdr = (struct hdr *) irealloc ((genptr_t) hdr, sizeof (struct hdr) + size + 1); - if (hdr == NULL) - return NULL; - - hdr->size = size; - hdr->magic = MAGICWORD; - ((char *) &hdr[1])[size] = MAGICBYTE; - if (size > osize) - zmemset ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize); - return (genptr_t) (hdr + 1); -#else - return (irealloc (ptr, size)); -#endif -} - -/* Allocate an array of NMEMB elements each SIZE bytes long. - The entire array is initialized to zeros. */ -genptr_t -calloc (nmemb, size) - register size_t nmemb; - register size_t size; -{ - register genptr_t result; - - result = malloc (nmemb * size); - if (result != NULL) - (void) memset (result, 0, nmemb * size); - - return result; -} - -/* Define the `cfree' alias for `free'. */ -void -cfree (ptr) - genptr_t ptr; -{ - free (ptr); -} - -genptr_t -memalign (alignment, size) - size_t alignment; - size_t size; -{ - genptr_t result; - unsigned long int adj, lastadj; - - /* Allocate a block with enough extra space to pad the block with up to - (ALIGNMENT - 1) bytes if necessary. */ - result = malloc (size + alignment - 1); - if (result == NULL) - return NULL; - - /* Figure out how much we will need to pad this particular block - to achieve the required alignment. */ - adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment; - - do - { - /* Reallocate the block with only as much excess as it needs. */ - free (result); - result = malloc (adj + size); - if (result == NULL) /* Impossible unless interrupted. */ - return NULL; - - lastadj = adj; - adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment; - /* It's conceivable we might have been so unlucky as to get a - different block with weaker alignment. If so, this block is too - short to contain SIZE after alignment correction. So we must - try again and get another block, slightly larger. */ - } while (adj > lastadj); - - if (adj != 0) - { - /* Record this block in the list of aligned blocks, so that `free' - can identify the pointer it is passed, which will be in the middle - of an allocated block. */ - - 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 *) imalloc (sizeof (struct alignlist)); - if (l == NULL) - { - free (result); - return NULL; - } - l->next = _aligned_blocks; - _aligned_blocks = l; - } - l->exact = result; - result = l->aligned = (char *) result + alignment - adj; - } - - return result; -} - -/* On some ANSI C systems, some libc functions call _malloc, _free - and _realloc. Make them use the GNU functions. */ - -genptr_t -_malloc (size) - size_t size; -{ - return malloc (size); -} - -void -_free (ptr) - genptr_t ptr; -{ - free (ptr); -} - -genptr_t -_realloc (ptr, size) - genptr_t ptr; - size_t size; -{ - return realloc (ptr, size); -} - -struct mstats -mstats () -{ - struct mstats result; - - result.bytes_total = (char *) default_morecore (0) - _heapbase; - result.chunks_used = chunks_used; - result.bytes_used = bytes_used; - result.chunks_free = chunks_free; - result.bytes_free = bytes_free; - result.nmalloc = nmalloc; - result.nrealloc = nrealloc; - result.nfree = nfree; - result.nsbrk = nsbrk; - result.tsbrk = tsbrk; - result.negsbrk = negsbrk; - result.tnegsbrk = tnegsbrk; - - return result; -} - -#ifdef RCHECK -/* Standard debugging hooks for `malloc'. */ - -static void -zmemset (ptr, val, size) - genptr_t ptr; - int val; - size_t size; -{ - char *cp = ptr; - - while (size--) - *cp++ = val; -} - -static enum mcheck_status -checkhdr (hdr) - const struct hdr *hdr; -{ - enum mcheck_status status; - - switch (hdr->magic) - { - default: - status = MCHECK_HEAD; - break; - case MAGICFREE: - status = MCHECK_FREE; - break; - case MAGICWORD: - if (((char *) &hdr[1])[hdr->size] != MAGICBYTE) - status = MCHECK_TAIL; - else - status = MCHECK_OK; - break; - } - if (status != MCHECK_OK) - mabort (status); - return status; -} - -#ifndef botch -botch (msg) - char *msg; -{ - fprintf (stderr, "mcheck: %s\n", msg); - fflush (stderr); - abort (); -} -#endif - -static void -mabort (status) - enum mcheck_status status; -{ - const char *msg; - - switch (status) - { - case MCHECK_OK: - msg = "memory is consistent, library is buggy"; - break; - case MCHECK_HEAD: - msg = "memory clobbered before allocated block"; - break; - case MCHECK_TAIL: - msg = "memory clobbered past end of allocated block"; - break; - case MCHECK_FREE: - msg = "block freed twice"; - break; - default: - msg = "bogus mcheck_status, library is buggy"; - break; - } - - botch (msg); -} - -enum mcheck_status -mprobe (ptr) - genptr_t ptr; -{ - return checkhdr ((struct hdr *)ptr); -} - -#ifndef STDIO_H_INCLUDED -# include <stdio.h> -#endif - -void -print_malloc_stats (s) - char *s; -{ - struct mstats ms; - - ms = mstats (); - fprintf (stderr, "Memory allocation statistics: %s\n", s ? s : ""); - fprintf (stderr, "\nTotal chunks in use: %d, total chunks free: %d\n", - ms.chunks_used, ms.chunks_free); - fprintf (stderr, "Total bytes in use: %u, total bytes free: %u\n", - ms.bytes_used, ms.bytes_free); - fprintf (stderr, "Total bytes (from heapbase): %d\n", ms.bytes_total); - fprintf (stderr, "Total mallocs: %d, total frees: %d, total reallocs: %d\n", - ms.nmalloc, ms.nfree, ms.nrealloc); - fprintf (stderr, "Total sbrks: %d, total bytes via sbrk: %d\n", - ms.nsbrk, ms.tsbrk); - fprintf (stderr, "Total negative sbrks: %d, total bytes returned to kernel: %d\n", - ms.negsbrk, ms.tnegsbrk); -} -#endif /* RCHECK */ diff --git a/lib/malloc/imalloc.h b/lib/malloc/imalloc.h new file mode 100644 index 0000000..ef08868 --- /dev/null +++ b/lib/malloc/imalloc.h @@ -0,0 +1,67 @@ +/* imalloc.h -- internal malloc definitions shared by source files. */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* Must be included *after* config.h */ + +#ifndef _IMALLOC_H_ +#define _IMALLOC_H + +#ifdef MALLOC_DEBUG +#define MALLOC_STATS +#define MALLOC_TRACE +#define MALLOC_REGISTER +#endif + +/* Generic pointer type. */ +#ifndef PTR_T +# if defined (__STDC__) +# define PTR_T void * +# else +# define PTR_T char * +# endif +#endif + +#if !defined (NULL) +# define NULL 0 +#endif + +#if !defined (__STRING) +# if defined (HAVE_STRINGIZE) +# define __STRING(x) #x +# else +# define __STRING(x) "x" +# endif /* !HAVE_STRINGIZE */ +#endif /* !__STRING */ + +#if __GNUC__ > 1 +# define FASTCOPY(s, d, n) __builtin_memcpy (d, s, n) +#else /* !__GNUC__ */ +# if !defined (HAVE_BCOPY) +# if !defined (HAVE_MEMMOVE) +# define FASTCOPY(s, d, n) memcpy (d, s, n) +# else +# define FASTCOPY(s, d, n) memmove (d, s, n) +# endif /* !HAVE_MEMMOVE */ +# else /* HAVE_BCOPY */ +# define FASTCOPY(s, d, n) bcopy (s, d, n) +# endif /* HAVE_BCOPY */ +#endif /* !__GNUC__ */ + +#endif diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c index 17cc0d2..03b8f08 100644 --- a/lib/malloc/malloc.c +++ b/lib/malloc/malloc.c @@ -45,7 +45,6 @@ what you give them. Help stamp out software-hoarding! */ * realloc knows how to return same block given, just changing its size, * if the power of 2 is correct. */ -#define MALLOC_STATS /* for the time being */ /* * nextf[i] is the pointer to the next free block of size 2^(i+3). The @@ -67,8 +66,18 @@ what you give them. Help stamp out software-hoarding! */ #if defined (SHELL) # include "bashtypes.h" +# include "stdc.h" #else # include <sys/types.h> + +# ifndef __P +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define __P(protos) protos +# else +# define __P(protos) () +# endif +# endif + #endif #if defined (HAVE_UNISTD_H) @@ -84,40 +93,24 @@ what you give them. Help stamp out software-hoarding! */ # include <strings.h> #endif -#if defined (MALLOC_STATS) || !defined (botch) -# include <stdio.h> -#endif /* MALLOC_STATS || !botch */ +#include <stdio.h> /* Define getpagesize () if the system does not. */ #ifndef HAVE_GETPAGESIZE # include "getpagesize.h" #endif -#if __GNUC__ > 1 -# define FASTCOPY(s, d, n) __builtin_memcpy (d, s, n) -#else /* !__GNUC__ */ -# if !defined (HAVE_BCOPY) -# if !defined (HAVE_MEMMOVE) -# define FASTCOPY(s, d, n) memcpy (d, s, n) -# else -# define FASTCOPY(s, d, n) memmove (d, s, n) -# endif /* !HAVE_MEMMOVE */ -# else /* HAVE_BCOPY */ -# define FASTCOPY(s, d, n) bcopy (s, d, n) -# endif /* HAVE_BCOPY */ -#endif /* !__GNUC__ */ - -/* Generic pointer type. */ -#ifndef PTR_T -# if defined (__STDC__) -# define PTR_T void * -# else -# define PTR_T char * -# endif +#include "imalloc.h" +#ifdef MALLOC_STATS +# include "mstats.h" +#endif +#ifdef MALLOC_REGISTER +# include "table.h" #endif -#if !defined (NULL) -# define NULL 0 +/* System-specific omissions. */ +#ifdef HPUX +# define NO_VALLOC #endif #define NBUCKETS 30 @@ -130,66 +123,6 @@ what you give them. Help stamp out software-hoarding! */ being the distance to the true beginning of the block. */ -#if !defined (SBRK_DECLARED) -extern char *sbrk (); -#endif /* !SBRK_DECLARED */ - -#ifdef MALLOC_STATS -/* - * NMALLOC[i] is the difference between the number of mallocs and frees - * for a given block size. TMALLOC[i] is the total number of mallocs for - * a given block size. NMORECORE[i] is the total number of calls to - * morecore(i). NMAL and NFRE are counts of the number of calls to malloc() - * and free(), respectively. NREALLOC is the total number of calls to - * realloc(); NRCOPY is the number of times realloc() had to allocate new - * memory and copy to it. NRECURSE is a count of the number of recursive - * calls to malloc() for the same bucket size, which can be caused by calls - * to malloc() from a signal handler. NSBRK is the number of calls to sbrk() - * (whether by morecore() or for alignment); TSBRK is the total number of - * bytes requested from the kernel with sbrk(). BYTESUSED is the total - * number of bytes consumed by blocks currently in use; BYTESFREE is the - * total number of bytes currently on all of the free lists. TBSPLIT is - * the number of times a larger block was split to satisfy a smaller request. - * NSPLIT[i] is the number of times a block of size I was split. - * TBCOALESCE is the number of times two adjacent smaller blocks off the free - * list were combined to satisfy a larger request. - */ -struct _malstats { - int nmalloc[NBUCKETS]; - int tmalloc[NBUCKETS]; - int nmorecore[NBUCKETS]; - int nmal; - int nfre; - int nrealloc; - int nrcopy; - int nrecurse; - int nsbrk; - bits32_t tsbrk; - bits32_t bytesused; - bits32_t bytesfree; - int tbsplit; - int nsplit[NBUCKETS]; - int tbcoalesce; -}; - -static struct _malstats _mstats; - -/* Return statistics describing allocation of blocks of size BLOCKSIZE. - NFREE is the number of free blocks for this allocation size. NUSED - is the number of blocks in use. NMAL is the number of requests for - blocks of size BLOCKSIZE. NMORECORE is the number of times we had - to call MORECORE to repopulate the free list for this bucket. NSPLIT - is the number of times a block of this size was split to satisfy a - smaller request. */ -struct bucket_stats { - u_bits32_t blocksize; - int nfree; - int nused; - int nmal; - int nmorecore; - int nsplit; -}; -#endif /* MALLOC_STATS */ /* We have a flag indicating whether memory is allocated, an index in nextf[], a size field, and a sentinel value to determine whether or @@ -198,13 +131,13 @@ struct bucket_stats { enough room in the block for the new size. Range checking is always done. */ union mhead { - bits64_t mh_align; /* 8 */ + bits64_t mh_align; /* 8 */ struct { - char mi_alloc; /* ISALLOC or ISFREE */ /* 1 */ - char mi_index; /* index in nextf[] */ /* 1 */ + char mi_alloc; /* ISALLOC or ISFREE */ /* 1 */ + char mi_index; /* index in nextf[] */ /* 1 */ /* Remainder are valid only when block is allocated */ - u_bits32_t mi_nbytes; /* # of bytes allocated */ /* 4 */ - u_bits16_t mi_magic2;/* should be == MAGIC2 */ /* 2 */ + u_bits16_t mi_magic2; /* should be == MAGIC2 */ /* 2 */ + u_bits32_t mi_nbytes; /* # of bytes allocated */ /* 4 */ } minfo; }; #define mh_alloc minfo.mi_alloc @@ -222,38 +155,28 @@ union mhead { #define CHAIN(a) \ (*(union mhead **) (sizeof (char *) + (char *) (a))) -#if defined (botch) -extern void botch (); -#else -static void -botch (s) - char *s; -{ - fprintf (stderr, "\r\nmalloc: assertion botched: %s\r\n", s); - (void)fflush (stderr); - abort (); -} -#endif /* !botch */ - -#if !defined (__STRING) -# if defined (__STDC__) -# define __STRING(x) #x -# else -# define __STRING(x) "x" -# endif -#endif /* !__STRING */ - /* To implement range checking, we write magic values in at the beginning and end of each allocated block, and make sure they are undisturbed whenever a free or a realloc occurs. */ /* Written in each of the 4 bytes following the block's real space */ #define MAGIC1 0x55 -/* Written in the 2 bytes before the block's real space */ +/* Written in the 2 bytes before the block's real space (-4 bytes) */ #define MAGIC2 0x5555 -#define ASSERT(p) do { if (!(p)) botch(__STRING(p)); } while (0) #define MSLOP 4 /* 4 bytes extra for MAGIC1s */ +/* How many bytes are actually allocated for a request of size N -- + rounded up to nearest multiple of 8 after accounting for malloc + overhead. */ +#define ALLOCATED_BYTES(n) (((n) + sizeof (union mhead) + MSLOP + 7) & ~7) + +#define ASSERT(p) \ + do \ + { \ + if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, __STRING(p), file, line); \ + } \ + while (0) + /* Minimum and maximum bucket indices for block splitting (and to bound the search for a block to split). */ #define SPLIT_MIN 3 @@ -266,6 +189,23 @@ botch (s) #define MIN_COMBINE_FREE 4 +/* Flags for the internal functions. */ +#define MALLOC_WRAPPER 0x01 /* wrapper function */ +#define MALLOC_INTERNAL 0x02 /* internal function calling another */ +#define MALLOC_NOTRACE 0x04 /* don't trace this allocation or free */ +#define MALLOC_NOREG 0x08 /* don't register this allocation or free */ + +/* Future use. */ +#define ERR_DUPFREE 0x01 +#define ERR_UNALLOC 0x02 +#define ERR_UNDERFLOW 0x04 +#define ERR_ASSERT_FAILED 0x08 + +/* Evaluates to true if NB is appropriate for bucket NU. NB is adjusted + appropriately by the caller to account for malloc overhead. */ +#define IN_BUCKET(nb, nu) \ + ((nb) > (4 << (nu)) && ((nb) <= (8 << (nu)))) + /* nextf[i] is free list of blocks of size 2**(i + 3) */ static union mhead *nextf[NBUCKETS]; @@ -278,11 +218,74 @@ static int pagesz; /* system page size. */ static int pagebucket; /* bucket for requests a page in size */ static int maxbuck; /* highest bucket receiving allocation request. */ +/* Declarations for internal functions */ +static PTR_T internal_malloc __P((size_t, const char *, int, int)); +static PTR_T internal_realloc __P((PTR_T, size_t, const char *, int, int)); +static void internal_free __P((PTR_T, const char *, int, int)); +static PTR_T internal_memalign __P((unsigned int, size_t, const char *, int, int)); +#ifndef NO_CALLOC +static PTR_T internal_calloc __P((size_t, size_t, const char *, int, int)); +static void internal_cfree __P((PTR_T, const char *, int, int)); +#endif +#ifndef NO_VALLOC +static PTR_T internal_valloc __P((size_t, const char *, int, int)); +#endif + +#if defined (botch) +extern void botch (); +#else +static void botch __P((const char *, const char *, int)); +#endif +static void xbotch __P((PTR_T, int, const char *, const char *, int)); + +#ifdef MALLOC_STATS +extern struct _malstats _mstats; +#endif /* MALLOC_STATS */ + +#if !HAVE_DECL_SBRK +extern char *sbrk (); +#endif /* !HAVE_DECL_SBRK */ + #ifdef SHELL extern int interrupt_immediately; -extern int signal_is_trapped (); +extern int signal_is_trapped __P((int)); #endif +/* Debugging variables available to applications. */ +int malloc_flags = 0; /* future use */ +int malloc_trace = 0; /* trace allocations and frees to stderr */ +int malloc_register = 0; /* future use */ + +#if !defined (botch) +static void +botch (s, file, line) +{ + fprintf (stderr, "malloc: failed assertion: %s\n", s); + (void)fflush (stderr); + abort (); +} +#endif + +/* print the file and line number that caused the assertion failure and + call botch() to do whatever the application wants with the information */ +static void +xbotch (mem, e, s, file, line) + PTR_T mem; + int e; + const char *s; + const char *file; + int line; +{ + fprintf (stderr, "\r\nmalloc: %s:%d: assertion botched\r\n", + file ? file : "unknown", line); +#ifdef MALLOC_REGISTER + if (mem != NULL && malloc_register) + mregister_describe_mem (mem, stderr); +#endif + (void)fflush (stderr); + botch(s, file, line); +} + #if 0 /* Coalesce two adjacent free blocks off the free list for size NU - 1, as long as there are at least MIN_COMBINE_FREE free blocks and we @@ -319,7 +322,7 @@ bcoalesce (nu) /* OK, now we have mp1 pointing to the block we want to add to nextf[NU]. CHAIN(mp2) must equal mp1. Check that mp1 and mp are adjacent. */ if (CHAIN(mp2) != mp1) - botch ("bcoalesce: CHAIN(mp2) != mp1"); + xbotch ((PTR_T)0, 0, "bcoalesce: CHAIN(mp2) != mp1", (char *)NULL, 0); siz = 1 << (nbuck + 3); if (CHAIN (mp1) != (union mhead *)((char *)mp1 + siz)) return; /* not adjacent */ @@ -464,11 +467,7 @@ morecore (nu) /* ask system for more memory */ /* Try to split a larger block here, if we're within the range of sizes to split. */ -#if 0 - if (nu >= SPLIT_MIN && nu < SPLIT_MAX) -#else if (nu >= SPLIT_MIN) -#endif { bsplit (nu); if (nextf[nu] != 0) @@ -522,7 +521,7 @@ morecore (nu) /* ask system for more memory */ /* shouldn't happen, but just in case -- require 8-byte alignment */ if ((long)mp & 7) { - mp = (union mhead *) (((long)mp + 8) & ~7); + mp = (union mhead *) (((long)mp + 7) & ~7); nblks--; } @@ -565,9 +564,11 @@ malloc_debug_dummy () write (1, "malloc_debug_dummy\n", 19); } -PTR_T -malloc (n) /* get a block */ +static PTR_T +internal_malloc (n, file, line, flags) /* get a block */ size_t n; + const char *file; + int line, flags; { register union mhead *p; register long nbytes; @@ -610,10 +611,10 @@ malloc (n) /* get a block */ } /* Figure out how many bytes are required, rounding up to the nearest - multiple of 4, then figure out which nextf[] area to use. Try to + multiple of 8, then figure out which nextf[] area to use. Try to be smart about where to start searching -- if the number of bytes needed is greater than the page size, we can start at pagebucket. */ - nbytes = (n + sizeof *p + MSLOP + 3) & ~3; + nbytes = ALLOCATED_BYTES(n); nunits = 0; if (nbytes <= (pagesz >> 1)) { @@ -636,6 +637,10 @@ malloc (n) /* get a block */ } } + /* Silently reject too-large requests. */ + if (nunits >= NBUCKETS) + return ((PTR_T) NULL); + /* In case this is reentrant use of malloc from signal handler, pick a block size that no other malloc level is currently trying to allocate. That's the easiest harmless way not to @@ -666,12 +671,12 @@ malloc (n) /* get a block */ /* If not for this check, we would gobble a clobbered free chain ptr and bomb out on the NEXT allocate of this size block */ if (p->mh_alloc != ISFREE || p->mh_index != nunits) - botch ("malloc: block on free list clobbered"); + xbotch ((PTR_T)0, 0, "malloc: block on free list clobbered", file, line); - /* Fill in the info, and if range checking, set up the magic numbers */ + /* Fill in the info, and set up the magic numbers for range checking. */ p->mh_alloc = ISALLOC; - p->mh_nbytes = n; p->mh_magic2 = MAGIC2; + p->mh_nbytes = n; { register char *m = (char *) (p + 1) + n; @@ -686,16 +691,31 @@ malloc (n) /* get a block */ _mstats.tmalloc[nunits]++; _mstats.nmal++; #endif /* MALLOC_STATS */ + +#ifdef MALLOC_TRACE + if (malloc_trace && (flags & MALLOC_NOTRACE) == 0) + mtrace_alloc ("malloc", p + 1, n, file, line); +#endif + +#ifdef MALLOC_REGISTER + if (malloc_register && (flags & MALLOC_NOREG) == 0) + mregister_alloc ("malloc", p + 1, n, file, line); +#endif + return (char *) (p + 1); /* XXX - should be cast to PTR_T? */ } -void -free (mem) +static void +internal_free (mem, file, line, flags) PTR_T mem; + const char *file; + int line, flags; { register union mhead *p; register char *ap; register int nunits; + register unsigned int nbytes; + int ubytes; /* caller-requested size */ if ((ap = (char *)mem) == 0) return; @@ -708,15 +728,37 @@ free (mem) p = (union mhead *) ap - 1; } +#if defined (MALLOC_TRACE) || defined (MALLOC_REGISTER) + if (malloc_trace || malloc_register) + ubytes = p->mh_nbytes; +#endif + if (p->mh_alloc != ISALLOC) { if (p->mh_alloc == ISFREE) - botch ("free: called with already freed block argument"); + xbotch (mem, ERR_DUPFREE, + "free: called with already freed block argument", file, line); else - botch ("free: called with unallocated block argument"); + xbotch (mem, ERR_UNALLOC, + "free: called with unallocated block argument", file, line); } ASSERT (p->mh_magic2 == MAGIC2); + + nunits = p->mh_index; + nbytes = ALLOCATED_BYTES(p->mh_nbytes); + /* Since the sizeof(u_bits32_t) bytes before the memory handed to the user + are now used for the number of bytes allocated, a simple check of + mh_magic2 is no longer sufficient to catch things like p[-1] = 'x'. + We sanity-check the value of mh_nbytes against the size of the blocks + in the appropriate bucket before we use it. This can still cause problems + and obscure errors if mh_nbytes is wrong but still within range; the + checks against MAGIC1 will probably fail then. Using MALLOC_REGISTER + will help here, since it saves the original number of bytes requested. */ + if (IN_BUCKET(nbytes, nunits) == 0) + xbotch (mem, ERR_UNDERFLOW, + "free: underflow detected; mh_nbytes out of range", file, line); + ap += p->mh_nbytes; ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); @@ -725,15 +767,11 @@ free (mem) zmemset (mem, 0xcf, p->mh_nbytes); #endif - nunits = p->mh_index; - ASSERT (nunits < NBUCKETS); p->mh_alloc = ISFREE; -#if 0 if (busy[nunits] == 1) - botch ("calling free %d while in malloc for %d", nunits, nunits); -#endif + return; /* this is bogus, but at least it won't corrupt the chains */ /* Protect against signal handlers calling malloc. */ busy[nunits] = 1; @@ -746,12 +784,24 @@ free (mem) _mstats.nmalloc[nunits]--; _mstats.nfre++; #endif /* MALLOC_STATS */ + +#ifdef MALLOC_TRACE + if (malloc_trace && (flags & MALLOC_NOTRACE) == 0) + mtrace_free (mem, ubytes, file, line); +#endif + +#ifdef MALLOC_REGISTER + if (malloc_register && (flags & MALLOC_NOREG) == 0) + mregister_free (mem, ubytes, file, line); +#endif } -PTR_T -realloc (mem, n) +static PTR_T +internal_realloc (mem, n, file, line, flags) PTR_T mem; register size_t n; + const char *file; + int line, flags; { register union mhead *p; register u_bits32_t tocopy; @@ -765,25 +815,43 @@ realloc (mem, n) if (n == 0) { - free (mem); + internal_free (mem, file, line, MALLOC_INTERNAL); return (NULL); } if ((p = (union mhead *) mem) == 0) - return malloc (n); + return internal_malloc (n, file, line, MALLOC_INTERNAL); + p--; nunits = p->mh_index; - ASSERT (p->mh_alloc == ISALLOC); + ASSERT (nunits < NBUCKETS); + + if (p->mh_alloc != ISALLOC) + xbotch (mem, ERR_UNALLOC, + "realloc: called with unallocated block argument", file, line); + ASSERT (p->mh_magic2 == MAGIC2); + nbytes = ALLOCATED_BYTES(p->mh_nbytes); + /* Since the sizeof(u_bits32_t) bytes before the memory handed to the user + are now used for the number of bytes allocated, a simple check of + mh_magic2 is no longer sufficient to catch things like p[-1] = 'x'. + We sanity-check the value of mh_nbytes against the size of the blocks + in the appropriate bucket before we use it. This can still cause problems + and obscure errors if mh_nbytes is wrong but still within range; the + checks against MAGIC1 will probably fail then. Using MALLOC_REGISTER + will help here, since it saves the original number of bytes requested. */ + if (IN_BUCKET(nbytes, nunits) == 0) + xbotch (mem, ERR_UNDERFLOW, + "realloc: underflow detected; mh_nbytes out of range", file, line); m = (char *)mem + (tocopy = p->mh_nbytes); ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); /* See if desired size rounds to same power of 2 as actual size. */ - nbytes = (n + sizeof *p + MSLOP + 7) & ~7; + nbytes = ALLOCATED_BYTES(n); /* If ok, use the same block, just marking its size as changed. */ - if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) + if (IN_BUCKET(nbytes, nunits)) { m = (char *)mem + tocopy; *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; @@ -800,182 +868,240 @@ realloc (mem, n) if (n < tocopy) tocopy = n; - if ((m = malloc (n)) == 0) + if ((m = internal_malloc (n, file, line, MALLOC_INTERNAL|MALLOC_NOTRACE|MALLOC_NOREG)) == 0) return 0; FASTCOPY (mem, m, tocopy); - free (mem); + internal_free (mem, file, line, MALLOC_INTERNAL); + +#ifdef MALLOC_TRACE + if (malloc_trace && (flags & MALLOC_NOTRACE) == 0) + mtrace_alloc ("realloc", m, n, file, line); +#endif + +#ifdef MALLOC_REGISTER + if (malloc_register && (flags & MALLOC_NOREG) == 0) + mregister_alloc ("realloc", m, n, file, line); +#endif + return m; } -PTR_T -memalign (alignment, size) +static PTR_T +internal_memalign (alignment, size, file, line, flags) unsigned int alignment; size_t size; + const char *file; + int line, flags; { register char *ptr; register char *aligned; register union mhead *p; - ptr = malloc (size + alignment); + ptr = internal_malloc (size + alignment, file, line, MALLOC_INTERNAL); if (ptr == 0) return 0; /* If entire block has the desired alignment, just accept it. */ - if (((int) ptr & (alignment - 1)) == 0) + if (((long) ptr & (alignment - 1)) == 0) return ptr; /* Otherwise, get address of byte in the block that has that alignment. */ - aligned = (char *) (((int) ptr + alignment - 1) & -alignment); +#if 0 + aligned = (char *) (((long) ptr + alignment - 1) & -alignment); +#else + aligned = (char *) (((long) ptr + alignment - 1) & (~alignment + 1)); +#endif /* Store a suitable indication of how to free the block, so that free can find the true beginning of it. */ p = (union mhead *) aligned - 1; p->mh_nbytes = aligned - ptr; p->mh_alloc = ISMEMALIGN; + return aligned; } -#if !defined (HPUX) +#if !defined (NO_VALLOC) /* This runs into trouble with getpagesize on HPUX, and Multimax machines. Patching out seems cleaner than the ugly fix needed. */ -PTR_T -valloc (size) +static PTR_T +internal_valloc (size, file, line, flags) size_t size; + const char *file; + int line, flags; { - return memalign (getpagesize (), size); + return internal_memalign (getpagesize (), size, file, line, flags|MALLOC_INTERNAL); } -#endif /* !HPUX */ +#endif /* !NO_VALLOC */ #ifndef NO_CALLOC -PTR_T -calloc (n, s) +static PTR_T +internal_calloc (n, s, file, line, flags) size_t n, s; + const char *file; + int line, flags; { size_t total; - char *result; + PTR_T result; total = n * s; - result = malloc (total); + result = internal_malloc (total, file, line, flags|MALLOC_INTERNAL); if (result) zmemset (result, 0, total); return result; } -void -cfree (p) +static void +internal_cfree (p, file, line, flags) PTR_T p; + const char *file; + int line, flags; { - free (p); + internal_free (p, file, line, flags|MALLOC_INTERNAL); } #endif /* !NO_CALLOC */ #ifdef MALLOC_STATS -struct bucket_stats -malloc_bucket_stats (size) +int +malloc_free_blocks (size) int size; { - struct bucket_stats v; + int nfree; register union mhead *p; - v.nfree = 0; + nfree = 0; + for (p = nextf[size]; p; p = CHAIN (p)) + nfree++; - if (size < 0 || size >= NBUCKETS) - { - v.blocksize = 0; - v.nused = v.nmal = v.nmorecore = v.nsplit = 0; - return v; - } + return nfree; +} +#endif - v.blocksize = 1 << (size + 3); - v.nused = _mstats.nmalloc[size]; - v.nmal = _mstats.tmalloc[size]; - v.nmorecore = _mstats.nmorecore[size]; - v.nsplit = _mstats.nsplit[size]; +#if defined (SHELL) +PTR_T +sh_malloc (bytes, file, line) + size_t bytes; + const char *file; + int line; +{ + return internal_malloc (bytes, file, line, MALLOC_WRAPPER); +} - for (p = nextf[size]; p; p = CHAIN (p)) - v.nfree++; +PTR_T +sh_realloc (ptr, size, file, line) + PTR_T ptr; + size_t size; + const char *file; + int line; +{ + return internal_realloc (ptr, size, file, line, MALLOC_WRAPPER); +} - return v; +void +sh_free (mem, file, line) + PTR_T mem; + const char *file; + int line; +{ + internal_free (mem, file, line, MALLOC_WRAPPER); } -/* Return a copy of _MSTATS, with two additional fields filled in: - BYTESFREE is the total number of bytes on free lists. BYTESUSED - is the total number of bytes in use. These two fields are fairly - expensive to compute, so we do it only when asked to. */ -struct _malstats -malloc_stats () +PTR_T +sh_memalign (alignment, size, file, line) + unsigned int alignment; + size_t size; + const char *file; + int line; { - struct _malstats result; - struct bucket_stats v; - register int i; + return internal_memalign (alignment, size, file, line, MALLOC_WRAPPER); +} - result = _mstats; - result.bytesused = result.bytesfree = 0; - for (i = 0; i < NBUCKETS; i++) - { - v = malloc_bucket_stats (i); - result.bytesfree += v.nfree * v.blocksize; - result.bytesused += v.nused * v.blocksize; - } - return (result); +#ifndef NO_CALLOC +PTR_T +sh_calloc (n, s, file, line) + size_t n, s; + const char *file; + int line; +{ + return internal_calloc (n, s, file, line, MALLOC_WRAPPER); } -static void -_print_malloc_stats (s, fp) - char *s; - FILE *fp; +void +sh_cfree (mem, file, line) + PTR_T mem; + const char *file; + int line; { - register int i; - int totused, totfree; - struct bucket_stats v; + internal_cfree (mem, file, line, MALLOC_WRAPPER); +} +#endif - fprintf (fp, "Memory allocation statistics: %s\n\tsize\tfree\tin use\ttotal\tmorecore\tsplit\n", s ? s : ""); - for (i = totused = totfree = 0; i < NBUCKETS; i++) - { - v = malloc_bucket_stats (i); - fprintf (fp, "%12lu\t%4d\t%6d\t%5d\t%8d\t%5d\n", v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nsplit); - totfree += v.nfree * v.blocksize; - totused += v.nused * v.blocksize; - } - fprintf (fp, "\nTotal bytes in use: %d, total bytes free: %d\n", - totused, totfree); - fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n", - _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy); - fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n", - _mstats.nsbrk, _mstats.tsbrk); - fprintf (fp, "Total blocks split: %d, total block coalesces: %d\n", - _mstats.tbsplit, _mstats.tbcoalesce); +#ifndef NO_VALLOC +PTR_T +sh_valloc (size, file, line) + size_t size; + const char *file; + int line; +{ + return internal_valloc (size, file, line, MALLOC_WRAPPER); +} +#endif + +#endif + +/* Externally-available functions that call their internal counterparts. */ + +PTR_T +malloc (size) + size_t size; +{ + return internal_malloc (size, (char *)NULL, 0, 0); +} + +PTR_T +realloc (mem, nbytes) + PTR_T mem; + size_t nbytes; +{ + return internal_realloc (mem, nbytes, (char *)NULL, 0, 0); } void -print_malloc_stats (s) - char *s; +free (mem) + PTR_T mem; { - _print_malloc_stats (s, stderr); + internal_free (mem, (char *)NULL, 0, 0); } -#define TRACEROOT "/var/tmp/maltrace/trace." -extern char *inttostr (); +PTR_T +memalign (alignment, size) + unsigned int alignment; + size_t size; +{ + return internal_memalign (alignment, size, (char *)NULL, 0, 0); +} + +#ifndef NO_VALLOC +PTR_T +valloc (size) + size_t size; +{ + return internal_valloc (size, (char *)NULL, 0, 0); +} +#endif + +#ifndef NO_CALLOC +PTR_T +calloc (n, s) + size_t n, s; +{ + return internal_calloc (n, s, (char *)NULL, 0, 0); +} void -trace_malloc_stats (s) - char *s; +cfree (mem) + PTR_T mem; { - char ibuf[32], *ip; - char fname[64]; - int p; - FILE *fp; - - p = (int)getpid(); - ip = inttostr(p, ibuf, sizeof(ibuf)); - strcpy (fname, TRACEROOT); - strcat (fname, ip); - fp = fopen(fname, "w"); - if (fp) - { - _print_malloc_stats (s, fp); - fflush(fp); - fclose(fp); - } + internal_cfree (mem, (char *)NULL, 0, 0); } -#endif /* MALLOC_STATS */ +#endif diff --git a/lib/malloc/mstats.h b/lib/malloc/mstats.h new file mode 100644 index 0000000..df51485 --- /dev/null +++ b/lib/malloc/mstats.h @@ -0,0 +1,90 @@ +/* mstats.h - definitions for malloc statistics */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _MSTATS_H +#define _MSTATS_H + +#include "imalloc.h" + +#ifdef MALLOC_STATS + +#ifndef NBUCKETS +# define NBUCKETS 30 +#endif + +/* + * NMALLOC[i] is the difference between the number of mallocs and frees + * for a given block size. TMALLOC[i] is the total number of mallocs for + * a given block size. NMORECORE[i] is the total number of calls to + * morecore(i). NMAL and NFRE are counts of the number of calls to malloc() + * and free(), respectively. NREALLOC is the total number of calls to + * realloc(); NRCOPY is the number of times realloc() had to allocate new + * memory and copy to it. NRECURSE is a count of the number of recursive + * calls to malloc() for the same bucket size, which can be caused by calls + * to malloc() from a signal handler. NSBRK is the number of calls to sbrk() + * (whether by morecore() or for alignment); TSBRK is the total number of + * bytes requested from the kernel with sbrk(). BYTESUSED is the total + * number of bytes consumed by blocks currently in use; BYTESFREE is the + * total number of bytes currently on all of the free lists. TBSPLIT is + * the number of times a larger block was split to satisfy a smaller request. + * NSPLIT[i] is the number of times a block of size I was split. + * TBCOALESCE is the number of times two adjacent smaller blocks off the free + * list were combined to satisfy a larger request. + */ +struct _malstats { + int nmalloc[NBUCKETS]; + int tmalloc[NBUCKETS]; + int nmorecore[NBUCKETS]; + int nmal; + int nfre; + int nrealloc; + int nrcopy; + int nrecurse; + int nsbrk; + bits32_t tsbrk; + bits32_t bytesused; + bits32_t bytesfree; + int tbsplit; + int nsplit[NBUCKETS]; + int tbcoalesce; +}; + +/* Return statistics describing allocation of blocks of size BLOCKSIZE. + NFREE is the number of free blocks for this allocation size. NUSED + is the number of blocks in use. NMAL is the number of requests for + blocks of size BLOCKSIZE. NMORECORE is the number of times we had + to call MORECORE to repopulate the free list for this bucket. NSPLIT + is the number of times a block of this size was split to satisfy a + smaller request. */ +struct bucket_stats { + u_bits32_t blocksize; + int nfree; + int nused; + int nmal; + int nmorecore; + int nsplit; +}; + +extern struct bucket_stats malloc_bucket_stats (); +extern struct _malstats malloc_stats (); +extern void print_malloc_stats (); +extern void trace_malloc_stats (); + +#endif /* MALLOC_STATS */ + +#endif /* _MSTATS_H */ diff --git a/lib/malloc/ogmalloc.c b/lib/malloc/ogmalloc.c deleted file mode 100644 index 6b3600a..0000000 --- a/lib/malloc/ogmalloc.c +++ /dev/null @@ -1,1579 +0,0 @@ -/* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */ - -#define _MALLOC_INTERNAL - -/* The malloc headers and source files from the C library follow here. */ - -/* Declarations for `malloc' and friends. - Copyright 1990, 91, 92, 93, 95, 96 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 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. */ - -#ifndef _MALLOC_H - -#define _MALLOC_H 1 - -#ifdef _MALLOC_INTERNAL - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG) -#include <string.h> -#else -#ifndef memset -#define memset(s, zero, n) bzero ((s), (n)) -#endif -#ifndef memcpy -#define memcpy(d, s, n) bcopy ((s), (d), (n)) -#endif -#endif - -#if defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__) -#include <limits.h> -#else -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#endif /* _MALLOC_INTERNAL. */ - - -#ifdef __cplusplus -extern "C" -{ -#endif - -#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) -#undef __P -#define __P(args) args -#undef __ptr_t -#define __ptr_t void * -#else /* Not C++ or ANSI C. */ -#undef __P -#define __P(args) () -#undef const -#define const -#undef __ptr_t -#define __ptr_t char * -#endif /* C++ or ANSI C. */ - -#if defined (__STDC__) && __STDC__ -#include <stddef.h> -#define __malloc_size_t size_t -#define __malloc_ptrdiff_t ptrdiff_t -#else -#define __malloc_size_t unsigned int -#define __malloc_ptrdiff_t int -#endif - -#ifndef NULL -#define NULL 0 -#endif - - -/* Allocate SIZE bytes of memory. */ -extern __ptr_t malloc __P ((__malloc_size_t __size)); -/* Re-allocate the previously allocated block - in __ptr_t, making the new block SIZE bytes long. */ -extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size)); -/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ -extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size)); -/* Free a block allocated by `malloc', `realloc' or `calloc'. */ -extern void free __P ((__ptr_t __ptr)); - -/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ -#if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict. */ -extern __ptr_t memalign __P ((__malloc_size_t __alignment, - __malloc_size_t __size)); -#endif - -/* Allocate SIZE bytes on a page boundary. */ -#if ! (defined (_MALLOC_INTERNAL) && defined (emacs)) /* Avoid conflict. */ -extern __ptr_t valloc __P ((__malloc_size_t __size)); -#endif - - -#ifdef _MALLOC_INTERNAL - -/* 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. */ -#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. */ -typedef union - { - /* Heap information for a busy block. */ - struct - { - /* Zero for a large (multiblock) object, or positive giving the - logarithm to the base two of the fragment size. */ - int type; - union - { - struct - { - __malloc_size_t nfree; /* Free frags in a fragmented block. */ - __malloc_size_t first; /* First free fragment of the block. */ - } frag; - /* For a large object, in its first block, this has the number - of blocks in the object. In the other blocks, this has a - negative number which says how far back the first block is. */ - __malloc_ptrdiff_t size; - } info; - } busy; - /* Heap information for a free block - (that may be the first of a free cluster). */ - struct - { - __malloc_size_t size; /* Size (in blocks) of a free cluster. */ - __malloc_size_t next; /* Index of next free cluster. */ - __malloc_size_t prev; /* Index of previous free cluster. */ - } free; - } malloc_info; - -/* Pointer to first block of the heap. */ -extern char *_heapbase; - -/* Table indexed by block number giving per-block information. */ -extern malloc_info *_heapinfo; - -/* Address to block number and vice versa. */ -#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) -#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) - -/* Current search index for the heap table. */ -extern __malloc_size_t _heapindex; - -/* Limit of valid info table indices. */ -extern __malloc_size_t _heaplimit; - -/* Doubly linked lists of free fragments. */ -struct list - { - struct list *next; - struct list *prev; - }; - -/* 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; - -/* Instrumentation. */ -extern __malloc_size_t _chunks_used; -extern __malloc_size_t _bytes_used; -extern __malloc_size_t _chunks_free; -extern __malloc_size_t _bytes_free; - -/* Internal versions of `malloc', `realloc', and `free' - used when these functions need to call each other. - They are the same but don't call the hooks. */ -extern __ptr_t _malloc_internal __P ((__malloc_size_t __size)); -extern __ptr_t _realloc_internal __P ((__ptr_t __ptr, __malloc_size_t __size)); -extern void _free_internal __P ((__ptr_t __ptr)); - -#endif /* _MALLOC_INTERNAL. */ - -/* Given an address in the middle of a malloc'd object, - return the address of the beginning of the object. */ -extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr)); - -/* Underlying allocation function; successive calls should - return contiguous pieces of memory. */ -extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size)); - -/* Default value of `__morecore'. */ -extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size)); - -/* If not NULL, this function is called after each time - `__morecore' is called to increase the data size. */ -extern void (*__after_morecore_hook) __P ((void)); - -/* Number of extra blocks to get each time we ask for more core. - This reduces the frequency of calling `(*__morecore)'. */ -extern __malloc_size_t __malloc_extra_blocks; - -/* Nonzero if `malloc' has been called and done its initialization. */ -extern int __malloc_initialized; -/* Function called to initialize malloc data structures. */ -extern int __malloc_initialize __P ((void)); - -/* Hooks for debugging versions. */ -extern void (*__malloc_initialize_hook) __P ((void)); -extern void (*__free_hook) __P ((__ptr_t __ptr)); -extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); -extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); -extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size, - __malloc_size_t __alignment)); - -/* Return values for `mprobe': these are the kinds of inconsistencies that - `mcheck' enables detection of. */ -enum mcheck_status - { - MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ - MCHECK_OK, /* Block is fine. */ - MCHECK_FREE, /* Block freed twice. */ - MCHECK_HEAD, /* Memory before the block was clobbered. */ - MCHECK_TAIL /* Memory after the block was clobbered. */ - }; - -/* Activate a standard collection of debugging hooks. This must be called - before `malloc' is ever called. ABORTFUNC is called with an error code - (see enum above) when an inconsistency is detected. If ABORTFUNC is - null, the standard function prints on stderr and then calls `abort'. */ -extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status)))); - -/* Check for aberrations in a particular malloc'd block. You must have - called `mcheck' already. These are the same checks that `mcheck' does - when you free or reallocate a block. */ -extern enum mcheck_status mprobe __P ((__ptr_t __ptr)); - -/* Activate a standard collection of tracing hooks. */ -extern void mtrace __P ((void)); -extern void muntrace __P ((void)); - -/* Statistics available to the user. */ -struct mstats - { - __malloc_size_t bytes_total; /* Total size of the heap. */ - __malloc_size_t chunks_used; /* Chunks allocated by the user. */ - __malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */ - __malloc_size_t chunks_free; /* Chunks in the free list. */ - __malloc_size_t bytes_free; /* Byte total of chunks in the free list. */ - }; - -/* Pick up the current statistics. */ -extern struct mstats mstats __P ((void)); - -/* Call WARNFUN with a warning message when memory usage is high. */ -extern void memory_warnings __P ((__ptr_t __start, - void (*__warnfun) __P ((const char *)))); - - -/* Relocating allocator. */ - -/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */ -extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size)); - -/* Free the storage allocated in HANDLEPTR. */ -extern void r_alloc_free __P ((__ptr_t *__handleptr)); - -/* Adjust the block at HANDLEPTR to be SIZE bytes long. */ -extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size)); - - -#ifdef __cplusplus -} -#endif - -#endif /* malloc.h */ -/* Memory allocator `malloc'. - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 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. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include <malloc.h> -#endif -#include <errno.h> - -/* How to really get more memory. */ -__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore; - -/* Debugging hook for `malloc'. */ -__ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); - -/* Pointer to the base of the first block. */ -char *_heapbase; - -/* Block information table. Allocated with align/__free (not malloc/free). */ -malloc_info *_heapinfo; - -/* Number of info entries. */ -static __malloc_size_t heapsize; - -/* Search index in the info table. */ -__malloc_size_t _heapindex; - -/* Limit of valid info table indices. */ -__malloc_size_t _heaplimit; - -/* Free lists for each fragment size. */ -struct list _fraghead[BLOCKLOG]; - -/* Instrumentation. */ -__malloc_size_t _chunks_used; -__malloc_size_t _bytes_used; -__malloc_size_t _chunks_free; -__malloc_size_t _bytes_free; - -/* Are you experienced? */ -int __malloc_initialized; - -__malloc_size_t __malloc_extra_blocks; - -void (*__malloc_initialize_hook) __P ((void)); -void (*__after_morecore_hook) __P ((void)); - - -/* Aligned allocation. */ -static __ptr_t align __P ((__malloc_size_t)); -static __ptr_t -align (size) - __malloc_size_t size; -{ - __ptr_t result; - unsigned long int adj; - - result = (*__morecore) (size); - adj = (unsigned long int) ((unsigned long int) ((char *) result - - (char *) NULL)) % BLOCKSIZE; - if (adj != 0) - { - __ptr_t new; - adj = BLOCKSIZE - adj; - new = (*__morecore) (adj); - result = (char *) result + adj; - } - - if (__after_morecore_hook) - (*__after_morecore_hook) (); - - return result; -} - -/* Get SIZE bytes, if we can get them starting at END. - Return the address of the space we got. - If we cannot get space at END, fail and return -1. */ -static __ptr_t get_contiguous_space __P ((__malloc_ptrdiff_t, __ptr_t)); -static __ptr_t -get_contiguous_space (size, position) - __malloc_ptrdiff_t size; - __ptr_t position; -{ - __ptr_t before; - __ptr_t after; - - before = (*__morecore) (0); - /* If we can tell in advance that the break is at the wrong place, - fail now. */ - if (before != position) - return 0; - - /* Allocate SIZE bytes and get the address of them. */ - after = (*__morecore) (size); - if (!after) - return 0; - - /* It was not contiguous--reject it. */ - if (after != position) - { - (*__morecore) (- size); - return 0; - } - - return after; -} - - -/* This is called when `_heapinfo' and `heapsize' have just - been set to describe a new info table. Set up the table - to describe itself and account for it in the statistics. */ -static void register_heapinfo __P ((void)); -#ifdef __GNUC__ -__inline__ -#endif -static void -register_heapinfo () -{ - __malloc_size_t block, blocks; - - block = BLOCK (_heapinfo); - blocks = BLOCKIFY (heapsize * sizeof (malloc_info)); - - /* Account for the _heapinfo block itself in the statistics. */ - _bytes_used += blocks * BLOCKSIZE; - ++_chunks_used; - - /* Describe the heapinfo block itself in the heapinfo. */ - _heapinfo[block].busy.type = 0; - _heapinfo[block].busy.info.size = blocks; - /* Leave back-pointers for malloc_find_address. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; -} - -/* Set everything up and remember that we have. */ -int -__malloc_initialize () -{ - if (__malloc_initialized) - return 0; - - if (__malloc_initialize_hook) - (*__malloc_initialize_hook) (); - - heapsize = HEAP / BLOCKSIZE; - _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); - if (_heapinfo == NULL) - return 0; - memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); - _heapinfo[0].free.size = 0; - _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; - _heapindex = 0; - _heapbase = (char *) _heapinfo; - _heaplimit = BLOCK (_heapbase + heapsize * sizeof (malloc_info)); - - register_heapinfo (); - - __malloc_initialized = 1; - return 1; -} - -static int morecore_recursing; - -/* Get neatly aligned memory, initializing or - growing the heap info table as necessary. */ -static __ptr_t morecore __P ((__malloc_size_t)); -static __ptr_t -morecore (size) - __malloc_size_t size; -{ - __ptr_t result; - malloc_info *newinfo, *oldinfo; - __malloc_size_t newsize; - - if (morecore_recursing) - /* Avoid recursion. The caller will know how to handle a null return. */ - return NULL; - - result = align (size); - if (result == NULL) - return NULL; - - /* Check if we need to grow the info table. */ - if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize) - { - /* Calculate the new _heapinfo table size. We do not account for the - added blocks in the table itself, as we hope to place them in - existing free space, which is already covered by part of the - existing table. */ - newsize = heapsize; - do - newsize *= 2; - while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize); - - /* We must not reuse existing core for the new info table when called - from realloc in the case of growing a large block, because the - block being grown is momentarily marked as free. In this case - _heaplimit is zero so we know not to reuse space for internal - allocation. */ - if (_heaplimit != 0) - { - /* First try to allocate the new info table in core we already - have, in the usual way using realloc. If realloc cannot - extend it in place or relocate it to existing sufficient core, - we will get called again, and the code above will notice the - `morecore_recursing' flag and return null. */ - int save = errno; /* Don't want to clobber errno with ENOMEM. */ - morecore_recursing = 1; - newinfo = (malloc_info *) _realloc_internal - (_heapinfo, newsize * sizeof (malloc_info)); - morecore_recursing = 0; - if (newinfo == NULL) - errno = save; - else - { - /* We found some space in core, and realloc has put the old - table's blocks on the free list. Now zero the new part - of the table and install the new table location. */ - memset (&newinfo[heapsize], 0, - (newsize - heapsize) * sizeof (malloc_info)); - _heapinfo = newinfo; - heapsize = newsize; - goto got_heap; - } - } - - /* Allocate new space for the malloc info table. */ - while (1) - { - newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); - - /* Did it fail? */ - if (newinfo == NULL) - { - (*__morecore) (-size); - return NULL; - } - - /* Is it big enough to record status for its own space? - If so, we win. */ - if ((__malloc_size_t) BLOCK ((char *) newinfo - + newsize * sizeof (malloc_info)) - < newsize) - break; - - /* Must try again. First give back most of what we just got. */ - (*__morecore) (- newsize * sizeof (malloc_info)); - newsize *= 2; - } - - /* Copy the old table to the beginning of the new, - and zero the rest of the new table. */ - memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); - memset (&newinfo[heapsize], 0, - (newsize - heapsize) * sizeof (malloc_info)); - oldinfo = _heapinfo; - _heapinfo = newinfo; - heapsize = newsize; - - register_heapinfo (); - - /* Reset _heaplimit so _free_internal never decides - it can relocate or resize the info table. */ - _heaplimit = 0; - _free_internal (oldinfo); - - /* The new heap limit includes the new table just allocated. */ - _heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info)); - return result; - } - - got_heap: - _heaplimit = BLOCK ((char *) result + size); - return result; -} - -/* Allocate memory from the heap. */ -__ptr_t -_malloc_internal (size) - __malloc_size_t size; -{ - __ptr_t result; - __malloc_size_t block, blocks, lastblocks, start; - register __malloc_size_t i; - struct list *next; - - /* ANSI C allows `malloc (0)' to either return NULL, or to return a - valid address you can realloc and free (though not dereference). - - It turns out that some extant code (sunrpc, at least Ultrix's version) - expects `malloc (0)' to return non-NULL and breaks otherwise. - Be compatible. */ - -#if 0 - if (size == 0) - return NULL; -#endif - - if (size < sizeof (struct list)) - size = sizeof (struct list); - -#ifdef SUNOS_LOCALTIME_BUG - if (size < 16) - size = 16; -#endif - - /* 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. */ - register __malloc_size_t log = 1; - --size; - while ((size /= 2) != 0) - ++log; - - /* Look in the fragment lists for a - free fragment of the desired size. */ - next = _fraghead[log].next; - if (next != NULL) - { - /* 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 = (__ptr_t) next; - next->prev->next = next->next; - if (next->next != NULL) - next->next->prev = next->prev; - block = BLOCK (result); - if (--_heapinfo[block].busy.info.frag.nfree != 0) - _heapinfo[block].busy.info.frag.first = (unsigned long int) - ((unsigned long int) ((char *) next->next - (char *) NULL) - % BLOCKSIZE) >> log; - - /* Update the statistics. */ - ++_chunks_used; - _bytes_used += 1 << log; - --_chunks_free; - _bytes_free -= 1 << 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 == NULL) - return NULL; - - /* Link all fragments but the first into the free list. */ - next = (struct list *) ((char *) result + (1 << log)); - next->next = NULL; - next->prev = &_fraghead[log]; - _fraghead[log].next = next; - - for (i = 2; i < (__malloc_size_t) (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; - - _chunks_free += (BLOCKSIZE >> log) - 1; - _bytes_free += BLOCKSIZE - (1 << log); - _bytes_used -= BLOCKSIZE - (1 << log); - } - } - 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. Get a little extra. */ - __malloc_size_t wantblocks = blocks + __malloc_extra_blocks; - block = _heapinfo[0].free.prev; - lastblocks = _heapinfo[block].free.size; - /* 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. */ - if (_heaplimit != 0 && block + lastblocks == _heaplimit && - /* We can't do this if we will have to make the heap info - table bigger to accomodate the new space. */ - block + wantblocks <= heapsize && - get_contiguous_space ((wantblocks - lastblocks) * BLOCKSIZE, - ADDRESS (block + lastblocks))) - { - /* We got it contiguously. Which block we are extending - (the `final free block' referred to above) might have - changed, if it got combined with a freed info table. */ - block = _heapinfo[0].free.prev; - _heapinfo[block].free.size += (wantblocks - lastblocks); - _bytes_free += (wantblocks - lastblocks) * BLOCKSIZE; - _heaplimit += wantblocks - lastblocks; - continue; - } - result = morecore (wantblocks * BLOCKSIZE); - if (result == NULL) - return NULL; - block = BLOCK (result); - /* Put the new block at the end of the free list. */ - _heapinfo[block].free.size = wantblocks; - _heapinfo[block].free.prev = _heapinfo[0].free.prev; - _heapinfo[block].free.next = 0; - _heapinfo[0].free.prev = block; - _heapinfo[_heapinfo[block].free.prev].free.next = block; - ++_chunks_free; - /* Now loop to use some of that block for this allocation. */ - } - } - - /* 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; - --_chunks_free; - } - - _heapinfo[block].busy.type = 0; - _heapinfo[block].busy.info.size = blocks; - ++_chunks_used; - _bytes_used += blocks * BLOCKSIZE; - _bytes_free -= blocks * BLOCKSIZE; - - /* Mark all the blocks of the object just allocated except for the - first with a negative number so you can find the first block by - adding that adjustment. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; - } - - return result; -} - -__ptr_t -malloc (size) - __malloc_size_t size; -{ - if (!__malloc_initialized && !__malloc_initialize ()) - return NULL; - - return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size); -} - -#ifndef _LIBC - -/* On some ANSI C systems, some libc functions call _malloc, _free - and _realloc. Make them use the GNU functions. */ - -__ptr_t -_malloc (size) - __malloc_size_t size; -{ - return malloc (size); -} - -void -_free (ptr) - __ptr_t ptr; -{ - free (ptr); -} - -__ptr_t -_realloc (ptr, size) - __ptr_t ptr; - __malloc_size_t size; -{ - return realloc (ptr, size); -} - -#endif -/* Free a block of memory allocated by `malloc'. - Copyright 1990, 1991, 1992, 1994, 1995 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 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. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include <malloc.h> -#endif - - -/* Cope with systems lacking `memmove'. */ -#ifndef memmove -#if (defined (MEMMOVE_MISSING) || \ - !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) -#ifdef emacs -#undef __malloc_safe_bcopy -#define __malloc_safe_bcopy safe_bcopy -#endif -/* This function is defined in realloc.c. */ -extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t)); -#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size)) -#endif -#endif - - -/* Debugging hook for free. */ -void (*__free_hook) __P ((__ptr_t __ptr)); - -/* List of blocks allocated by memalign. */ -struct alignlist *_aligned_blocks = NULL; - -/* Return memory to the heap. - Like `free' but don't call a __free_hook if there is one. */ -void -_free_internal (ptr) - __ptr_t ptr; -{ - int type; - __malloc_size_t block, blocks; - register __malloc_size_t i; - struct list *prev, *next; - __ptr_t curbrk; - const __malloc_size_t lesscore_threshold - /* Threshold of free space at which we will return some to the system. */ - = FINAL_FREE_BLOCKS + 2 * __malloc_extra_blocks; - - 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; - } - - block = BLOCK (ptr); - - type = _heapinfo[block].busy.type; - switch (type) - { - case 0: - /* Get as many statistics as early as we can. */ - --_chunks_used; - _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; - _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; - - /* 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; - ++_chunks_free; - } - - /* 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; - --_chunks_free; - } - - /* How many trailing free blocks are there now? */ - blocks = _heapinfo[block].free.size; - - /* Where is the current end of accessible core? */ - curbrk = (*__morecore) (0); - - if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit)) - { - /* The end of the malloc heap is at the end of accessible core. - It's possible that moving _heapinfo will allow us to - return some space to the system. */ - - __malloc_size_t info_block = BLOCK (_heapinfo); - __malloc_size_t info_blocks = _heapinfo[info_block].busy.info.size; - __malloc_size_t prev_block = _heapinfo[block].free.prev; - __malloc_size_t prev_blocks = _heapinfo[prev_block].free.size; - __malloc_size_t next_block = _heapinfo[block].free.next; - __malloc_size_t next_blocks = _heapinfo[next_block].free.size; - - if (/* Win if this block being freed is last in core, the info table - is just before it, the previous free block is just before the - info table, and the two free blocks together form a useful - amount to return to the system. */ - (block + blocks == _heaplimit && - info_block + info_blocks == block && - prev_block != 0 && prev_block + prev_blocks == info_block && - blocks + prev_blocks >= lesscore_threshold) || - /* Nope, not the case. We can also win if this block being - freed is just before the info table, and the table extends - to the end of core or is followed only by a free block, - and the total free space is worth returning to the system. */ - (block + blocks == info_block && - ((info_block + info_blocks == _heaplimit && - blocks >= lesscore_threshold) || - (info_block + info_blocks == next_block && - next_block + next_blocks == _heaplimit && - blocks + next_blocks >= lesscore_threshold))) - ) - { - malloc_info *newinfo; - __malloc_size_t oldlimit = _heaplimit; - - /* Free the old info table, clearing _heaplimit to avoid - recursion into this code. We don't want to return the - table's blocks to the system before we have copied them to - the new location. */ - _heaplimit = 0; - _free_internal (_heapinfo); - _heaplimit = oldlimit; - - /* Tell malloc to search from the beginning of the heap for - free blocks, so it doesn't reuse the ones just freed. */ - _heapindex = 0; - - /* Allocate new space for the info table and move its data. */ - newinfo = (malloc_info *) _malloc_internal (info_blocks - * BLOCKSIZE); - memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE); - _heapinfo = newinfo; - - /* We should now have coalesced the free block with the - blocks freed from the old info table. Examine the entire - trailing free block to decide below whether to return some - to the system. */ - block = _heapinfo[0].free.prev; - blocks = _heapinfo[block].free.size; - } - - /* Now see if we can return stuff to the system. */ - if (block + blocks == _heaplimit && blocks >= lesscore_threshold) - { - register __malloc_size_t bytes = blocks * BLOCKSIZE; - _heaplimit -= blocks; - (*__morecore) (-bytes); - _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; - --_chunks_free; - _bytes_free -= bytes; - } - } - - /* Set the next search to begin at this block. */ - _heapindex = block; - break; - - default: - /* Do some of the statistics. */ - --_chunks_used; - _bytes_used -= 1 << type; - ++_chunks_free; - _bytes_free += 1 << type; - - /* 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) - { - /* If all fragments of this block are free, remove them - from the fragment list and free the whole block. */ - next = prev; - for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i) - next = next->next; - prev->prev->next = next; - if (next != NULL) - next->prev = prev->prev; - _heapinfo[block].busy.type = 0; - _heapinfo[block].busy.info.size = 1; - - /* Keep the statistics accurate. */ - ++_chunks_used; - _bytes_used += BLOCKSIZE; - _chunks_free -= BLOCKSIZE >> type; - _bytes_free -= BLOCKSIZE; - - free (ADDRESS (block)); - } - else if (_heapinfo[block].busy.info.frag.nfree != 0) - { - /* If some fragments of this block are free, link this - fragment into the fragment list after the first free - fragment of this block. */ - next = (struct list *) ptr; - next->next = prev->next; - next->prev = prev; - prev->next = next; - if (next->next != NULL) - 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 long int) - ((unsigned long int) ((char *) ptr - (char *) NULL) - % BLOCKSIZE >> type); - prev->next = _fraghead[type].next; - prev->prev = &_fraghead[type]; - prev->prev->next = prev; - if (prev->next != NULL) - prev->next->prev = prev; - } - break; - } -} - -/* Return memory to the heap. */ -void -free (ptr) - __ptr_t ptr; -{ - if (__free_hook != NULL) - (*__free_hook) (ptr); - else - _free_internal (ptr); -} - -/* Define the `cfree' alias for `free'. */ -#ifdef weak_alias -weak_alias (free, cfree) -#else -void -cfree (ptr) - __ptr_t ptr; -{ - free (ptr); -} -#endif -/* Change the size of a block allocated by `malloc'. - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 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. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include <malloc.h> -#endif - - - -/* Cope with systems lacking `memmove'. */ -#if (defined (MEMMOVE_MISSING) || \ - !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) - -#ifdef emacs -#undef __malloc_safe_bcopy -#define __malloc_safe_bcopy safe_bcopy -#else - -/* Snarfed directly from Emacs src/dispnew.c: - XXX Should use system bcopy if it handles overlap. */ - -/* Like bcopy except never gets confused by overlap. */ - -void -__malloc_safe_bcopy (afrom, ato, size) - __ptr_t afrom; - __ptr_t ato; - __malloc_size_t size; -{ - char *from = afrom, *to = ato; - - if (size <= 0 || from == to) - return; - - /* If the source and destination don't overlap, then bcopy can - handle it. If they do overlap, but the destination is lower in - memory than the source, we'll assume bcopy can handle that. */ - if (to < from || from + size <= to) - bcopy (from, to, size); - - /* Otherwise, we'll copy from the end. */ - else - { - register char *endf = from + size; - register char *endt = to + size; - - /* If TO - FROM is large, then we should break the copy into - nonoverlapping chunks of TO - FROM bytes each. However, if - TO - FROM is small, then the bcopy function call overhead - makes this not worth it. The crossover point could be about - anywhere. Since I don't think the obvious copy loop is too - bad, I'm trying to err in its favor. */ - if (to - from < 64) - { - do - *--endt = *--endf; - while (endf != from); - } - else - { - for (;;) - { - endt -= (to - from); - endf -= (to - from); - - if (endt < to) - break; - - bcopy (endf, endt, to - from); - } - - /* If SIZE wasn't a multiple of TO - FROM, there will be a - little left over. The amount left over is - (endt + (to - from)) - to, which is endt - from. */ - bcopy (from, to, endt - from); - } - } -} -#endif /* emacs */ - -#ifndef memmove -extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t)); -#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size)) -#endif - -#endif - - -#define min(A, B) ((A) < (B) ? (A) : (B)) - -/* Debugging hook for realloc. */ -__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); - -/* 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. This module has incestuous knowledge of the - internals of both free and malloc. */ -__ptr_t -_realloc_internal (ptr, size) - __ptr_t ptr; - __malloc_size_t size; -{ - __ptr_t result; - int type; - __malloc_size_t block, blocks, oldlimit; - - if (size == 0) - { - _free_internal (ptr); - return _malloc_internal (0); - } - else if (ptr == NULL) - return _malloc_internal (size); - - block = BLOCK (ptr); - - type = _heapinfo[block].busy.type; - switch (type) - { - case 0: - /* Maybe reallocate a large block to a small fragment. */ - if (size <= BLOCKSIZE / 2) - { - result = _malloc_internal (size); - if (result != NULL) - { - memcpy (result, ptr, size); - _free_internal (ptr); - 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; - /* We have just created a new chunk by splitting a chunk in two. - Now we will free this chunk; increment the statistics counter - so it doesn't become wrong when _free_internal decrements it. */ - ++_chunks_used; - _free_internal (ADDRESS (block + blocks)); - result = ptr; - } - else if (blocks == _heapinfo[block].busy.info.size) - /* No size change necessary. */ - result = 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; - _free_internal (ptr); - result = _malloc_internal (size); - if (_heaplimit == 0) - _heaplimit = oldlimit; - if (result == NULL) - { - /* 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) - (void) _malloc_internal (blocks * BLOCKSIZE); - else - { - __ptr_t previous - = _malloc_internal ((block - _heapindex) * BLOCKSIZE); - (void) _malloc_internal (blocks * BLOCKSIZE); - _free_internal (previous); - } - return NULL; - } - if (ptr != result) - memmove (result, ptr, blocks * BLOCKSIZE); - } - break; - - default: - /* Old size is a fragment; type is logarithm - to base two of the fragment size. */ - if (size > (__malloc_size_t) (1 << (type - 1)) && - size <= (__malloc_size_t) (1 << type)) - /* The new size is the same kind of fragment. */ - result = ptr; - else - { - /* The new size is different; allocate a new space, - and copy the lesser of the new size and the old. */ - result = _malloc_internal (size); - if (result == NULL) - return NULL; - memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type)); - _free_internal (ptr); - } - break; - } - - return result; -} - -__ptr_t -realloc (ptr, size) - __ptr_t ptr; - __malloc_size_t size; -{ - if (!__malloc_initialized && !__malloc_initialize ()) - return NULL; - - return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal) - (ptr, size); -} -/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 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. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include <malloc.h> -#endif - -/* Allocate an array of NMEMB elements each SIZE bytes long. - The entire array is initialized to zeros. */ -__ptr_t -calloc (nmemb, size) - register __malloc_size_t nmemb; - register __malloc_size_t size; -{ - register __ptr_t result = malloc (nmemb * size); - - if (result != NULL) - (void) memset (result, 0, nmemb * size); - - return result; -} -/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. -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 General Public License as published by -the Free Software Foundation; either version 2, 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with the GNU C Library; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include <malloc.h> -#endif - -#ifndef __GNU_LIBRARY__ -#define __sbrk sbrk -#endif - -#ifdef __GNU_LIBRARY__ -/* It is best not to declare this and cast its result on foreign operating - systems with potentially hostile include files. */ - -#include <stddef.h> -extern __ptr_t __sbrk __P ((ptrdiff_t increment)); -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/* Allocate INCREMENT more bytes of data space, - and return the start of data space, or NULL on errors. - If INCREMENT is negative, shrink data space. */ -__ptr_t -__default_morecore (increment) - __malloc_ptrdiff_t increment; -{ - __ptr_t result = (__ptr_t) __sbrk (increment); - if (result == (__ptr_t) -1) - return NULL; - return result; -} -/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111 USA. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include <malloc.h> -#endif - -#if __DJGPP__ - 0 == 1 - -/* There is some problem with memalign in DJGPP v1 and we are supposed - to omit it. Noone told me why, they just told me to do it. */ - -#else - -__ptr_t (*__memalign_hook) __P ((size_t __size, size_t __alignment)); - -__ptr_t -memalign (alignment, size) - __malloc_size_t alignment; - __malloc_size_t size; -{ - __ptr_t result; - unsigned long int adj, lastadj; - - if (__memalign_hook) - return (*__memalign_hook) (alignment, size); - - /* Allocate a block with enough extra space to pad the block with up to - (ALIGNMENT - 1) bytes if necessary. */ - result = malloc (size + alignment - 1); - if (result == NULL) - return NULL; - - /* Figure out how much we will need to pad this particular block - to achieve the required alignment. */ - adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment; - - do - { - /* Reallocate the block with only as much excess as it needs. */ - free (result); - result = malloc (adj + size); - if (result == NULL) /* Impossible unless interrupted. */ - return NULL; - - lastadj = adj; - adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment; - /* It's conceivable we might have been so unlucky as to get a - different block with weaker alignment. If so, this block is too - short to contain SIZE after alignment correction. So we must - try again and get another block, slightly larger. */ - } while (adj > lastadj); - - if (adj != 0) - { - /* Record this block in the list of aligned blocks, so that `free' - can identify the pointer it is passed, which will be in the middle - of an allocated block. */ - - 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) - { - free (result); - return NULL; - } - l->next = _aligned_blocks; - _aligned_blocks = l; - } - l->exact = result; - result = l->aligned = (char *) result + alignment - adj; - } - - return result; -} - -#endif /* Not DJGPP v1 */ diff --git a/lib/malloc/omalloc.c b/lib/malloc/omalloc.c deleted file mode 100644 index 413faeb..0000000 --- a/lib/malloc/omalloc.c +++ /dev/null @@ -1,759 +0,0 @@ -/* dynamic memory allocation for GNU. */ - -/* Copyright (C) 1985, 1987 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -In other words, you are welcome to use, share and improve this program. -You are forbidden to forbid anyone else to use, share and improve -what you give them. Help stamp out software-hoarding! */ - -/* - * @(#)nmalloc.c 1 (Caltech) 2/21/82 - * - * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs - * - * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD. - * - * This is a very fast storage allocator. It allocates blocks of a small - * number of different sizes, and keeps free lists of each size. Blocks - * that don't exactly fit are passed up to the next larger size. In this - * implementation, the available sizes are (2^n)-4 (or -16) bytes long. - * This is designed for use in a program that uses vast quantities of - * memory, but bombs when it runs out. To make it a little better, it - * warns the user when he starts to get near the end. - * - * June 84, ACT: modified rcheck code to check the range given to malloc, - * rather than the range determined by the 2-power used. - * - * Jan 85, RMS: calls malloc_warning to issue warning on nearly full. - * No longer Emacs-specific; can serve as all-purpose malloc for GNU. - * You should call malloc_init to reinitialize after loading dumped Emacs. - * Call malloc_stats to get info on memory stats if MSTATS turned on. - * realloc knows how to return same block given, just changing its size, - * if the power of 2 is correct. - */ - -/* - * nextf[i] is the pointer to the next free block of size 2^(i+3). The - * smallest allocatable block is 8 bytes. The overhead information will - * go in the first int of the block, and the returned pointer will point - * to the second. - * -#ifdef MSTATS - * nmalloc[i] is the difference between the number of mallocs and frees - * for a given block size. -#endif - */ - -/* Define this to have free() write 0xcf into memory as it's freed, to - uncover callers that refer to freed memory. */ -/* SCO 3.2v4 getcwd and possibly other libc routines fail with MEMSCRAMBLE */ -#if !defined (NO_MEMSCRAMBLE) -# define MEMSCRAMBLE -#endif - -#if defined (emacs) || defined (HAVE_CONFIG_H) -# include <config.h> -#endif /* emacs */ - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -/* Determine which kind of system this is. */ -#if defined (SHELL) -# include "bashtypes.h" -#else -# include <sys/types.h> -#endif -#include <signal.h> - -/* Define getpagesize () if the system does not. */ -#ifndef HAVE_GETPAGESIZE -# include "getpagesize.h" -#endif - -#if defined (HAVE_RESOURCE) -# include <sys/time.h> -# include <sys/resource.h> -#endif /* HAVE_RESOURCE */ - -/* Check for the needed symbols. If they aren't present, this - system's <sys/resource.h> isn't very useful to us. */ -#if !defined (RLIMIT_DATA) -# undef HAVE_RESOURCE -#endif - -#if __GNUC__ > 1 -# define FASTCOPY(s, d, n) __builtin_memcpy (d, s, n) -#else /* !__GNUC__ */ -# if !defined (HAVE_BCOPY) -# if !defined (HAVE_MEMMOVE) -# define FASTCOPY(s, d, n) memcpy (d, s, n) -# else -# define FASTCOPY(s, d, n) memmove (d, s, n) -# endif /* !HAVE_MEMMOVE */ -# else /* HAVE_BCOPY */ -# define FASTCOPY(s, d, n) bcopy (s, d, n) -# endif /* HAVE_BCOPY */ -#endif /* !__GNUC__ */ - -#if !defined (NULL) -# define NULL 0 -#endif - -#define start_of_data() &etext - -#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ -#define ISFREE ((char) 0x54) /* magic byte that implies free block */ - /* this is for error checking only */ -#define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by - memalign, with the rest of the word - being the distance to the true - beginning of the block. */ -extern char etext; - -#if !defined (SBRK_DECLARED) -extern char *sbrk (); -#endif /* !SBRK_DECLARED */ - -/* These two are for user programs to look at, when they are interested. */ -unsigned int malloc_sbrk_used; /* amount of data space used now */ -unsigned int malloc_sbrk_unused; /* amount more we can have */ - -/* start of data space; can be changed by calling init_malloc */ -static char *data_space_start; - -static void get_lim_data (); - -#ifdef MSTATS -static int nmalloc[30]; -static int nmal, nfre; -#endif /* MSTATS */ - -/* If range checking is not turned on, all we have is a flag indicating - whether memory is allocated, an index in nextf[], and a size field; to - realloc() memory we copy either size bytes or 1<<(index+3) bytes depending - on whether the former can hold the exact size (given the value of - 'index'). If range checking is on, we always need to know how much space - is allocated, so the 'size' field is never used. */ - -struct mhead { - char mh_alloc; /* ISALLOC or ISFREE */ - char mh_index; /* index in nextf[] */ -/* Remainder are valid only when block is allocated */ - unsigned short mh_size; /* size, if < 0x10000 */ -#ifdef RCHECK - unsigned int mh_nbytes; /* number of bytes allocated */ - int mh_magic4; /* should be == MAGIC4 */ -#endif /* RCHECK */ -}; - -/* Access free-list pointer of a block. - It is stored at block + 4. - This is not a field in the mhead structure - because we want sizeof (struct mhead) - to describe the overhead for when the block is in use, - and we do not want the free-list pointer to count in that. */ - -#define CHAIN(a) \ - (*(struct mhead **) (sizeof (char *) + (char *) (a))) - -#ifdef RCHECK -# include <stdio.h> -# if !defined (botch) -# define botch(x) abort () -# else -extern void botch(); -# endif /* botch */ - -# if !defined (__STRING) -# if defined (__STDC__) -# define __STRING(x) #x -# else -# define __STRING(x) "x" -# endif -# endif - - /* To implement range checking, we write magic values in at the beginning - and end of each allocated block, and make sure they are undisturbed - whenever a free or a realloc occurs. */ - - /* Written in each of the 4 bytes following the block's real space */ -# define MAGIC1 0x55 - /* Written in the 4 bytes before the block's real space */ -# define MAGIC4 0x55555555 -# define ASSERT(p) if (!(p)) botch(__STRING(p)); else -# define EXTRA 4 /* 4 bytes extra for MAGIC1s */ -#else /* !RCHECK */ -# define ASSERT(p) -# define EXTRA 0 -#endif /* RCHECK */ - -/* nextf[i] is free list of blocks of size 2**(i + 3) */ - -static struct mhead *nextf[30]; - -/* busy[i] is nonzero while allocation of block size i is in progress. */ - -static char busy[30]; - -/* Number of bytes of writable memory we can expect to be able to get */ -static unsigned int lim_data; - -/* Level number of warnings already issued. - 0 -- no warnings issued. - 1 -- 75% warning already issued. - 2 -- 85% warning already issued. -*/ -static int warnlevel; - -/* Function to call to issue a warning; - 0 means don't issue them. */ -static void (*warnfunction) (); - -/* nonzero once initial bunch of free blocks made */ -static int gotpool; - -char *_malloc_base; - -static void getpool (); - -/* Cause reinitialization based on job parameters; - also declare where the end of pure storage is. */ -void -malloc_init (start, warnfun) - char *start; - void (*warnfun) (); -{ - if (start) - data_space_start = start; - lim_data = 0; - warnlevel = 0; - warnfunction = warnfun; -} - -/* Return the maximum size to which MEM can be realloc'd - without actually requiring copying. */ - -int -malloc_usable_size (mem) - char *mem; -{ - int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index; - - return blocksize - sizeof (struct mhead) - EXTRA; -} - -static void -morecore (nu) /* ask system for more memory */ - register int nu; /* size index to get more of */ -{ - register char *cp; - register int nblks; - register unsigned int siz; - - /* Block all signals in case we are executed from a signal handler. */ -#if defined (HAVE_BSD_SIGNALS) - int oldmask; - oldmask = sigsetmask (-1); -#else -# if defined (HAVE_POSIX_SIGNALS) - sigset_t set, oset; - sigfillset (&set); - sigemptyset (&oset); - sigprocmask (SIG_BLOCK, &set, &oset); -# endif /* HAVE_POSIX_SIGNALS */ -#endif /* HAVE_BSD_SIGNALS */ - - if (!data_space_start) - { - data_space_start = start_of_data (); - } - - if (lim_data == 0) - get_lim_data (); - - /* On initial startup, get two blocks of each size up to 1k bytes */ - if (!gotpool) - { getpool (); getpool (); gotpool = 1; } - - /* Find current end of memory and issue warning if getting near max */ - - cp = sbrk (0); - siz = cp - data_space_start; - malloc_sbrk_used = siz; - malloc_sbrk_unused = lim_data - siz; - - if (warnfunction) - switch (warnlevel) - { - case 0: - if (siz > (lim_data / 4) * 3) - { - warnlevel++; - (*warnfunction) ("Warning: past 75% of memory limit"); - } - break; - case 1: - if (siz > (lim_data / 20) * 17) - { - warnlevel++; - (*warnfunction) ("Warning: past 85% of memory limit"); - } - break; - case 2: - if (siz > (lim_data / 20) * 19) - { - warnlevel++; - (*warnfunction) ("Warning: past 95% of memory limit"); - } - break; - } - - if ((int) cp & 0x3ff) /* land on 1K boundaries */ - sbrk (1024 - ((int) cp & 0x3ff)); - - /* Take at least 2k, and figure out how many blocks of the desired size - we're about to get */ - nblks = 1; - if ((siz = nu) < 8) - nblks = 1 << ((siz = 8) - nu); - - if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) - return; /* no more room! */ - - if ((int) cp & 7) - { /* shouldn't happen, but just in case */ - cp = (char *) (((int) cp + 8) & ~7); - nblks--; - } - - /* save new header and link the nblks blocks together */ - nextf[nu] = (struct mhead *) cp; - siz = 1 << (nu + 3); - while (1) - { - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = nu; - if (--nblks <= 0) break; - CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); - cp += siz; - } - CHAIN ((struct mhead *) cp) = 0; - -#if defined (HAVE_BSD_SIGNALS) - sigsetmask (oldmask); -#else -# if defined (HAVE_POSIX_SIGNALS) - sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); -# endif -#endif /* HAVE_BSD_SIGNALS */ -} - -static void -getpool () -{ - register int nu; - register char *cp = sbrk (0); - - if ((int) cp & 0x3ff) /* land on 1K boundaries */ - sbrk (1024 - ((int) cp & 0x3ff)); - - /* Record address of start of space allocated by malloc. */ - if (_malloc_base == 0) - _malloc_base = cp; - - /* Get 2k of storage */ - - cp = sbrk (04000); - if (cp == (char *) -1) - return; - - /* Divide it into an initial 8-word block - plus one block of size 2**nu for nu = 3 ... 10. */ - - CHAIN (cp) = nextf[0]; - nextf[0] = (struct mhead *) cp; - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = 0; - cp += 8; - - for (nu = 0; nu < 7; nu++) - { - CHAIN (cp) = nextf[nu]; - nextf[nu] = (struct mhead *) cp; - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = nu; - cp += 8 << nu; - } -} - -#if defined (MEMSCRAMBLE) || !defined (NO_CALLOC) -static char * -zmemset (s, c, n) - char *s; - int c; - register int n; -{ - register char *sp; - - sp = s; - while (--n >= 0) - *sp++ = c; - return (s); -} -#endif /* MEMSCRAMBLE || !NO_CALLOC */ - -char * -malloc (n) /* get a block */ - unsigned int n; -{ - register struct mhead *p; - register unsigned int nbytes; - register int nunits = 0; - - /* Figure out how many bytes are required, rounding up to the nearest - multiple of 4, then figure out which nextf[] area to use */ - nbytes = (n + sizeof *p + EXTRA + 3) & ~3; - { - register unsigned int shiftr = (nbytes - 1) >> 2; - - while (shiftr >>= 1) - nunits++; - } - - /* In case this is reentrant use of malloc from signal handler, - pick a block size that no other malloc level is currently - trying to allocate. That's the easiest harmless way not to - interfere with the other level of execution. */ - while (busy[nunits]) nunits++; - busy[nunits] = 1; - - /* If there are no blocks of the appropriate size, go get some */ - /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ - if (nextf[nunits] == 0) - morecore (nunits); - - /* Get one block off the list, and set the new list head */ - if ((p = nextf[nunits]) == 0) - { - busy[nunits] = 0; - return 0; - } - nextf[nunits] = CHAIN (p); - busy[nunits] = 0; - - /* Check for free block clobbered */ - /* If not for this check, we would gobble a clobbered free chain ptr */ - /* and bomb out on the NEXT allocate of this size block */ - if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) -#ifdef RCHECK - botch ("block on free list clobbered"); -#else /* not RCHECK */ - abort (); -#endif /* not RCHECK */ - - /* Fill in the info, and if range checking, set up the magic numbers */ - p -> mh_alloc = ISALLOC; -#ifdef RCHECK - p -> mh_nbytes = n; - p -> mh_magic4 = MAGIC4; - { - register char *m = (char *) (p + 1) + n; - - *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; - } -#else /* not RCHECK */ - p -> mh_size = n; -#endif /* not RCHECK */ -#ifdef MEMSCRAMBLE - zmemset ((char *)(p + 1), 0xdf, n); /* scramble previous contents */ -#endif -#ifdef MSTATS - nmalloc[nunits]++; - nmal++; -#endif /* MSTATS */ - return (char *) (p + 1); -} - -void -free (mem) - char *mem; -{ - register struct mhead *p; - { - register char *ap = mem; - - if (ap == 0) - return; - - p = (struct mhead *) ap - 1; - - if (p -> mh_alloc == ISMEMALIGN) - { -#ifdef RCHECK - ap -= p->mh_nbytes; -#else - ap -= p->mh_size; /* XXX */ -#endif - p = (struct mhead *) ap - 1; - } - -#ifndef RCHECK - if (p -> mh_alloc != ISALLOC) - abort (); - -#else /* RCHECK */ - if (p -> mh_alloc != ISALLOC) - { - if (p -> mh_alloc == ISFREE) - botch ("free: Called with already freed block argument\n"); - else - botch ("free: Called with unallocated block argument\n"); - } - - ASSERT (p -> mh_magic4 == MAGIC4); - ap += p -> mh_nbytes; - ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); - ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); -#endif /* RCHECK */ - } -#ifdef MEMSCRAMBLE - { - register int n; - -#ifdef RCHECK - n = p->mh_nbytes; -#else /* not RCHECK */ - n = p->mh_size; -#endif /* not RCHECK */ - zmemset (mem, 0xcf, n); - } -#endif - { - register int nunits = p -> mh_index; - - ASSERT (nunits <= 29); - p -> mh_alloc = ISFREE; - - /* Protect against signal handlers calling malloc. */ - busy[nunits] = 1; - /* Put this block on the free list. */ - CHAIN (p) = nextf[nunits]; - nextf[nunits] = p; - busy[nunits] = 0; - -#ifdef MSTATS - nmalloc[nunits]--; - nfre++; -#endif /* MSTATS */ - } -} - -char * -realloc (mem, n) - char *mem; - register unsigned int n; -{ - register struct mhead *p; - register unsigned int tocopy; - register unsigned int nbytes; - register int nunits; - - if ((p = (struct mhead *) mem) == 0) - return malloc (n); - p--; - nunits = p -> mh_index; - ASSERT (p -> mh_alloc == ISALLOC); -#ifdef RCHECK - ASSERT (p -> mh_magic4 == MAGIC4); - { - register char *m = mem + (tocopy = p -> mh_nbytes); - ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); - ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); - } -#else /* not RCHECK */ - if (p -> mh_index >= 13) - tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; - else - tocopy = p -> mh_size; -#endif /* not RCHECK */ - - /* See if desired size rounds to same power of 2 as actual size. */ - nbytes = (n + sizeof *p + EXTRA + 7) & ~7; - - /* If ok, use the same block, just marking its size as changed. */ - if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) - { -#ifdef RCHECK - register char *m = mem + tocopy; - *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; - p-> mh_nbytes = n; - m = mem + n; - *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; -#else /* not RCHECK */ - p -> mh_size = n; -#endif /* not RCHECK */ - return mem; - } - - if (n < tocopy) - tocopy = n; - { - register char *new; - - if ((new = malloc (n)) == 0) - return 0; - FASTCOPY (mem, new, tocopy); - free (mem); - return new; - } -} - -char * -memalign (alignment, size) - unsigned int alignment, size; -{ - register char *ptr; - register char *aligned; - register struct mhead *p; - - ptr = malloc (size + alignment); - - if (ptr == 0) - return 0; - /* If entire block has the desired alignment, just accept it. */ - if (((int) ptr & (alignment - 1)) == 0) - return ptr; - /* Otherwise, get address of byte in the block that has that alignment. */ - aligned = (char *) (((int) ptr + alignment - 1) & -alignment); - - /* Store a suitable indication of how to free the block, - so that free can find the true beginning of it. */ - p = (struct mhead *) aligned - 1; - p -> mh_size = aligned - ptr; - p -> mh_alloc = ISMEMALIGN; - return aligned; -} - -#if !defined (HPUX) -/* This runs into trouble with getpagesize on HPUX, and Multimax machines. - Patching out seems cleaner than the ugly fix needed. */ -#if defined (__STDC__) -void * -#else -char * -#endif -valloc (size) - size_t size; -{ - return memalign (getpagesize (), size); -} -#endif /* !HPUX */ - -#ifndef NO_CALLOC -char * -calloc (n, s) - size_t n, s; -{ - size_t total; - char *result; - - total = n * s; - result = malloc (total); - if (result) - zmemset (result, 0, total); - return result; -} - -void -cfree (p) - char *p; -{ - free (p); -} -#endif /* !NO_CALLOC */ - -#ifdef MSTATS -/* Return statistics describing allocation of blocks of size 2**n. */ - -struct mstats_value - { - int blocksize; - int nfree; - int nused; - }; - -struct mstats_value -malloc_stats (size) - int size; -{ - struct mstats_value v; - register int i; - register struct mhead *p; - - v.nfree = 0; - - if (size < 0 || size >= 30) - { - v.blocksize = 0; - v.nused = 0; - return v; - } - - v.blocksize = 1 << (size + 3); - v.nused = nmalloc[size]; - - for (p = nextf[size]; p; p = CHAIN (p)) - v.nfree++; - - return v; -} -#endif /* MSTATS */ - -/* - * This function returns the total number of bytes that the process - * will be allowed to allocate via the sbrk(2) system call. On - * BSD systems this is the total space allocatable to stack and - * data. On USG systems this is the data space only. - */ - -#if !defined (HAVE_RESOURCE) -extern long ulimit (); - -static void -get_lim_data () -{ - lim_data = ulimit (3, 0); - lim_data -= (long) data_space_start; -} - -#else /* HAVE_RESOURCE */ -static void -get_lim_data () -{ - struct rlimit XXrlimit; - - getrlimit (RLIMIT_DATA, &XXrlimit); -#ifdef RLIM_INFINITY - lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ -#else - lim_data = XXrlimit.rlim_cur; /* soft limit */ -#endif -} - -#endif /* HAVE_RESOURCE */ diff --git a/lib/malloc/shmalloc.h b/lib/malloc/shmalloc.h new file mode 100644 index 0000000..7143803 --- /dev/null +++ b/lib/malloc/shmalloc.h @@ -0,0 +1,67 @@ +/* Functions (currently) for use by the shell to do malloc debugging and + tracking. */ +/* Copyright (C) 2001 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _SH_MALLOC_H +#define _SH_MALLOC_H + +#ifndef __P +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define __P(protos) protos +# else +# define __P(protos) () +# endif +#endif + +/* Generic pointer type. */ +#ifndef PTR_T + +#if defined (__STDC__) +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* PTR_T */ + + +extern PTR_T sh_malloc __P((size_t, const char *, int)); +extern PTR_T sh_realloc __P((PTR_T, size_t, const char *, int)); +extern void sh_free __P((PTR_T, const char *, int)); + +extern PTR_T sh_memalign __P((unsigned int, size_t, const char *, int)); + +extern PTR_T sh_calloc __P((size_t, size_t, const char *, int)); +extern void sh_cfree __P((PTR_T, const char *, int)); + +extern PTR_T sh_valloc __P((size_t, const char *, int)); + +/* trace.c */ +extern int malloc_set_trace __P((int)); +extern void malloc_set_tracefp (); /* full prototype requires stdio.h */ + +/* table.c */ +extern void mregister_dump_table __P((void)); +extern void mregister_table_init __P((void)); +extern int malloc_set_register __P((int)); + +/* stats.c */ +extern void print_malloc_stats __P((char *)); +extern void fprint_malloc_stats (); /* full prototype requires stdio.h */ +extern void trace_malloc_stats __P((char *)); + +#endif diff --git a/lib/malloc/stats.c b/lib/malloc/stats.c new file mode 100644 index 0000000..48fba1b --- /dev/null +++ b/lib/malloc/stats.c @@ -0,0 +1,147 @@ +/* stats.c - malloc statistics */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imalloc.h" + +#ifdef MALLOC_STATS + +#include <stdio.h> +#include "mstats.h" + +struct _malstats _mstats; + +struct bucket_stats +malloc_bucket_stats (size) + int size; +{ + struct bucket_stats v; + + v.nfree = 0; + + if (size < 0 || size >= NBUCKETS) + { + v.blocksize = 0; + v.nused = v.nmal = v.nmorecore = v.nsplit = 0; + return v; + } + + v.blocksize = 1 << (size + 3); + v.nused = _mstats.nmalloc[size]; + v.nmal = _mstats.tmalloc[size]; + v.nmorecore = _mstats.nmorecore[size]; + v.nsplit = _mstats.nsplit[size]; + + v.nfree = malloc_free_blocks (size); /* call back to malloc.c */ + + return v; +} + +/* Return a copy of _MSTATS, with two additional fields filled in: + BYTESFREE is the total number of bytes on free lists. BYTESUSED + is the total number of bytes in use. These two fields are fairly + expensive to compute, so we do it only when asked to. */ +struct _malstats +malloc_stats () +{ + struct _malstats result; + struct bucket_stats v; + register int i; + + result = _mstats; + result.bytesused = result.bytesfree = 0; + for (i = 0; i < NBUCKETS; i++) + { + v = malloc_bucket_stats (i); + result.bytesfree += v.nfree * v.blocksize; + result.bytesused += v.nused * v.blocksize; + } + return (result); +} + +static void +_print_malloc_stats (s, fp) + char *s; + FILE *fp; +{ + register int i; + unsigned long totused, totfree; + struct bucket_stats v; + + fprintf (fp, "Memory allocation statistics: %s\n\tsize\tfree\tin use\ttotal\tmorecore\tsplit\n", s ? s : ""); + for (i = totused = totfree = 0; i < NBUCKETS; i++) + { + v = malloc_bucket_stats (i); + fprintf (fp, "%12lu\t%4d\t%6d\t%5d\t%8d\t%5d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nsplit); + totfree += v.nfree * v.blocksize; + totused += v.nused * v.blocksize; + } + fprintf (fp, "\nTotal bytes in use: %lu, total bytes free: %lu\n", + totused, totfree); + fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n", + _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy); + fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n", + _mstats.nsbrk, _mstats.tsbrk); + fprintf (fp, "Total blocks split: %d, total block coalesces: %d\n", + _mstats.tbsplit, _mstats.tbcoalesce); +} + +void +print_malloc_stats (s) + char *s; +{ + _print_malloc_stats (s, stderr); +} + +void +fprint_malloc_stats (s, fp) + char *s; + FILE *fp; +{ + _print_malloc_stats (s, fp); +} + +#define TRACEROOT "/var/tmp/maltrace/trace." +extern char *inttostr (); + +void +trace_malloc_stats (s) + char *s; +{ + char ibuf[32], *ip; + char fname[64]; + long p; + FILE *fp; + + p = getpid(); + ip = inttostr(p, ibuf, sizeof(ibuf)); + strcpy (fname, TRACEROOT); + strcat (fname, ip); + fp = fopen(fname, "w"); + if (fp) + { + _print_malloc_stats (s, fp); + fflush(fp); + fclose(fp); + } +} + +#endif /* MALLOC_STATS */ diff --git a/lib/malloc/table.c b/lib/malloc/table.c new file mode 100644 index 0000000..d7c48c5 --- /dev/null +++ b/lib/malloc/table.c @@ -0,0 +1,267 @@ +/* table.c - bookkeeping functions for allocated memory */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#include "imalloc.h" +#include "table.h" + +extern int malloc_register; + +#ifdef MALLOC_REGISTER + +#define FIND_ALLOC 0x01 /* allocate new entry or find existing */ +#define FIND_EXIST 0x02 /* find existing entry */ + +static int table_count = 0; +static mr_table_t mem_table[REG_TABLE_SIZE]; + +/* + * NOTE: taken from dmalloc (http://dmalloc.com) and modified. + */ +static unsigned int +mt_hash (key) + const PTR_T key; +{ + unsigned int a, b, c, len; + unsigned long x; + + /* set up the internal state */ + a = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + x = (unsigned long)key; /* truncation is OK */ + b = x >> 8; + c = x >> 3; /* XXX - was >> 4 */ + + HASH_MIX(a, b, c); + return c; +} + +#if 0 +static unsigned int +which_bucket (mem) + PTR_T mem; +{ + return (mt_hash ((unsigned char *)mem) % REG_TABLE_SIZE); +} +#else +#define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) % REG_TABLE_SIZE); +#endif + +static mr_table_t * +find_entry (mem, flags) + PTR_T mem; + int flags; +{ + unsigned int bucket; + register mr_table_t *tp; + mr_table_t *endp, *lastp; + + bucket = which_bucket (mem); /* get initial hash */ + tp = endp = mem_table + bucket; + lastp = mem_table + REG_TABLE_SIZE; + + while (1) + { + if (tp->mem == mem) + return (tp); + if (tp->mem == 0 && (flags & FIND_ALLOC)) + { + table_count++; + return (tp); + } + + tp++; + + if (tp == lastp) /* wrap around */ + tp = mem_table; + + if (tp == endp && (flags & FIND_EXIST)) + return ((mr_table_t *)NULL); + + if (tp == endp && (flags & FIND_ALLOC)) + break; + } + + /* oops. table is full. replace an existing free entry. */ + do + { + if (tp->flags & MT_FREE) + { + memset(tp, 0, sizeof (mr_table_t)); + return (tp); + } + tp++; + } + while (tp != endp); + + /* wow. entirely full. return NULL. */ + return ((mr_table_t *)NULL); +} + +mr_table_t * +mr_table_entry (mem) + PTR_T mem; +{ + return (find_entry (mem, FIND_EXIST)); +} + +void +mregister_describe_mem (mem, fp) + PTR_T mem; + FILE *fp; +{ + mr_table_t *entry; + + entry = find_entry (mem, FIND_EXIST); + if (entry == 0) + return; + fprintf (fp, "malloc: %p: %s: last %s from %s:%d\n", + mem, + (entry->flags & MT_ALLOC) ? "allocated" : "free", + (entry->flags & MT_ALLOC) ? "allocated" : "freed", + entry->file ? entry->file : "unknown", + entry->line); +} + +void +mregister_alloc (tag, mem, size, file, line) + const char *tag; + PTR_T mem; + size_t size; + const char *file; + int line; +{ + mr_table_t *tentry; + + tentry = find_entry (mem, FIND_ALLOC); + + if (tentry == 0) + { + /* oops. table is full. punt. */ + fprintf (stderr, "register_alloc: alloc table is full?\n"); + return; + } + + if (tentry->flags & MT_ALLOC) + { + /* oops. bad bookkeeping. ignore for now */ + fprintf (stderr, "register_alloc: %p already in table as allocated?\n", mem); + } + + tentry->mem = mem; + tentry->size = size; + tentry->func = tag; + tentry->flags = MT_ALLOC; + tentry->file = file; + tentry->line = line; + tentry->nalloc++; +} + +void +mregister_free (mem, size, file, line) + PTR_T mem; + int size; + const char *file; + int line; +{ + mr_table_t *tentry; + + tentry = find_entry (mem, FIND_EXIST); + if (tentry == 0) + { + /* oops. not found. */ + fprintf (stderr, "register_free: %p not in allocation table?\n", mem); + return; + } + if (tentry->flags & MT_FREE) + { + /* oops. bad bookkeeping. ignore for now */ + fprintf (stderr, "register_free: %p already in table as free?\n", mem); + } + + tentry->flags = MT_FREE; + tentry->func = "free"; + tentry->file = file; + tentry->line = line; + tentry->nfree++; +} + +/* If we ever add more flags, this will require changes. */ +static char * +_entry_flags(x) + int x; +{ + if (x & MT_FREE) + return "free"; + else if (x & MT_ALLOC) + return "allocated"; + else + return "undetermined?"; +} + +static void +_register_dump_table(fp) + FILE *fp; +{ + register int i; + mr_table_t entry; + + for (i = 0; i < REG_TABLE_SIZE; i++) + { + entry = mem_table[i]; + if (entry.mem) + fprintf (fp, "[%d] %p:%d:%s:%s:%s:%d:%d:%d\n", i, + entry.mem, entry.size, + _entry_flags(entry.flags), + entry.func ? entry.func : "unknown", + entry.file ? entry.file : "unknown", + entry.line, + entry.nalloc, entry.nfree); + } +} + +void +mregister_dump_table() +{ + _register_dump_table (stderr); +} + +void +mregister_table_init () +{ + memset (mem_table, 0, sizeof(mr_table_t) * REG_TABLE_SIZE); + table_count = 0; +} + +#endif /* MALLOC_REGISTER */ + +int +malloc_set_register(n) + int n; +{ + int old; + + old = malloc_register; + malloc_register = n; + return old; +} diff --git a/lib/malloc/table.h b/lib/malloc/table.h new file mode 100644 index 0000000..f39beb8 --- /dev/null +++ b/lib/malloc/table.h @@ -0,0 +1,103 @@ +/* table.h - definitions for tables for keeping track of allocated memory */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _MTABLE_H +#define _MTABLE_H + +#include "imalloc.h" + +#ifdef MALLOC_REGISTER + +/* values for flags byte. */ +#define MT_ALLOC 0x01 +#define MT_FREE 0x02 + +/* + * Memory table entry. + * + * MEM is the address of the allocated pointer. + * SIZE is the requested allocation size. + * FLAGS includes either MT_ALLOC (MEM is allocated) or MT_FREE (MEM is + * not allocated). Other flags later. + * FUNC is set to the name of the function doing the allocation (from the + * `tag' argument to register_alloc(). + * FILE and LINE are the filename and line number of the last allocation + * and free (depending on STATUS) of MEM. + * NALLOC and NFREE are incremented on each allocation that returns MEM or + * each free of MEM, respectively (way to keep track of memory reuse + * and how well the free lists are working). + * + */ +typedef struct mr_table { + PTR_T mem; + size_t size; + char flags; + const char *func; + const char *file; + int line; + int nalloc, nfree; +} mr_table_t; + +#define REG_TABLE_SIZE 8192 + +extern mr_table_t *mr_table_entry (); +extern void mregister_alloc (); +extern void mregister_free (); +extern void mregister_describe_mem (); +extern void mregister_dump_table (); +extern void mregister_table_init (); + +/* NOTE: HASH_MIX taken from dmalloc (http://dmalloc.com) */ + +/* + * void HASH_MIX + * + * DESCRIPTION: + * + * Mix 3 32-bit values reversibly. For every delta with one or two + * bits set, and the deltas of all three high bits or all three low + * bits, whether the original value of a,b,c is almost all zero or is + * uniformly distributed. + * + * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c + * have at least 1/4 probability of changing. If mix() is run + * forward, every bit of c will change between 1/3 and 2/3 of the + * time. (Well, 22/100 and 78/100 for some 2-bit deltas.) + * + * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a + * superscalar machine (like a Pentium or a Sparc). No faster mixer + * seems to work, that's the result of my brute-force search. There + * were about 2^68 hashes to choose from. I only tested about a + * billion of those. + */ +#define HASH_MIX(a, b, c) \ + do { \ + a -= b; a -= c; a ^= (c >> 13); \ + b -= c; b -= a; b ^= (a << 8); \ + c -= a; c -= b; c ^= (b >> 13); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 16); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 3); \ + b -= c; b -= a; b ^= (a << 10); \ + c -= a; c -= b; c ^= (b >> 15); \ + } while(0) + +#endif /* MALLOC_REGISTER */ + +#endif /* _MTABLE_H */ diff --git a/lib/malloc/trace.c b/lib/malloc/trace.c new file mode 100644 index 0000000..418509e --- /dev/null +++ b/lib/malloc/trace.c @@ -0,0 +1,93 @@ +/* trace.c - tracing functions for malloc */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#include "imalloc.h" + +extern int malloc_trace; + +static int _mtrace_verbose = 0; + +#ifdef MALLOC_TRACE + +FILE *_mtrace_fp = NULL; + +void +mtrace_alloc (tag, mem, size, file, line) + const char *tag; + PTR_T mem; + size_t size; + const char *file; + int line; +{ + if (_mtrace_fp == NULL) + _mtrace_fp = stderr; + + if (_mtrace_verbose) + fprintf (_mtrace_fp, "alloc: %s: %p (%d bytes) from '%s:%d'\n", + tag, mem, size, file ? file : "unknown", line); + else + fprintf (_mtrace_fp, "alloc:%p:%d:%s:%d\n", + mem, size, file ? file : "unknown", line); +} + +void +mtrace_free (mem, size, file, line) + PTR_T mem; + int size; + const char *file; + int line; +{ + if (_mtrace_fp == NULL) + _mtrace_fp = stderr; + + if (_mtrace_verbose) + fprintf (_mtrace_fp, "free: %p (%d bytes) from '%s:%d'\n", + mem, size, file ? file : "unknown", line); + else + fprintf (_mtrace_fp, "free:%p:%d:%s:%d\n", + mem, size, file ? file : "unknown", line); +} +#endif /* MALLOC_TRACE */ + +int +malloc_set_trace(n) + int n; +{ + int old; + + old = malloc_trace; + malloc_trace = n; + _mtrace_verbose = (n > 1); + return old; +} + +void +malloc_set_tracefp(fp) + FILE *fp; +{ +#ifdef MALLOC_TRACE + _mtrace_fp = fp ? fp : stderr; +#endif +} diff --git a/lib/malloc/xleaktrace b/lib/malloc/xleaktrace new file mode 100755 index 0000000..573437c --- /dev/null +++ b/lib/malloc/xleaktrace @@ -0,0 +1,43 @@ +#! /usr/bin/awk -f +# +# xleaktrace - print unfreed memory using input generated by compact malloc +# tracing (malloc_set_trace(1)) +# +# NOTE: we ignore `realloc' tags because they're just extra information +# +# Chet Ramey +# chet@po.cwru.edu +# +BEGIN { + FS=":"; +} + +$1 == "alloc" { + alloc[$2] = 1; + + size[$2] = $3; + file[$2] = $4; + line[$2] = $5; + +# printf "allocated: %s %d %d %s %d\n", $2, alloc[$2], size[$2], file[$2], line[$2]; + } + +$1 == "free" { + if ($2 in alloc) { + alloc[$2] = 0; +# printf "freed: %s %d\n", $2, alloc[$2]; + } else + printf "freeing unallocated pointer: %s\n", $2; + + } + +END { + printf "unfreed memory\n"; + for (ptr in alloc) { + if (alloc[ptr] == 1) { + printf "%s (%d) from %s:%d\n", ptr, size[ptr], file[ptr], line[ptr]; + } + } +} + + diff --git a/lib/malloc/xmalloc.c b/lib/malloc/xmalloc.c index a495d77..b037222 100644 --- a/lib/malloc/xmalloc.c +++ b/lib/malloc/xmalloc.c @@ -31,7 +31,16 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ -static void memory_error_and_abort (); +/* Generic pointer type. */ +#ifndef PTR_T + +#if defined (__STDC__) +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* PTR_T */ /* **************************************************************** */ /* */ @@ -39,48 +48,46 @@ static void memory_error_and_abort (); /* */ /* **************************************************************** */ +static void +memory_error_and_abort (fname) + char *fname; +{ + fprintf (stderr, "%s: out of virtual memory\n", fname); + exit (2); +} + /* Return a pointer to free()able block of memory large enough to hold BYTES number of bytes. If the memory cannot be allocated, print an error message and abort. */ -char * +PTR_T xmalloc (bytes) - int bytes; + size_t bytes; { - char *temp; + PTR_T temp; - temp = (char *)malloc (bytes); + temp = malloc (bytes); if (temp == 0) memory_error_and_abort ("xmalloc"); return (temp); } -char * +PTR_T xrealloc (pointer, bytes) - char *pointer; - int bytes; + PTR_T pointer; + size_t bytes; { - char *temp; + PTR_T temp; - temp = pointer ? (char *)realloc (pointer, bytes) : (char *)malloc (bytes); + temp = pointer ? realloc (pointer, bytes) : malloc (bytes); if (temp == 0) memory_error_and_abort ("xrealloc"); return (temp); } -static void -memory_error_and_abort (fname) - char *fname; -{ - fprintf (stderr, "%s: out of virtual memory\n", fname); - exit (2); -} - -/* Use this as the function to call when adding unwind protects so we - don't need to know what free() returns. */ void xfree (string) - char *string; + PTR_T string; { if (string) free (string); diff --git a/lib/readline/Makefile.in b/lib/readline/Makefile.in index 7bfcffd..2f47e3a 100644 --- a/lib/readline/Makefile.in +++ b/lib/readline/Makefile.in @@ -121,6 +121,12 @@ documentation: force test -d doc || mkdir doc -( cd doc && $(MAKE) $(MFLAGS) ) +# Since tilde.c is shared between readline and bash, make sure we compile +# it with the right flags when it's built as part of readline +tilde.o: tilde.c + rm -f $@ + $(CC) $(CCFLAGS) -DREADLINE_LIBRARY -c $(srcdir)/tilde.c + force: install: @@ -152,7 +158,7 @@ bind.o: ansi_stdlib.h posixstat.h bind.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h bind.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h bind.o: history.h rlstdc.h -callback.o: rlconf.h +callback.o: rlconf.h ansi_stdlib.h callback.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h callback.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h compat.o: rlstdc.h @@ -228,7 +234,7 @@ tilde.o: tilde.h undo.o: ansi_stdlib.h undo.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h undo.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h -undo.o: history.h rlstdc.h +undo.o: history.h rlstdc.h xmalloc.h util.o: posixjmp.h ansi_stdlib.h util.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h util.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h diff --git a/lib/readline/ansi_stdlib.h b/lib/readline/ansi_stdlib.h index 3a354f2..db13cd2 100644 --- a/lib/readline/ansi_stdlib.h +++ b/lib/readline/ansi_stdlib.h @@ -25,14 +25,24 @@ /* String conversion functions. */ extern int atoi (); -extern long int atol (); extern double atof (); extern double strtod (); /* Memory allocation functions. */ -extern char *malloc (); -extern char *realloc (); +/* Generic pointer type. */ +#ifndef PTR_T + +#if defined (__STDC__) +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* PTR_T */ + +extern PTR_T malloc (); +extern PTR_T realloc (); extern void free (); /* Other miscellaneous functions. */ diff --git a/lib/readline/bind.c b/lib/readline/bind.c index 74fa6f2..d429177 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -68,9 +68,9 @@ extern char *strchr (), *strrchr (); /* Variables exported by this file. */ Keymap rl_binding_keymap; -static int _rl_read_init_file __P((const char *, int)); -static int glean_key_from_name __P((char *)); -static int substring_member_of_array __P((char *, const char **)); +static int _rl_read_init_file PARAMS((const char *, int)); +static int glean_key_from_name PARAMS((char *)); +static int substring_member_of_array PARAMS((char *, const char **)); static int currently_reading_init_file; @@ -255,7 +255,7 @@ rl_generic_bind (type, keyseq, data, map) return -1; } - keys = xmalloc (1 + (2 * strlen (keyseq))); + keys = (char *)xmalloc (1 + (2 * strlen (keyseq))); /* Translate the ASCII representation of KEYSEQ into an array of characters. Stuff the characters into KEYS, and the length of @@ -269,7 +269,7 @@ rl_generic_bind (type, keyseq, data, map) /* Bind keys, making new keymaps as necessary. */ for (i = 0; i < keys_len; i++) { - int ic = (int) ((unsigned char)keys[i]); + unsigned char ic = keys[i]; if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic)) { @@ -393,16 +393,16 @@ rl_translate_keyseq (seq, array, len) for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++) c = (c * 8) + OCTVALUE (seq[i]); i--; /* auto-increment in for loop */ - array[l++] = c % (largest_char + 1); + array[l++] = c & largest_char; break; case 'x': i++; - for (temp = 3, c = 0; isxdigit (seq[i]) && temp--; i++) + for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++) c = (c * 16) + HEXVALUE (seq[i]); - if (temp == 3) + if (temp == 2) c = 'x'; i--; /* auto-increment in for loop */ - array[l++] = c % (largest_char + 1); + array[l++] = c & largest_char; break; default: /* backslashes before non-special chars just add the char */ array[l++] = c; @@ -472,7 +472,7 @@ _rl_untranslate_macro_value (seq) char *ret, *r, *s; int c; - r = ret = xmalloc (7 * strlen (seq) + 1); + r = ret = (char *)xmalloc (7 * strlen (seq) + 1); for (s = seq; *s; s++) { c = *s; @@ -547,7 +547,7 @@ rl_function_of_keyseq (keyseq, map, type) for (i = 0; keyseq && keyseq[i]; i++) { - int ic = keyseq[i]; + unsigned char ic = keyseq[i]; if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { @@ -782,7 +782,7 @@ _rl_init_file_error (msg) /* */ /* **************************************************************** */ -typedef int _rl_parser_func_t __P((char *)); +typedef int _rl_parser_func_t PARAMS((char *)); /* Things that mean `Control'. */ const char *_rl_possible_control_prefixes[] = { @@ -1145,7 +1145,7 @@ rl_parse_and_bind (string) char *seq; register int j, k, passc; - seq = xmalloc (1 + strlen (string)); + seq = (char *)xmalloc (1 + strlen (string)); for (j = 1, k = passc = 0; string[j]; j++) { /* Allow backslash to quote characters, but leave them in place. @@ -1203,7 +1203,7 @@ rl_parse_and_bind (string) /* Temporary. Handle old-style keyname with macro-binding. */ if (*funname == '\'' || *funname == '"') { - unsigned char useq[2]; + char useq[2]; int fl = strlen (funname); useq[0] = key; useq[1] = '\0'; @@ -1245,10 +1245,12 @@ static struct { { "disable-completion", &rl_inhibit_completion, 0 }, { "enable-keypad", &_rl_enable_keypad, 0 }, { "expand-tilde", &rl_complete_with_tilde_expansion, 0 }, + { "history-preserve-point", &_rl_history_preserve_point, 0 }, { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode, 0 }, { "input-meta", &_rl_meta_flag, 0 }, { "mark-directories", &_rl_complete_mark_directories, 0 }, { "mark-modified-lines", &_rl_mark_modified_lines, 0 }, + { "match-hidden-files", &_rl_match_hidden_files, 0 }, { "meta-flag", &_rl_meta_flag, 0 }, { "output-meta", &_rl_output_meta_chars, 0 }, { "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL }, @@ -1294,7 +1296,7 @@ hack_special_boolean_var (i) } } -typedef int _rl_sv_func_t __P((const char *)); +typedef int _rl_sv_func_t PARAMS((const char *)); /* These *must* correspond to the array indices for the appropriate string variable. (Though they're not used right now.) */ @@ -1308,12 +1310,12 @@ typedef int _rl_sv_func_t __P((const char *)); #define V_INT 2 /* Forward declarations */ -static int sv_bell_style __P((const char *)); -static int sv_combegin __P((const char *)); -static int sv_compquery __P((const char *)); -static int sv_editmode __P((const char *)); -static int sv_isrchterm __P((const char *)); -static int sv_keymap __P((const char *)); +static int sv_bell_style PARAMS((const char *)); +static int sv_combegin PARAMS((const char *)); +static int sv_compquery PARAMS((const char *)); +static int sv_editmode PARAMS((const char *)); +static int sv_isrchterm PARAMS((const char *)); +static int sv_keymap PARAMS((const char *)); static struct { const char *name; @@ -1446,24 +1448,22 @@ sv_keymap (value) return 1; } -#define _SET_BELL(v) do { _rl_bell_preference = v; return 0; } while (0) - static int sv_bell_style (value) const char *value; { if (value == 0 || *value == '\0') - _SET_BELL (AUDIBLE_BELL); + _rl_bell_preference = AUDIBLE_BELL; else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0) - _SET_BELL (NO_BELL); + _rl_bell_preference = NO_BELL; else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0) - _SET_BELL (AUDIBLE_BELL); + _rl_bell_preference = AUDIBLE_BELL; else if (_rl_stricmp (value, "visible") == 0) - _SET_BELL (VISIBLE_BELL); + _rl_bell_preference = VISIBLE_BELL; else return 1; + return 0; } -#undef _SET_BELL static int sv_isrchterm (value) @@ -1493,7 +1493,7 @@ sv_isrchterm (value) v[end] = '\0'; /* The value starts at v + beg. Translate it into a character string. */ - _rl_isearch_terminators = (unsigned char *)xmalloc (2 * strlen (v) + 1); + _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1); rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end); _rl_isearch_terminators[end] = '\0'; @@ -1751,7 +1751,7 @@ rl_invoking_keyseqs_in_map (function, map) if (result_index + 2 > result_size) { result_size += 10; - result = (char **) xrealloc (result, result_size * sizeof (char *)); + result = (char **)xrealloc (result, result_size * sizeof (char *)); } result[result_index++] = keyname; @@ -1803,7 +1803,7 @@ rl_invoking_keyseqs_in_map (function, map) if (result_index + 2 > result_size) { result_size += 10; - result = (char **) xrealloc (result, result_size * sizeof (char *)); + result = (char **)xrealloc (result, result_size * sizeof (char *)); } result[result_index++] = keyname; @@ -1951,7 +1951,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix) prefix_len = prefix ? strlen (prefix) : 0; if (key == ESC) { - keyname = xmalloc (3 + prefix_len); + keyname = (char *)xmalloc (3 + prefix_len); if (prefix) strcpy (keyname, prefix); keyname[prefix_len] = '\\'; @@ -1963,7 +1963,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix) keyname = _rl_get_keyname (key); if (prefix) { - out = xmalloc (strlen (keyname) + prefix_len + 1); + out = (char *)xmalloc (strlen (keyname) + prefix_len + 1); strcpy (out, prefix); strcpy (out + prefix_len, keyname); free (keyname); diff --git a/lib/readline/callback.c b/lib/readline/callback.c index 9ddf9f1..a8f4323 100644 --- a/lib/readline/callback.c +++ b/lib/readline/callback.c @@ -30,6 +30,13 @@ #if defined (READLINE_CALLBACKS) #include <sys/types.h> + +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#else +# include "ansi_stdlib.h" +#endif + #include <stdio.h> /* System-specific feature definitions and include files. */ diff --git a/lib/readline/chardefs.h b/lib/readline/chardefs.h index aec704d..33ee512 100644 --- a/lib/readline/chardefs.h +++ b/lib/readline/chardefs.h @@ -27,10 +27,14 @@ #if defined (HAVE_CONFIG_H) # if defined (HAVE_STRING_H) +# if ! defined (STDC_HEADERS) && defined (HAVE_MEMORY_H) +# include <memory.h> +# endif # include <string.h> -# else -# include <strings.h> # endif /* HAVE_STRING_H */ +# if defined (HAVE_STRINGS_H) +# include <strings.h> +# endif /* HAVE_STRINGS_H */ #else # include <string.h> #endif /* !HAVE_CONFIG_H */ @@ -60,33 +64,56 @@ #define UNMETA(c) ((c) & (~meta_character_bit)) #define UNCTRL(c) _rl_to_upper(((c)|control_character_bit)) -/* Old versions -#define _rl_lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1))) -#define _rl_uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1))) -#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') -*/ +#if defined STDC_HEADERS || (!defined (isascii) && !defined (HAVE_ISASCII)) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii(c) +#endif + +#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT) +# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#endif + +#define NON_NEGATIVE(c) ((unsigned char)(c) == (c)) -#define _rl_lowercase_p(c) (islower(c)) -#define _rl_uppercase_p(c) (isupper(c)) -#define _rl_digit_p(x) (isdigit (x)) +#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) +#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) +#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) +#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) +#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) -#define _rl_pure_alphabetic(c) (_rl_lowercase_p(c) || _rl_uppercase_p(c)) -#define ALPHABETIC(c) (_rl_lowercase_p(c) || _rl_uppercase_p(c) || _rl_digit_p(c)) +#define _rl_lowercase_p(c) (NON_NEGATIVE(c) && ISLOWER(c)) +#define _rl_uppercase_p(c) (NON_NEGATIVE(c) && ISUPPER(c)) +#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') -/* Old versions -# define _rl_to_upper(c) (_rl_lowercase_p(c) ? ((c) - 32) : (c)) -# define _rl_to_lower(c) (_rl_uppercase_p(c) ? ((c) + 32) : (c)) -*/ +#define _rl_pure_alphabetic(c) (NON_NEGATIVE(c) && ISALPHA(c)) +#define ALPHABETIC(c) (NON_NEGATIVE(c) && ISALNUM(c)) #ifndef _rl_to_upper -# define _rl_to_upper(c) (islower(c) ? toupper(c) : (c)) -# define _rl_to_lower(c) (isupper(c) ? tolower(c) : (c)) +# define _rl_to_upper(c) (_rl_lowercase_p(c) ? toupper((unsigned char)c) : (c)) +# define _rl_to_lower(c) (_rl_uppercase_p(c) ? tolower((unsigned char)c) : (c)) #endif #ifndef _rl_digit_value -#define _rl_digit_value(x) ((x) - '0') +# define _rl_digit_value(x) ((x) - '0') #endif +#ifndef _rl_isident +# define _rl_isident(c) (ISALNUM(c) || (c) == '_') +#endif + +#ifndef ISOCTAL +# define ISOCTAL(c) ((c) >= '0' && (c) <= '7') +#endif +#define OCTVALUE(c) ((c) - '0') + +#define HEXVALUE(c) \ + (((c) >= 'a' && (c) <= 'f') \ + ? (c)-'a'+10 \ + : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') + #ifndef NEWLINE #define NEWLINE '\n' #endif @@ -123,18 +150,4 @@ #endif #define ESC CTRL('[') -#ifndef ISOCTAL -#define ISOCTAL(c) ((c) >= '0' && (c) <= '7') -#endif -#define OCTVALUE(c) ((c) - '0') - -#ifndef isxdigit -# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - -#define HEXVALUE(c) \ - (((c) >= 'a' && (c) <= 'f') \ - ? (c)-'a'+10 \ - : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') - #endif /* _CHARDEFS_H_ */ diff --git a/lib/readline/compat.c b/lib/readline/compat.c index 1f41559..a66d210 100644 --- a/lib/readline/compat.c +++ b/lib/readline/compat.c @@ -30,18 +30,18 @@ #include "rlstdc.h" #include "rltypedefs.h" -extern void rl_free_undo_list __P((void)); -extern int rl_maybe_save_line __P((void)); -extern int rl_maybe_unsave_line __P((void)); -extern int rl_maybe_replace_line __P((void)); - -extern int rl_crlf __P((void)); -extern int rl_ding __P((void)); -extern int rl_alphabetic __P((int)); - -extern char **rl_completion_matches __P((const char *, rl_compentry_func_t *)); -extern char *rl_username_completion_function __P((const char *, int)); -extern char *rl_filename_completion_function __P((const char *, int)); +extern void rl_free_undo_list PARAMS((void)); +extern int rl_maybe_save_line PARAMS((void)); +extern int rl_maybe_unsave_line PARAMS((void)); +extern int rl_maybe_replace_line PARAMS((void)); + +extern int rl_crlf PARAMS((void)); +extern int rl_ding PARAMS((void)); +extern int rl_alphabetic PARAMS((int)); + +extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *)); +extern char *rl_username_completion_function PARAMS((const char *, int)); +extern char *rl_filename_completion_function PARAMS((const char *, int)); /* Provide backwards-compatible entry points for old function names. */ diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 927bd52..cbcee28 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -67,10 +67,19 @@ typedef int QSFUNC (const void *, const void *); typedef int QSFUNC (); #endif +#ifdef HAVE_LSTAT +# define LSTAT lstat +#else +# define LSTAT stat +#endif + +/* Unix version of a hidden file. Could be different on other systems. */ +#define HIDDEN_FILE(fname) ((fname)[0] == '.') + /* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is defined. */ #if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE) -extern struct passwd *getpwent __P((void)); +extern struct passwd *getpwent PARAMS((void)); #endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */ /* If non-zero, then this is the address of a function to call when @@ -86,17 +95,28 @@ rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)N # if !defined (X_OK) # define X_OK 1 # endif -static int stat_char __P((char *)); +static int stat_char PARAMS((char *)); #endif -static char *rl_quote_filename __P((char *, int, char *)); +static char *rl_quote_filename PARAMS((char *, int, char *)); + +static int get_y_or_n PARAMS((void)); +static char *printable_part PARAMS((char *)); +static int print_filename PARAMS((char *, char *)); +static char find_completion_word PARAMS((int *, int *)); + +static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int)); -static char **remove_duplicate_matches __P((char **)); -static void insert_match __P((char *, int, int, char *)); -static int append_to_match __P((char *, int, int)); -static void insert_all_matches __P((char **, int, char *)); -static void display_matches __P((char **)); -static int compute_lcd_of_matches __P((char **, int, const char *)); +static char **remove_duplicate_matches PARAMS((char **)); +static void insert_match PARAMS((char *, int, int, char *)); +static int append_to_match PARAMS((char *, int, int, int)); +static void insert_all_matches PARAMS((char **, int, char *)); +static void display_matches PARAMS((char **)); +static int compute_lcd_of_matches PARAMS((char **, int, const char *)); +static int postprocess_matches PARAMS((char ***, int)); + +static char *make_quoted_replacement PARAMS((char *, int, char *)); +static void free_match_list PARAMS((char **)); /* **************************************************************** */ /* */ @@ -123,6 +143,10 @@ int _rl_completion_case_fold = 1; int _rl_completion_case_fold; #endif +/* If non-zero, don't match hidden files (filenames beginning with a `.' on + Unix) when doing filename completion. */ +int _rl_match_hidden_files = 1; + /* Global variables available to applications using readline. */ #if defined (VISIBLE_STATS) @@ -387,7 +411,7 @@ printable_part (pathname) temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL; #if defined (__MSDOS__) - if (rl_filename_completion_desired && temp == 0 && isalpha (pathname[0]) && pathname[1] == ':') + if (rl_filename_completion_desired && temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') temp = pathname + 1; #endif return (temp ? ++temp : pathname); @@ -461,7 +485,7 @@ print_filename (to_print, full_pathname) slen = strlen (s); tlen = strlen (to_print); - new_full_pathname = xmalloc (slen + tlen + 2); + new_full_pathname = (char *)xmalloc (slen + tlen + 2); strcpy (new_full_pathname, s); new_full_pathname[slen] = '/'; strcpy (new_full_pathname + slen + 1, to_print); @@ -496,7 +520,7 @@ rl_quote_filename (s, rtype, qcp) { char *r; - r = xmalloc (strlen (s) + 2); + r = (char *)xmalloc (strlen (s) + 2); *r = *rl_completer_quote_characters; strcpy (r + 1, s); if (qcp) @@ -507,7 +531,7 @@ rl_quote_filename (s, rtype, qcp) /* Find the bounds of the current word for completion purposes, and leave rl_point set to the end of the word. This function skips quoted substrings (characters between matched pairs of characters in - rl_completer_quote_characters. First we try to find an unclosed + rl_completer_quote_characters). First we try to find an unclosed quoted substring on which to do matching. If one is not found, we use the word break characters to find the boundaries of the current word. We call an application-specific function to decide whether or not a @@ -797,13 +821,40 @@ compute_lcd_of_matches (match_list, matches, text) value of matches[0]. */ if (low == 0 && text && *text) { - match_list[0] = xmalloc (strlen (text) + 1); + match_list[0] = (char *)xmalloc (strlen (text) + 1); strcpy (match_list[0], text); } else { - match_list[0] = xmalloc (low + 1); - strncpy (match_list[0], match_list[1], low); + match_list[0] = (char *)xmalloc (low + 1); + + /* If we are ignoring case, try to preserve the case of the string + the user typed in the face of multiple matches differing in case. */ + if (_rl_completion_case_fold) + { + /* sort the list to get consistent answers. */ + qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); + + si = strlen (text); + if (si <= low) + { + for (i = 1; i <= matches; i++) + if (strncmp (match_list[i], text, si) == 0) + { + strncpy (match_list[0], match_list[i], low); + break; + } + /* no casematch, use first entry */ + if (i > matches) + strncpy (match_list[0], match_list[1], low); + } + else + /* otherwise, just use the text the user typed. */ + strncpy (match_list[0], text, low); + } + else + strncpy (match_list[0], match_list[1], low); + match_list[0][low] = '\0'; } @@ -1102,14 +1153,16 @@ insert_match (match, start, mtype, qc) just-inserted match. If the user has specified that directories should be marked by a trailing `/', append one of those instead. The default trailing character is a space. Returns the number of characters - appended. */ + appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS + has them) and don't add a suffix for a symlink to a directory. A + nontrivial match is one that actually adds to the word being completed. */ static int -append_to_match (text, delimiter, quote_char) +append_to_match (text, delimiter, quote_char, nontrivial_match) char *text; - int delimiter, quote_char; + int delimiter, quote_char, nontrivial_match; { char temp_string[4], *filename; - int temp_string_index; + int temp_string_index, s; struct stat finfo; temp_string_index = 0; @@ -1126,11 +1179,19 @@ append_to_match (text, delimiter, quote_char) if (rl_filename_completion_desired) { filename = tilde_expand (text); - if (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) + s = nontrivial_match ? LSTAT (filename, &finfo) : stat (filename, &finfo); + if (s == 0 && S_ISDIR (finfo.st_mode)) { if (_rl_complete_mark_directories && rl_line_buffer[rl_point] != '/') rl_insert_text ("/"); } +#ifdef S_ISLNK + /* Don't add anything if the filename is a symlink and resolves to a + directory. */ + else if (s == 0 && S_ISLNK (finfo.st_mode) && + stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) + ; +#endif else { if (rl_point == rl_end) @@ -1210,7 +1271,7 @@ rl_complete_internal (what_to_do) { char **matches; rl_compentry_func_t *our_func; - int start, end, delimiter, found_quote, i; + int start, end, delimiter, found_quote, i, nontrivial_lcd; char *text, *saved_line_buffer; char quote_char; @@ -1240,6 +1301,9 @@ rl_complete_internal (what_to_do) text = rl_copy_text (start, end); matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); + /* nontrivial_lcd is set if the common prefix adds something to the word + being completed. */ + nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; free (text); if (matches == 0) @@ -1291,7 +1355,7 @@ rl_complete_internal (what_to_do) rl_ding (); /* There are other matches remaining. */ } else - append_to_match (matches[0], delimiter, quote_char); + append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); break; @@ -1428,7 +1492,7 @@ rl_username_completion_function (text, state) } else { - value = xmalloc (2 + strlen (entry->pw_name)); + value = (char *)xmalloc (2 + strlen (entry->pw_name)); *value = *text; @@ -1483,7 +1547,7 @@ rl_filename_completion_function (text, state) #if defined (__MSDOS__) /* special hack for //X/... */ - if (dirname[0] == '/' && dirname[1] == '/' && isalpha (dirname[2]) && dirname[3] == '/') + if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/') temp = strrchr (dirname + 3, '/'); #endif @@ -1494,7 +1558,7 @@ rl_filename_completion_function (text, state) } #if defined (__MSDOS__) /* searches from current directory on the drive */ - else if (isalpha (dirname[0]) && dirname[1] == ':') + else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':') { strcpy (filename, dirname + 2); dirname[2] = '\0'; @@ -1544,10 +1608,14 @@ rl_filename_completion_function (text, state) entry = (struct dirent *)NULL; while (directory && (entry = readdir (directory))) { - /* Special case for no filename. - All entries except "." and ".." match. */ + /* Special case for no filename. If the user has disabled the + `match-hidden-files' variable, skip filenames beginning with `.'. + All other entries except "." and ".." match. */ if (filename_len == 0) { + if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name)) + continue; + if (entry->d_name[0] != '.' || (entry->d_name[1] && (entry->d_name[1] != '.' || entry->d_name[2]))) @@ -1607,7 +1675,7 @@ rl_filename_completion_function (text, state) if (rl_complete_with_tilde_expansion && *users_dirname == '~') { dirlen = strlen (dirname); - temp = xmalloc (2 + dirlen + D_NAMLEN (entry)); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, dirname); /* Canonicalization cuts off any final slash present. We may need to add it back. */ @@ -1620,7 +1688,7 @@ rl_filename_completion_function (text, state) else { dirlen = strlen (users_dirname); - temp = xmalloc (2 + dirlen + D_NAMLEN (entry)); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, users_dirname); /* Make sure that temp has a trailing slash here. */ if (users_dirname[dirlen - 1] != '/') @@ -1745,7 +1813,8 @@ rl_menu_complete (count, ignore) else { insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); - append_to_match (matches[match_list_index], delimiter, quote_char); + append_to_match (matches[match_list_index], delimiter, quote_char, + strcmp (orig_text, matches[match_list_index])); } completion_changed_buffer = 1; diff --git a/lib/readline/display.c b/lib/readline/display.c index cb1c500..4ce7d6b 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -62,11 +62,11 @@ extern char *strchr (), *strrchr (); extern char *_rl_term_forward_char; #endif -static void update_line __P((char *, char *, int, int, int, int)); -static void space_to_eol __P((int)); -static void delete_chars __P((int)); -static void insert_some_chars __P((char *, int)); -static void cr __P((void)); +static void update_line PARAMS((char *, char *, int, int, int, int)); +static void space_to_eol PARAMS((int)); +static void delete_chars PARAMS((int)); +static void insert_some_chars PARAMS((char *, int)); +static void cr PARAMS((void)); static int *inv_lbreaks, *vis_lbreaks; static int inv_lbsize, vis_lbsize; @@ -202,7 +202,7 @@ expand_prompt (pmt, lp, lip, niflp) } l = strlen (pmt); - r = ret = xmalloc (l + 1); + r = ret = (char *)xmalloc (l + 1); invfl = 0; /* invisible chars in first line of prompt */ @@ -335,16 +335,16 @@ init_line_structures (minsize) { if (line_size < minsize) line_size = minsize; - visible_line = xmalloc (line_size); - invisible_line = xmalloc (line_size); + visible_line = (char *)xmalloc (line_size); + invisible_line = (char *)xmalloc (line_size); } else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ { line_size *= 2; if (line_size < minsize) line_size = minsize; - visible_line = xrealloc (visible_line, line_size); - invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + invisible_line = (char *)xrealloc (invisible_line, line_size); } for (n = minsize; n < line_size; n++) @@ -421,8 +421,8 @@ rl_redisplay () if (temp >= line_size) { line_size = (temp + 1024) - (temp % 1024); - visible_line = xrealloc (visible_line, line_size); - line = invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + line = invisible_line = (char *)xrealloc (invisible_line, line_size); } strncpy (line + out, local_prompt, local_len); out += local_len; @@ -455,8 +455,8 @@ rl_redisplay () if (temp >= line_size) { line_size = (temp + 1024) - (temp % 1024); - visible_line = xrealloc (visible_line, line_size); - line = invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + line = invisible_line = (char *)xrealloc (invisible_line, line_size); } strncpy (line + out, prompt_this_line, pmtlen); out += pmtlen; @@ -530,8 +530,8 @@ rl_redisplay () if (out + 8 >= line_size) /* XXX - 8 for \t */ { line_size *= 2; - visible_line = xrealloc (visible_line, line_size); - invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + invisible_line = (char *)xrealloc (invisible_line, line_size); line = invisible_line; } @@ -1330,7 +1330,7 @@ rl_character_len (c, pos) if (CTRL_CHAR (c) || c == RUBOUT) return (2); - return ((isprint (uc)) ? 1 : 2); + return ((ISPRINT (uc)) ? 1 : 2); } /* How to print things in the "echo-area". The prompt is treated as a @@ -1357,7 +1357,12 @@ rl_message (va_alist) format = va_arg (args, char *); #endif +#if defined (HAVE_VSNPRINTF) + vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); +#else vsprintf (msg_buf, format, args); + msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ +#endif va_end (args); rl_display_prompt = msg_buf; @@ -1370,6 +1375,7 @@ rl_message (format, arg1, arg2) char *format; { sprintf (msg_buf, format, arg1, arg2); + msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ rl_display_prompt = msg_buf; (*rl_redisplay_function) (); return 0; @@ -1436,7 +1442,7 @@ _rl_make_prompt_for_search (pchar) if (saved_local_prompt == 0) { len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; - pmt = xmalloc (len + 2); + pmt = (char *)xmalloc (len + 2); if (len) strcpy (pmt, rl_prompt); pmt[len] = pchar; @@ -1445,7 +1451,7 @@ _rl_make_prompt_for_search (pchar) else { len = *saved_local_prompt ? strlen (saved_local_prompt) : 0; - pmt = xmalloc (len + 2); + pmt = (char *)xmalloc (len + 2); if (len) strcpy (pmt, saved_local_prompt); pmt[len] = pchar; diff --git a/lib/readline/doc/hstech.texinfo b/lib/readline/doc/hstech.texinfo index e4ac50c..003721a 100644 --- a/lib/readline/doc/hstech.texinfo +++ b/lib/readline/doc/hstech.texinfo @@ -422,7 +422,7 @@ This is disabled by default. @end deftypevar @deftypevar {char *} history_word_delimiters -The characters that separate tokens for \fBhistory_tokenize()\fP. +The characters that separate tokens for @code{history_tokenize()}. The default value is @code{" \t\n()<>;&|"}. @end deftypevar diff --git a/lib/readline/doc/manvers.texinfo b/lib/readline/doc/manvers.texinfo index 23d3073..859afc1 100644 --- a/lib/readline/doc/manvers.texinfo +++ b/lib/readline/doc/manvers.texinfo @@ -1,6 +1,6 @@ -@set EDITION 4.2-beta -@set VERSION 4.2-beta -@set UPDATED 2001 Mar 12 -@set UPDATE-MONTH Mar 2001 +@set EDITION 4.2a +@set VERSION 4.2a +@set UPDATED 2001 October 9 +@set UPDATE-MONTH October 2001 -@set LASTCHANGE Mon Mar 12 05:36:44 EST 2001 +@set LASTCHANGE Tue Oct 9 15:03:34 EDT 2001 diff --git a/lib/readline/doc/rltech.texinfo b/lib/readline/doc/rltech.texinfo index acc8d4d..be9f662 100644 --- a/lib/readline/doc/rltech.texinfo +++ b/lib/readline/doc/rltech.texinfo @@ -176,6 +176,16 @@ in any file that uses Readline's features. Since some of the definitions in @code{readline.h} use the @code{stdio} library, the file @code{<stdio.h>} should be included before @code{readline.h}. +@code{readline.h} defines a C preprocessor variable that should +be treated as an integer, @code{RL_READLINE_VERSION}, which may +be used to conditionally compile application code depending on +the installed Readline version. The value is a hexadecimal +encoding of the major and minor version numbers of the library, +of the form 0x@var{MMmm}. @var{MM} is the two-digit major +version number; @var{mm} is the two-digit minor version number. +For Readline 4.2, for example, the value of +@code{RL_READLINE_VERSION} would be @code{0x0402}. + @menu * Readline Typedefs:: C declarations to make code readable. * Function Writing:: Variables and calling conventions. @@ -348,6 +358,14 @@ never sets it. The version number of this revision of the library. @end deftypevar +@deftypevar int rl_readline_version +An integer encoding the current version of the library. The encoding is +of the form 0x@var{MMmm}, where @var{MM} is the two-digit major version +number, and @var{mm} is the two-digit minor version number. +For example, for Readline-4.2, @code{rl_readline_version} would have the +value 0x0402. +@end deftypevar + @deftypevar {int} rl_gnu_readline_p Always set to 1, denoting that this is @sc{gnu} readline rather than some emulation. @@ -1076,6 +1094,15 @@ Set the time interval (in microseconds) that Readline waits when showing a balancing character when @code{blink-matching-paren} has been enabled. @end deftypefun +@deftypefun {char *} rl_get_termcap (const char *cap) +Retrieve the string value of the termcap capability @var{cap}. +Readline fetches the termcap entry for the current terminal name and +uses those capabilities to move around the screen line and perform other +terminal-specific operations, like erasing a line. Readline does not +use all of a terminal's capabilities, and this function will return +values for only those capabilities Readline uses. +@end deftypefun + @node Alternate Interface @subsection Alternate Interface diff --git a/lib/readline/doc/rluser.texinfo b/lib/readline/doc/rluser.texinfo index e5bf54d..e4e56ff 100644 --- a/lib/readline/doc/rluser.texinfo +++ b/lib/readline/doc/rluser.texinfo @@ -10,7 +10,7 @@ use these features. There is a document entitled "readline.texinfo" which contains both end-user and programmer documentation for the GNU Readline Library. -Copyright (C) 1988-2000 Free Software Foundation, Inc. +Copyright (C) 1988-2001 Free Software Foundation, Inc. Authored by Brian Fox and Chet Ramey. @@ -235,7 +235,7 @@ words, to the end of the next word. Word boundaries are the same as those used by @kbd{M-f}. @item M-@key{DEL} -Kill from the cursor the start of the previous word, or, if between +Kill from the cursor the start of the current word, or, if between words, to the start of the previous word. Word boundaries are the same as those used by @kbd{M-b}. @@ -312,6 +312,10 @@ the line, thereby executing the command from the history list. A movement command will terminate the search, make the last line found the current line, and begin editing. +Readline remembers the last incremental search string. If two +@kbd{C-r}s are typed without any intervening characters defining a new +search string, any remembered search string is used. + Non-incremental searches read the entire search string before starting to search for matching history lines. The search string may be typed by the user or be part of the contents of the current line. @@ -452,6 +456,11 @@ arrow keys. The default is @samp{off}. If set to @samp{on}, tilde expansion is performed when Readline attempts word completion. The default is @samp{off}. +@vindex history-preserve-point +If set to @samp{on}, the history code attempts to place point at the +same location on each history line retrived with @code{previous-history} +or @code{next-history}. + @item horizontal-scroll-mode @vindex horizontal-scroll-mode This variable can be set to either @samp{on} or @samp{off}. Setting it @@ -503,6 +512,14 @@ This variable, when set to @samp{on}, causes Readline to display an asterisk (@samp{*}) at the start of history lines which have been modified. This variable is @samp{off} by default. +@item match-hidden-files +@vindex match-hidden-files +This variable, when set to @samp{on}, causes Readline to match files whose +names begin with a @samp{.} (hidden files) when performing filename +completion, unless the leading @samp{.} is +supplied by the user in the filename to be completed. +This variable is @samp{on} by default. + @item output-meta @vindex output-meta If set to @samp{on}, Readline will display characters with the @@ -644,11 +661,11 @@ horizontal tab @item \v vertical tab @item \@var{nnn} -the character whose @sc{ascii} code is the octal value @var{nnn} -(one to three digits) -@item \x@var{nnn} -the character whose @sc{ascii} code is the hexadecimal value @var{nnn} +the eight-bit character whose value is the octal value @var{nnn} (one to three digits) +@item \x@var{HH} +the eight-bit character whose value is the hexadecimal value @var{HH} +(one or two hex digits) @end table When entering the text of a macro, single or double quotes must @@ -1021,6 +1038,8 @@ Negative arguments have no effect. @item transpose-words (M-t) Drag the word before point past the word after point, moving point past that word as well. +If the insertion point is at the end of the line, this transposes +the last two words on the line. @item upcase-word (M-u) Uppercase the current (or following) word. With a negative argument, @@ -1534,7 +1553,7 @@ matches were generated. @item complete @btindex complete @example -@code{complete [-abcdefjkvu] [-o @var{comp-option}] [-A @var{action}] [-G @var{globpat}] [-W @var{wordlist}] +@code{complete [-abcdefgjkvu] [-o @var{comp-option}] [-A @var{action}] [-G @var{globpat}] [-W @var{wordlist}] [-P @var{prefix}] [-S @var{suffix}] [-X @var{filterpat}] [-F @var{function}] [-C @var{command}] @var{name} [@var{name} @dots{}]} @code{complete -pr [@var{name} @dots{}]} @@ -1617,6 +1636,9 @@ File names. May also be specified as @option{-f}. @item function Names of shell functions. +@item group +Group names. May also be specified as @option{-g}. + @item helptopic Help topics as accepted by the @code{help} builtin (@pxref{Bash Builtins}). diff --git a/lib/readline/examples/fileman.c b/lib/readline/examples/fileman.c index e976848..578491a 100644 --- a/lib/readline/examples/fileman.c +++ b/lib/readline/examples/fileman.c @@ -41,15 +41,15 @@ extern char *xmalloc (); /* The names of functions that actually do the manipulation. */ -int com_list __P((char *)); -int com_view __P((char *)); -int com_rename __P((char *)); -int com_stat __P((char *)); -int com_pwd __P((char *)); -int com_delete __P((char *)); -int com_help __P((char *)); -int com_cd __P((char *)); -int com_quit __P((char *)); +int com_list PARAMS((char *)); +int com_view PARAMS((char *)); +int com_rename PARAMS((char *)); +int com_stat PARAMS((char *)); +int com_pwd PARAMS((char *)); +int com_delete PARAMS((char *)); +int com_help PARAMS((char *)); +int com_cd PARAMS((char *)); +int com_quit PARAMS((char *)); /* A structure which contains information on the commands this program can understand. */ @@ -212,8 +212,8 @@ stripwhite (string) /* */ /* **************************************************************** */ -char *command_generator __P((const char *, int)); -char **fileman_completion __P((const char *, int, int)); +char *command_generator PARAMS((const char *, int)); +char **fileman_completion PARAMS((const char *, int, int)); /* Tell the GNU Readline library how to complete. We want to try to complete on command names if this is the first word in the line, or on filenames diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c index e09faf5..e4f2801 100644 --- a/lib/readline/funmap.c +++ b/lib/readline/funmap.c @@ -46,7 +46,7 @@ typedef int QSFUNC (const void *, const void *); typedef int QSFUNC (); #endif -extern int _rl_qsort_string_compare __P((char **, char **)); +extern int _rl_qsort_string_compare PARAMS((char **, char **)); FUNMAP **funmap; static int funmap_size; diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c index 1c8a1d9..04f6478 100644 --- a/lib/readline/histexpand.c +++ b/lib/readline/histexpand.c @@ -56,7 +56,7 @@ #define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" #define HISTORY_QUOTE_CHARACTERS "\"'`" -typedef int _hist_search_func_t __P((const char *, int)); +typedef int _hist_search_func_t PARAMS((const char *, int)); static char error_pointer; @@ -65,10 +65,10 @@ static char *subst_rhs; static int subst_lhs_len; static int subst_rhs_len; -static char *get_history_word_specifier __P((char *, char *, int *)); -static char *history_find_word __P((char *, int)); +static char *get_history_word_specifier PARAMS((char *, char *, int *)); +static char *history_find_word PARAMS((char *, int)); -static char *quote_breaks __P((char *)); +static char *quote_breaks PARAMS((char *)); /* Variables exported by this file. */ /* The character that represents the start of a history expansion @@ -212,7 +212,7 @@ get_history_event (string, caller_index, delimiting_quote) break; which = i - local_index; - temp = xmalloc (1 + which); + temp = (char *)xmalloc (1 + which); if (which) strncpy (temp, string + local_index, which); temp[which] = '\0'; @@ -314,7 +314,7 @@ quote_breaks (s) len += 2; } - r = ret = xmalloc (len); + r = ret = (char *)xmalloc (len); *r++ = '\''; for (p = s; p && *p; ) { @@ -379,7 +379,7 @@ hist_error(s, start, current, errtype) break; } - temp = xmalloc (ll + elen + 3); + temp = (char *)xmalloc (ll + elen + 3); strncpy (temp, s + start, ll); temp[ll] = ':'; temp[ll + 1] = ' '; @@ -415,7 +415,7 @@ get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) if (si > i || is_rhs) { - s = xmalloc (si - i + 1); + s = (char *)xmalloc (si - i + 1); for (j = 0, k = i; k < si; j++, k++) { /* Remove a backslash quoting the search string delimiter. */ @@ -442,13 +442,13 @@ postproc_subst_rhs () char *new; int i, j, new_size; - new = xmalloc (new_size = subst_rhs_len + subst_lhs_len); + new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len); for (i = j = 0; i < subst_rhs_len; i++) { if (subst_rhs[i] == '&') { if (j + subst_lhs_len >= new_size) - new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); + new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); strcpy (new + j, subst_lhs); j += subst_lhs_len; } @@ -458,7 +458,7 @@ postproc_subst_rhs () if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&') i++; if (j >= new_size) - new = xrealloc (new, new_size *= 2); + new = (char *)xrealloc (new, new_size *= 2); new[j++] = subst_rhs[i]; } } @@ -485,7 +485,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) char *event, *temp, *result, *tstr, *t, c, *word_spec; int result_len; - result = xmalloc (result_len = 128); + result = (char *)xmalloc (result_len = 128); i = start; @@ -698,7 +698,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) if (STREQN (temp+si, subst_lhs, subst_lhs_len)) { int len = subst_rhs_len - subst_lhs_len + l_temp; - new_event = xmalloc (1 + len); + new_event = (char *)xmalloc (1 + len); strncpy (new_event, temp, si); strncpy (new_event + si, subst_rhs, subst_rhs_len); strncpy (new_event + si + subst_rhs_len, @@ -759,7 +759,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) n = strlen (temp); if (n >= result_len) - result = xrealloc (result, n + 2); + result = (char *)xrealloc (result, n + 2); strcpy (result, temp); free (temp); @@ -790,7 +790,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) { \ while (j >= result_len) \ result_len += 128; \ - result = xrealloc (result, result_len); \ + result = (char *)xrealloc (result, result_len); \ } \ strcpy (result + j - sl, s); \ } \ @@ -800,7 +800,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) do \ { \ if (j >= result_len - 1) \ - result = xrealloc (result, result_len += 64); \ + result = (char *)xrealloc (result, result_len += 64); \ result[j++] = c; \ result[j] = '\0'; \ } \ @@ -834,7 +834,7 @@ history_expand (hstring, output) } /* Prepare the buffer for printing error messages. */ - result = xmalloc (result_len = 256); + result = (char *)xmalloc (result_len = 256); result[0] = '\0'; only_printing = modified = 0; @@ -851,7 +851,7 @@ history_expand (hstring, output) that is the substitution that we do. */ if (hstring[0] == history_subst_char) { - string = xmalloc (l + 5); + string = (char *)xmalloc (l + 5); string[0] = string[1] = history_expansion_char; string[2] = ':'; @@ -960,7 +960,7 @@ history_expand (hstring, output) hist_string_extract_single_quoted (string, &i); slen = i - quote + 2; - temp = xmalloc (slen); + temp = (char *)xmalloc (slen); strncpy (temp, string + quote, slen); temp[slen - 1] = '\0'; ADD_STRING (temp); @@ -974,7 +974,7 @@ history_expand (hstring, output) case -2: /* history_comment_char */ if (i == 0 || member (string[i - 1], history_word_delimiters)) { - temp = xmalloc (l - i + 1); + temp = (char *)xmalloc (l - i + 1); strcpy (temp, string + i); ADD_STRING (temp); free (temp); @@ -1006,7 +1006,7 @@ history_expand (hstring, output) { if (result) { - temp = xmalloc (1 + strlen (result)); + temp = (char *)xmalloc (1 + strlen (result)); strcpy (temp, result); ADD_STRING (temp); free (temp); @@ -1140,7 +1140,14 @@ get_history_word_specifier (spec, from, caller_index) i++; last = '$'; } - else if (!spec[i] || spec[i] == ':') /* could be modifier separator */ +#if 0 + else if (!spec[i] || spec[i] == ':') + /* check against `:' because there could be a modifier separator */ +#else + else + /* csh seems to allow anything to terminate the word spec here, + leaving it as an abbreviation. */ +#endif last = -1; /* x- abbreviates x-$ omitting word `$' */ } @@ -1196,7 +1203,7 @@ history_arg_extract (first, last, string) { for (size = 0, i = first; i < last; i++) size += strlen (list[i]) + 1; - result = xmalloc (size + 1); + result = (char *)xmalloc (size + 1); result[0] = '\0'; for (i = first, offset = 0; i < last; i++) @@ -1329,7 +1336,7 @@ history_tokenize_internal (string, wind, indp) len = i - start; if (result_index + 2 >= size) result = (char **)xrealloc (result, ((size += 10) * sizeof (char *))); - result[result_index] = xmalloc (1 + len); + result[result_index] = (char *)xmalloc (1 + len); strncpy (result[result_index], string + start, len); result[result_index][len] = '\0'; result[++result_index] = (char *)NULL; diff --git a/lib/readline/histfile.c b/lib/readline/histfile.c index c0582de..ab3c6c1 100644 --- a/lib/readline/histfile.c +++ b/lib/readline/histfile.c @@ -105,7 +105,7 @@ history_filename (filename) else home_len = strlen (home); - return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ + return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ strcpy (return_val, home); return_val[home_len] = '/'; #if defined (__MSDOS__) @@ -161,7 +161,7 @@ read_history_range (filename, from, to) goto error_and_exit; } - buffer = xmalloc (file_size + 1); + buffer = (char *)xmalloc (file_size + 1); chars_read = read (file, buffer, file_size); if (chars_read < 0) @@ -276,7 +276,7 @@ history_truncate_file (fname, lines) goto truncate_exit; } - buffer = xmalloc (file_size + 1); + buffer = (char *)xmalloc (file_size + 1); chars_read = read (file, buffer, file_size); close (file); @@ -367,7 +367,7 @@ history_do_write (filename, nelements, overwrite) buffer_size += 1 + strlen (the_history[i]->line); /* Allocate the buffer, and fill it. */ - buffer = xmalloc (buffer_size); + buffer = (char *)xmalloc (buffer_size); for (j = 0, i = history_length - nelements; i < history_length; i++) { diff --git a/lib/readline/history.c b/lib/readline/history.c index d59d8ce..e2d65ea 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -71,6 +71,9 @@ static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; history that we save. */ static int history_stifled; +/* The current number of slots allocated to the input_history. */ +static int history_size; + /* If HISTORY_STIFLED is non-zero, then this is the maximum number of entries to remember. */ int history_max_entries; @@ -83,9 +86,6 @@ int history_offset; /* The number of strings currently stored in the history list. */ int history_length; -/* The current number of slots allocated to the input_history. */ -static int history_size; - /* The logical `base' of the history array. It defaults to 1. */ int history_base = 1; diff --git a/lib/readline/history.h b/lib/readline/history.h index 947902e..58b5de4 100644 --- a/lib/readline/history.h +++ b/lib/readline/history.h @@ -62,81 +62,81 @@ typedef struct _hist_state { /* Begin a session in which the history functions might be used. This just initializes the interactive variables. */ -extern void using_history __P((void)); +extern void using_history PARAMS((void)); /* Return the current HISTORY_STATE of the history. */ -extern HISTORY_STATE *history_get_history_state __P((void)); +extern HISTORY_STATE *history_get_history_state PARAMS((void)); /* Set the state of the current history array to STATE. */ -extern void history_set_history_state __P((HISTORY_STATE *)); +extern void history_set_history_state PARAMS((HISTORY_STATE *)); /* Manage the history list. */ /* Place STRING at the end of the history list. The associated data field (if any) is set to NULL. */ -extern void add_history __P((const char *)); +extern void add_history PARAMS((const char *)); /* A reasonably useless function, only here for completeness. WHICH is the magic number that tells us which element to delete. The elements are numbered from 0. */ -extern HIST_ENTRY *remove_history __P((int)); +extern HIST_ENTRY *remove_history PARAMS((int)); /* Make the history entry at WHICH have LINE and DATA. This returns the old entry so you can dispose of the data. In the case of an invalid WHICH, a NULL pointer is returned. */ -extern HIST_ENTRY *replace_history_entry __P((int, const char *, histdata_t)); +extern HIST_ENTRY *replace_history_entry PARAMS((int, const char *, histdata_t)); /* Clear the history list and start over. */ -extern void clear_history __P((void)); +extern void clear_history PARAMS((void)); /* Stifle the history list, remembering only MAX number of entries. */ -extern void stifle_history __P((int)); +extern void stifle_history PARAMS((int)); /* Stop stifling the history. This returns the previous amount the history was stifled by. The value is positive if the history was stifled, negative if it wasn't. */ -extern int unstifle_history __P((void)); +extern int unstifle_history PARAMS((void)); /* Return 1 if the history is stifled, 0 if it is not. */ -extern int history_is_stifled __P((void)); +extern int history_is_stifled PARAMS((void)); /* Information about the history list. */ /* Return a NULL terminated array of HIST_ENTRY which is the current input history. Element 0 of this list is the beginning of time. If there is no history, return NULL. */ -extern HIST_ENTRY **history_list __P((void)); +extern HIST_ENTRY **history_list PARAMS((void)); /* Returns the number which says what history element we are now looking at. */ -extern int where_history __P((void)); +extern int where_history PARAMS((void)); /* Return the history entry at the current position, as determined by history_offset. If there is no entry there, return a NULL pointer. */ -extern HIST_ENTRY *current_history __P((void)); +extern HIST_ENTRY *current_history PARAMS((void)); /* Return the history entry which is logically at OFFSET in the history array. OFFSET is relative to history_base. */ -extern HIST_ENTRY *history_get __P((int)); +extern HIST_ENTRY *history_get PARAMS((int)); /* Return the number of bytes that the primary history entries are using. This just adds up the lengths of the_history->lines. */ -extern int history_total_bytes __P((void)); +extern int history_total_bytes PARAMS((void)); /* Moving around the history list. */ /* Set the position in the history list to POS. */ -extern int history_set_pos __P((int)); +extern int history_set_pos PARAMS((int)); /* Back up history_offset to the previous history entry, and return a pointer to that entry. If there is no previous entry, return a NULL pointer. */ -extern HIST_ENTRY *previous_history __P((void)); +extern HIST_ENTRY *previous_history PARAMS((void)); /* Move history_offset forward to the next item in the input_history, and return the a pointer to that entry. If there is no next entry, return a NULL pointer. */ -extern HIST_ENTRY *next_history __P((void)); +extern HIST_ENTRY *next_history PARAMS((void)); /* Searching the history list. */ @@ -146,45 +146,45 @@ extern HIST_ENTRY *next_history __P((void)); current_history () is the history entry, and the value of this function is the offset in the line of that history entry that the string was found in. Otherwise, nothing is changed, and a -1 is returned. */ -extern int history_search __P((const char *, int)); +extern int history_search PARAMS((const char *, int)); /* Search the history for STRING, starting at history_offset. The search is anchored: matching lines must begin with string. DIRECTION is as in history_search(). */ -extern int history_search_prefix __P((const char *, int)); +extern int history_search_prefix PARAMS((const char *, int)); /* Search for STRING in the history list, starting at POS, an absolute index into the list. DIR, if negative, says to search backwards from POS, else forwards. Returns the absolute index of the history element where STRING was found, or -1 otherwise. */ -extern int history_search_pos __P((const char *, int, int)); +extern int history_search_pos PARAMS((const char *, int, int)); /* Managing the history file. */ /* Add the contents of FILENAME to the history list, a line at a time. If FILENAME is NULL, then read from ~/.history. Returns 0 if successful, or errno if not. */ -extern int read_history __P((const char *)); +extern int read_history PARAMS((const char *)); /* Read a range of lines from FILENAME, adding them to the history list. Start reading at the FROM'th line and end at the TO'th. If FROM is zero, start at the beginning. If TO is less than FROM, read until the end of the file. If FILENAME is NULL, then read from ~/.history. Returns 0 if successful, or errno if not. */ -extern int read_history_range __P((const char *, int, int)); +extern int read_history_range PARAMS((const char *, int, int)); /* Write the current history to FILENAME. If FILENAME is NULL, then write the history list to ~/.history. Values returned are as in read_history (). */ -extern int write_history __P((const char *)); +extern int write_history PARAMS((const char *)); /* Append NELEMENT entries to FILENAME. The entries appended are from the end of the list minus NELEMENTs up to the end of the list. */ -extern int append_history __P((int, const char *)); +extern int append_history PARAMS((int, const char *)); /* Truncate the history file, leaving only the last NLINES lines. */ -extern int history_truncate_file __P((const char *, int)); +extern int history_truncate_file PARAMS((const char *, int)); /* History expansion. */ @@ -200,12 +200,12 @@ extern int history_truncate_file __P((const char *, int)); If an error ocurred in expansion, then OUTPUT contains a descriptive error message. */ -extern int history_expand __P((char *, char **)); +extern int history_expand PARAMS((char *, char **)); /* Extract a string segment consisting of the FIRST through LAST arguments present in STRING. Arguments are broken up as in the shell. */ -extern char *history_arg_extract __P((int, int, const char *)); +extern char *history_arg_extract PARAMS((int, int, const char *)); /* Return the text of the history event beginning at the current offset into STRING. Pass STRING with *INDEX equal to the @@ -213,11 +213,11 @@ extern char *history_arg_extract __P((int, int, const char *)); DELIMITING_QUOTE is a character that is allowed to end the string specification for what to search for in addition to the normal characters `:', ` ', `\t', `\n', and sometimes `?'. */ -extern char *get_history_event __P((const char *, int *, int)); +extern char *get_history_event PARAMS((const char *, int *, int)); /* Return an array of tokens, much as the shell might. The tokens are parsed out of STRING. */ -extern char **history_tokenize __P((const char *)); +extern char **history_tokenize PARAMS((const char *)); /* Exported history variables. */ extern int history_base; diff --git a/lib/readline/histsearch.c b/lib/readline/histsearch.c index ff4f3a1..76303f4 100644 --- a/lib/readline/histsearch.c +++ b/lib/readline/histsearch.c @@ -51,6 +51,8 @@ string. */ char *history_search_delimiter_chars = (char *)NULL; +static int history_search_internal PARAMS((const char *, int, int)); + /* Search the history for STRING, starting at history_offset. If DIRECTION < 0, then the search is through previous entries, else through subsequent. If ANCHORED is non-zero, the string must diff --git a/lib/readline/input.c b/lib/readline/input.c index e5af52d..e34558b 100644 --- a/lib/readline/input.c +++ b/lib/readline/input.c @@ -84,6 +84,11 @@ rl_getc_func_t *rl_getc_function = rl_getc; static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ +static int ibuffer_space PARAMS((void)); +static int rl_get_char PARAMS((int *)); +static int rl_unget_char PARAMS((int)); +static void rl_gather_tyi PARAMS((void)); + /* **************************************************************** */ /* */ /* Character Input Buffering */ @@ -245,7 +250,7 @@ _rl_input_available () fd_set readfds, exceptfds; struct timeval timeout; #endif -#if defined(FIONREAD) +#if !defined (HAVE_SELECT) && defined(FIONREAD) int chars_avail; #endif int tty; @@ -260,13 +265,15 @@ _rl_input_available () timeout.tv_sec = 0; timeout.tv_usec = _keyboard_input_timeout; return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); -#endif +#else #if defined (FIONREAD) if (ioctl (tty, FIONREAD, &chars_avail) == 0) return (chars_avail); #endif +#endif + return 0; } @@ -278,7 +285,7 @@ _rl_insert_typein (c) char *string; i = key = 0; - string = xmalloc (ibuffer_len + 1); + string = (char *)xmalloc (ibuffer_len + 1); string[i++] = (char) c; while ((t = rl_get_char (&key)) && diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c index f8d7695..2e3e16b 100644 --- a/lib/readline/isearch.c +++ b/lib/readline/isearch.c @@ -52,19 +52,23 @@ #include "xmalloc.h" /* Variables exported to other files in the readline library. */ -unsigned char *_rl_isearch_terminators = (unsigned char *)NULL; +char *_rl_isearch_terminators = (char *)NULL; /* Variables imported from other files in the readline library. */ extern HIST_ENTRY *_rl_saved_line_for_history; /* Forward declarations */ -static int rl_search_history __P((int, int)); +static int rl_search_history PARAMS((int, int)); /* Last line found by the current incremental search, so we don't `find' identical lines many times in a row. */ static char *prev_line_found; -static unsigned char *default_isearch_terminators = "\033\012"; +/* Last search string and its length. */ +static char *last_isearch_string; +static int last_isearch_string_len; + +static char *default_isearch_terminators = "\033\012"; /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ @@ -99,7 +103,7 @@ rl_display_search (search_string, reverse_p, where) searchlen = (search_string && *search_string) ? strlen (search_string) : 0; - message = xmalloc (searchlen + 33); + message = (char *)xmalloc (searchlen + 33); msglen = 0; #if defined (NOTDEF) @@ -129,7 +133,7 @@ rl_display_search (search_string, reverse_p, where) strcpy (message + msglen, "': "); - rl_message ("%s", message, 0); + rl_message ("%s", message); free (message); (*rl_redisplay_function) (); } @@ -176,7 +180,7 @@ rl_search_history (direction, invoking_key) /* The list of characters which terminate the search, but are not subsequently executed. If the variable isearch-terminators has been set, we use that value, otherwise we use ESC and C-J. */ - unsigned char *isearch_terminators; + char *isearch_terminators; RL_SETSTATE(RL_STATE_ISEARCH); orig_point = rl_point; @@ -205,7 +209,7 @@ rl_search_history (direction, invoking_key) else { /* Keep track of this so we can free it. */ - allocated_line = xmalloc (1 + strlen (rl_line_buffer)); + allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); strcpy (allocated_line, &rl_line_buffer[0]); lines[i] = allocated_line; } @@ -218,7 +222,7 @@ rl_search_history (direction, invoking_key) rl_save_prompt (); /* Initialize search parameters. */ - search_string = xmalloc (search_string_size = 128); + search_string = (char *)xmalloc (search_string_size = 128); *search_string = '\0'; search_string_index = 0; prev_line_found = (char *)0; /* XXX */ @@ -242,7 +246,7 @@ rl_search_history (direction, invoking_key) c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (_rl_keymap[c].type == ISFUNC) + if (c >= 0 && _rl_keymap[c].type == ISFUNC) { f = _rl_keymap[c].function; @@ -288,7 +292,18 @@ rl_search_history (direction, invoking_key) { case -1: if (search_string_index == 0) - continue; + { + if (last_isearch_string) + { + search_string_size = 64 + last_isearch_string_len; + search_string = (char *)xrealloc (search_string, search_string_size); + strcpy (search_string, last_isearch_string); + search_string_index = last_isearch_string_len; + rl_display_search (search_string, reverse, -1); + break; + } + continue; + } else if (reverse) --line_index; else if (line_index != sline_len) @@ -335,7 +350,7 @@ rl_search_history (direction, invoking_key) if (search_string_index + 2 >= search_string_size) { search_string_size += 128; - search_string = xrealloc (search_string, search_string_size); + search_string = (char *)xrealloc (search_string, search_string_size); } search_string[search_string_index++] = c; search_string[search_string_index] = '\0'; @@ -428,8 +443,15 @@ rl_search_history (direction, invoking_key) rl_restore_prompt (); +#if 1 + /* Save the search string for possible later use. */ + FREE (last_isearch_string); + last_isearch_string = search_string; + last_isearch_string_len = search_string_index; +#else /* Free the search string. */ free (search_string); +#endif if (last_found_line < orig_line) rl_get_previous_history (orig_line - last_found_line, 0); @@ -442,8 +464,7 @@ rl_search_history (direction, invoking_key) rl_point = line_index; rl_clear_message (); - if (allocated_line) - free (allocated_line); + FREE (allocated_line); free (lines); RL_UNSETSTATE(RL_STATE_ISEARCH); diff --git a/lib/readline/keymaps.h b/lib/readline/keymaps.h index d8cba23..93cc820 100644 --- a/lib/readline/keymaps.h +++ b/lib/readline/keymaps.h @@ -70,30 +70,30 @@ extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap; /* Return a new, empty keymap. Free it with free() when you are done. */ -extern Keymap rl_make_bare_keymap __P((void)); +extern Keymap rl_make_bare_keymap PARAMS((void)); /* Return a new keymap which is a copy of MAP. */ -extern Keymap rl_copy_keymap __P((Keymap)); +extern Keymap rl_copy_keymap PARAMS((Keymap)); /* Return a new keymap with the printing characters bound to rl_insert, the lowercase Meta characters bound to run their equivalents, and the Meta digits bound to produce numeric arguments. */ -extern Keymap rl_make_keymap __P((void)); +extern Keymap rl_make_keymap PARAMS((void)); /* Free the storage associated with a keymap. */ -extern void rl_discard_keymap __P((Keymap)); +extern void rl_discard_keymap PARAMS((Keymap)); /* These functions actually appear in bind.c */ /* Return the keymap corresponding to a given name. Names look like `emacs' or `emacs-meta' or `vi-insert'. */ -extern Keymap rl_get_keymap_by_name __P((const char *)); +extern Keymap rl_get_keymap_by_name PARAMS((const char *)); /* Return the current keymap. */ -extern Keymap rl_get_keymap __P((void)); +extern Keymap rl_get_keymap PARAMS((void)); /* Set the current keymap to MAP. */ -extern void rl_set_keymap __P((Keymap)); +extern void rl_set_keymap PARAMS((Keymap)); #ifdef __cplusplus } diff --git a/lib/readline/kill.c b/lib/readline/kill.c index 3ced8fb..90ce6e4 100644 --- a/lib/readline/kill.c +++ b/lib/readline/kill.c @@ -70,6 +70,11 @@ static int rl_kill_index; /* How many slots we have in the kill ring. */ static int rl_kill_ring_length; +static int _rl_copy_to_kill_ring PARAMS((char *, int)); +static int region_kill_internal PARAMS((int)); +static int _rl_copy_word_as_kill PARAMS((int, int)); +static int rl_yank_nth_arg_internal PARAMS((int, int, int)); + /* How to say that you only want to save a certain amount of kill material. */ int @@ -129,7 +134,7 @@ _rl_copy_to_kill_ring (text, append) if (_rl_last_command_was_kill && rl_editing_mode != vi_mode) { old = rl_kill_ring[slot]; - new = xmalloc (1 + strlen (old) + strlen (text)); + new = (char *)xmalloc (1 + strlen (old) + strlen (text)); if (append) { @@ -612,7 +617,7 @@ rl_paste_from_clipboard (count, key) if (ptr) { len = ptr - data; - ptr = xmalloc (len + 1); + ptr = (char *)xmalloc (len + 1); ptr[len] = '\0'; strncpy (ptr, data, len); } diff --git a/lib/readline/macro.c b/lib/readline/macro.c index fed298a..347f89b 100644 --- a/lib/readline/macro.c +++ b/lib/readline/macro.c @@ -163,9 +163,9 @@ _rl_add_macro_char (c) if (current_macro_index + 1 >= current_macro_size) { if (current_macro == 0) - current_macro = xmalloc (current_macro_size = 25); + current_macro = (char *)xmalloc (current_macro_size = 25); else - current_macro = xrealloc (current_macro, current_macro_size += 25); + current_macro = (char *)xrealloc (current_macro, current_macro_size += 25); } current_macro[current_macro_index++] = c; diff --git a/lib/readline/nls.c b/lib/readline/nls.c index f807995..706c819 100644 --- a/lib/readline/nls.c +++ b/lib/readline/nls.c @@ -71,8 +71,8 @@ static char *legal_lang_values[] = 0 }; -static char *normalize_codeset __P((char *)); -static char *find_codeset __P((char *, size_t *)); +static char *normalize_codeset PARAMS((char *)); +static char *find_codeset PARAMS((char *, size_t *)); #endif /* !HAVE_SETLOCALE */ /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value @@ -141,10 +141,10 @@ normalize_codeset (codeset) all_digits = 1; for (len = 0, i = 0; i < namelen; i++) { - if (isalnum (codeset[i])) + if (ISALNUM ((unsigned char)codeset[i])) { len++; - all_digits &= isdigit (codeset[i]); + all_digits &= _rl_digit_p (codeset[i]); } } @@ -162,9 +162,9 @@ normalize_codeset (codeset) } for (i = 0; i < namelen; i++) - if (isalpha (codeset[i])) - *wp++ = (isupper (codeset[i])) ? tolower (codeset[i]) : codeset[i]; - else if (isdigit (codeset[i])) + if (ISALPHA ((unsigned char)codeset[i])) + *wp++ = _rl_to_lower (codeset[i]); + else if (_rl_digit_p (codeset[i])) *wp++ = codeset[i]; *wp = '\0'; diff --git a/lib/readline/parens.c b/lib/readline/parens.c index d1e66f5..ca6c368 100644 --- a/lib/readline/parens.c +++ b/lib/readline/parens.c @@ -54,7 +54,7 @@ extern char *strchr (), *strrchr (); #include "readline.h" #include "rlprivate.h" -static int find_matching_open __P((char *, int, int)); +static int find_matching_open PARAMS((char *, int, int)); /* Non-zero means try to blink the matching open parenthesis when the close parenthesis is inserted. */ diff --git a/lib/readline/readline.c b/lib/readline/readline.c index 9d7cc5b..3efd810 100644 --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -67,22 +67,26 @@ #include "xmalloc.h" #ifndef RL_LIBRARY_VERSION -# define RL_LIBRARY_VERSION "4.2" +# define RL_LIBRARY_VERSION "4.2a" +#endif + +#ifndef RL_READLINE_VERSION +# define RL_READLINE_VERSION 0x0402 #endif /* Evaluates its arguments multiple times. */ #define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) /* Forward declarations used in this file. */ -void _rl_free_history_entry __P((HIST_ENTRY *)); +void _rl_free_history_entry PARAMS((HIST_ENTRY *)); -static char *readline_internal __P((void)); -static void readline_initialize_everything __P((void)); -static void start_using_history __P((void)); -static void bind_arrow_keys __P((void)); -static int rl_change_case __P((int, int)); +static char *readline_internal PARAMS((void)); +static void readline_initialize_everything PARAMS((void)); +static void start_using_history PARAMS((void)); +static void bind_arrow_keys PARAMS((void)); +static int rl_change_case PARAMS((int, int)); -static void readline_default_bindings __P((void)); +static void readline_default_bindings PARAMS((void)); /* **************************************************************** */ /* */ @@ -92,6 +96,8 @@ static void readline_default_bindings __P((void)); const char *rl_library_version = RL_LIBRARY_VERSION; +int rl_readline_version = RL_READLINE_VERSION; + /* True if this is `real' readline as opposed to some stub substitute. */ int rl_gnu_readline_p = 1; @@ -155,8 +161,11 @@ FILE *_rl_in_stream, *_rl_out_stream; FILE *rl_instream = (FILE *)NULL; FILE *rl_outstream = (FILE *)NULL; -/* Non-zero means echo characters as they are read. */ -int readline_echoing_p = 1; +/* Non-zero means echo characters as they are read. Defaults to no echo; + set to 1 if there is a controlling terminal, we can get its attributes, + and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings + for the code that sets it. */ +int readline_echoing_p = 0; /* Current prompt. */ char *rl_prompt = (char *)NULL; @@ -219,7 +228,7 @@ int rl_num_chars_to_read; char *rl_line_buffer = (char *)NULL; int rl_line_buffer_len = 0; -/* Forward declarations used by the display and termcap code. */ +/* Forward declarations used by the display, termcap, and history code. */ /* **************************************************************** */ /* */ @@ -240,6 +249,14 @@ int _rl_convert_meta_chars_to_ascii = 1; rather than as a meta-prefixed escape sequence. */ int _rl_output_meta_chars = 0; +/* If non-zero, rl_get_previous_history and rl_get_next_history attempt + to preserve the value of rl_point from line to line. */ +int _rl_history_preserve_point = 0; + +/* Saved target point for when _rl_history_preserve_point is set. Special + value of -1 means that point is at the end of the line. */ +static int _rl_history_saved_point = -1; + /* **************************************************************** */ /* */ /* Top Level Functions */ @@ -258,9 +275,7 @@ rl_set_prompt (prompt) FREE (rl_prompt); rl_prompt = prompt ? savestring (prompt) : (char *)NULL; - rl_visible_prompt_length = (rl_prompt && *rl_prompt) - ? rl_expand_prompt (rl_prompt) - : 0; + rl_visible_prompt_length = rl_expand_prompt (rl_prompt); return 0; } @@ -583,6 +598,12 @@ _rl_dispatch (key, map) if (key == ESC) RL_UNSETSTATE(RL_STATE_METANEXT); + if (newkey < 0) + { + _rl_abort_internal (); + return -1; + } + r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key)); } else @@ -714,7 +735,7 @@ readline_initialize_everything () /* Allocate data structures. */ if (rl_line_buffer == 0) - rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); + rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); /* Initialize the terminal interface. */ if (rl_terminal_name == 0) @@ -855,6 +876,12 @@ rl_digit_loop () key = c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + { + _rl_abort_internal (); + return -1; + } + /* If we see a key bound to `universal-argument' after seeing digits, it ends the argument but is otherwise ignored. */ if (_rl_keymap[c].type == ISFUNC && @@ -901,8 +928,7 @@ rl_digit_loop () } } - RL_UNSETSTATE(RL_STATE_NUMERICARG); - return 0; + /*NOTREACHED*/ } /* Add the current digit to the argument in progress. */ @@ -1139,6 +1165,10 @@ rl_backward (count, key) else rl_point -= count; } + + if (rl_point < 0) + rl_point = 0; + return 0; } @@ -1344,7 +1374,7 @@ rl_insert (count, c) readline because of extra large arguments. */ if (count > 1 && count <= 1024) { - string = xmalloc (1 + count); + string = (char *)xmalloc (1 + count); for (i = 0; i < count; i++) string[i] = c; @@ -1431,6 +1461,10 @@ rl_newline (count, key) int count, key; { rl_done = 1; + + if (_rl_history_preserve_point) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + RL_SETSTATE(RL_STATE_DONE); #if defined (VI_MODE) @@ -1487,10 +1521,10 @@ rl_rubout (count, key) } else { - int c = the_line[--rl_point]; + unsigned char c = the_line[--rl_point]; rl_delete_text (rl_point, rl_point + 1); - if (rl_point == rl_end && isprint (c) && _rl_last_c_pos) + if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) { int l; l = rl_character_len (c, rl_point); @@ -1685,7 +1719,8 @@ rl_change_case (count, op) /* */ /* **************************************************************** */ -/* Transpose the words at point. */ +/* Transpose the words at point. If point is at the end of the line, + transpose the two words before point. */ int rl_transpose_words (count, key) int count, key; @@ -2000,6 +2035,10 @@ rl_get_next_history (count, key) rl_maybe_replace_line (); + /* either not saved by rl_newline or at end of line, so set appropriately. */ + if (_rl_history_saved_point == -1 && (rl_point || rl_end)) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + temp = (HIST_ENTRY *)NULL; while (count) { @@ -2020,7 +2059,12 @@ rl_get_next_history (count, key) strcpy (the_line, temp->line); rl_undo_list = (UNDO_LIST *)temp->data; - rl_end = rl_point = strlen (the_line); + rl_end = strlen (the_line); + rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) + ? _rl_history_saved_point + : rl_end; + if (rl_point > rl_end) + rl_point = rl_end; #if defined (VI_MODE) if (rl_editing_mode == vi_mode) rl_point = 0; @@ -2044,6 +2088,10 @@ rl_get_previous_history (count, key) if (count == 0) return 0; + /* either not saved by rl_newline or at end of line, so set appropriately. */ + if (_rl_history_saved_point == -1 && (rl_point || rl_end)) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + /* If we don't have a line saved, then save this one. */ rl_maybe_save_line (); @@ -2077,7 +2125,12 @@ rl_get_previous_history (count, key) strcpy (the_line, temp->line); rl_undo_list = (UNDO_LIST *)temp->data; - rl_end = rl_point = line_len; + rl_end = line_len; + rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) + ? _rl_history_saved_point + : rl_end; + if (rl_point > rl_end) + rl_point = rl_end; #if defined (VI_MODE) if (rl_editing_mode == vi_mode) diff --git a/lib/readline/readline.h b/lib/readline/readline.h index d362df1..d608c7a 100644 --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -37,6 +37,11 @@ extern "C" { # include <readline/tilde.h> #endif +/* Hex-encoded Readline version number. */ +#define RL_READLINE_VERSION 0x0402 /* Readline 4.2 */ +#define RL_VERSION_MAJOR 4 +#define RL_VERSION_MINOR 2 + /* Readline data structures. */ /* Maintaining the state of undo. We remember individual deletes and inserts @@ -73,184 +78,184 @@ extern FUNMAP **funmap; /* **************************************************************** */ /* Bindable commands for numeric arguments. */ -extern int rl_digit_argument __P((int, int)); -extern int rl_universal_argument __P((int, int)); +extern int rl_digit_argument PARAMS((int, int)); +extern int rl_universal_argument PARAMS((int, int)); /* Bindable commands for moving the cursor. */ -extern int rl_forward __P((int, int)); -extern int rl_backward __P((int, int)); -extern int rl_beg_of_line __P((int, int)); -extern int rl_end_of_line __P((int, int)); -extern int rl_forward_word __P((int, int)); -extern int rl_backward_word __P((int, int)); -extern int rl_refresh_line __P((int, int)); -extern int rl_clear_screen __P((int, int)); -extern int rl_arrow_keys __P((int, int)); +extern int rl_forward PARAMS((int, int)); +extern int rl_backward PARAMS((int, int)); +extern int rl_beg_of_line PARAMS((int, int)); +extern int rl_end_of_line PARAMS((int, int)); +extern int rl_forward_word PARAMS((int, int)); +extern int rl_backward_word PARAMS((int, int)); +extern int rl_refresh_line PARAMS((int, int)); +extern int rl_clear_screen PARAMS((int, int)); +extern int rl_arrow_keys PARAMS((int, int)); /* Bindable commands for inserting and deleting text. */ -extern int rl_insert __P((int, int)); -extern int rl_quoted_insert __P((int, int)); -extern int rl_tab_insert __P((int, int)); -extern int rl_newline __P((int, int)); -extern int rl_do_lowercase_version __P((int, int)); -extern int rl_rubout __P((int, int)); -extern int rl_delete __P((int, int)); -extern int rl_rubout_or_delete __P((int, int)); -extern int rl_delete_horizontal_space __P((int, int)); -extern int rl_delete_or_show_completions __P((int, int)); -extern int rl_insert_comment __P((int, int)); +extern int rl_insert PARAMS((int, int)); +extern int rl_quoted_insert PARAMS((int, int)); +extern int rl_tab_insert PARAMS((int, int)); +extern int rl_newline PARAMS((int, int)); +extern int rl_do_lowercase_version PARAMS((int, int)); +extern int rl_rubout PARAMS((int, int)); +extern int rl_delete PARAMS((int, int)); +extern int rl_rubout_or_delete PARAMS((int, int)); +extern int rl_delete_horizontal_space PARAMS((int, int)); +extern int rl_delete_or_show_completions PARAMS((int, int)); +extern int rl_insert_comment PARAMS((int, int)); /* Bindable commands for changing case. */ -extern int rl_upcase_word __P((int, int)); -extern int rl_downcase_word __P((int, int)); -extern int rl_capitalize_word __P((int, int)); +extern int rl_upcase_word PARAMS((int, int)); +extern int rl_downcase_word PARAMS((int, int)); +extern int rl_capitalize_word PARAMS((int, int)); /* Bindable commands for transposing characters and words. */ -extern int rl_transpose_words __P((int, int)); -extern int rl_transpose_chars __P((int, int)); +extern int rl_transpose_words PARAMS((int, int)); +extern int rl_transpose_chars PARAMS((int, int)); /* Bindable commands for searching within a line. */ -extern int rl_char_search __P((int, int)); -extern int rl_backward_char_search __P((int, int)); +extern int rl_char_search PARAMS((int, int)); +extern int rl_backward_char_search PARAMS((int, int)); /* Bindable commands for readline's interface to the command history. */ -extern int rl_beginning_of_history __P((int, int)); -extern int rl_end_of_history __P((int, int)); -extern int rl_get_next_history __P((int, int)); -extern int rl_get_previous_history __P((int, int)); +extern int rl_beginning_of_history PARAMS((int, int)); +extern int rl_end_of_history PARAMS((int, int)); +extern int rl_get_next_history PARAMS((int, int)); +extern int rl_get_previous_history PARAMS((int, int)); /* Bindable commands for managing the mark and region. */ -extern int rl_set_mark __P((int, int)); -extern int rl_exchange_point_and_mark __P((int, int)); +extern int rl_set_mark PARAMS((int, int)); +extern int rl_exchange_point_and_mark PARAMS((int, int)); /* Bindable commands to set the editing mode (emacs or vi). */ -extern int rl_vi_editing_mode __P((int, int)); -extern int rl_emacs_editing_mode __P((int, int)); +extern int rl_vi_editing_mode PARAMS((int, int)); +extern int rl_emacs_editing_mode PARAMS((int, int)); /* Bindable commands for managing key bindings. */ -extern int rl_re_read_init_file __P((int, int)); -extern int rl_dump_functions __P((int, int)); -extern int rl_dump_macros __P((int, int)); -extern int rl_dump_variables __P((int, int)); +extern int rl_re_read_init_file PARAMS((int, int)); +extern int rl_dump_functions PARAMS((int, int)); +extern int rl_dump_macros PARAMS((int, int)); +extern int rl_dump_variables PARAMS((int, int)); /* Bindable commands for word completion. */ -extern int rl_complete __P((int, int)); -extern int rl_possible_completions __P((int, int)); -extern int rl_insert_completions __P((int, int)); -extern int rl_menu_complete __P((int, int)); +extern int rl_complete PARAMS((int, int)); +extern int rl_possible_completions PARAMS((int, int)); +extern int rl_insert_completions PARAMS((int, int)); +extern int rl_menu_complete PARAMS((int, int)); /* Bindable commands for killing and yanking text, and managing the kill ring. */ -extern int rl_kill_word __P((int, int)); -extern int rl_backward_kill_word __P((int, int)); -extern int rl_kill_line __P((int, int)); -extern int rl_backward_kill_line __P((int, int)); -extern int rl_kill_full_line __P((int, int)); -extern int rl_unix_word_rubout __P((int, int)); -extern int rl_unix_line_discard __P((int, int)); -extern int rl_copy_region_to_kill __P((int, int)); -extern int rl_kill_region __P((int, int)); -extern int rl_copy_forward_word __P((int, int)); -extern int rl_copy_backward_word __P((int, int)); -extern int rl_yank __P((int, int)); -extern int rl_yank_pop __P((int, int)); -extern int rl_yank_nth_arg __P((int, int)); -extern int rl_yank_last_arg __P((int, int)); +extern int rl_kill_word PARAMS((int, int)); +extern int rl_backward_kill_word PARAMS((int, int)); +extern int rl_kill_line PARAMS((int, int)); +extern int rl_backward_kill_line PARAMS((int, int)); +extern int rl_kill_full_line PARAMS((int, int)); +extern int rl_unix_word_rubout PARAMS((int, int)); +extern int rl_unix_line_discard PARAMS((int, int)); +extern int rl_copy_region_to_kill PARAMS((int, int)); +extern int rl_kill_region PARAMS((int, int)); +extern int rl_copy_forward_word PARAMS((int, int)); +extern int rl_copy_backward_word PARAMS((int, int)); +extern int rl_yank PARAMS((int, int)); +extern int rl_yank_pop PARAMS((int, int)); +extern int rl_yank_nth_arg PARAMS((int, int)); +extern int rl_yank_last_arg PARAMS((int, int)); /* Not available unless __CYGWIN__ is defined. */ #ifdef __CYGWIN__ -extern int rl_paste_from_clipboard __P((int, int)); +extern int rl_paste_from_clipboard PARAMS((int, int)); #endif /* Bindable commands for incremental searching. */ -extern int rl_reverse_search_history __P((int, int)); -extern int rl_forward_search_history __P((int, int)); +extern int rl_reverse_search_history PARAMS((int, int)); +extern int rl_forward_search_history PARAMS((int, int)); /* Bindable keyboard macro commands. */ -extern int rl_start_kbd_macro __P((int, int)); -extern int rl_end_kbd_macro __P((int, int)); -extern int rl_call_last_kbd_macro __P((int, int)); +extern int rl_start_kbd_macro PARAMS((int, int)); +extern int rl_end_kbd_macro PARAMS((int, int)); +extern int rl_call_last_kbd_macro PARAMS((int, int)); /* Bindable undo commands. */ -extern int rl_revert_line __P((int, int)); -extern int rl_undo_command __P((int, int)); +extern int rl_revert_line PARAMS((int, int)); +extern int rl_undo_command PARAMS((int, int)); /* Bindable tilde expansion commands. */ -extern int rl_tilde_expand __P((int, int)); +extern int rl_tilde_expand PARAMS((int, int)); /* Bindable terminal control commands. */ -extern int rl_restart_output __P((int, int)); -extern int rl_stop_output __P((int, int)); +extern int rl_restart_output PARAMS((int, int)); +extern int rl_stop_output PARAMS((int, int)); /* Miscellaneous bindable commands. */ -extern int rl_abort __P((int, int)); -extern int rl_tty_status __P((int, int)); +extern int rl_abort PARAMS((int, int)); +extern int rl_tty_status PARAMS((int, int)); /* Bindable commands for incremental and non-incremental history searching. */ -extern int rl_history_search_forward __P((int, int)); -extern int rl_history_search_backward __P((int, int)); -extern int rl_noninc_forward_search __P((int, int)); -extern int rl_noninc_reverse_search __P((int, int)); -extern int rl_noninc_forward_search_again __P((int, int)); -extern int rl_noninc_reverse_search_again __P((int, int)); +extern int rl_history_search_forward PARAMS((int, int)); +extern int rl_history_search_backward PARAMS((int, int)); +extern int rl_noninc_forward_search PARAMS((int, int)); +extern int rl_noninc_reverse_search PARAMS((int, int)); +extern int rl_noninc_forward_search_again PARAMS((int, int)); +extern int rl_noninc_reverse_search_again PARAMS((int, int)); /* Bindable command used when inserting a matching close character. */ -extern int rl_insert_close __P((int, int)); +extern int rl_insert_close PARAMS((int, int)); /* Not available unless READLINE_CALLBACKS is defined. */ -extern void rl_callback_handler_install __P((const char *, rl_vcpfunc_t *)); -extern void rl_callback_read_char __P((void)); -extern void rl_callback_handler_remove __P((void)); +extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *)); +extern void rl_callback_read_char PARAMS((void)); +extern void rl_callback_handler_remove PARAMS((void)); /* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ /* VI-mode bindable commands. */ -extern int rl_vi_redo __P((int, int)); -extern int rl_vi_undo __P((int, int)); -extern int rl_vi_yank_arg __P((int, int)); -extern int rl_vi_fetch_history __P((int, int)); -extern int rl_vi_search_again __P((int, int)); -extern int rl_vi_search __P((int, int)); -extern int rl_vi_complete __P((int, int)); -extern int rl_vi_tilde_expand __P((int, int)); -extern int rl_vi_prev_word __P((int, int)); -extern int rl_vi_next_word __P((int, int)); -extern int rl_vi_end_word __P((int, int)); -extern int rl_vi_insert_beg __P((int, int)); -extern int rl_vi_append_mode __P((int, int)); -extern int rl_vi_append_eol __P((int, int)); -extern int rl_vi_eof_maybe __P((int, int)); -extern int rl_vi_insertion_mode __P((int, int)); -extern int rl_vi_movement_mode __P((int, int)); -extern int rl_vi_arg_digit __P((int, int)); -extern int rl_vi_change_case __P((int, int)); -extern int rl_vi_put __P((int, int)); -extern int rl_vi_column __P((int, int)); -extern int rl_vi_delete_to __P((int, int)); -extern int rl_vi_change_to __P((int, int)); -extern int rl_vi_yank_to __P((int, int)); -extern int rl_vi_delete __P((int, int)); -extern int rl_vi_back_to_indent __P((int, int)); -extern int rl_vi_first_print __P((int, int)); -extern int rl_vi_char_search __P((int, int)); -extern int rl_vi_match __P((int, int)); -extern int rl_vi_change_char __P((int, int)); -extern int rl_vi_subst __P((int, int)); -extern int rl_vi_overstrike __P((int, int)); -extern int rl_vi_overstrike_delete __P((int, int)); -extern int rl_vi_replace __P((int, int)); -extern int rl_vi_set_mark __P((int, int)); -extern int rl_vi_goto_mark __P((int, int)); +extern int rl_vi_redo PARAMS((int, int)); +extern int rl_vi_undo PARAMS((int, int)); +extern int rl_vi_yank_arg PARAMS((int, int)); +extern int rl_vi_fetch_history PARAMS((int, int)); +extern int rl_vi_search_again PARAMS((int, int)); +extern int rl_vi_search PARAMS((int, int)); +extern int rl_vi_complete PARAMS((int, int)); +extern int rl_vi_tilde_expand PARAMS((int, int)); +extern int rl_vi_prev_word PARAMS((int, int)); +extern int rl_vi_next_word PARAMS((int, int)); +extern int rl_vi_end_word PARAMS((int, int)); +extern int rl_vi_insert_beg PARAMS((int, int)); +extern int rl_vi_append_mode PARAMS((int, int)); +extern int rl_vi_append_eol PARAMS((int, int)); +extern int rl_vi_eof_maybe PARAMS((int, int)); +extern int rl_vi_insertion_mode PARAMS((int, int)); +extern int rl_vi_movement_mode PARAMS((int, int)); +extern int rl_vi_arg_digit PARAMS((int, int)); +extern int rl_vi_change_case PARAMS((int, int)); +extern int rl_vi_put PARAMS((int, int)); +extern int rl_vi_column PARAMS((int, int)); +extern int rl_vi_delete_to PARAMS((int, int)); +extern int rl_vi_change_to PARAMS((int, int)); +extern int rl_vi_yank_to PARAMS((int, int)); +extern int rl_vi_delete PARAMS((int, int)); +extern int rl_vi_back_to_indent PARAMS((int, int)); +extern int rl_vi_first_print PARAMS((int, int)); +extern int rl_vi_char_search PARAMS((int, int)); +extern int rl_vi_match PARAMS((int, int)); +extern int rl_vi_change_char PARAMS((int, int)); +extern int rl_vi_subst PARAMS((int, int)); +extern int rl_vi_overstrike PARAMS((int, int)); +extern int rl_vi_overstrike_delete PARAMS((int, int)); +extern int rl_vi_replace PARAMS((int, int)); +extern int rl_vi_set_mark PARAMS((int, int)); +extern int rl_vi_goto_mark PARAMS((int, int)); /* VI-mode utility functions. */ -extern int rl_vi_check __P((void)); -extern int rl_vi_domove __P((int, int *)); -extern int rl_vi_bracktype __P((int)); +extern int rl_vi_check PARAMS((void)); +extern int rl_vi_domove PARAMS((int, int *)); +extern int rl_vi_bracktype PARAMS((int)); /* VI-mode pseudo-bindable commands, used as utility functions. */ -extern int rl_vi_fWord __P((int, int)); -extern int rl_vi_bWord __P((int, int)); -extern int rl_vi_eWord __P((int, int)); -extern int rl_vi_fword __P((int, int)); -extern int rl_vi_bword __P((int, int)); -extern int rl_vi_eword __P((int, int)); +extern int rl_vi_fWord PARAMS((int, int)); +extern int rl_vi_bWord PARAMS((int, int)); +extern int rl_vi_eWord PARAMS((int, int)); +extern int rl_vi_fword PARAMS((int, int)); +extern int rl_vi_bword PARAMS((int, int)); +extern int rl_vi_eword PARAMS((int, int)); /* **************************************************************** */ /* */ @@ -260,171 +265,172 @@ extern int rl_vi_eword __P((int, int)); /* Readline functions. */ /* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */ -extern char *readline __P((const char *)); +extern char *readline PARAMS((const char *)); -extern int rl_set_prompt __P((const char *)); -extern int rl_expand_prompt __P((char *)); +extern int rl_set_prompt PARAMS((const char *)); +extern int rl_expand_prompt PARAMS((char *)); -extern int rl_initialize __P((void)); +extern int rl_initialize PARAMS((void)); /* Undocumented; unused by readline */ -extern int rl_discard_argument __P((void)); +extern int rl_discard_argument PARAMS((void)); /* Utility functions to bind keys to readline commands. */ -extern int rl_add_defun __P((const char *, rl_command_func_t *, int)); -extern int rl_bind_key __P((int, rl_command_func_t *)); -extern int rl_bind_key_in_map __P((int, rl_command_func_t *, Keymap)); -extern int rl_unbind_key __P((int)); -extern int rl_unbind_key_in_map __P((int, Keymap)); -extern int rl_unbind_function_in_map __P((rl_command_func_t *, Keymap)); -extern int rl_unbind_command_in_map __P((const char *, Keymap)); -extern int rl_set_key __P((const char *, rl_command_func_t *, Keymap)); -extern int rl_generic_bind __P((int, const char *, char *, Keymap)); -extern int rl_variable_bind __P((const char *, const char *)); +extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int)); +extern int rl_bind_key PARAMS((int, rl_command_func_t *)); +extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap)); +extern int rl_unbind_key PARAMS((int)); +extern int rl_unbind_key_in_map PARAMS((int, Keymap)); +extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap)); +extern int rl_unbind_command_in_map PARAMS((const char *, Keymap)); +extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap)); +extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap)); +extern int rl_variable_bind PARAMS((const char *, const char *)); /* Backwards compatibility, use rl_generic_bind instead. */ -extern int rl_macro_bind __P((const char *, const char *, Keymap)); +extern int rl_macro_bind PARAMS((const char *, const char *, Keymap)); /* Undocumented in the texinfo manual; not really useful to programs. */ -extern int rl_translate_keyseq __P((const char *, char *, int *)); -extern char *rl_untranslate_keyseq __P((int)); +extern int rl_translate_keyseq PARAMS((const char *, char *, int *)); +extern char *rl_untranslate_keyseq PARAMS((int)); -extern rl_command_func_t *rl_named_function __P((const char *)); -extern rl_command_func_t *rl_function_of_keyseq __P((const char *, Keymap, int *)); +extern rl_command_func_t *rl_named_function PARAMS((const char *)); +extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *)); -extern void rl_list_funmap_names __P((void)); -extern char **rl_invoking_keyseqs_in_map __P((rl_command_func_t *, Keymap)); -extern char **rl_invoking_keyseqs __P((rl_command_func_t *)); +extern void rl_list_funmap_names PARAMS((void)); +extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap)); +extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *)); -extern void rl_function_dumper __P((int)); -extern void rl_macro_dumper __P((int)); -extern void rl_variable_dumper __P((int)); +extern void rl_function_dumper PARAMS((int)); +extern void rl_macro_dumper PARAMS((int)); +extern void rl_variable_dumper PARAMS((int)); -extern int rl_read_init_file __P((const char *)); -extern int rl_parse_and_bind __P((char *)); +extern int rl_read_init_file PARAMS((const char *)); +extern int rl_parse_and_bind PARAMS((char *)); /* Functions for manipulating keymaps. */ -extern Keymap rl_make_bare_keymap __P((void)); -extern Keymap rl_copy_keymap __P((Keymap)); -extern Keymap rl_make_keymap __P((void)); -extern void rl_discard_keymap __P((Keymap)); - -extern Keymap rl_get_keymap_by_name __P((const char *)); -extern char *rl_get_keymap_name __P((Keymap)); -extern void rl_set_keymap __P((Keymap)); -extern Keymap rl_get_keymap __P((void)); +extern Keymap rl_make_bare_keymap PARAMS((void)); +extern Keymap rl_copy_keymap PARAMS((Keymap)); +extern Keymap rl_make_keymap PARAMS((void)); +extern void rl_discard_keymap PARAMS((Keymap)); + +extern Keymap rl_get_keymap_by_name PARAMS((const char *)); +extern char *rl_get_keymap_name PARAMS((Keymap)); +extern void rl_set_keymap PARAMS((Keymap)); +extern Keymap rl_get_keymap PARAMS((void)); /* Undocumented; used internally only. */ -extern void rl_set_keymap_from_edit_mode __P((void)); -extern char *rl_get_keymap_name_from_edit_mode __P((void)); +extern void rl_set_keymap_from_edit_mode PARAMS((void)); +extern char *rl_get_keymap_name_from_edit_mode PARAMS((void)); /* Functions for manipulating the funmap, which maps command names to functions. */ -extern int rl_add_funmap_entry __P((const char *, rl_command_func_t *)); -extern const char **rl_funmap_names __P((void)); +extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *)); +extern const char **rl_funmap_names PARAMS((void)); /* Undocumented, only used internally -- there is only one funmap, and this function may be called only once. */ -extern void rl_initialize_funmap __P((void)); +extern void rl_initialize_funmap PARAMS((void)); /* Utility functions for managing keyboard macros. */ -extern void rl_push_macro_input __P((char *)); +extern void rl_push_macro_input PARAMS((char *)); /* Functions for undoing, from undo.c */ -extern void rl_add_undo __P((enum undo_code, int, int, char *)); -extern void rl_free_undo_list __P((void)); -extern int rl_do_undo __P((void)); -extern int rl_begin_undo_group __P((void)); -extern int rl_end_undo_group __P((void)); -extern int rl_modifying __P((int, int)); +extern void rl_add_undo PARAMS((enum undo_code, int, int, char *)); +extern void rl_free_undo_list PARAMS((void)); +extern int rl_do_undo PARAMS((void)); +extern int rl_begin_undo_group PARAMS((void)); +extern int rl_end_undo_group PARAMS((void)); +extern int rl_modifying PARAMS((int, int)); /* Functions for redisplay. */ -extern void rl_redisplay __P((void)); -extern int rl_on_new_line __P((void)); -extern int rl_on_new_line_with_prompt __P((void)); -extern int rl_forced_update_display __P((void)); -extern int rl_clear_message __P((void)); -extern int rl_reset_line_state __P((void)); -extern int rl_crlf __P((void)); +extern void rl_redisplay PARAMS((void)); +extern int rl_on_new_line PARAMS((void)); +extern int rl_on_new_line_with_prompt PARAMS((void)); +extern int rl_forced_update_display PARAMS((void)); +extern int rl_clear_message PARAMS((void)); +extern int rl_reset_line_state PARAMS((void)); +extern int rl_crlf PARAMS((void)); #if (defined (__STDC__) || defined (__cplusplus)) && defined (USE_VARARGS) && defined (PREFER_STDARG) -extern int rl_message (const char *, ...); +extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2))); #else extern int rl_message (); #endif -extern int rl_show_char __P((int)); +extern int rl_show_char PARAMS((int)); /* Undocumented in texinfo manual. */ -extern int rl_character_len __P((int, int)); +extern int rl_character_len PARAMS((int, int)); /* Save and restore internal prompt redisplay information. */ -extern void rl_save_prompt __P((void)); -extern void rl_restore_prompt __P((void)); +extern void rl_save_prompt PARAMS((void)); +extern void rl_restore_prompt PARAMS((void)); /* Modifying text. */ -extern int rl_insert_text __P((const char *)); -extern int rl_delete_text __P((int, int)); -extern int rl_kill_text __P((int, int)); -extern char *rl_copy_text __P((int, int)); +extern int rl_insert_text PARAMS((const char *)); +extern int rl_delete_text PARAMS((int, int)); +extern int rl_kill_text PARAMS((int, int)); +extern char *rl_copy_text PARAMS((int, int)); /* Terminal and tty mode management. */ -extern void rl_prep_terminal __P((int)); -extern void rl_deprep_terminal __P((void)); -extern void rl_tty_set_default_bindings __P((Keymap)); +extern void rl_prep_terminal PARAMS((int)); +extern void rl_deprep_terminal PARAMS((void)); +extern void rl_tty_set_default_bindings PARAMS((Keymap)); + +extern int rl_reset_terminal PARAMS((const char *)); +extern void rl_resize_terminal PARAMS((void)); +extern void rl_set_screen_size PARAMS((int, int)); +extern void rl_get_screen_size PARAMS((int *, int *)); -extern int rl_reset_terminal __P((const char *)); -extern void rl_resize_terminal __P((void)); -extern void rl_set_screen_size __P((int, int)); -extern void rl_get_screen_size __P((int *, int *)); +extern char *rl_get_termcap PARAMS((const char *)); /* Functions for character input. */ -extern int rl_stuff_char __P((int)); -extern int rl_execute_next __P((int)); -extern int rl_clear_pending_input __P((void)); -extern int rl_read_key __P((void)); -extern int rl_getc __P((FILE *)); -extern int rl_set_keyboard_input_timeout __P((int)); +extern int rl_stuff_char PARAMS((int)); +extern int rl_execute_next PARAMS((int)); +extern int rl_clear_pending_input PARAMS((void)); +extern int rl_read_key PARAMS((void)); +extern int rl_getc PARAMS((FILE *)); +extern int rl_set_keyboard_input_timeout PARAMS((int)); /* `Public' utility functions . */ -extern void rl_extend_line_buffer __P((int)); -extern int rl_ding __P((void)); -extern int rl_alphabetic __P((int)); +extern void rl_extend_line_buffer PARAMS((int)); +extern int rl_ding PARAMS((void)); +extern int rl_alphabetic PARAMS((int)); /* Readline signal handling, from signals.c */ -extern int rl_set_signals __P((void)); -extern int rl_clear_signals __P((void)); -extern void rl_cleanup_after_signal __P((void)); -extern void rl_reset_after_signal __P((void)); -extern void rl_free_line_state __P((void)); +extern int rl_set_signals PARAMS((void)); +extern int rl_clear_signals PARAMS((void)); +extern void rl_cleanup_after_signal PARAMS((void)); +extern void rl_reset_after_signal PARAMS((void)); +extern void rl_free_line_state PARAMS((void)); -/* Undocumented. */ -extern int rl_set_paren_blink_timeout __P((int)); +extern int rl_set_paren_blink_timeout PARAMS((int)); /* Undocumented. */ -extern int rl_maybe_save_line __P((void)); -extern int rl_maybe_unsave_line __P((void)); -extern int rl_maybe_replace_line __P((void)); +extern int rl_maybe_save_line PARAMS((void)); +extern int rl_maybe_unsave_line PARAMS((void)); +extern int rl_maybe_replace_line PARAMS((void)); /* Completion functions. */ -extern int rl_complete_internal __P((int)); -extern void rl_display_match_list __P((char **, int, int)); +extern int rl_complete_internal PARAMS((int)); +extern void rl_display_match_list PARAMS((char **, int, int)); -extern char **rl_completion_matches __P((const char *, rl_compentry_func_t *)); -extern char *rl_username_completion_function __P((const char *, int)); -extern char *rl_filename_completion_function __P((const char *, int)); +extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *)); +extern char *rl_username_completion_function PARAMS((const char *, int)); +extern char *rl_filename_completion_function PARAMS((const char *, int)); #if 0 /* Backwards compatibility (compat.c). These will go away sometime. */ -extern void free_undo_list __P((void)); -extern int maybe_save_line __P((void)); -extern int maybe_unsave_line __P((void)); -extern int maybe_replace_line __P((void)); - -extern int ding __P((void)); -extern int alphabetic __P((int)); -extern int crlf __P((void)); - -extern char **completion_matches __P((char *, rl_compentry_func_t *)); -extern char *username_completion_function __P((const char *, int)); -extern char *filename_completion_function __P((const char *, int)); +extern void free_undo_list PARAMS((void)); +extern int maybe_save_line PARAMS((void)); +extern int maybe_unsave_line PARAMS((void)); +extern int maybe_replace_line PARAMS((void)); + +extern int ding PARAMS((void)); +extern int alphabetic PARAMS((int)); +extern int crlf PARAMS((void)); + +extern char **completion_matches PARAMS((char *, rl_compentry_func_t *)); +extern char *username_completion_function PARAMS((const char *, int)); +extern char *filename_completion_function PARAMS((const char *, int)); #endif /* **************************************************************** */ @@ -434,7 +440,8 @@ extern char *filename_completion_function __P((const char *, int)); /* **************************************************************** */ /* The version of this incarnation of the readline library. */ -extern const char *rl_library_version; +extern const char *rl_library_version; /* e.g., "4.2" */ +extern int rl_readline_version; /* e.g., 0x0402 */ /* True if this is real GNU readline. */ extern int rl_gnu_readline_p; @@ -551,8 +558,8 @@ extern int rl_catch_sigwinch; /* Completion variables. */ /* Pointer to the generator function for completion_matches (). - NULL means to use filename_entry_function (), the default filename - completer. */ + NULL means to use rl_filename_completion_function (), the default + filename completer. */ extern rl_compentry_func_t *rl_completion_entry_function; /* If rl_ignore_some_completions_function is non-NULL it is the address diff --git a/lib/readline/rldefs.h b/lib/readline/rldefs.h index 4e094bf..bd055e3 100644 --- a/lib/readline/rldefs.h +++ b/lib/readline/rldefs.h @@ -73,8 +73,14 @@ extern char *strchr (), *strrchr (); #define _rl_stricmp strcasecmp #define _rl_strnicmp strncasecmp #else -extern int _rl_stricmp __P((char *, char *); -extern int _rl_strnicmp __P((char *, char *)); +extern int _rl_stricmp PARAMS((char *, char *)); +extern int _rl_strnicmp PARAMS((char *, char *)); +#endif + +#if defined (HAVE_STRPBRK) +# define _rl_strpbrk(a,b) strpbrk((a),(b)) +#else +extern char *_rl_strpbrk PARAMS((const char *, const char *)); #endif #if !defined (emacs_mode) @@ -97,8 +103,7 @@ extern int _rl_strnicmp __P((char *, char *)); #endif #ifndef savestring -extern char *xmalloc __P((int)); -#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) #endif /* Possible values for _rl_bell_preference. */ diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index a36de9b..9347b36 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -26,7 +26,7 @@ #include "rlconf.h" /* for VISIBLE_STATS */ #include "rlstdc.h" -#include "posixjmp.h" /* defines procenv_t */ +#include "posixjmp.h" /* defines procenv_t */ /************************************************************************* * * @@ -34,9 +34,6 @@ * * *************************************************************************/ -/* terminal.c */ -extern char *rl_get_termcap __P((const char *)); - /************************************************************************* * * * Global variables undocumented in texinfo manual and not in readline.h * @@ -69,25 +66,25 @@ extern int rl_blink_matching_paren; *************************************************************************/ /* bind.c */ -extern char *rl_untranslate_keyseq __P((int)); +extern char *rl_untranslate_keyseq PARAMS((int)); /* kill.c */ -extern int rl_set_retained_kills __P((int)); +extern int rl_set_retained_kills PARAMS((int)); /* readline.c */ -extern int rl_discard_argument __P((void)); +extern int rl_discard_argument PARAMS((void)); /* rltty.c */ -extern int rl_stop_output __P((int, int)); +extern int rl_stop_output PARAMS((int, int)); /* terminal.c */ -extern void _rl_set_screen_size __P((int, int)); +extern void _rl_set_screen_size PARAMS((int, int)); /* undo.c */ -extern int _rl_fix_last_undo_of_type __P((int, int, int)); +extern int _rl_fix_last_undo_of_type PARAMS((int, int, int)); /* util.c */ -extern char *_rl_savestring __P((const char *)); +extern char *_rl_savestring PARAMS((const char *)); /************************************************************************* * * @@ -107,98 +104,97 @@ extern char *_rl_savestring __P((const char *)); #if defined(READLINE_CALLBACKS) /* readline.c */ -extern void readline_internal_setup __P((void)); -extern char *readline_internal_teardown __P((int)); -extern int readline_internal_char __P((void)); +extern void readline_internal_setup PARAMS((void)); +extern char *readline_internal_teardown PARAMS((int)); +extern int readline_internal_char PARAMS((void)); #endif /* READLINE_CALLBACKS */ /* bind.c */ -extern void _rl_bind_if_unbound __P((const char *, rl_command_func_t *)); +extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *)); /* display.c */ -extern char *_rl_strip_prompt __P((char *)); -extern void _rl_move_cursor_relative __P((int, const char *)); -extern void _rl_move_vert __P((int)); -extern void _rl_save_prompt __P((void)); -extern void _rl_restore_prompt __P((void)); -extern char *_rl_make_prompt_for_search __P((int)); -extern void _rl_erase_at_end_of_line __P((int)); -extern void _rl_clear_to_eol __P((int)); -extern void _rl_clear_screen __P((void)); -extern void _rl_update_final __P((void)); -extern void _rl_redisplay_after_sigwinch __P((void)); -extern void _rl_clean_up_for_exit __P((void)); -extern void _rl_erase_entire_line __P((void)); -extern int _rl_current_display_line __P((void)); +extern char *_rl_strip_prompt PARAMS((char *)); +extern void _rl_move_cursor_relative PARAMS((int, const char *)); +extern void _rl_move_vert PARAMS((int)); +extern void _rl_save_prompt PARAMS((void)); +extern void _rl_restore_prompt PARAMS((void)); +extern char *_rl_make_prompt_for_search PARAMS((int)); +extern void _rl_erase_at_end_of_line PARAMS((int)); +extern void _rl_clear_to_eol PARAMS((int)); +extern void _rl_clear_screen PARAMS((void)); +extern void _rl_update_final PARAMS((void)); +extern void _rl_redisplay_after_sigwinch PARAMS((void)); +extern void _rl_clean_up_for_exit PARAMS((void)); +extern void _rl_erase_entire_line PARAMS((void)); +extern int _rl_current_display_line PARAMS((void)); /* input.c */ -extern int _rl_any_typein __P((void)); -extern int _rl_input_available __P((void)); -extern void _rl_insert_typein __P((int)); +extern int _rl_any_typein PARAMS((void)); +extern int _rl_input_available PARAMS((void)); +extern void _rl_insert_typein PARAMS((int)); /* macro.c */ -extern void _rl_with_macro_input __P((char *)); -extern int _rl_next_macro_key __P((void)); -extern void _rl_push_executing_macro __P((void)); -extern void _rl_pop_executing_macro __P((void)); -extern void _rl_add_macro_char __P((int)); -extern void _rl_kill_kbd_macro __P((void)); +extern void _rl_with_macro_input PARAMS((char *)); +extern int _rl_next_macro_key PARAMS((void)); +extern void _rl_push_executing_macro PARAMS((void)); +extern void _rl_pop_executing_macro PARAMS((void)); +extern void _rl_add_macro_char PARAMS((int)); +extern void _rl_kill_kbd_macro PARAMS((void)); /* nls.c */ -extern int _rl_init_eightbit __P((void)); +extern int _rl_init_eightbit PARAMS((void)); /* parens.c */ -extern void _rl_enable_paren_matching __P((int)); +extern void _rl_enable_paren_matching PARAMS((int)); /* readline.c */ -extern void _rl_init_line_state __P((void)); -extern void _rl_set_the_line __P((void)); -extern int _rl_dispatch __P((int, Keymap)); -extern int _rl_init_argument __P((void)); -extern void _rl_fix_point __P((int)); -extern void _rl_replace_text __P((const char *, int, int)); -extern int _rl_char_search_internal __P((int, int, int)); -extern int _rl_set_mark_at_pos __P((int)); -extern int _rl_free_saved_history_line __P((void)); +extern void _rl_init_line_state PARAMS((void)); +extern void _rl_set_the_line PARAMS((void)); +extern int _rl_dispatch PARAMS((int, Keymap)); +extern int _rl_init_argument PARAMS((void)); +extern void _rl_fix_point PARAMS((int)); +extern void _rl_replace_text PARAMS((const char *, int, int)); +extern int _rl_char_search_internal PARAMS((int, int, int)); +extern int _rl_set_mark_at_pos PARAMS((int)); +extern int _rl_free_saved_history_line PARAMS((void)); /* rltty.c */ -extern int _rl_disable_tty_signals __P((void)); -extern int _rl_restore_tty_signals __P((void)); +extern int _rl_disable_tty_signals PARAMS((void)); +extern int _rl_restore_tty_signals PARAMS((void)); /* terminal.c */ -extern void _rl_get_screen_size __P((int, int)); -extern int _rl_init_terminal_io __P((const char *)); +extern void _rl_get_screen_size PARAMS((int, int)); +extern int _rl_init_terminal_io PARAMS((const char *)); #ifdef _MINIX -extern void _rl_output_character_function __P((int)); +extern void _rl_output_character_function PARAMS((int)); #else -extern int _rl_output_character_function __P((int)); +extern int _rl_output_character_function PARAMS((int)); #endif -extern void _rl_output_some_chars __P((const char *, int)); -extern int _rl_backspace __P((int)); -extern void _rl_enable_meta_key __P((void)); -extern void _rl_control_keypad __P((int)); +extern void _rl_output_some_chars PARAMS((const char *, int)); +extern int _rl_backspace PARAMS((int)); +extern void _rl_enable_meta_key PARAMS((void)); +extern void _rl_control_keypad PARAMS((int)); /* util.c */ -extern int rl_alphabetic __P((int)); -extern int _rl_abort_internal __P((void)); -extern char *_rl_strindex __P((const char *, const char *)); -extern char *_rl_strpbrk __P((const char *, const char *)); -extern int _rl_qsort_string_compare __P((char **, char **)); -extern int (_rl_uppercase_p) __P((int)); -extern int (_rl_lowercase_p) __P((int)); -extern int (_rl_pure_alphabetic) __P((int)); -extern int (_rl_digit_p) __P((int)); -extern int (_rl_to_lower) __P((int)); -extern int (_rl_to_upper) __P((int)); -extern int (_rl_digit_value) __P((int)); +extern int rl_alphabetic PARAMS((int)); +extern int _rl_abort_internal PARAMS((void)); +extern char *_rl_strindex PARAMS((const char *, const char *)); +extern int _rl_qsort_string_compare PARAMS((char **, char **)); +extern int (_rl_uppercase_p) PARAMS((int)); +extern int (_rl_lowercase_p) PARAMS((int)); +extern int (_rl_pure_alphabetic) PARAMS((int)); +extern int (_rl_digit_p) PARAMS((int)); +extern int (_rl_to_lower) PARAMS((int)); +extern int (_rl_to_upper) PARAMS((int)); +extern int (_rl_digit_value) PARAMS((int)); /* vi_mode.c */ -extern void _rl_vi_initialize_line __P((void)); -extern void _rl_vi_reset_last __P((void)); -extern void _rl_vi_set_last __P((int, int, int)); -extern int _rl_vi_textmod_command __P((int)); -extern void _rl_vi_done_inserting __P((void)); +extern void _rl_vi_initialize_line PARAMS((void)); +extern void _rl_vi_reset_last PARAMS((void)); +extern void _rl_vi_set_last PARAMS((int, int, int)); +extern int _rl_vi_textmod_command PARAMS((int)); +extern void _rl_vi_done_inserting PARAMS((void)); /************************************************************************* * Undocumented private variables * @@ -213,6 +209,7 @@ extern int _rl_complete_show_all; extern int _rl_complete_mark_directories; extern int _rl_print_completions_horizontally; extern int _rl_completion_case_fold; +extern int _rl_match_hidden_files; /* display.c */ extern int _rl_vis_botlin; @@ -221,7 +218,7 @@ extern int _rl_suppress_redisplay; extern char *rl_display_prompt; /* isearch.c */ -extern unsigned char *_rl_isearch_terminators; +extern char *_rl_isearch_terminators; /* macro.c */ extern int _rl_defining_kbd_macro; @@ -234,6 +231,7 @@ extern int _rl_bell_preference; extern int _rl_meta_flag; extern int _rl_convert_meta_chars_to_ascii; extern int _rl_output_meta_chars; +extern int _rl_history_preserve_point; extern char *_rl_comment_begin; extern unsigned char _rl_parsing_conditionalized_out; extern Keymap _rl_keymap; diff --git a/lib/readline/rlshell.h b/lib/readline/rlshell.h index 6032275..3c03fba 100644 --- a/lib/readline/rlshell.h +++ b/lib/readline/rlshell.h @@ -25,10 +25,10 @@ #include "rlstdc.h" -extern char *sh_single_quote __P((char *)); -extern void sh_set_lines_and_columns __P((int, int)); -extern char *sh_get_env_value __P((const char *)); -extern char *sh_get_home_dir __P((void)); -extern int sh_unset_nodelay_mode __P((int)); +extern char *sh_single_quote PARAMS((char *)); +extern void sh_set_lines_and_columns PARAMS((int, int)); +extern char *sh_get_env_value PARAMS((const char *)); +extern char *sh_get_home_dir PARAMS((void)); +extern int sh_unset_nodelay_mode PARAMS((int)); #endif /* _RL_SHELL_H_ */ diff --git a/lib/readline/rlstdc.h b/lib/readline/rlstdc.h index a1ca208..d6a22b3 100644 --- a/lib/readline/rlstdc.h +++ b/lib/readline/rlstdc.h @@ -26,26 +26,20 @@ /* A function can be defined using prototypes and compile on both ANSI C and traditional C compilers with something like this: - extern char *func __P((char *, char *, int)); */ + extern char *func PARAMS((char *, char *, int)); */ -#if !defined (__P) +#if !defined (PARAMS) # if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) -# define __P(protos) protos +# define PARAMS(protos) protos # else -# define __P(protos) () +# define PARAMS(protos) () # endif #endif -#if !defined (__STDC__) && !defined (__cplusplus) -# if defined (__GNUC__) /* gcc with -traditional */ -# if !defined (const) -# define const __const -# endif /* !const */ -# else /* !__GNUC__ */ -# if !defined (const) -# define const -# endif /* !const */ -# endif /* !__GNUC__ */ -#endif /* !__STDC__ && !__cplusplus */ +#ifndef __attribute__ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +# endif +#endif #endif /* !_RL_STDC_H_ */ diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c index 636e7f7..cc0dc03 100644 --- a/lib/readline/rltty.c +++ b/lib/readline/rltty.c @@ -52,6 +52,11 @@ extern int errno; rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal; rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal; +static void block_sigint PARAMS((void)); +static void release_sigint PARAMS((void)); + +static void set_winsize PARAMS((int)); + /* **************************************************************** */ /* */ /* Signal Management */ @@ -173,6 +178,14 @@ struct bsdtty { static TIOTYPE otio; +static void save_tty_chars PARAMS((TIOTYPE *)); +static int _get_tty_settings PARAMS((int, TIOTYPE *)); +static int get_tty_settings PARAMS((int, TIOTYPE *)); +static int _set_tty_settings PARAMS((int, TIOTYPE *)); +static int set_tty_settings PARAMS((int, TIOTYPE *)); + +static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); + static void save_tty_chars (tiop) TIOTYPE *tiop; @@ -379,6 +392,14 @@ prepare_terminal_settings (meta_flag, oldtio, tiop) static TIOTYPE otio; +static void save_tty_chars PARAMS((TIOTYPE *)); +static int _get_tty_settings PARAMS((int, TIOTYPE *)); +static int get_tty_settings PARAMS((int, TIOTYPE *)); +static int _set_tty_settings PARAMS((int, TIOTYPE *)); +static int set_tty_settings PARAMS((int, TIOTYPE *)); + +static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); + #if defined (FLUSHO) # define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO) #else @@ -626,6 +647,7 @@ rl_prep_terminal (meta_flag) if (get_tty_settings (tty, &tio) < 0) { release_sigint (); +fprintf(stderr, "readline: warning: rl_prep_terminal: cannot get terminal settings"); return; } @@ -771,8 +793,8 @@ rltty_set_default_bindings (kmap) { \ int ic; \ ic = sc; \ - if (ic != -1 && kmap[ic].type == ISFUNC) \ - kmap[ic].function = func; \ + if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \ + kmap[(unsigned char)ic].function = func; \ } \ while (0) @@ -861,6 +883,7 @@ _rl_disable_tty_signals () nosigstty = sigstty; nosigstty.c_lflag &= ~ISIG; + nosigstty.c_iflag &= ~IXON; if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0) return (_set_tty_settings (fileno (rl_instream), &sigstty)); @@ -872,10 +895,17 @@ _rl_disable_tty_signals () int _rl_restore_tty_signals () { + int r; + if (tty_sigs_disabled == 0) return 0; - return (_set_tty_settings (fileno (rl_instream), &sigstty)); + r = _set_tty_settings (fileno (rl_instream), &sigstty); + + if (r == 0) + tty_sigs_disabled = 0; + + return r; } #endif /* !NEW_TTY_DRIVER */ diff --git a/lib/readline/rltypedefs.h b/lib/readline/rltypedefs.h index b6f9b42..f3280e9 100644 --- a/lib/readline/rltypedefs.h +++ b/lib/readline/rltypedefs.h @@ -45,40 +45,40 @@ typedef char **CPPFunction (); # define _RL_FUNCTION_TYPEDEF /* Bindable functions */ -typedef int rl_command_func_t __P((int, int)); +typedef int rl_command_func_t PARAMS((int, int)); /* Typedefs for the completion system */ -typedef char *rl_compentry_func_t __P((const char *, int)); -typedef char **rl_completion_func_t __P((const char *, int, int)); +typedef char *rl_compentry_func_t PARAMS((const char *, int)); +typedef char **rl_completion_func_t PARAMS((const char *, int, int)); -typedef char *rl_quote_func_t __P((char *, int, char *)); -typedef char *rl_dequote_func_t __P((char *, int)); +typedef char *rl_quote_func_t PARAMS((char *, int, char *)); +typedef char *rl_dequote_func_t PARAMS((char *, int)); -typedef int rl_compignore_func_t __P((char **)); +typedef int rl_compignore_func_t PARAMS((char **)); -typedef void rl_compdisp_func_t __P((char **, int, int)); +typedef void rl_compdisp_func_t PARAMS((char **, int, int)); /* Type for input and pre-read hook functions like rl_event_hook */ -typedef int rl_hook_func_t __P((void)); +typedef int rl_hook_func_t PARAMS((void)); /* Input function type */ -typedef int rl_getc_func_t __P((FILE *)); +typedef int rl_getc_func_t PARAMS((FILE *)); /* Generic function that takes a character buffer (which could be the readline line buffer) and an index into it (which could be rl_point) and returns an int. */ -typedef int rl_linebuf_func_t __P((char *, int)); +typedef int rl_linebuf_func_t PARAMS((char *, int)); /* `Generic' function pointer typedefs */ -typedef int rl_intfunc_t __P((int)); +typedef int rl_intfunc_t PARAMS((int)); #define rl_ivoidfunc_t rl_hook_func_t -typedef int rl_icpfunc_t __P((char *)); -typedef int rl_icppfunc_t __P((char **)); +typedef int rl_icpfunc_t PARAMS((char *)); +typedef int rl_icppfunc_t PARAMS((char **)); -typedef void rl_voidfunc_t __P((void)); -typedef void rl_vintfunc_t __P((int)); -typedef void rl_vcpfunc_t __P((char *)); -typedef void rl_vcppfunc_t __P((char **)); +typedef void rl_voidfunc_t PARAMS((void)); +typedef void rl_vintfunc_t PARAMS((int)); +typedef void rl_vcpfunc_t PARAMS((char *)); +typedef void rl_vcppfunc_t PARAMS((char **)); #endif /* _RL_FUNCTION_TYPEDEF */ #ifdef __cplusplus diff --git a/lib/readline/savestring.c b/lib/readline/savestring.c index 7414175..c7ebeb1 100644 --- a/lib/readline/savestring.c +++ b/lib/readline/savestring.c @@ -20,8 +20,11 @@ have a copy of the license, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -extern char *strcpy (); -extern char *xmalloc (); +#include <config.h> +#ifdef HAVE_STRING_H +# include <string.h> +#endif +#include "xmalloc.h" /* Backwards compatibility, now that savestring has been removed from all `public' readline header files. */ @@ -29,5 +32,5 @@ char * savestring (s) const char *s; { - return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s))); + return ((char *)strcpy ((char *)xmalloc (1 + strlen (s)), (s))); } diff --git a/lib/readline/search.c b/lib/readline/search.c index 45d7f13..9c2feb1 100644 --- a/lib/readline/search.c +++ b/lib/readline/search.c @@ -54,7 +54,7 @@ extern HIST_ENTRY *_rl_saved_line_for_history; /* Functions imported from the rest of the library. */ -extern int _rl_free_history_entry __P((HIST_ENTRY *)); +extern int _rl_free_history_entry PARAMS((HIST_ENTRY *)); static char *noninc_search_string = (char *) NULL; static int noninc_history_pos; @@ -66,6 +66,13 @@ static int rl_history_search_pos; static char *history_search_string; static int history_string_size; +static void make_history_line_current PARAMS((HIST_ENTRY *)); +static int noninc_search_from_pos PARAMS((char *, int, int)); +static void noninc_dosearch PARAMS((char *, int)); +static void noninc_search PARAMS((int, int)); +static int rl_history_search_internal PARAMS((int, int)); +static void rl_history_search_reinit PARAMS((void)); + /* Make the data from the history entry ENTRY be the contents of the current line. This doesn't do anything with rl_point; the caller must set it. */ @@ -391,7 +398,7 @@ rl_history_search_reinit () if (rl_history_search_len >= history_string_size - 2) { history_string_size = rl_history_search_len + 2; - history_search_string = xrealloc (history_search_string, history_string_size); + history_search_string = (char *)xrealloc (history_search_string, history_string_size); } history_search_string[0] = '^'; strncpy (history_search_string + 1, rl_line_buffer, rl_point); diff --git a/lib/readline/shell.c b/lib/readline/shell.c index 3727f7c..ad27cc1 100644 --- a/lib/readline/shell.c +++ b/lib/readline/shell.c @@ -44,6 +44,10 @@ # include <strings.h> #endif /* !HAVE_STRING_H */ +#if defined (HAVE_LIMITS_H) +# include <limits.h> +#endif + #include <fcntl.h> #include <pwd.h> @@ -54,13 +58,29 @@ #include "xmalloc.h" #if !defined (HAVE_GETPW_DECLS) -extern struct passwd *getpwuid __P((uid_t)); +extern struct passwd *getpwuid PARAMS((uid_t)); #endif /* !HAVE_GETPW_DECLS */ #ifndef NULL # define NULL 0 #endif +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +/* Nonzero if the integer type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Bound on length of the string representing an integer value of type T. + Subtract one for the sign bit if T is signed; + 302 / 1000 is log10 (2) rounded up; + add one for integer division truncation; + add one more for a minus sign if t is signed. */ +#define INT_STRLEN_BOUND(t) \ + ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \ + + 1 + TYPE_SIGNED (t)) + /* All of these functions are resolved from bash if we are linking readline as part of bash. */ @@ -103,18 +123,18 @@ sh_set_lines_and_columns (lines, cols) char *b; #if defined (HAVE_PUTENV) - b = xmalloc (24); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1); sprintf (b, "LINES=%d", lines); putenv (b); - b = xmalloc (24); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1); sprintf (b, "COLUMNS=%d", cols); putenv (b); #else /* !HAVE_PUTENV */ # if defined (HAVE_SETENV) - b = xmalloc (8); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); sprintf (b, "%d", lines); setenv ("LINES", b, 1); - b = xmalloc (8); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); sprintf (b, "%d", cols); setenv ("COLUMNS", b, 1); # endif /* HAVE_SETENV */ diff --git a/lib/readline/signals.c b/lib/readline/signals.c index ddc6563..a191269 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -73,7 +73,7 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt # define sigemptyset(m) #endif /* !HAVE_POSIX_SIGNALS */ -static SigHandler *rl_set_sighandler __P((int, SigHandler *, sighandler_cxt *)); +static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); /* Exported variables for use by applications. */ diff --git a/lib/readline/terminal.c b/lib/readline/terminal.c index 64256b4..4d2268c 100644 --- a/lib/readline/terminal.c +++ b/lib/readline/terminal.c @@ -64,6 +64,7 @@ #include "rlprivate.h" #include "rlshell.h" +#include "xmalloc.h" /* **************************************************************** */ /* */ @@ -326,7 +327,11 @@ get_term_capabilities (bp) register int i; for (i = 0; i < NUM_TC_STRINGS; i++) +# ifdef __LCC__ + *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp); +# else *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp); +# endif #endif tcap_initialized = 1; } @@ -361,10 +366,10 @@ _rl_init_terminal_io (terminal_name) else { if (term_string_buffer == 0) - term_string_buffer = xmalloc(2032); + term_string_buffer = (char *)xmalloc(2032); if (term_buffer == 0) - term_buffer = xmalloc(4080); + term_buffer = (char *)xmalloc(4080); buffer = term_string_buffer; diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c index 7f33db4..6e4f116 100644 --- a/lib/readline/tilde.c +++ b/lib/readline/tilde.c @@ -48,22 +48,21 @@ #include "tilde.h" #if defined (TEST) || defined (STATIC_MALLOC) -static char *xmalloc (), *xrealloc (); +static void *xmalloc (), *xrealloc (); #else -extern char *xmalloc __P((int)); -extern char *xrealloc __P((void *, int)); +# include "xmalloc.h" #endif /* TEST || STATIC_MALLOC */ #if !defined (HAVE_GETPW_DECLS) -extern struct passwd *getpwuid __P((uid_t)); -extern struct passwd *getpwnam __P((const char *)); +extern struct passwd *getpwuid PARAMS((uid_t)); +extern struct passwd *getpwnam PARAMS((const char *)); #endif /* !HAVE_GETPW_DECLS */ #if !defined (savestring) # ifndef strcpy extern char *strcpy (); # endif -#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) #endif /* !savestring */ #if !defined (NULL) @@ -77,8 +76,8 @@ extern char *strcpy (); /* If being compiled as part of bash, these will be satisfied from variables.o. If being compiled as part of readline, they will be satisfied from shell.o. */ -extern char *sh_get_home_dir __P((void)); -extern char *sh_get_env_value __P((const char *)); +extern char *sh_get_home_dir PARAMS((void)); +extern char *sh_get_env_value PARAMS((const char *)); /* The default value of tilde_additional_prefixes. This is set to whitespace preceding a tilde so that simple programs which do not @@ -114,12 +113,17 @@ char **tilde_additional_prefixes = (char **)default_prefixes; `:' and `=~'. */ char **tilde_additional_suffixes = (char **)default_suffixes; +static int tilde_find_prefix PARAMS((const char *, int *)); +static int tilde_find_suffix PARAMS((const char *)); +static char *isolate_tilde_prefix PARAMS((const char *, int *)); +static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); + /* Find the start of a tilde expansion in STRING, and return the index of the tilde which starts the expansion. Place the length of the text which identified this tilde starter in LEN, excluding the tilde itself. */ static int tilde_find_prefix (string, len) - char *string; + const char *string; int *len; { register int i, j, string_len; @@ -154,7 +158,7 @@ tilde_find_prefix (string, len) the character which ends the tilde definition. */ static int tilde_find_suffix (string) - char *string; + const char *string; { register int i, j, string_len; register char **suffixes; @@ -190,9 +194,9 @@ tilde_expand (string) result_index = result_size = 0; if (result = strchr (string, '~')) - result = xmalloc (result_size = (strlen (string) + 16)); + result = (char *)xmalloc (result_size = (strlen (string) + 16)); else - result = xmalloc (result_size = (strlen (string) + 1)); + result = (char *)xmalloc (result_size = (strlen (string) + 1)); /* Scan through STRING expanding tildes as we come to them. */ while (1) @@ -206,7 +210,7 @@ tilde_expand (string) /* Copy the skipped text into the result. */ if ((result_index + start + 1) > result_size) - result = xrealloc (result, 1 + (result_size += (start + 20))); + result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); strncpy (result + result_index, string, start); result_index += start; @@ -223,7 +227,7 @@ tilde_expand (string) break; /* Expand the entire tilde word, and copy it into RESULT. */ - tilde_word = xmalloc (1 + end); + tilde_word = (char *)xmalloc (1 + end); strncpy (tilde_word, string, end); tilde_word[end] = '\0'; string += end; @@ -239,7 +243,7 @@ tilde_expand (string) #endif { if ((result_index + len + 1) > result_size) - result = xrealloc (result, 1 + (result_size += (len + 20))); + result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); strcpy (result + result_index, expansion); result_index += len; @@ -257,13 +261,13 @@ tilde_expand (string) the location it points to. */ static char * isolate_tilde_prefix (fname, lenp) - char *fname; + const char *fname; int *lenp; { char *ret; int i; - ret = xmalloc (strlen (fname)); + ret = (char *)xmalloc (strlen (fname)); #if defined (__MSDOS__) for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) #else @@ -280,7 +284,8 @@ isolate_tilde_prefix (fname, lenp) SUFFIND. */ static char * glue_prefix_and_suffix (prefix, suffix, suffind) - char *prefix, *suffix; + char *prefix; + const char *suffix; int suffind; { char *ret; @@ -288,7 +293,7 @@ glue_prefix_and_suffix (prefix, suffix, suffind) plen = (prefix && *prefix) ? strlen (prefix) : 0; slen = strlen (suffix + suffind); - ret = xmalloc (plen + slen + 1); + ret = (char *)xmalloc (plen + slen + 1); if (plen) strcpy (ret, prefix); strcpy (ret + plen, suffix + suffind); @@ -412,28 +417,28 @@ main (argc, argv) static void memory_error_and_abort (); -static char * +static void * xmalloc (bytes) - int bytes; + size_t bytes; { - char *temp = (char *)malloc (bytes); + void *temp = (char *)malloc (bytes); if (!temp) memory_error_and_abort (); return (temp); } -static char * +static void * xrealloc (pointer, bytes) - char *pointer; + void *pointer; int bytes; { - char *temp; + void *temp; if (!pointer) - temp = (char *)malloc (bytes); + temp = malloc (bytes); else - temp = (char *)realloc (pointer, bytes); + temp = realloc (pointer, bytes); if (!temp) memory_error_and_abort (); diff --git a/lib/readline/tilde.h b/lib/readline/tilde.h index d3966a6..0df608b 100644 --- a/lib/readline/tilde.h +++ b/lib/readline/tilde.h @@ -24,35 +24,27 @@ #if !defined (_TILDE_H_) # define _TILDE_H_ +#if defined (HAVE_CONFIG_H) +# include <config.h> +#endif + #ifdef __cplusplus extern "C" { #endif /* A function can be defined using prototypes and compile on both ANSI C and traditional C compilers with something like this: - extern char *func __P((char *, char *, int)); */ + extern char *func PARAMS((char *, char *, int)); */ -#if !defined (__P) +#if !defined (PARAMS) # if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) -# define __P(protos) protos +# define PARAMS(protos) protos # else -# define __P(protos) () +# define PARAMS(protos) () # endif #endif -#if !defined (__STDC__) && !defined (__cplusplus) -# if defined (__GNUC__) /* gcc with -traditional */ -# if !defined (const) -# define const __const -# endif /* !const */ -# else /* !__GNUC__ */ -# if !defined (const) -# define const -# endif /* !const */ -# endif /* !__GNUC__ */ -#endif /* !__STDC__ && !__cplusplus */ - -typedef char *tilde_hook_func_t __P((char *)); +typedef char *tilde_hook_func_t PARAMS((char *)); /* If non-null, this contains the address of a function that the application wants called before trying the standard tilde expansions. The function @@ -77,11 +69,11 @@ extern char **tilde_additional_prefixes; extern char **tilde_additional_suffixes; /* Return a new string which is the result of tilde expanding STRING. */ -extern char *tilde_expand __P((const char *)); +extern char *tilde_expand PARAMS((const char *)); /* Do the work of tilde expansion on FILENAME. FILENAME starts with a tilde. If there is no expansion, call tilde_expansion_failure_hook. */ -extern char *tilde_expand_word __P((const char *)); +extern char *tilde_expand_word PARAMS((const char *)); #ifdef __cplusplus } diff --git a/lib/readline/undo.c b/lib/readline/undo.c index e29e940..9be231d 100644 --- a/lib/readline/undo.c +++ b/lib/readline/undo.c @@ -48,6 +48,7 @@ #include "history.h" #include "rlprivate.h" +#include "xmalloc.h" #define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) diff --git a/lib/readline/util.c b/lib/readline/util.c index 6d0a6e3..bd08b38 100644 --- a/lib/readline/util.c +++ b/lib/readline/util.c @@ -132,7 +132,7 @@ rl_copy_text (from, to) SWAP (from, to); length = to - from; - copy = xmalloc (1 + length); + copy = (char *)xmalloc (1 + length); strncpy (copy, rl_line_buffer + from, length); copy[length] = '\0'; return (copy); @@ -147,7 +147,7 @@ rl_extend_line_buffer (len) while (len >= rl_line_buffer_len) { rl_line_buffer_len += DEFAULT_BUFFER_SIZE; - rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len); + rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len); } _rl_set_the_line (); @@ -193,7 +193,7 @@ rl_tilde_expand (ignore, key) if (rl_line_buffer[start] == '~') { len = end - start + 1; - temp = xmalloc (len + 1); + temp = (char *)xmalloc (len + 1); strncpy (temp, rl_line_buffer + start, len); temp[len] = '\0'; homedir = tilde_expand (temp); @@ -225,6 +225,7 @@ _rl_strindex (s1, s2) return ((char *)NULL); } +#ifndef HAVE_STRPBRK /* Find the first occurrence in STRING1 of any character from STRING2. Return a pointer to the character in STRING1. */ char * @@ -243,6 +244,7 @@ _rl_strpbrk (string1, string2) } return ((char *)NULL); } +#endif #if !defined (HAVE_STRCASECMP) /* Compare at most COUNT characters from string1 to string2. Case @@ -302,62 +304,16 @@ _rl_qsort_string_compare (s1, s2) #endif } -/* Function equivalents for the macros defined in chartypes.h. */ -#undef _rl_uppercase_p -int -_rl_uppercase_p (c) - int c; -{ - return (isupper (c)); -} - -#undef _rl_lowercase_p -int -_rl_lowercase_p (c) - int c; -{ - return (islower (c)); -} - -#undef _rl_pure_alphabetic -int -_rl_pure_alphabetic (c) - int c; -{ - return (isupper (c) || islower (c)); -} - -#undef _rl_digit_p -int -_rl_digit_p (c) - int c; -{ - return (isdigit (c)); -} - -#undef _rl_to_lower -int -_rl_to_lower (c) - int c; -{ - return (isupper (c) ? tolower (c) : c); -} +/* Function equivalents for the macros defined in chardefs.h. */ +#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); } -#undef _rl_to_upper -int -_rl_to_upper (c) - int c; -{ - return (islower (c) ? toupper (c) : c); -} - -#undef _rl_digit_value -int -_rl_digit_value (c) - int c; -{ - return (isdigit (c) ? c - '0' : c); -} +FUNCTION_FOR_MACRO (_rl_digit_p) +FUNCTION_FOR_MACRO (_rl_digit_value) +FUNCTION_FOR_MACRO (_rl_lowercase_p) +FUNCTION_FOR_MACRO (_rl_pure_alphabetic) +FUNCTION_FOR_MACRO (_rl_to_lower) +FUNCTION_FOR_MACRO (_rl_to_upper) +FUNCTION_FOR_MACRO (_rl_uppercase_p) /* Backwards compatibility, now that savestring has been removed from all `public' readline header files. */ @@ -366,5 +322,5 @@ char * _rl_savestring (s) const char *s; { - return (strcpy (xmalloc (1 + (int)strlen (s)), (s))); + return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); } diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index b9c0ea8..09ccecf 100644 --- a/lib/readline/vi_mode.c +++ b/lib/readline/vi_mode.c @@ -57,22 +57,10 @@ #include "rlprivate.h" #include "xmalloc.h" -#ifndef _rl_digit_p -#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') -#endif - -#ifndef _rl_digit_value -#define _rl_digit_value(c) ((c) - '0') -#endif - #ifndef member #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) #endif -#ifndef isident -#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_')) -#endif - #ifndef exchange #define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0) #endif @@ -81,7 +69,7 @@ static int _rl_vi_doing_insert; /* Command keys which do movement for xxx_to commands. */ -static const char *vi_motion = " hl^$0ftFt;,%wbeWBE|"; +static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; /* Keymap used for vi replace characters. Created dynamically since rarely used. */ @@ -112,9 +100,11 @@ static int vi_redoing; static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; /* Arrays for the saved marks. */ -static int vi_mark_chars[27]; +static int vi_mark_chars['z' - 'a' + 1]; -static int rl_digit_loop1 __P((void)); +static void _rl_vi_stuff_insert PARAMS((int)); +static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static int rl_digit_loop1 PARAMS((void)); void _rl_vi_initialize_line () @@ -460,14 +450,14 @@ rl_vi_fword (count, ignore) while (count-- && rl_point < (rl_end - 1)) { /* Move to white space (really non-identifer). */ - if (isident (rl_line_buffer[rl_point])) + if (_rl_isident (rl_line_buffer[rl_point])) { - while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } else /* if (!whitespace (rl_line_buffer[rl_point])) */ { - while (!isident (rl_line_buffer[rl_point]) && + while (!_rl_isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } @@ -497,9 +487,9 @@ rl_vi_bword (count, ignore) back so we don't get messed up by the rl_point++ down there in the while loop. Without this code, words like `l;' screw up the function. */ - last_is_ident = isident (rl_line_buffer[rl_point - 1]); - if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) || - (!isident (rl_line_buffer[rl_point]) && last_is_ident)) + last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); + if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) rl_point--; while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) @@ -507,10 +497,10 @@ rl_vi_bword (count, ignore) if (rl_point > 0) { - if (isident (rl_line_buffer[rl_point])) - while (--rl_point >= 0 && isident (rl_line_buffer[rl_point])); + if (_rl_isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); else - while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) && + while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point])); rl_point++; } @@ -532,10 +522,10 @@ rl_vi_eword (count, ignore) if (rl_point < rl_end) { - if (isident (rl_line_buffer[rl_point])) - while (++rl_point < rl_end && isident (rl_line_buffer[rl_point])); + if (_rl_isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); else - while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point]) + while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point])); } rl_point--; @@ -611,7 +601,7 @@ _rl_vi_save_insert (up) if (len >= vi_insert_buffer_size) { vi_insert_buffer_size += (len + 32) - (len % 32); - vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); } strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); vi_insert_buffer[len-1] = '\0'; @@ -847,12 +837,12 @@ rl_digit_loop1 () RL_UNSETSTATE(RL_STATE_NUMERICARG); return 1; } - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); RL_SETSTATE(RL_STATE_MOREINPUT); key = c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (_rl_keymap[c].type == ISFUNC && + if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) { rl_numeric_arg *= 4; @@ -1356,7 +1346,7 @@ rl_vi_set_mark (count, key) ch = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (_rl_lowercase_p (ch) == 0) + if (ch < 'a' || ch > 'z') { rl_ding (); return -1; @@ -1381,7 +1371,7 @@ rl_vi_goto_mark (count, key) rl_point = rl_mark; return 0; } - else if (_rl_lowercase_p (ch) == 0) + else if (ch < 'a' || ch > 'z') { rl_ding (); return -1; diff --git a/lib/readline/xmalloc.c b/lib/readline/xmalloc.c index c0d0640..8985d34 100644 --- a/lib/readline/xmalloc.c +++ b/lib/readline/xmalloc.c @@ -51,26 +51,26 @@ memory_error_and_abort (fname) /* Return a pointer to free()able block of memory large enough to hold BYTES number of bytes. If the memory cannot be allocated, print an error message and abort. */ -char * +PTR_T xmalloc (bytes) - int bytes; + size_t bytes; { - char *temp; + PTR_T temp; - temp = (char *)malloc (bytes); + temp = malloc (bytes); if (temp == 0) memory_error_and_abort ("xmalloc"); return (temp); } -char * +PTR_T xrealloc (pointer, bytes) PTR_T pointer; - int bytes; + size_t bytes; { - char *temp; + PTR_T temp; - temp = pointer ? (char *)realloc (pointer, bytes) : (char *)malloc (bytes); + temp = pointer ? realloc (pointer, bytes) : malloc (bytes); if (temp == 0) memory_error_and_abort ("xrealloc"); diff --git a/lib/readline/xmalloc.h b/lib/readline/xmalloc.h index bdf251b..9cb08ba 100644 --- a/lib/readline/xmalloc.h +++ b/lib/readline/xmalloc.h @@ -39,8 +39,8 @@ #endif /* !PTR_T */ -extern char *xmalloc __P((int)); -extern char *xrealloc __P((void *, int)); -extern void xfree __P((void *)); +extern PTR_T xmalloc PARAMS((size_t)); +extern PTR_T xrealloc PARAMS((void *, size_t)); +extern void xfree PARAMS((void *)); #endif /* _XMALLOC_H_ */ diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in index 1c52e0d..126f5f8 100644 --- a/lib/sh/Makefile.in +++ b/lib/sh/Makefile.in @@ -40,7 +40,7 @@ MV = mv SHELL = @MAKE_SHELL@ CFLAGS = @CFLAGS@ -LOCAL_CFLAGS = @LOCAL_CFLAGS@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG} CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@ @@ -54,6 +54,10 @@ INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(BASHINCDIR) -I$(srcdir) CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \ $(CFLAGS) $(CPPFLAGS) +GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \ + -Wcast-align -Wstrict-prototypes -Wconversion \ + -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic + .c.o: $(CC) -c $(CCFLAGS) $< @@ -66,18 +70,20 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \ vprint.c itos.c rename.c zread.c zwrite.c shtty.c \ inet_aton.c netopen.c strpbrk.c timeval.c makepath.c pathcanon.c \ pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \ - shquote.c strtrans.c strindex.c + shquote.c strtrans.c strindex.c snprintf.c mailstat.c fmtulong.c \ + fmtullong.c strtoll.c strtoull.c strtoimax.c strtoumax.c # The header files for this library. HSOURCES = # The object files contained in $(LIBRARY_NAME) -OBJECTS = clktck.o clock.o getcwd.o getenv.o oslib.o setlinebuf.o \ - strcasecmp.o strerror.o strtod.o strtol.o strtoul.o \ - vprint.o itos.o rename.o zread.o zwrite.o shtty.o \ - inet_aton.o netopen.o strpbrk.o timeval.o makepath.o pathcanon.o \ +LIBOBJS = @LIBOBJS@ +OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o \ + itos.o zread.o zwrite.o shtty.o \ + netopen.o timeval.o makepath.o pathcanon.o \ pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \ - strtrans.o strindex.o + strtrans.o strindex.o snprintf.o mailstat.o fmtulong.o \ + fmtullong.o ${LIBOBJS} SUPPORT = Makefile @@ -108,10 +114,13 @@ mostlyclean: clean # rules for losing makes, like SunOS clktck.o: clktck.c clock.o: clock.c +fmtullong.o: fmtullong.c +fmtulong.o: fmtulong.c getcwd.o: getcwd.c getenv.o: getenv.c inet_aton.o: inet_aton.c itos.o: itos.c +mailstat.o: mailstat.c makepath.o: makepath.c netopen.o: netopen.c oslib.o: oslib.c @@ -121,6 +130,7 @@ rename.o: rename.c setlinebuf.o: setlinebuf.c shquote.o: shquote.c shtty.o: shtty.c +snprintf.o: snprintf.c spell.o: spell.c strcasecmp.o: strcasecmp.c strerror.o: strerror.c @@ -129,8 +139,12 @@ stringlist.o: stringlist.c stringvec.o: stringvec.c strpbrk.o: strpbrk.c strtod.o: strtod.c +strtoimax.o: strtoimax.c strtol.o: strtol.c +strtoll.o: strtoll.c strtoul.o: strtoul.c +strtoull.o: strtoull.c +strtoumax.o: strtoumax.c strtrans.o: strtrans.c times.o: times.c timeval.o: timeval.c @@ -139,13 +153,22 @@ vprint.o: vprint.c zread.o: zread.c zwrite.o: zwrite.c +# dependencies for c files that include other c files +fmtullong.o: fmtulong.c +strtoll.o: strtol.c +strtoul.o: strtol.c +strtoull.o: strtol.c + # all files in the library depend on config.h clktck.o: ${BUILD_DIR}/config.h clock.o: ${BUILD_DIR}/config.h +fmtullong.o: ${BUILD_DIR}/config.h +fmtulong.o: ${BUILD_DIR}/config.h getcwd.o: ${BUILD_DIR}/config.h getenv.o: ${BUILD_DIR}/config.h inet_aton.o: ${BUILD_DIR}/config.h itos.o: ${BUILD_DIR}/config.h +mailstat.o: ${BUILD_DIR}/config.h makepath.o: ${BUILD_DIR}/config.h netopen.o: ${BUILD_DIR}/config.h oslib.o: ${BUILD_DIR}/config.h @@ -155,6 +178,7 @@ rename.o: ${BUILD_DIR}/config.h setlinebuf.o: ${BUILD_DIR}/config.h shquote.o: ${BUILD_DIR}/config.h shtty.o: ${BUILD_DIR}/config.h +snprintf.o: ${BUILD_DIR}/config.h spell.o: ${BUILD_DIR}/config.h strcasecmp.o: ${BUILD_DIR}/config.h strerror.o: ${BUILD_DIR}/config.h @@ -163,8 +187,12 @@ stringlist.o: ${BUILD_DIR}/config.h stringvec.o: ${BUILD_DIR}/config.h strpbrk.o: ${BUILD_DIR}/config.h strtod.o: ${BUILD_DIR}/config.h +strtoimax.o: ${BUILD_DIR}/config.h strtol.o: ${BUILD_DIR}/config.h +strtoll.o: ${BUILD_DIR}/config.h strtoul.o: ${BUILD_DIR}/config.h +strtoull.o: ${BUILD_DIR}/config.h +strtoumax.o: ${BUILD_DIR}/config.h strtrans.o: ${BUILD_DIR}/config.h times.o: ${BUILD_DIR}/config.h timeval.o: ${BUILD_DIR}/config.h @@ -182,7 +210,7 @@ getcwd.o: ${BASHINCDIR}/memalloc.h ${BASHINCDIR}/ansi_stdlib.h getenv.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h getenv.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h getenv.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h @@ -194,7 +222,7 @@ inet_aton.o: ${BASHINCDIR}/stdc.h itos.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h itos.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h itos.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h @@ -203,84 +231,101 @@ itos.o: ${topdir}/pathnames.h ${topdir}/externs.h makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h makepath.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h makepath.o: ${topdir}/pathnames.h ${topdir}/externs.h -netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h +netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h +netopen.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h +netopen.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h +netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h +netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h +netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h +netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h +netopen.o: ${topdir}/pathnames.h ${topdir}/externs.h oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h oslib.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h oslib.o: ${topdir}/pathnames.h ${topdir}/externs.h oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h -oslib.o: ${BASHINCDIR}/ansi_stdlib.h +oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h pathcanon.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h pathcanon.o: ${topdir}/pathnames.h ${topdir}/externs.h pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h -pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h +pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h pathphys.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h pathphys.o: ${topdir}/pathnames.h ${topdir}/externs.h pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h -pathphys.o: ${BASHINCDIR}/ansi_stdlib.h +pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h +setlinebuf.o: ${topdir}/xmalloc.h ${topdir}/bashansi.h +setlinebuf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/stdc.h + +shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h +shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h + shtty.o: ${BASHINCDIR}/shtty.h shtty.o: ${BASHINCDIR}/stdc.h +snprintf.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h ${topdir}/xmalloc.h +snprintf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h +snprintf.o: ${BASHINCDIR}/typemax.h + spell.o: ${topdir}/bashtypes.h spell.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h spell.o: ${BASHINCDIR}/ansi_stdlib.h strcasecmp.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h -strcasecmp.o: ${BASHINCDIR}/ansi_stdlib.h +strcasecmp.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h strerror.o: ${topdir}/bashtypes.h strerror.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h strerror.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h strerror.o: ${topdir}/pathnames.h ${topdir}/externs.h strindex.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h -strindex.o: ${BASHINCDIR}/ansi_stdlib.h +strindex.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h stringlist.o: ${topdir}/bashansi.h stringlist.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h stringlist.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h stringlist.o: ${topdir}/pathnames.h ${topdir}/externs.h -stringvec.o: ${topdir}/bashansi.h +stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h stringvec.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h @@ -289,19 +334,33 @@ stringvec.o: ${topdir}/pathnames.h ${topdir}/externs.h strpbrk.o: ${BASHINCDIR}/stdc.h strtod.o: ${topdir}/bashansi.h -strtod.o: ${BASHINCDIR}/ansi_stdlib.h +strtod.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h + +strtoimax.o: ${BASHINCDIR}/stdc.h strtol.o: ${topdir}/bashansi.h -strtol.o: ${BASHINCDIR}/ansi_stdlib.h +strtol.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h +strtol.o: ${BASHINCDIR}/typemax.h + +strtoll.o: ${topdir}/bashansi.h +strtoll.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h +strtoll.o: ${BASHINCDIR}/typemax.h strtoul.o: ${topdir}/bashansi.h -strtoul.o: ${BASHINCDIR}/ansi_stdlib.h +strtoul.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h +strtoul.o: ${BASHINCDIR}/typemax.h + +strtoull.o: ${topdir}/bashansi.h +strtoull.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h +strtoull.o: ${BASHINCDIR}/typemax.h + +strtoumax.o: ${BASHINCDIR}/stdc.h strtrans.o: ${topdir}/bashansi.h -strtrans.o: ${BASHINCDIR}/ansi_stdlib.h +strtrans.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h strtrans.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h strtrans.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h -strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h +strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h @@ -317,3 +376,22 @@ tmpfile.o: ${BASHINCDIR}/posixstat.h tmpfile.o: ${BASHINCDIR}/filecntl.h clock.o: ${BASHINCDIR}/posixtime.h + +mailstat.o: ${topdir}/bashansi.h +mailstat.o: ${topdir}/bashtypes.h +mailstat.o: ${BASHINCDIR}/ansi_stdlib.h +mailstat.o: ${BASHINCDIR}/posixstat.h +mailstat.o: ${BASHINCDIR}/posixdir.h +mailstat.o: ${BASHINCDIR}/maxpath.h + +fmtulong.o: ${topdir}/bashansi.h +fmtulong.o: ${BASHINCDIR}/ansi_stdlib.h +fmtulong.o: ${BASHINCDIR}/chartypes.h +fmtulong.o: ${BASHINCDIR}/stdc.h +fmtulong.o: ${BASHINCDIR}/typemax.h + +fmtullong.o: ${topdir}/bashansi.h +fmtullong.o: ${BASHINCDIR}/ansi_stdlib.h +fmtullong.o: ${BASHINCDIR}/chartypes.h +fmtullong.o: ${BASHINCDIR}/stdc.h +fmtullong.o: ${BASHINCDIR}/typemax.h diff --git a/lib/sh/clock.c b/lib/sh/clock.c index 9a91e38..1186a19 100644 --- a/lib/sh/clock.c +++ b/lib/sh/clock.c @@ -30,11 +30,14 @@ #endif #include <stdio.h> +#include <stdc.h> + +extern long get_clk_tck __P((void)); void clock_t_to_secs (t, sp, sfp) clock_t t; - long *sp; + time_t *sp; int *sfp; { static long clk_tck = -1; @@ -64,15 +67,15 @@ print_clock_t (fp, t) FILE *fp; clock_t t; { - int minutes, seconds_fraction; - long seconds; + time_t timestamp; + long minutes; + int seconds, seconds_fraction; - clock_t_to_secs (t, &seconds, &seconds_fraction); + clock_t_to_secs (t, ×tamp, &seconds_fraction); - minutes = seconds / 60; - seconds %= 60; + minutes = timestamp / 60; + seconds = timestamp % 60; - fprintf (fp, "%0dm%0ld.%03ds", minutes, seconds, seconds_fraction); + fprintf (fp, "%ldm%d.%03ds", minutes, seconds, seconds_fraction); } #endif /* HAVE_TIMES */ - diff --git a/lib/sh/fmtullong.c b/lib/sh/fmtullong.c new file mode 100644 index 0000000..8139a7e --- /dev/null +++ b/lib/sh/fmtullong.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software Foundation, +Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> + +#ifdef HAVE_LONG_LONG + +#define QUAD 1 +#include "fmtulong.c" + +#endif diff --git a/lib/sh/fmtulong.c b/lib/sh/fmtulong.c new file mode 100644 index 0000000..15e73ef --- /dev/null +++ b/lib/sh/fmtulong.c @@ -0,0 +1,196 @@ +/* fmtulong.c -- Convert unsigned long int to string. */ + +/* Copyright (C) 1998, Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#if defined (HAVE_LIMITS_H) +# include <limits.h> +#endif + +#include <bashansi.h> +#ifdef HAVE_STDDEF_H +# include <stddef.h> +#endif + +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <chartypes.h> +#include <errno.h> + +#include "stdc.h" + +#include <typemax.h> + +#ifndef errno +extern int errno; +#endif + +#define x_digs "0123456789abcdef" +#define X_digs "0123456789ABCDEF" + +/* XXX -- assumes uppercase letters, lowercase letters, and digits are + contiguous */ +#define FMTCHAR(x) \ + ((x) < 10) ? (x) + '0' \ + : (((x) < 36) ? (x) - 10 + 'a' \ + : (((x) < 62) ? (x) - 36 + 'A' \ + : (((x) == 62) ? '@' : '_'))) + +#ifndef FL_PREFIX +# define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */ +# define FL_ADDBASE 0x02 /* add base# prefix to converted value */ +# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */ +# define FL_UNSIGNED 0x08 /* don't add any sign */ +#endif + +#ifdef QUAD + /* fmtullong */ +# define LONG long long +# define FMTUL_LONG_MAX LLONG_MAX +# define FMTUL_ULONG_MAX ULLONG_MAX +#else +# define LONG long +# define FMTUL_LONG_MAX LONG_MAX +# define FMTUL_ULONG_MAX ULONG_MAX +#endif + +/* Set the name */ +#ifdef QUAD +# define fmtulong fmtullong +#endif + +/* `unsigned long' (or unsigned long long) to string conversion for a given + base. The caller passes the output buffer and the size. This should + check for buffer underflow, but currently does not. */ +char * +fmtulong (ui, base, buf, len, flags) + unsigned LONG ui; + int base; + char *buf; + size_t len; + int flags; +{ + char *p; + int sign; + LONG si; + + if (base == 0) + base = 10; + + if (base < 2 || base > 64) + { +#if 1 + strncpy (buf, "invalid base", len - 1); + buf[len] = '\0'; + errno = EINVAL; + return (p = buf); +#else + base = 10; +#endif + } + + sign = 0; + if ((flags & FL_UNSIGNED) == 0 && (LONG)ui < 0) + { + ui = -ui; + sign = '-'; + } + + p = buf + len - 2; + p[1] = '\0'; + + /* handle common cases explicitly */ + switch (base) + { + case 10: + if (ui < 10) + { + *p-- = TOCHAR (ui); + break; + } + /* Favor signed arithmetic over unsigned arithmetic; it is faster on + many machines. */ + if (ui > FMTUL_LONG_MAX) + { + *p-- = TOCHAR (ui % 10); + si = ui / 10; + } + else + si = ui; + do + *p-- = TOCHAR (si % 10); + while (si /= 10); + break; + + case 8: + do + *p-- = TOCHAR (ui & 7); + while (ui >>= 3); + break; + + case 16: + do + *p-- = (flags & FL_HEXUPPER) ? X_digs[ui & 15] : x_digs[ui & 15]; + while (ui >>= 4); + break; + + case 2: + do + *p-- = TOCHAR (ui & 1); + while (ui >>= 1); + break; + + default: + do + *p-- = FMTCHAR (ui % base); + while (ui /= base); + break; + } + + if ((flags & FL_PREFIX) && (base == 8 || base == 16)) + { + if (base == 16) + { + *p-- = (flags & FL_HEXUPPER) ? 'X' : 'x'; + *p-- = '0'; + } + else if (p[1] != '0') + *p-- = '0'; + } + else if ((flags & FL_ADDBASE) && base != 10) + { + *p-- = '#'; + *p-- = TOCHAR (base % 10); + if (base > 10) + *p-- = TOCHAR (base / 10); + } + + if (sign) + *p-- = '-'; + + return (p + 1); +} diff --git a/lib/sh/getcwd.c b/lib/sh/getcwd.c index d39655d..0c8b1da 100644 --- a/lib/sh/getcwd.c +++ b/lib/sh/getcwd.c @@ -40,26 +40,12 @@ #include <bashansi.h> +#include <xmalloc.h> + #if !defined (errno) extern int errno; #endif /* !errno */ -#if defined (__STDC__) -# define CONST const -# define PTR void * -#else /* !__STDC__ */ -# define CONST -# define PTR char * -#endif /* !__STDC__ */ - -#if !defined (PATH_MAX) -# if defined (MAXPATHLEN) -# define PATH_MAX MAXPATHLEN -# else /* !MAXPATHLEN */ -# define PATH_MAX 1024 -# endif /* !MAXPATHLEN */ -#endif /* !PATH_MAX */ - #if !defined (HAVE_LSTAT) # define lstat stat #endif @@ -85,11 +71,11 @@ getcwd (buf, size) size_t size; #endif /* !__STDC__ */ { - static CONST char dots[] + static const char dots[] = "../../../../../../../../../../../../../../../../../../../../../../../\ ../../../../../../../../../../../../../../../../../../../../../../../../../../\ ../../../../../../../../../../../../../../../../../../../../../../../../../.."; - CONST char *dotp, *dotlist; + const char *dotp, *dotlist; size_t dotsize; dev_t rootdev, thisdev; ino_t rootino, thisino; @@ -149,7 +135,7 @@ getcwd (buf, size) } else { - new = (char *)realloc ((PTR) dotlist, dotsize * 2 + 1); + new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1); if (new == NULL) goto lose; } @@ -232,7 +218,7 @@ getcwd (buf, size) } else { - new = (char *)realloc ((PTR) pathbuf, (pathsize * 2)); + new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2)); if (!new) goto lose; pathp = new + space; @@ -257,7 +243,7 @@ getcwd (buf, size) *--pathp = '/'; if (dotlist != dots) - free ((PTR) dotlist); + free ((PTR_T) dotlist); { size_t len = pathbuf + pathsize - pathp; @@ -274,7 +260,7 @@ getcwd (buf, size) errno = ERANGE; goto lose2; } - (void) memcpy((PTR) buf, (PTR) pathp, len); + (void) memcpy((PTR_T) buf, (PTR_T) pathp, len); } if (pathbuf != path) @@ -286,7 +272,7 @@ getcwd (buf, size) if ((dotlist != dots) && dotlist) { int e = errno; - free ((PTR) dotlist); + free ((PTR_T) dotlist); errno = e; } @@ -294,7 +280,7 @@ getcwd (buf, size) if ((pathbuf != path) && pathbuf) { int e = errno; - free ((PTR) pathbuf); + free ((PTR_T) pathbuf); errno = e; } return ((char *)NULL); diff --git a/lib/sh/inet_aton.c b/lib/sh/inet_aton.c index 28cd979..2835d62 100644 --- a/lib/sh/inet_aton.c +++ b/lib/sh/inet_aton.c @@ -115,7 +115,7 @@ inet_aton(cp, addr) { register u_bits32_t val; register int base, n; - register char c; + register unsigned char c; u_int parts[4]; register u_int *pp = parts; @@ -126,7 +126,12 @@ inet_aton(cp, addr) * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ +#if 0 if (!isdigit(c)) +#else + if (c != '0' && c != '1' && c != '2' && c != '3' && c != '4' && + c != '5' && c != '6' && c != '7' && c != '8' && c != '9') +#endif return (0); val = 0; base = 10; if (c == '0') { diff --git a/lib/sh/itos.c b/lib/sh/itos.c index dee7883..e836536 100644 --- a/lib/sh/itos.c +++ b/lib/sh/itos.c @@ -18,61 +18,56 @@ with Bash; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#include <config.h> +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif #if defined (HAVE_UNISTD_H) # include <unistd.h> #endif -#include "bashansi.h" +#include <bashansi.h> +#include <chartypes.h> #include "shell.h" -/* Number of characters that can appear in a string representation - of an integer. 32 is larger than the string rep of 2^^31 - 1. */ -#define MAX_INT_LEN 32 - -/* Integer to string conversion. The caller passes the buffer and - the size. This should check for buffer underflow, but currently - does not. */ char * inttostr (i, buf, len) - int i; + long i; char *buf; - int len; + size_t len; { - char *p; - int negative = 0; - unsigned int ui; - - if (i < 0) - { - negative++; - i = -i; - } - - ui = (unsigned int) i; - - p = buf + len - 2; - p[1] = '\0'; + return (fmtulong (i, 10, buf, len, 0)); +} - do - *p-- = (ui % 10) + '0'; - while (ui /= 10); +/* Integer to string conversion. This conses the string; the + caller should free it. */ +char * +itos (i) + long i; +{ + char *p, lbuf[INT_STRLEN_BOUND(long) + 1]; - if (negative) - *p-- = '-'; + p = fmtulong (i, 10, lbuf, sizeof(lbuf), 0); + return (savestring (p)); +} - return (p + 1); +char * +uinttostr (i, buf, len) + unsigned long i; + char *buf; + size_t len; +{ + return (fmtulong (i, 10, buf, len, FL_UNSIGNED)); } /* Integer to string conversion. This conses the string; the caller should free it. */ char * -itos (i) - int i; +uitos (i) + unsigned long i; { - char *p, lbuf[MAX_INT_LEN]; + char *p, lbuf[INT_STRLEN_BOUND(long) + 1]; - p = inttostr (i, lbuf, sizeof(lbuf)); + p = fmtulong (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED); return (savestring (p)); } diff --git a/lib/sh/mailstat.c b/lib/sh/mailstat.c new file mode 100644 index 0000000..8005252 --- /dev/null +++ b/lib/sh/mailstat.c @@ -0,0 +1,159 @@ +/* mailstat.c -- stat a mailbox file, handling maildir-type mail directories */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include <config.h> + +#include <stdio.h> +#include <errno.h> + +#include <bashtypes.h> +#include <posixstat.h> +#include <posixdir.h> +#include <bashansi.h> + +#ifndef _MINIX +# include <sys/param.h> +#endif + +#include <maxpath.h> + +/* + * Stat a file. If it's a maildir, check all messages + * in the maildir and present the grand total as a file. + * The fields in the 'struct stat' are from the mail directory. + * The following fields are emulated: + * + * st_nlink always 1, unless st_blocks is not present, in which case it's + * the total number of messages + * st_size total number of bytes in all files + * st_blocks total number of messages, if present in struct stat + * st_atime access time of newest file in maildir + * st_mtime modify time of newest file in maildir + * st_mode S_IFDIR changed to S_IFREG + * + * This is good enough for most mail-checking applications. + */ + +int +mailstat(path, st) + const char *path; + struct stat *st; +{ + static struct stat st_new_last, st_ret_last; + struct stat st_ret, st_tmp; + DIR *dd; + struct dirent *fn; + char dir[PATH_MAX * 2], file[PATH_MAX * 2]; + int i, l; + time_t atime, mtime; + + atime = mtime = 0; + + /* First see if it's a directory. */ + if ((i = stat(path, st)) != 0 || S_ISDIR(st->st_mode) == 0) + return i; + + if (strlen(path) > sizeof(dir) - 5) + { +#ifdef ENAMETOOLONG + errno = ENAMETOOLONG; +#else + errno = EINVAL; +#endif + return -1; + } + + st_ret = *st; + st_ret.st_nlink = 1; + st_ret.st_size = 0; +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + st_ret.st_blocks = 0; +#else + st_ret.st_nlink = 0; +#endif + st_ret.st_mode &= ~S_IFDIR; + st_ret.st_mode |= S_IFREG; + + /* See if cur/ is present */ + sprintf(dir, "%s/cur", path); + if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0) + return 0; + st_ret.st_atime = st_tmp.st_atime; + + /* See if tmp/ is present */ + sprintf(dir, "%s/tmp", path); + if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0) + return 0; + st_ret.st_mtime = st_tmp.st_mtime; + + /* And new/ */ + sprintf(dir, "%s/new", path); + if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0) + return 0; + st_ret.st_mtime = st_tmp.st_mtime; + + /* Optimization - if new/ didn't change, nothing else did. */ + if (st_tmp.st_dev == st_new_last.st_dev && + st_tmp.st_ino == st_new_last.st_ino && + st_tmp.st_atime == st_new_last.st_atime && + st_tmp.st_mtime == st_new_last.st_mtime) + { + *st = st_ret_last; + return 0; + } + st_new_last = st_tmp; + + /* Loop over new/ and cur/ */ + for (i = 0; i < 2; i++) + { + sprintf(dir, "%s/%s", path, i ? "cur" : "new"); + sprintf(file, "%s/", dir); + l = strlen(file); + if ((dd = opendir(dir)) == NULL) + return 0; + while ((fn = readdir(dd)) != NULL) + { + if (fn->d_name[0] == '.' || strlen(fn->d_name) + l >= sizeof(file)) + continue; + strcpy(file + l, fn->d_name); + if (stat(file, &st_tmp) != 0) + continue; + st_ret.st_size += st_tmp.st_size; +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + st_ret.st_blocks++; +#else + st_ret.st_nlink++; +#endif + if (st_tmp.st_atime != st_tmp.st_mtime && st_tmp.st_atime > atime) + atime = st_tmp.st_atime; + if (st_tmp.st_mtime > mtime) + mtime = st_tmp.st_mtime; + } + closedir(dd); + } + + if (atime) + st_ret.st_atime = atime; + if (mtime) + st_ret.st_mtime = mtime; + + *st = st_ret_last = st_ret; + return 0; +} diff --git a/lib/sh/makepath.c b/lib/sh/makepath.c index ba2bcb9..13aad3f 100644 --- a/lib/sh/makepath.c +++ b/lib/sh/makepath.c @@ -27,7 +27,7 @@ # include <unistd.h> #endif -#include "bashansi.h" +#include <bashansi.h> #include "shell.h" #include <tilde/tilde.h> @@ -56,7 +56,7 @@ extern char *get_working_directory __P((char *)); #define MAKEDOT() \ do { \ - xpath = xmalloc (2); \ + xpath = (char *)xmalloc (2); \ xpath[0] = '.'; \ xpath[1] = '\0'; \ pathlen = 1; \ @@ -64,11 +64,11 @@ extern char *get_working_directory __P((char *)); char * sh_makepath (path, dir, flags) - char *path, *dir; + const char *path, *dir; int flags; { int dirlen, pathlen; - char *ret, *xpath, *r, *s; + char *ret, *xpath, *xdir, *r, *s; if (path == 0 || *path == '\0') { @@ -91,24 +91,25 @@ sh_makepath (path, dir, flags) } else { - xpath = ((flags & MP_DOTILDE) && *path == '~') ? bash_tilde_expand (path) : path; + xpath = ((flags & MP_DOTILDE) && *path == '~') ? bash_tilde_expand (path) : (char *)path; pathlen = strlen (xpath); } - dirlen = strlen (dir); + xdir = (char *)dir; + dirlen = strlen (xdir); if ((flags & MP_RMDOT) && dir[0] == '.' && dir[1] == '/') { - dir += 2; + xdir += 2; dirlen -= 2; } - r = ret = xmalloc (2 + dirlen + pathlen); + r = ret = (char *)xmalloc (2 + dirlen + pathlen); s = xpath; while (*s) *r++ = *s++; if (s[-1] != '/') *r++ = '/'; - s = dir; + s = xdir; while (*r++ = *s++) ; if (xpath != path) diff --git a/lib/sh/netopen.c b/lib/sh/netopen.c index f0b0b9b..76a389b 100644 --- a/lib/sh/netopen.c +++ b/lib/sh/netopen.c @@ -27,6 +27,10 @@ #if defined (HAVE_NETWORK) +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + #include <stdio.h> #include <sys/types.h> @@ -47,19 +51,20 @@ #endif #include <bashansi.h> -#include <ctype.h> #include <errno.h> +#include <shell.h> +#include <xmalloc.h> + #ifndef errno extern int errno; #endif #if !defined (HAVE_INET_ATON) -extern int inet_aton (); +extern int inet_aton __P((const char *, struct in_addr *)); #endif -extern char *xmalloc (); - +#ifndef HAVE_GETADDRINFO /* Stuff the internet address corresponding to HOST into AP, in network byte order. Return 1 on success, 0 on failure. */ @@ -72,7 +77,7 @@ _getaddr (host, ap) int r; r = 0; - if (isdigit (host[0])) + if (host[0] >= '0' && host[0] <= '9') { /* If the first character is a digit, guess that it's an Internet address and return immediately if inet_aton succeeds. */ @@ -107,9 +112,9 @@ _getserv (serv, proto, pp) if (legal_number (serv, &l)) { - if (l > 65535) - return 0; s = (unsigned short)(l & 0xFFFF); + if (s != l) + return (0); s = htons (s); if (pp) *pp = s; @@ -132,8 +137,12 @@ _getserv (serv, proto, pp) #endif /* !HAVE_GETSERVBYNAME */ } +/* + * Open a TCP or UDP connection to HOST on port SERV. Uses the + * traditional BSD mechanisms. Returns the connected socket or -1 on error. + */ static int -_netopen(host, serv, typ) +_netopen4(host, serv, typ) char *host, *serv; int typ; { @@ -141,7 +150,6 @@ _netopen(host, serv, typ) struct sockaddr_in sin; unsigned short p; int s, e; - char **cp; if (_getaddr(host, &ina) == 0) { @@ -180,6 +188,90 @@ _netopen(host, serv, typ) return(s); } +#endif /* ! HAVE_GETADDRINFO */ + +#ifdef HAVE_GETADDRINFO +/* + * Open a TCP or UDP connection to HOST on port SERV. Uses getaddrinfo(3) + * which provides support for IPv6. Returns the connected socket or -1 + * on error. + */ +static int +_netopen6 (host, serv, typ) + char *host, *serv; + int typ; +{ + int s, e; + struct addrinfo hints, *res, *res0; + int gerr; + + bzero ((char *)&hints, sizeof (hints)); + /* XXX -- if problems with IPv6, set to PF_INET for IPv4 only */ +#ifdef DEBUG /* PF_INET is the one that works for me */ + hints.ai_family = PF_INET; +#else + hints.ai_family = PF_UNSPEC; +#endif + hints.ai_socktype = (typ == 't') ? SOCK_STREAM : SOCK_DGRAM; + + gerr = getaddrinfo (host, serv, &hints, &res0); + if (gerr) + { + if (gerr == EAI_SERVICE) + internal_error ("%s: %s", serv, gai_strerror (gerr)); + else + internal_error ("%s: %s", host, gai_strerror (gerr)); + errno = EINVAL; + return -1; + } + + for (res = res0; res; res = res->ai_next) + { + if ((s = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) + { + if (res->ai_next) + continue; + sys_error ("socket"); + freeaddrinfo (res0); + return -1; + } + if (connect (s, res->ai_addr, res->ai_addrlen) < 0) + { + if (res->ai_next) + { + close (s); + continue; + } + e = errno; + sys_error ("connect"); + close (s); + freeaddrinfo (res0); + errno = e; + return -1; + } + freeaddrinfo (res0); + break; + } + return s; +} +#endif /* HAVE_GETADDRINFO */ + +/* + * Open a TCP or UDP connection to HOST on port SERV. Uses getaddrinfo(3) + * if available, falling back to the traditional BSD mechanisms otherwise. + * Returns the connected socket or -1 on error. + */ +static int +_netopen(host, serv, typ) + char *host, *serv; + int typ; +{ +#ifdef HAVE_GETADDRINFO + return (_netopen6 (host, serv, typ)); +#else + return (_netopen4 (host, serv, typ)); +#endif +} /* * Open a TCP or UDP connection given a path like `/dev/tcp/host/port' to @@ -192,7 +284,7 @@ netopen (path) char *np, *s, *t; int fd; - np = xmalloc (strlen (path) + 1); + np = (char *)xmalloc (strlen (path) + 1); strcpy (np, path); s = np + 9; diff --git a/lib/sh/oslib.c b/lib/sh/oslib.c index 3d58711..69a3513 100644 --- a/lib/sh/oslib.c +++ b/lib/sh/oslib.c @@ -35,7 +35,7 @@ #include <stdio.h> #include <errno.h> -#include <ctype.h> +#include <chartypes.h> #include <shell.h> diff --git a/lib/sh/pathcanon.c b/lib/sh/pathcanon.c index 41fc727..dcde8b0 100644 --- a/lib/sh/pathcanon.c +++ b/lib/sh/pathcanon.c @@ -18,26 +18,25 @@ with Bash; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#include "config.h" +#include <config.h> -#include "bashtypes.h" +#include <bashtypes.h> #ifndef _MINIX # include <sys/param.h> #endif -#include "posixstat.h" +#include <posixstat.h> #if defined (HAVE_UNISTD_H) # include <unistd.h> #endif -#include "filecntl.h" -#include "bashansi.h" +#include <filecntl.h> +#include <bashansi.h> #include <stdio.h> +#include <chartypes.h> #include "shell.h" -#include "maxpath.h" - /* Return 1 if PATH corresponds to a directory. A function for debugging. */ static int _path_isdir (path) @@ -80,7 +79,7 @@ sh_canonpath (path, flags) { stub_char = DIRSEP; #if defined (__CYGWIN__) - base = (isalpha(result[0]) && result[1] == ':') ? result + 3 : result + 1; + base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 3 : result + 1; #else base = result + 1; #endif @@ -91,10 +90,11 @@ sh_canonpath (path, flags) { stub_char = '.'; #if defined (__CYGWIN__) - base = (isalpha(result[0]) && result[1] == ':') ? result + 2 : result; + base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 2 : result; #else base = result; #endif + double_slash_path = 0; } /* diff --git a/lib/sh/pathphys.c b/lib/sh/pathphys.c index eb58524..df69204 100644 --- a/lib/sh/pathphys.c +++ b/lib/sh/pathphys.c @@ -18,27 +18,26 @@ with Bash; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#include "config.h" +#include <config.h> -#include "bashtypes.h" +#include <bashtypes.h> #ifndef _MINIX # include <sys/param.h> #endif -#include "posixstat.h" +#include <posixstat.h> #if defined (HAVE_UNISTD_H) # include <unistd.h> #endif -#include "filecntl.h" -#include "bashansi.h" +#include <filecntl.h> +#include <bashansi.h> #include <stdio.h> +#include <chartypes.h> #include <errno.h> #include "shell.h" -#include "maxpath.h" - #if !defined (MAXSYMLINKS) # define MAXSYMLINKS 32 #endif @@ -82,9 +81,9 @@ sh_physpath (path, flags) int double_slash_path, linklen, nlink; nlink = 0; - q = result = xmalloc (PATH_MAX + 1); + q = result = (char *)xmalloc (PATH_MAX + 1); - workpath = xmalloc (PATH_MAX + 1); + workpath = (char *)xmalloc (PATH_MAX + 1); strcpy (workpath, path); /* This always gets an absolute pathname. */ @@ -92,7 +91,7 @@ sh_physpath (path, flags) /* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any leading `x:' (dos drive name). */ #if defined (__CYGWIN__) - qbase = (isalpha(workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; + qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; #else qbase = workpath + 1; #endif @@ -176,7 +175,7 @@ error: q = result; /* Duplicating some code here... */ #if defined (__CYGWIN__) - qbase = (isalpha(workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; + qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; #else qbase = workpath + 1; #endif diff --git a/lib/sh/setlinebuf.c b/lib/sh/setlinebuf.c index fb097de..3c5d056 100644 --- a/lib/sh/setlinebuf.c +++ b/lib/sh/setlinebuf.c @@ -22,7 +22,7 @@ #include <stdio.h> -extern char *xmalloc(); +#include <xmalloc.h> #if defined (USING_BASH_MALLOC) # define LBUF_BUFSIZE 1008 @@ -42,7 +42,7 @@ sh_setlinebuf (stream) #endif #if defined (USING_BASH_MALLOC) - local_linebuf = xmalloc (LBUF_BUFSIZE); + local_linebuf = (char *)xmalloc (LBUF_BUFSIZE); #else local_linebuf = (char *)NULL; #endif @@ -56,7 +56,7 @@ sh_setlinebuf (stream) # endif /* !SETVBUF_REVERSED */ # else /* !HAVE_SETVBUF */ - setlinebuf (stream)); + setlinebuf (stream); return (0); #endif /* !HAVE_SETVBUF */ diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c index 981e967..4160e70 100644 --- a/lib/sh/shquote.c +++ b/lib/sh/shquote.c @@ -28,8 +28,7 @@ #include <stdio.h> #include "syntax.h" - -extern char *xmalloc (); +#include <xmalloc.h> /* **************************************************************** */ /* */ @@ -46,7 +45,7 @@ sh_single_quote (string) register int c; char *result, *r, *s; - result = xmalloc (3 + (4 * strlen (string))); + result = (char *)xmalloc (3 + (4 * strlen (string))); r = result; *r++ = '\''; @@ -73,10 +72,10 @@ char * sh_double_quote (string) char *string; { - register int c; + register unsigned char c; char *result, *r, *s; - result = xmalloc (3 + (2 * strlen (string))); + result = (char *)xmalloc (3 + (2 * strlen (string))); r = result; *r++ = '"'; @@ -103,7 +102,7 @@ sh_un_double_quote (string) register int c, pass_next; char *result, *r, *s; - r = result = xmalloc (strlen (string) + 1); + r = result = (char *)xmalloc (strlen (string) + 1); for (pass_next = 0, s = string; s && (c = *s); s++) { @@ -113,7 +112,7 @@ sh_un_double_quote (string) pass_next = 0; continue; } - if (c == '\\' && (sh_syntaxtab[s[1]] & CBSDQUOTE)) + if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE)) { pass_next = 1; continue; @@ -134,7 +133,7 @@ sh_backslash_quote (string) int c; char *result, *r, *s; - result = xmalloc (2 * strlen (string) + 1); + result = (char *)xmalloc (2 * strlen (string) + 1); for (r = result, s = string; s && (c = *s); s++) { @@ -179,10 +178,10 @@ char * sh_backslash_quote_for_double_quotes (string) char *string; { - int c; + unsigned char c; char *result, *r, *s; - result = xmalloc (2 * strlen (string) + 1); + result = (char *)xmalloc (2 * strlen (string) + 1); for (r = result, s = string; s && (c = *s); s++) { @@ -219,6 +218,7 @@ sh_contains_shell_metas (string) case '~': /* tilde expansion */ if (s == string || s[-1] == '=' || s[-1] == ':') return (1); + break; case '#': if (s == string) /* comment char */ return (1); diff --git a/lib/sh/snprintf.c b/lib/sh/snprintf.c new file mode 100644 index 0000000..f84d60c --- /dev/null +++ b/lib/sh/snprintf.c @@ -0,0 +1,1665 @@ +/* + build a test version with + gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o +*/ + +/* + Unix snprintf implementation. + derived from inetutils/libinetutils/snprintf.c Version 1.1 + + Copyright (C) 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General License for more details. + + You should have received a copy of the GNU General License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Revision History: + + 1.1: + * added changes from Miles Bader + * corrected a bug with %f + * added support for %#g + * added more comments :-) + 1.0: + * supporting must ANSI syntaxic_sugars + 0.0: + * support %s %c %d + + THANKS(for the patches and ideas): + Miles Bader + Cyrille Rustom + Jacek Slabocewiz + Mike Parker(mouse) + +*/ + +/* + * Currently doesn't handle (and bash/readline doesn't use): + * *M$ width, precision specifications + * %N$ numbered argument conversions + * inf, nan floating values (could use isinf(), isnan()) + * `,', `'' flags + * `C', `S' conversions + * support for `F' is imperfect, since underlying printf may not handle it + */ + +#define FLOATING_POINT + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(DRIVER) && !defined(HAVE_CONFIG_H) +#define HAVE_LONG_LONG +#define HAVE_LONG_DOUBLE +#ifdef __linux__ +#define HAVE_PRINTF_A_FORMAT +#endif +#define PREFER_STDARG +#define HAVE_STRINGIZE +#define HAVE_LIMITS_H +#define HAVE_STDDEF_H +#define intmax_t long +#endif + +#if !defined (HAVE_SNPRINTF) || !defined (HAVE_ASPRINTF) + +#include <bashtypes.h> + +#if defined(PREFER_STDARG) +# include <stdarg.h> +#else +# include <varargs.h> +#endif + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif +#include <bashansi.h> +#ifdef HAVE_STDDEF_H +# include <stddef.h> +#endif +#include <chartypes.h> + +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#ifdef FLOATING_POINT +# include <stdio.h> /* for sprintf */ +#endif + +#include <typemax.h> + +#include "stdc.h" + +#ifndef DRIVER +# include "shell.h" +#else +# define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */ +# define FL_ADDBASE 0x02 /* add base# prefix to converted value */ +# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */ +# define FL_UNSIGNED 0x08 /* don't add any sign */ +extern char *fmtulong __P((unsigned long int, int, char *, size_t, int)); +extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int)); +#endif + +/* Bound on length of the string representing an integer value of type T. + Subtract one for the sign bit if T is signed; + 302 / 1000 is log10 (2) rounded up; + add one for integer division truncation; + add one more for a minus sign if t is signed. */ +#define INT_STRLEN_BOUND(t) \ + ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \ + + 1 + TYPE_SIGNED (t)) + +/* conversion flags */ +#define PF_ALTFORM 0x00001 /* # */ +#define PF_HEXPREFIX 0x00002 /* 0[Xx] */ +#define PF_LADJUST 0x00004 /* - */ +#define PF_ZEROPAD 0x00008 /* 0 */ +#define PF_PLUS 0x00010 /* + */ +#define PF_SPACE 0x00020 /* ' ' */ +#define PF_COMMA 0x00040 /* , */ + +#define PF_DOT 0x00080 /* `.precision' */ +#define PF_STAR_P 0x00100 /* `*' after precision */ +#define PF_STAR_W 0x00200 /* `*' before or without precision */ + +/* length modifiers */ +#define PF_SIGNEDCHAR 0x00400 /* hh */ +#define PF_SHORTINT 0x00800 /* h */ +#define PF_LONGINT 0x01000 /* l */ +#define PF_LONGLONG 0x02000 /* ll */ +#define PF_LONGDBL 0x04000 /* L */ +#define PF_INTMAX_T 0x08000 /* j */ +#define PF_SIZE_T 0x10000 /* z */ +#define PF_PTRDIFF_T 0x20000 /* t */ + +#define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */ + +#define PFM_SN 0x01 /* snprintf, vsnprintf */ +#define PFM_AS 0x02 /* asprintf, vasprintf */ + +#define ASBUFSIZE 128 + +#define x_digs "0123456789abcdef" +#define X_digs "0123456789ABCDEF" + +static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1]; + +/* + * For the FLOATING POINT FORMAT : + * the challenge was finding a way to + * manipulate the Real numbers without having + * to resort to mathematical function(it + * would require to link with -lm) and not + * going down to the bit pattern(not portable) + * + * so a number, a real is: + + real = integral + fraction + + integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0 + fraction = b(1)*10^-1 + b(2)*10^-2 + ... + + where: + 0 <= a(i) => 9 + 0 <= b(i) => 9 + + from then it was simple math + */ + +/* + * size of the buffer for the integral part + * and the fraction part + */ +#define MAX_INT 99 + 1 /* 1 for the null */ +#define MAX_FRACT 307 + 1 + +/* + * These functions use static buffers to store the results, + * and so are not reentrant + */ +#define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0); +#define dtoa(n, p, f) numtoa(n, 10, p, f) + +#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;} + +/* Macros that do proper sign extension and handle length modifiers. Used + for the integer conversion specifiers. */ +#define GETSIGNED(p) \ + (((p)->flags & PF_LONGINT) \ + ? va_arg(args, long) \ + : (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \ + : (long)va_arg(args, int))) + +#define GETUNSIGNED(p) \ + (((p)->flags & PF_LONGINT) \ + ? va_arg(args, unsigned long) \ + : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \ + : (unsigned long)va_arg(args, unsigned int))) + + +#ifdef HAVE_LONG_DOUBLE +#define GETLDOUBLE(p) va_arg(args, long double) +#endif +#define GETDOUBLE(p) va_arg(args, double) + +#define SET_SIZE_FLAGS(p, type) \ + if (sizeof (type) > sizeof (int)) \ + (p)->flags |= PF_LONGINT; \ + if (sizeof (type) > sizeof (long)) \ + (p)->flags |= PF_LONGLONG; + +/* this struct holds everything we need */ +struct DATA +{ + int length; + char *base; /* needed for [v]asprintf */ + char *holder; + int counter; + const char *pf; + +/* FLAGS */ + int flags; + int justify; + int width, precision; + char pad; +}; + +/* the floating point stuff */ +#ifdef FLOATING_POINT +static double pow_10 __P((int)); +static int log_10 __P((double)); +static double integral __P((double, double *)); +static char *numtoa __P((double, int, int, char **)); +#endif + +static void init_data __P((struct DATA *, char *, size_t, const char *, int)); +static void init_conv_flag __P((struct DATA *)); + +/* for the format */ +#ifdef FLOATING_POINT +static void floating __P((struct DATA *, double)); +static void exponent __P((struct DATA *, double)); +#endif +static void number __P((struct DATA *, unsigned long, int)); +#ifdef HAVE_LONG_LONG +static void lnumber __P((struct DATA *, unsigned long long, int)); +#endif +static void pointer __P((struct DATA *, unsigned long)); +static void strings __P((struct DATA *, char *)); + +#ifdef FLOATING_POINT +# define FALLBACK_FMTSIZE 32 +# define FALLBACK_BASE 4096 +# define LFALLBACK_BASE 5120 +# ifdef HAVE_LONG_DOUBLE +static void ldfallback __P((struct DATA *, const char *, const char *, long double)); +# endif +static void dfallback __P((struct DATA *, const char *, const char *, double)); +#endif + +#ifdef DRIVER +static void memory_error_and_abort (); +static void *xmalloc __P((size_t)); +static void *xrealloc __P((void *, size_t)); +static void xfree __P((void *)); +#else +# include <xmalloc.h> +#endif + +/* those are defines specific to snprintf to hopefully + * make the code clearer :-) + */ +#define RIGHT 1 +#define LEFT 0 +#define NOT_FOUND -1 +#define FOUND 1 +#define MAX_FIELD 15 + +/* round off to the precision */ +#define ROUND(d, p) \ + (d < 0.) ? \ + d - pow_10(-(p)->precision) * 0.5 : \ + d + pow_10(-(p)->precision) * 0.5 + +/* set default precision */ +#define DEF_PREC(p) \ + if ((p)->precision == NOT_FOUND) \ + (p)->precision = 6 + +/* put a char. increment the number of chars written even if we've exceeded + the vsnprintf/snprintf buffer size (for the return value) */ +#define PUT_CHAR(c, p) \ + do \ + { \ + if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \ + { \ + (p)->length += ASBUFSIZE; \ + (p)->base = (char *)xrealloc((p)->base, (p)->length); \ + (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \ + } \ + if ((p)->counter < (p)->length) \ + *(p)->holder++ = (c); \ + (p)->counter++; \ + } \ + while (0) + +#define PUT_PLUS(d, p, zero) \ + if ((d) > zero && (p)->justify == RIGHT) \ + PUT_CHAR('+', p) + +#define PUT_SPACE(d, p, zero) \ + if (((p)->flags & PF_SPACE) && (d) > zero) \ + PUT_CHAR(' ', p) + +/* pad right */ +#define PAD_RIGHT(p) \ + if ((p)->width > 0 && (p)->justify != LEFT) \ + for (; (p)->width > 0; (p)->width--) \ + PUT_CHAR((p)->pad, p) + +/* pad left */ +#define PAD_LEFT(p) \ + if ((p)->width > 0 && (p)->justify == LEFT) \ + for (; (p)->width > 0; (p)->width--) \ + PUT_CHAR((p)->pad, p) + +/* if width and prec. in the args */ +#define STAR_ARGS(p) \ + if ((p)->flags & PF_STAR_W) \ + (p)->width = va_arg(args, int); \ + if ((p)->flags & PF_STAR_P) \ + (p)->precision = va_arg(args, int) + +#ifdef FLOATING_POINT +/* + * Find the nth power of 10 + */ +static double +pow_10(n) + int n; +{ + double P; + + /* handle common cases with fast switch statement. */ + switch (n) + { + case -3: return .001; + case -2: return .01; + case -1: return .1; + case 0: return 1.; + case 1: return 10.; + case 2: return 100.; + case 3: return 1000.; + } + + if (n < 0) + { + P = .0001; + for (n += 4; n < 0; n++) + P /= 10.; + } + else + { + P = 10000.; + for (n -= 4; n > 0; n--) + P *= 10.; + } + + return P; +} + +/* + * Find the integral part of the log in base 10 + * Note: this not a real log10() + I just need and approximation(integerpart) of x in: + 10^x ~= r + * log_10(200) = 2; + * log_10(250) = 2; + */ +static int +log_10(r) + double r; +{ + int i = 0; + double result = 1.; + + if (r < 0.) + r = -r; + + if (r < 1.) + { + while (result >= r) + { + result /= 10.; + i++; + } + return (-i); + } + else + { + while (result <= r) + { + result *= 10.; + i++; + } + return (i - 1); + } +} + +/* + * This function return the fraction part of a double + * and set in ip the integral part. + * In many ways it resemble the modf() found on most Un*x + */ +static double +integral(real, ip) + double real; + double *ip; +{ + int j; + double i, s, p; + double real_integral = 0.; + + /* take care of the obvious */ + /* equal to zero ? */ + if (real == 0.) + { + *ip = 0.; + return (0.); + } + + /* negative number ? */ + if (real < 0.) + real = -real; + + /* a fraction ? */ + if ( real < 1.) + { + *ip = 0.; + return real; + } + + /* the real work :-) */ + for (j = log_10(real); j >= 0; j--) + { + p = pow_10(j); + s = (real - real_integral)/p; + i = 0.; + while (i + 1. <= s) + i++; + real_integral += i*p; + } + *ip = real_integral; + return (real - real_integral); +} + +#define PRECISION 1.e-6 +/* + * return an ascii representation of the integral part of the number + * and set fract to be an ascii representation of the fraction part + * the container for the fraction and the integral part or staticly + * declare with fix size + */ +static char * +numtoa(number, base, precision, fract) + double number; + int base, precision; + char **fract; +{ + register int i, j; + double ip, fp; /* integer and fraction part */ + double fraction; + int digits = MAX_INT - 1; + static char integral_part[MAX_INT]; + static char fraction_part[MAX_FRACT]; + double sign; + int ch; + + /* taking care of the obvious case: 0.0 */ + if (number == 0.) + { + integral_part[0] = '0'; + integral_part[1] = '\0'; + fraction_part[0] = '0'; + fraction_part[1] = '\0'; + return integral_part; + } + + /* for negative numbers */ + if ((sign = number) < 0.) + { + number = -number; + digits--; /* sign consume one digit */ + } + + fraction = integral(number, &ip); + number = ip; + + /* do the integral part */ + if (ip == 0.) + { + integral_part[0] = '0'; + i = 1; + } + else + { + for ( i = 0; i < digits && number != 0.; ++i) + { + number /= base; + fp = integral(number, &ip); + ch = (int)((fp + PRECISION)*base); /* force to round */ + integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10; + if (! ISXDIGIT((unsigned char)integral_part[i])) + break; /* bail out overflow !! */ + number = ip; + } + } + + /* Oh No !! out of bound, ho well fill it up ! */ + if (number != 0.) + for (i = 0; i < digits; ++i) + integral_part[i] = '9'; + + /* put the sign ? */ + if (sign < 0.) + integral_part[i++] = '-'; + + integral_part[i] = '\0'; + + /* reverse every thing */ + for ( i--, j = 0; j < i; j++, i--) + SWAP_INT(integral_part[i], integral_part[j]); + + /* the fractional part */ + for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--) + { + fraction_part[i] = (int)((fp + PRECISION)*10. + '0'); + if (! DIGIT(fraction_part[i])) /* underflow ? */ + break; + fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.); + } + fraction_part[i] = '\0'; + + if (fract != (char **)0) + *fract = fraction_part; + + return integral_part; +} +#endif + +/* for %d and friends, it puts in holder + * the representation with the right padding + */ +static void +number(p, d, base) + struct DATA *p; + unsigned long d; + int base; +{ + char *tmp; + long sd; + int flags; + + sd = d; /* signed for ' ' padding in base 10 */ + flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; + if (*p->pf == 'X') + flags |= FL_HEXUPPER; + + tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags); + p->width -= strlen(tmp); + PAD_RIGHT(p); + + switch (base) + { + case 10: + PUT_PLUS(sd, p, 0); + PUT_SPACE(sd, p, 0); + break; + case 8: + if (p->flags & PF_ALTFORM) + PUT_CHAR('0', p); + break; + case 16: + if (p->flags & PF_ALTFORM) + { + PUT_CHAR('0', p); + PUT_CHAR(*p->pf, p); + } + break; + } + + while (*tmp) + { + PUT_CHAR(*tmp, p); + tmp++; + } + + PAD_LEFT(p); +} + +#ifdef HAVE_LONG_LONG +/* + * identical to number() but works for `long long' + */ +static void +lnumber(p, d, base) + struct DATA *p; + unsigned long long d; + int base; +{ + char *tmp; + long long sd; + int flags; + + sd = d; /* signed for ' ' padding in base 10 */ + flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; + if (*p->pf == 'X') + flags |= FL_HEXUPPER; + + tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags); + p->width -= strlen(tmp); + PAD_RIGHT(p); + + switch (base) + { + case 10: + PUT_PLUS(sd, p, 0); + PUT_SPACE(sd, p, 0); + break; + case 8: + if (p->flags & PF_ALTFORM) + PUT_CHAR('0', p); + break; + case 16: + if (p->flags & PF_ALTFORM) + { + PUT_CHAR('0', p); + PUT_CHAR(*p->pf, p); + } + break; + } + + while (*tmp) + { + PUT_CHAR(*tmp, p); + tmp++; + } + + PAD_LEFT(p); +} +#endif + +static void +pointer(p, d) + struct DATA *p; + unsigned long d; +{ + char *tmp; + + tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0); + p->width -= strlen(tmp); + PAD_RIGHT(p); + + /* prefix '0x' for pointers */ + PUT_CHAR('0', p); + PUT_CHAR('x', p); + + while (*tmp) + { + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* %s strings */ +static void +strings(p, tmp) + struct DATA *p; + char *tmp; +{ + int i; + + i = strlen(tmp); + if (p->precision != NOT_FOUND) /* the smallest number */ + i = (i < p->precision ? i : p->precision); + p->width -= i; + PAD_RIGHT(p); + while (i-- > 0) + { /* put the sting */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +#ifdef FLOATING_POINT +/* %f %F %g %G floating point representation */ +static void +floating(p, d) + struct DATA *p; + double d; +{ + char *tmp, *tmp2; + int i; + + DEF_PREC(p); + d = ROUND(d, p); + tmp = dtoa(d, p->precision, &tmp2); + /* calculate the padding. 1 for the dot */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->flags & PF_SPACE) ? 1:0) - + strlen(tmp) - p->precision - 1; + PAD_RIGHT(p); + PUT_PLUS(d, p, 0.); + PUT_SPACE(d, p, 0.); + while (*tmp) + { /* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + if (p->precision != 0 || (p->flags & PF_ALTFORM)) + PUT_CHAR('.', p); /* put the '.' */ + if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0) + /* smash the trailing zeros unless altform */ + for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) + tmp2[i] = '\0'; + for (; *tmp2; tmp2++) + PUT_CHAR(*tmp2, p); /* the fraction */ + + PAD_LEFT(p); +} + +/* %e %E %g %G exponent representation */ +static void +exponent(p, d) + struct DATA *p; + double d; +{ + char *tmp, *tmp2; + int j, i, nsig, ndig; + + DEF_PREC(p); + j = log_10(d); + d = d / pow_10(j); /* get the Mantissa */ + d = ROUND(d, p); + tmp = dtoa(d, p->precision, &tmp2); + /* 1 for unit, 1 for the '.', 1 for 'e|E', + * 1 for '+|-', 2 for 'exp' */ + /* calculate how much padding need */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6; + PAD_RIGHT(p); + PUT_PLUS(d, p, 0.); + PUT_SPACE(d, p, 0.); + /* + * When supplied %g or %G, an optional precision is the number of + * significant digits to print. + * + * nsig = number of significant digits we've printed (leading zeros are + * never significant) + * ndig = if non-zero, max number of significant digits to print (only + * applicable to %g/%G) + */ + nsig = ndig = 0; + if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT)) + ndig = (p->precision == 0) ? 1 : p->precision; + + while (*tmp) + { + PUT_CHAR(*tmp, p); + tmp++; + if (ndig && (++nsig >= ndig)) + break; + } + + if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig)) + PUT_CHAR('.', p); /* the '.' */ + if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0) + /* smash the trailing zeros unless altform */ + for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) + tmp2[i] = '\0'; + for (; *tmp2; tmp2++) + { + if (ndig && (nsig++ >= ndig)) + break; + PUT_CHAR(*tmp2, p); /* the fraction */ + } + + /* the exponent put the 'e|E' */ + if (*p->pf == 'g' || *p->pf == 'e') + { + PUT_CHAR('e', p); + } + else + PUT_CHAR('E', p); + + /* the sign of the exp */ + if (j > 0) + { + PUT_CHAR('+', p); + } + else + { + PUT_CHAR('-', p); + j = -j; + } + + tmp = itoa(j); + /* pad out to at least two spaces. pad with `0' if the exponent is a + single digit. */ + if (j <= 9) + { + PUT_CHAR('0', p); + } + + /* the exponent */ + while (*tmp) + { + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} +#endif + +/* initialize the conversion specifiers */ +static void +init_conv_flag (p) + struct DATA *p; +{ + p->flags &= PF_ALLOCBUF; /* preserve PF_ALLOCBUF flag */ + p->precision = p->width = NOT_FOUND; + p->justify = NOT_FOUND; + p->pad = ' '; +} + +static void +init_data (p, string, length, format, mode) + struct DATA *p; + char *string; + size_t length; + const char *format; + int mode; +{ + p->length = length - 1; /* leave room for '\0' */ + p->holder = p->base = string; + p->pf = format; + p->counter = 0; + p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0; +} + +static int +#if defined (__STDC__) +vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args) +#else +vsnprintf_internal(data, string, length, format, args) + struct DATA *data; + char *string; + size_t length; + const char *format; + va_list args; +#endif +{ + double d; /* temporary holder */ +#ifdef HAVE_LONG_DOUBLE + long double ld; /* for later */ +#endif + unsigned long ul; +#ifdef HAVE_LONG_LONG + unsigned long long ull; +#endif + int state, i, c, n; + char *s; + const char *convstart; + + /* Sanity check, the string must be > 1. C99 actually says that LENGTH + can be zero here, in the case of snprintf/vsnprintf (it's never 0 in + the case of asprintf/vasprintf), and the return value is the number + of characters that would have been written. */ + if (length < 1) + return -1; + + if (format == 0) + return 0; + + for (; c = *(data->pf); data->pf++) + { + if (c != '%') + { + PUT_CHAR (c, data); + continue; + } + + convstart = data->pf; + init_conv_flag (data); /* initialise format flags */ + + state = 1; + for (state = 1; state && *data->pf; ) + { + c = *(++data->pf); + /* fmtend = data->pf */ +#if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE) + if (data->flags & PF_LONGDBL) + { + switch (c) + { + case 'f': case 'F': + case 'e': case 'E': + case 'g': case 'G': +# ifdef HAVE_PRINTF_A_FORMAT + case 'a': case 'A': +# endif + STAR_ARGS (data); + ld = GETLDOUBLE (data); + ldfallback (data, convstart, data->pf, ld); + goto conv_break; + } + } +#endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */ + + switch (c) + { + /* Parse format flags */ + case '\0': /* a NULL here ? ? bail out */ + *data->holder = '\0'; + return data->counter; + break; + case '#': + data->flags |= PF_ALTFORM; + continue; + case '0': + data->flags |= PF_ZEROPAD; + data->pad = '0'; + continue; + case '*': + if (data->flags & PF_DOT) + data->flags |= PF_STAR_P; + else + data->flags |= PF_STAR_W; + continue; + case '-': + data->flags |= PF_LADJUST; + data->justify = LEFT; + continue; + case ' ': + if ((data->flags & PF_PLUS) == 0) + data->flags |= PF_SPACE; + continue; + case '+': + data->flags |= PF_PLUS; + data->justify = RIGHT; + continue; + case ',': + data->flags |= PF_COMMA; /* not implemented yet */ + continue; + + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + n = 0; + do + { + n = n * 10 + TODIGIT(c); + c = *(++data->pf); + } + while (DIGIT(c)); + data->pf--; /* went too far */ + if (n < 0) + n = 0; + if (data->flags & PF_DOT) + data->precision = n; + else + data->width = n; + continue; + + /* optional precision */ + case '.': + data->flags |= PF_DOT; + data->precision = 0; + continue; + + /* length modifiers */ + case 'h': + data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT; + continue; + case 'l': + data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT; + continue; + case 'L': + data->flags |= PF_LONGDBL; + continue; + case 'q': + data->flags |= PF_LONGLONG; + continue; + case 'j': + data->flags |= PF_INTMAX_T; + SET_SIZE_FLAGS(data, intmax_t); + continue; + case 'z': + data->flags |= PF_SIZE_T; + SET_SIZE_FLAGS(data, size_t); + continue; + case 't': + data->flags |= PF_PTRDIFF_T; + SET_SIZE_FLAGS(data, ptrdiff_t); + continue; + + /* Conversion specifiers */ +#ifdef FLOATING_POINT + case 'f': /* float, double */ + case 'F': + STAR_ARGS(data); + d = GETDOUBLE(data); + floating(data, d); +conv_break: + state = 0; + break; + case 'g': + case 'G': + STAR_ARGS(data); + DEF_PREC(data); + d = GETDOUBLE(data); + i = log_10(d); + /* + * for '%g|%G' ANSI: use f if exponent + * is in the range or [-4,p] exclusively + * else use %e|%E + */ + if (-4 < i && i < data->precision) + floating(data, d); + else + exponent(data, d); + state = 0; + break; + case 'e': + case 'E': /* Exponent double */ + STAR_ARGS(data); + d = GETDOUBLE(data); + exponent(data, d); + state = 0; + break; +# ifdef HAVE_PRINTF_A_FORMAT + case 'a': + case 'A': + STAR_ARGS(data); + d = GETDOUBLE(data); + dfallback(data, convstart, data->pf, d); + state = 0; + break; +# endif /* HAVE_PRINTF_A_FORMAT */ +#endif /* FLOATING_POINT */ + case 'U': + data->flags |= PF_LONGINT; + /* FALLTHROUGH */ + case 'u': + STAR_ARGS(data); +#ifdef HAVE_LONG_LONG + if (data->flags & PF_LONGLONG) + { + ull = va_arg(args, unsigned long long); + lnumber(data, ull, 10); + } + else +#endif + { + ul = GETUNSIGNED(data); + number(data, ul, 10); + } + state = 0; + break; + case 'D': + data->flags |= PF_LONGINT; + /* FALLTHROUGH */ + case 'd': /* decimal */ + case 'i': + STAR_ARGS(data); +#ifdef HAVE_LONG_LONG + if (data->flags & PF_LONGLONG) + { + ull = va_arg(args, long long); + lnumber(data, ull, 10); + } + else +#endif + { + ul = GETSIGNED(data); + number(data, ul, 10); + } + state = 0; + break; + case 'o': /* octal */ + STAR_ARGS(data); +#ifdef HAVE_LONG_LONG + if (data->flags & PF_LONGLONG) + { + ull = va_arg(args, unsigned long long); + lnumber(data, ull, 8); + } + else +#endif + { + ul = GETUNSIGNED(data); + number(data, ul, 8); + } + state = 0; + break; + case 'x': + case 'X': /* hexadecimal */ + STAR_ARGS(data); +#ifdef HAVE_LONG_LONG + if (data->flags & PF_LONGLONG) + { + ull = va_arg(args, unsigned long long); + lnumber(data, ull, 16); + } + else +#endif + { + ul = GETUNSIGNED(data); + number(data, ul, 16); + } + state = 0; + break; + case 'p': + STAR_ARGS(data); + ul = (unsigned long)va_arg(args, void *); + pointer(data, ul); + state = 0; + break; + case 'c': /* character */ + ul = va_arg(args, int); + PUT_CHAR(ul, data); + state = 0; + break; + case 's': /* string */ + STAR_ARGS(data); + s = va_arg(args, char *); + strings(data, s); + state = 0; + break; + case 'n': +#ifdef HAVE_LONG_LONG + if (data->flags & PF_LONGLONG) + *(va_arg(args, long long *)) = data->counter; + else +#endif + if (data->flags & PF_LONGINT) + *(va_arg(args, long *)) = data->counter; + else if (data->flags & PF_SHORTINT) + *(va_arg(args, short *)) = data->counter; + else + *(va_arg(args, int *)) = data->counter; + state = 0; + break; + case '%': /* nothing just % */ + PUT_CHAR('%', data); + state = 0; + break; + default: + /* is this an error ? maybe bail out */ + state = 0; + break; + } /* end switch */ + } /* end of `%' for loop */ + } /* end of format string for loop */ + + if (data->length >= 0) + *data->holder = '\0'; /* the end ye ! */ + + return data->counter; +} + +#if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE) +/* + * Printing floating point numbers accurately is an art. I'm not good + * at it. Fall back to sprintf for long double formats. + */ +static void +ldfallback (data, fs, fe, ld) + struct DATA *data; + const char *fs, *fe; + long double ld; +{ + register char *x; + char fmtbuf[FALLBACK_FMTSIZE], *obuf; + int fl; + + obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2); + fl = fe - fs + 1; + strncpy (fmtbuf, fs, fl); + fmtbuf[fl] = '\0'; + sprintf (obuf, fmtbuf, ld); + for (x = obuf; *x; x++) + PUT_CHAR (*x, data); + xfree (obuf); +} +#endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */ + +#ifdef FLOATING_POINT +/* Used for %a, %A if the libc printf supports them. */ +static void +dfallback (data, fs, fe, d) + struct DATA *data; + const char *fs, *fe; + double d; +{ + register char *x; + char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE]; + int fl; + + fl = fe - fs + 1; + strncpy (fmtbuf, fs, fl); + fmtbuf[fl] = '\0'; + sprintf (obuf, fmtbuf, d); + for (x = obuf; *x; x++) + PUT_CHAR (*x, data); +} +#endif /* FLOATING_POINT */ + +#ifndef HAVE_SNPRINTF + +int +#if defined (__STDC__) +vsnprintf(char *string, size_t length, const char *format, va_list args) +#else +vsnprintf(string, length, format, args) + char *string; + size_t length; + const char *format; + va_list args; +#endif +{ + struct DATA data; + + init_data (&data, string, length, format, PFM_SN); + return (vsnprintf_internal(&data, string, length, format, args)); +} + +int +#if defined(PREFER_STDARG) +snprintf(char *string, size_t length, const char * format, ...) +#else +snprintf(string, length, format, va_alist) + char *string; + size_t length; + const char *format; + va_dcl +#endif +{ + struct DATA data; + int rval; + va_list args; + +#if defined(PREFER_STDARG) + va_start(args, format); +#else + va_start(args); +#endif + + init_data (&data, string, length, format, PFM_SN); + rval = vsnprintf_internal (&data, string, length, format, args); + + va_end(args); + + return rval; +} + +#endif /* HAVE_SNPRINTF */ + +#ifndef HAVE_ASPRINTF + +int +#if defined (__STDC__) +vasprintf(char **stringp, const char *format, va_list args) +#else +vasprintf(stringp, format, args) + char **stringp; + const char *format; + va_list args; +#endif +{ + struct DATA data; + char *string; + int r; + + string = (char *)xmalloc(ASBUFSIZE); + init_data (&data, string, ASBUFSIZE, format, PFM_AS); + r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args); + *stringp = data.base; /* not string in case reallocated */ + return r; +} + +int +#if defined(PREFER_STDARG) +asprintf(char **stringp, const char * format, ...) +#else +asprintf(stringp, format, va_alist) + char **stringp; + const char *format; + va_dcl +#endif +{ + int rval; + va_list args; + +#if defined(PREFER_STDARG) + va_start(args, format); +#else + va_start(args); +#endif + + rval = vasprintf (stringp, format, args); + + va_end(args); + + return rval; +} + +#endif + +#endif + +#ifdef DRIVER + +static void +memory_error_and_abort () +{ + write (2, "out of virtual memory\n", 22); + abort (); +} + +static void * +xmalloc(bytes) + size_t bytes; +{ + void *ret; + + ret = malloc(bytes); + if (ret == 0) + memory_error_and_abort (); + return ret; +} + +static void * +xrealloc (pointer, bytes) + void *pointer; + size_t bytes; +{ + void *ret; + + ret = pointer ? realloc(pointer, bytes) : malloc(bytes); + if (ret == 0) + memory_error_and_abort (); + return ret; +} + +static void +xfree(x) + void *x; +{ + if (x) + free (x); +} + +#ifdef FLOATING_POINT +# include <float.h> +#endif + +/* set of small tests for snprintf() */ +main() +{ + char holder[100]; + char *h; + int i, si, ai; + +/* + printf("Suite of test for snprintf:\n"); + printf("a_format\n"); + printf("printf() format\n"); + printf("snprintf() format\n\n"); +*/ +/* Checking the field widths */ + + printf("/%%ld %%ld/, 336, 336\n"); + snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336); + asprintf(&h, "/%ld %ld/\n", 336, 336); + printf("/%ld %ld/\n", 336, 336); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%d/, 336\n"); + snprintf(holder, sizeof holder, "/%d/\n", 336); + asprintf(&h, "/%d/\n", 336); + printf("/%d/\n", 336); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%2d/, 336\n"); + snprintf(holder, sizeof holder, "/%2d/\n", 336); + asprintf(&h, "/%2d/\n", 336); + printf("/%2d/\n", 336); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%10d/, 336\n"); + snprintf(holder, sizeof holder, "/%10d/\n", 336); + asprintf(&h, "/%10d/\n", 336); + printf("/%10d/\n", 336); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%-10d/, 336\n"); + snprintf(holder, sizeof holder, "/%-10d/\n", 336); + asprintf(&h, "/%-10d/\n", 336); + printf("/%-10d/\n", 336); + printf("%s", holder); + printf("%s\n", h); + + +/* floating points */ + + printf("/%%f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%f/\n", 1234.56); + asprintf(&h, "/%f/\n", 1234.56); + printf("/%f/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%e/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%e/\n", 1234.56); + asprintf(&h, "/%e/\n", 1234.56); + printf("/%e/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%4.2f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56); + asprintf(&h, "/%4.2f/\n", 1234.56); + printf("/%4.2f/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%3.1f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56); + asprintf(&h, "/%3.1f/\n", 1234.56); + printf("/%3.1f/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%10.3f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56); + asprintf(&h, "/%10.3f/\n", 1234.56); + printf("/%10.3f/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%10.3e/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56); + asprintf(&h, "/%10.3e/\n", 1234.56); + printf("/%10.3e/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%+4.2f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56); + asprintf(&h, "/%+4.2f/\n", 1234.56); + printf("/%+4.2f/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%010.2f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56); + asprintf(&h, "/%010.2f/\n", 1234.56); + printf("/%010.2f/\n", 1234.56); + printf("%s", holder); + printf("%s\n", h); + +#define BLURB "Outstanding acting !" +/* strings precisions */ + + printf("/%%2s/, \"%s\"\n", BLURB); + snprintf(holder, sizeof holder, "/%2s/\n", BLURB); + asprintf(&h, "/%2s/\n", BLURB); + printf("/%2s/\n", BLURB); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%22s/ %s\n", BLURB); + snprintf(holder, sizeof holder, "/%22s/\n", BLURB); + asprintf(&h, "/%22s/\n", BLURB); + printf("/%22s/\n", BLURB); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%22.5s/ %s\n", BLURB); + snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB); + asprintf(&h, "/%22.5s/\n", BLURB); + printf("/%22.5s/\n", BLURB); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%-22.5s/ %s\n", BLURB); + snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB); + asprintf(&h, "/%-22.5s/\n", BLURB); + printf("/%-22.5s/\n", BLURB); + printf("%s", holder); + printf("%s\n", h); + +/* see some flags */ + + printf("%%x %%X %%#x, 31, 31, 31\n"); + snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31); + asprintf(&h, "%x %X %#x\n", 31, 31, 31); + printf("%x %X %#x\n", 31, 31, 31); + printf("%s", holder); + printf("%s\n", h); + + printf("**%%d**%% d**%% d**, 42, 42, -42\n"); + snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42); + asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42); + printf("**%d**% d**% d**\n", 42, 42, -42); + printf("%s", holder); + printf("%s\n", h); + +/* other flags */ + + printf("/%%g/, 31.4\n"); + snprintf(holder, sizeof holder, "/%g/\n", 31.4); + asprintf(&h, "/%g/\n", 31.4); + printf("/%g/\n", 31.4); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%.6g/, 31.4\n"); + snprintf(holder, sizeof holder, "/%.6g/\n", 31.4); + asprintf(&h, "/%.6g/\n", 31.4); + printf("/%.6g/\n", 31.4); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%.1G/, 31.4\n"); + snprintf(holder, sizeof holder, "/%.1G/\n", 31.4); + asprintf(&h, "/%.1G/\n", 31.4); + printf("/%.1G/\n", 31.4); + printf("%s", holder); + printf("%s\n", h); + + printf("/%%.1G/, 3100000000.4\n"); + snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4); + asprintf(&h, "/%.1G/\n", 3100000000.4); + printf("/%.1G/\n", 3100000000.4); + printf("%s", holder); + printf("%s\n", h); + + printf("abc%%n\n"); + printf("abc%n", &i); printf("%d\n", i); + snprintf(holder, sizeof holder, "abc%n", &i); + printf("%s", holder); printf("%d\n\n", i); + asprintf(&h, "abc%n", &i); + printf("%s", h); printf("%d\n\n", i); + + printf("%%*.*s --> 10.10\n"); + snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB); + asprintf(&h, "%*.*s\n", 10, 10, BLURB); + printf("%*.*s\n", 10, 10, BLURB); + printf("%s", holder); + printf("%s\n", h); + + printf("%%%%%%%%\n"); + snprintf(holder, sizeof holder, "%%%%\n"); + asprintf(&h, "%%%%\n"); + printf("%%%%\n"); + printf("%s", holder); + printf("%s\n", h); + +#define BIG "Hello this is a too big string for the buffer" +/* printf("A buffer to small of 10, trying to put this:\n");*/ + printf("<%%>, %s\n", BIG); + i = snprintf(holder, 10, "%s\n", BIG); + i = asprintf(&h, "%s", BIG); + printf("<%s>\n", BIG); + printf("<%s>\n", holder); + printf("<%s>\n\n", h); + + printf ("<%%p> vsnprintf\n"); + i = snprintf(holder, 100, "%p", vsnprintf); + i = asprintf(&h, "%p", vsnprintf); + printf("<%p>\n", vsnprintf); + printf("<%s>\n", holder); + printf("<%s>\n\n", h); + + printf ("<%%lu> LONG_MAX+1\n"); + i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1); + i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1); + printf("<%lu>\n", (unsigned long)(LONG_MAX)+1); + printf("<%s>\n", holder); + printf("<%s>\n\n", h); + +#ifdef HAVE_LONG_LONG + printf ("<%%llu> LLONG_MAX+1\n"); + i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1); + i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1); + printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1); + printf("<%s>\n", holder); + printf("<%s>\n\n", h); +#endif + +#ifdef HAVE_LONG_DOUBLE + printf ("<%%6.2LE> 42.42\n"); + i = snprintf(holder, 100, "%6.2LE", (long double)42.42); + i = asprintf(&h, "%6.2LE", (long double)42.42); + printf ("<%6.2LE>\n", (long double)42.42); + printf ("<%s>\n", holder); + printf ("<%s>\n\n", h); +#endif + +#ifdef HAVE_PRINTF_A_FORMAT + printf ("<%%6.2A> 42.42\n"); + i = snprintf(holder, 100, "%6.2A", 42.42); + i = asprintf(&h, "%6.2A", 42.42); + printf ("<%6.2A>\n", 42.42); + printf ("<%s>\n", holder); + printf ("<%s>\n\n", h); + + printf ("<%%6.2LA> 42.42\n"); + i = snprintf(holder, 100, "%6.2LA", (long double)42.42); + i = asprintf(&h, "%6.2LA", (long double)42.42); + printf ("<%6.2LA>\n", (long double)42.42); + printf ("<%s>\n", holder); + printf ("<%s>\n\n", h); +#endif + + printf ("<%%.10240f> DBL_MAX\n"); + si = snprintf(holder, 100, "%.10240f", DBL_MAX); + ai = asprintf(&h, "%.10240f", DBL_MAX); + printf ("<%.10240f>\n", DBL_MAX); + printf ("<%d> <%s>\n", si, holder); + printf ("<%d> <%s>\n\n", ai, h); + + printf ("<%%.10240Lf> LDBL_MAX\n"); + si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX); + ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX); + printf ("<%.10240Lf>\n", (long double)LDBL_MAX); + printf ("<%d> <%s>\n", si, holder); + printf ("<%d> <%s>\n\n", ai, h); + + exit (0); +} +#endif diff --git a/lib/sh/strcasecmp.c b/lib/sh/strcasecmp.c index 1e15c02..33d925b 100644 --- a/lib/sh/strcasecmp.c +++ b/lib/sh/strcasecmp.c @@ -24,11 +24,7 @@ #include <stdc.h> #include <bashansi.h> -#include <ctype.h> - -#if !defined (to_lower) -# define to_lower(c) (islower(c) ? (c) : tolower(c)) -#endif /* to_lower */ +#include <chartypes.h> /* Compare at most COUNT characters from string1 to string2. Case doesn't matter. */ @@ -49,7 +45,7 @@ strncasecmp (string1, string2, count) s2 = string2; do { - if ((r = to_lower (*s1) - to_lower (*s2)) != 0) + if ((r = TOLOWER ((unsigned char) *s1) - TOLOWER ((unsigned char) *s2)) != 0) return r; if (*s1++ == '\0') break; @@ -76,7 +72,7 @@ strcasecmp (string1, string2) if (s1 == s2) return (0); - while ((r = to_lower (*s1) - to_lower (*s2)) == 0) + while ((r = TOLOWER ((unsigned char)*s1) - TOLOWER ((unsigned char)*s2)) == 0) { if (*s1++ == '\0') return 0; diff --git a/lib/sh/strindex.c b/lib/sh/strindex.c index 9d3f302..9172862 100644 --- a/lib/sh/strindex.c +++ b/lib/sh/strindex.c @@ -22,16 +22,11 @@ #include <config.h> -#include "bashansi.h" -#include <ctype.h> +#include <bashansi.h> +#include <chartypes.h> #include <stdc.h> -#ifndef to_upper -# define to_upper(c) (islower(c) ? toupper(c) : (c)) -# define to_lower(c) (isupper(c) ? tolower(c) : (c)) -#endif - /* Determine if s2 occurs in s1. If so, return a pointer to the match in s1. The compare is case insensitive. This is a case-insensitive strstr(3). */ @@ -42,11 +37,11 @@ strindex (s1, s2) { register int i, l, len, c; - c = to_upper (s2[0]); + c = TOLOWER ((unsigned char)s2[0]); len = strlen (s1); l = strlen (s2); for (i = 0; (len - i) >= l; i++) - if ((to_upper (s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0)) + if ((TOLOWER ((unsigned char)s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0)) return ((char *)s1 + i); return ((char *)0); } diff --git a/lib/sh/stringlist.c b/lib/sh/stringlist.c index 8fc57cb..29937d3 100644 --- a/lib/sh/stringlist.c +++ b/lib/sh/stringlist.c @@ -25,7 +25,7 @@ #endif #include <stdio.h> -#include "bashansi.h" +#include <bashansi.h> #include "shell.h" @@ -67,6 +67,9 @@ realloc_stringlist (sl, n) { register int i; + if (sl == 0) + return (sl = alloc_stringlist(n)); + if (n > sl->list_size) { sl->list = (char **)xrealloc (sl->list, (n+1) * sizeof (char *)); @@ -95,6 +98,8 @@ copy_stringlist (sl) STRINGLIST *new; register int i; + if (sl == 0) + return ((STRINGLIST *)0); new = alloc_stringlist (sl->list_size); /* I'd like to use copy_array, but that doesn't copy everything. */ if (sl->list) @@ -129,6 +134,7 @@ merge_stringlists (m1, m2) sl->list[n] = STRDUP (m2->list[i]); sl->list_len = n; sl->list[n] = (char *)NULL; + return (sl); } /* Make STRINGLIST M1 contain everything in M1 and M2. */ @@ -139,10 +145,7 @@ append_stringlist (m1, m2) register int i, n, len1, len2; if (m1 == 0) - { - m1 = copy_stringlist (m2); - return m1; - } + return (m2 ? copy_stringlist (m2) : (STRINGLIST *)0); len1 = m1->list_len; len2 = m2 ? m2->list_len : 0; @@ -180,7 +183,7 @@ prefix_suffix_stringlist (sl, prefix, suffix) { llen = STRLEN (sl->list[i]); tlen = plen + llen + slen + 1; - t = xmalloc (tlen + 1); + t = (char *)xmalloc (tlen + 1); if (plen) strcpy (t, prefix); strcpy (t + plen, sl->list[i]); @@ -223,6 +226,12 @@ word_list_to_stringlist (list, copy, starting_index, ip) STRINGLIST *ret; int slen, len; + if (list == 0) + { + if (ip) + *ip = 0; + return ((STRINGLIST *)0); + } slen = list_length (list); ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST)); ret->list = word_list_to_argv (list, copy, starting_index, &len); diff --git a/lib/sh/stringvec.c b/lib/sh/stringvec.c index 977ef48..fa16ad4 100644 --- a/lib/sh/stringvec.c +++ b/lib/sh/stringvec.c @@ -18,17 +18,17 @@ with Bash; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#include "config.h" +#include <config.h> -#include "bashtypes.h" +#include <bashtypes.h> #if defined (HAVE_UNISTD_H) # include <unistd.h> #endif -#include "bashansi.h" +#include <bashansi.h> #include <stdio.h> -#include <ctype.h> +#include <chartypes.h> #include "shell.h" @@ -100,16 +100,16 @@ copy_array (array) { register int i; int len; - char **new_array; + char **ret; len = array_len (array); - new_array = (char **)xmalloc ((len + 1) * sizeof (char *)); + ret = (char **)xmalloc ((len + 1) * sizeof (char *)); for (i = 0; array[i]; i++) - new_array[i] = savestring (array[i]); - new_array[i] = (char *)NULL; + ret[i] = savestring (array[i]); + ret[i] = (char *)NULL; - return (new_array); + return (ret); } /* Comparison routine for use with qsort() on arrays of strings. Uses @@ -135,7 +135,5 @@ void sort_char_array (array) char **array; { - qsort (array, array_len (array), sizeof (char *), - (Function *)qsort_string_compare); + qsort (array, array_len (array), sizeof (char *), (QSFUNC *)qsort_string_compare); } - diff --git a/lib/sh/strtod.c b/lib/sh/strtod.c index fe0f09d..cc3bec9 100644 --- a/lib/sh/strtod.c +++ b/lib/sh/strtod.c @@ -25,7 +25,7 @@ extern int errno; #endif -#include <ctype.h> +#include <chartypes.h> #include <math.h> #if HAVE_FLOAT_H @@ -73,7 +73,7 @@ strtod (nptr, endptr) s = nptr; /* Eat whitespace. */ - while (isspace (*s)) + while (ISSPACE ((unsigned char)*s)) ++s; /* Get the sign. */ @@ -87,7 +87,7 @@ strtod (nptr, endptr) exponent = 0; for (;; ++s) { - if (isdigit (*s)) + if (DIGIT (*s)) { got_digit = 1; @@ -120,7 +120,7 @@ strtod (nptr, endptr) if (!got_digit) goto noconv; - if (tolower (*s) == 'e') + if (TOLOWER ((unsigned char)*s) == 'e') { /* Get the exponent specified after the `e' or `E'. */ int save = errno; diff --git a/lib/sh/strtoimax.c b/lib/sh/strtoimax.c new file mode 100644 index 0000000..30075ce --- /dev/null +++ b/lib/sh/strtoimax.c @@ -0,0 +1,102 @@ +/* Convert string representation of a number into an intmax_t value. + Copyright 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. Modified by Chet Ramey for Bash. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#if HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#include <stdc.h> + +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + +#ifndef HAVE_DECL_STRTOL +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_STRTOL +extern long strtol __P((const char *, char **, int)); +#endif + +#ifndef HAVE_DECL_STRTOLL +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG +extern long long strtoll __P((const char *, char **, int)); +#endif + +intmax_t +strtoimax (ptr, endptr, base) + const char *ptr; + char **endptr; + int base; +{ +#if HAVE_LONG_LONG + verify(size_is_that_of_long_or_long_long, + (sizeof (intmax_t) == sizeof (long) || + sizeof (intmax_t) == sizeof (long long))); + + if (sizeof (intmax_t) != sizeof (long)) + return (strtoll (ptr, endptr, base)); +#else + verify (size_is_that_of_long, sizeof (intmax_t) == sizeof (long)); +#endif + + return (strtol (ptr, endptr, base)); +} + +#ifdef TESTING +# include <stdio.h> +int +main () +{ + char *p, *endptr; + intmax_t x; +#if HAVE_LONG_LONG + long long y; +#endif + long z; + + printf ("sizeof intmax_t: %d\n", sizeof (intmax_t)); + +#if HAVE_LONG_LONG + printf ("sizeof long long: %d\n", sizeof (long long)); +#endif + printf ("sizeof long: %d\n", sizeof (long)); + + x = strtoimax("42", &endptr, 10); +#if HAVE_LONG_LONG + y = strtoll("42", &endptr, 10); +#else + y = -1; +#endif + z = strtol("42", &endptr, 10); + + printf ("%lld %lld %ld\n", x, y, z); + + exit (0); +} +#endif diff --git a/lib/sh/strtol.c b/lib/sh/strtol.c index e990932..2adbb89 100644 --- a/lib/sh/strtol.c +++ b/lib/sh/strtol.c @@ -1,25 +1,27 @@ -/* strtol - Convert string representation of a number into an integer value. - Copyright (C) 1997 Free Software Foundation, Inc. +/* Convert string representation of a number into an integer value. + Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + 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 General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <config.h> #if !defined (HAVE_STRTOL) -#include <ctype.h> +#include <chartypes.h> #include <errno.h> #ifndef errno @@ -34,6 +36,8 @@ extern int errno; # include <limits.h> #endif +#include <typemax.h> + #include <stdc.h> #include <bashansi.h> @@ -41,61 +45,74 @@ extern int errno; # define NULL 0 #endif -/* Nonzero if we are defining `strtoul', operating on unsigned integers. */ +/* Nonzero if we are defining `strtoul' or `strtoull', operating on + unsigned integers. */ #ifndef UNSIGNED -# define UNSIGNED 0 -# define RETTYPE long +# define UNSIGNED 0 +# define INT LONG int #else -# define RETTYPE unsigned long +# define INT unsigned LONG int #endif -/* Determine the name. */ #if UNSIGNED -# define strtol strtoul -#endif - -#ifndef CHAR_BIT -# define CHAR_BIT 8 -#endif - -#ifndef ULONG_MAX -# define ULONG_MAX ((unsigned long) ~(unsigned long) 0) -# define ULONG_MIN ((unsigned long) 0 - ULONG_MAX) +# ifdef QUAD +# define strtol strtoull +# else +# define strtol strtoul +# endif +#else +# ifdef QUAD +# define strtol strtoll +# endif #endif -#ifndef LONG_MAX -# define LONG_MAX ((long) (ULONG_MAX >> 1)) -# define LONG_MIN ((long) (0 - LONG_MAX)) +/* If QUAD is defined, we are defining `strtoll' or `strtoull', + operating on `long long ints. */ + +#ifdef QUAD +# define LONG long long +# define STRTOL_LONG_MIN LLONG_MIN +# define STRTOL_LONG_MAX LLONG_MAX +# define STRTOL_ULONG_MAX ULLONG_MAX +#else /* !QUAD */ +# define LONG long +# define STRTOL_LONG_MIN LONG_MIN +# define STRTOL_LONG_MAX LONG_MAX +# define STRTOL_ULONG_MAX ULONG_MAX #endif /* Convert NPTR to an `unsigned long int' or `long int' in base BASE. If BASE is 0 the base is determined by the presence of a leading zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. - If BASE is < 2 or > 36, it is reset to 10. + If BASE is < 2 or > 36, it is no longer reset to 10; EINVAL is returned. If ENDPTR is not NULL, a pointer to the character after the last one converted is stored in *ENDPTR. */ -RETTYPE +INT strtol (nptr, endptr, base) const char *nptr; char **endptr; int base; { int negative; - register unsigned long cutoff, i; + register unsigned LONG int cutoff; register unsigned int cutlim; + register unsigned LONG int i; register const char *s; register unsigned char c; const char *save, *end; int overflow; if (base < 0 || base == 1 || base > 36) - base = 10; + { + __set_errno (EINVAL); + return 0; + } save = s = nptr; /* Skip white space. */ - while (isspace (*s)) + while (ISSPACE ((unsigned char)*s)) ++s; if (*s == '\0') goto noconv; @@ -109,58 +126,85 @@ strtol (nptr, endptr, base) else negative = 0; - if (base == 16 && *s == '0' && toupper (s[1]) == 'X') - s += 2; - - /* If BASE is zero, figure it out ourselves. */ - if (base == 0) - if (*s == '0') - { - if (toupper (s[1]) == 'X') - { - s += 2; - base = 16; - } - else - base = 8; - } - else - base = 10; + /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ + if (*s == '0') + { + if ((base == 0 || base == 16) && TOUPPER ((unsigned char) s[1]) == 'X') + { + s += 2; + base = 16; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; /* Save the pointer so we can check later if anything happened. */ save = s; end = NULL; - cutoff = ULONG_MAX / (unsigned long int) base; - cutlim = ULONG_MAX % (unsigned long int) base; + cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; + cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; overflow = 0; i = 0; - for (c = *s; c != '\0'; c = *++s) + c = *s; + if (sizeof (long int) != sizeof (LONG int)) { - if (s == end) - break; + unsigned long int j = 0; + unsigned long int jmax = ULONG_MAX / base; - if (c >= '0' && c <= '9') - c -= '0'; - else if (isalpha (c)) - c = toupper (c) - 'A' + 10; - else - break; - - if ((int) c >= base) - break; - - /* Check for overflow. */ - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; - else + for (;c != '\0'; c = *++s) { - i *= (unsigned long int) base; - i += c; + if (s == end) + break; + if (DIGIT (c)) + c -= '0'; + else if (ISALPHA (c)) + c = TOUPPER (c) - 'A' + 10; + else + break; + + if ((int) c >= base) + break; + /* Note that we never can have an overflow. */ + else if (j >= jmax) + { + /* We have an overflow. Now use the long representation. */ + i = (unsigned LONG int) j; + goto use_long; + } + else + j = j * (unsigned long int) base + c; } + + i = (unsigned LONG int) j; } + else + for (;c != '\0'; c = *++s) + { + if (s == end) + break; + if (DIGIT (c)) + c -= '0'; + else if (ISALPHA (c)) + c = TOUPPER (c) - 'A' + 10; + else + break; + if ((int) c >= base) + break; + /* Check for overflow. */ + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + use_long: + i *= (unsigned LONG int) base; + i += c; + } + } /* Check if anything actually happened. */ if (s == save) @@ -173,11 +217,11 @@ strtol (nptr, endptr, base) #if !UNSIGNED /* Check for a value that is within the range of - `unsigned long int', but outside the range of `long int'. */ + `unsigned LONG int', but outside the range of `LONG int'. */ if (overflow == 0 && i > (negative - ? -((unsigned long) (LONG_MIN + 1)) + 1 - : (unsigned long) LONG_MAX)) + ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 + : (unsigned LONG int) STRTOL_LONG_MAX)) overflow = 1; #endif @@ -185,23 +229,23 @@ strtol (nptr, endptr, base) { __set_errno (ERANGE); #if UNSIGNED - return ULONG_MAX; + return STRTOL_ULONG_MAX; #else - return negative ? LONG_MIN : LONG_MAX; + return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; #endif } - /* Return the result with the appropriate sign. */ - return (negative ? -i : i); + /* Return the result of the appropriate sign. */ + return negative ? -i : i; noconv: /* We must handle a special case here: the base is 0 or 16 and the first two characters are '0' and 'x', but the rest are no hexadecimal digits. This is no error case. We return 0 and - ENDPTR points to the `x'. */ + ENDPTR points to the `x`. */ if (endptr != NULL) { - if (save - nptr >= 2 && toupper (save[-1]) == 'X' && save[-2] == '0') + if (save - nptr >= 2 && TOUPPER ((unsigned char) save[-1]) == 'X' && save[-2] == '0') *endptr = (char *) &save[-1]; else /* There was no number to convert. */ diff --git a/lib/sh/strtoll.c b/lib/sh/strtoll.c new file mode 100644 index 0000000..2000497 --- /dev/null +++ b/lib/sh/strtoll.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software Foundation, +Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> + +#if defined (HAVE_LONG_LONG) && !defined (HAVE_STRTOLL) + +#define QUAD 1 +#undef HAVE_STRTOL + +#include "strtol.c" + +#endif /* HAVE_LONG_LONG && !HAVE_STRTOLL */ diff --git a/lib/sh/strtoull.c b/lib/sh/strtoull.c new file mode 100644 index 0000000..09a2fac --- /dev/null +++ b/lib/sh/strtoull.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software Foundation, +Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> + +#if defined (HAVE_LONG_LONG) && !defined (HAVE_STRTOULL) + +#define QUAD 1 +#define UNSIGNED 1 +#undef HAVE_STRTOL + +#include "strtol.c" + +#endif /* HAVE_LONG_LONG && !HAVE_STRTOULL */ diff --git a/lib/sh/strtoumax.c b/lib/sh/strtoumax.c new file mode 100644 index 0000000..c35461a --- /dev/null +++ b/lib/sh/strtoumax.c @@ -0,0 +1,102 @@ +/* Convert string representation of a number into an uintmax_t value. + Copyright 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. Modified by Chet Ramey for Bash. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#if HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#include <stdc.h> + +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + +#ifndef HAVE_DECL_STRTOUL +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_STRTOUL +extern unsigned long strtoul __P((const char *, char **, int)); +#endif + +#ifndef HAVE_DECL_STRTOULL +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG +extern unsigned long long strtoull __P((const char *, char **, int)); +#endif + +uintmax_t +strtoumax (ptr, endptr, base) + const char *ptr; + char **endptr; + int base; +{ +#if HAVE_UNSIGNED_LONG_LONG + verify (size_is_that_of_unsigned_long_or_unsigned_long_long, + (sizeof (uintmax_t) == sizeof (unsigned long) || + sizeof (uintmax_t) == sizeof (unsigned long long))); + + if (sizeof (uintmax_t) != sizeof (unsigned long)) + return (strtoull (ptr, endptr, base)); +#else + verify (size_is_that_of_unsigned_long, sizeof (uintmax_t) == sizeof (unsigned long)); +#endif + + return (strtoul (ptr, endptr, base)); +} + +#ifdef TESTING +# include <stdio.h> +int +main () +{ + char *p, *endptr; + uintmax_t x; +#if HAVE_UNSIGNED_LONG_LONG + unsigned long long y; +#endif + unsigned long z; + + printf ("sizeof uintmax_t: %d\n", sizeof (uintmax_t)); + +#if HAVE_UNSIGNED_LONG_LONG + printf ("sizeof unsigned long long: %d\n", sizeof (unsigned long long)); +#endif + printf ("sizeof unsigned long: %d\n", sizeof (unsigned long)); + + x = strtoumax("42", &endptr, 10); +#if HAVE_LONG_LONG + y = strtoull("42", &endptr, 10); +#else + y = 0; +#endif + z = strtoul("42", &endptr, 10); + + printf ("%llu %llu %lu\n", x, y, z); + + exit (0); +} +#endif diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c index 7005c46..9192e62 100644 --- a/lib/sh/strtrans.c +++ b/lib/sh/strtrans.c @@ -26,9 +26,9 @@ # include <unistd.h> #endif -#include "bashansi.h" +#include <bashansi.h> #include <stdio.h> -#include <ctype.h> +#include <chartypes.h> #include "shell.h" @@ -37,21 +37,6 @@ #endif #define ESC '\033' /* ASCII */ -#ifndef ISOCTAL -#define ISOCTAL(c) ((c) >= '0' && (c) <= '7') -#endif - -#ifndef OCTVALUE -#define OCTVALUE(c) ((c) - '0') -#endif - -#ifndef isxdigit -# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - -#define HEXVALUE(c) \ - ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') - /* Convert STRING by expanding the escape sequences specified by the ANSI C standard. If SAWC is non-null, recognize `\c' and use that as a string terminator. If we see \c, set *SAWC to 1 before @@ -70,7 +55,7 @@ ansicstr (string, len, for_echo, sawc, rlen) if (string == 0 || *string == '\0') return ((char *)NULL); - ret = xmalloc (len + 1); + ret = (char *)xmalloc (len + 1); for (r = ret, s = string; s && *s; ) { c = *s++; @@ -98,16 +83,18 @@ ansicstr (string, len, for_echo, sawc, rlen) case '4': case '5': case '6': case '7': for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++) c = (c * 8) + OCTVALUE (*s); + c &= 0xFF; break; case 'x': /* Hex digit -- non-ANSI */ - for (temp = 3, c = 0; isxdigit (*s) && temp--; s++) + for (temp = 2, c = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++) c = (c * 16) + HEXVALUE (*s); /* \x followed by non-hex digits is passed through unchanged */ - if (temp == 3) + if (temp == 2) { *r++ = '\\'; c = 'x'; } + c &= 0xFF; break; case '\\': break; @@ -143,21 +130,22 @@ ansic_quote (str, flags, rlen) int flags, *rlen; { char *r, *ret, *s, obuf[8]; - int l, c, rsize, t; + int l, rsize, t; + unsigned char c; if (str == 0 || *str == 0) return ((char *)0); l = strlen (str); rsize = 2 * l + 4; - r = ret = xmalloc (rsize); + r = ret = (char *)xmalloc (rsize); *r++ = '$'; *r++ = '\''; for (s = str, l = 0; *s; s++) { - c = *(unsigned char *)s; + c = *s; l = 1; /* 1 == add backslash; 0 == no backslash */ switch (c) { @@ -179,7 +167,7 @@ ansic_quote (str, flags, rlen) case '\'': break; default: - if (isprint (c) == 0) + if (ISPRINT (c) == 0) { sprintf (obuf, "\\%.3o", c); t = r - ret; @@ -203,3 +191,20 @@ ansic_quote (str, flags, rlen) *rlen = r - ret; return ret; } + +/* return 1 if we need to quote with $'...' because of non-printing chars. */ +ansic_shouldquote (string) + const char *string; +{ + const char *s; + unsigned char c; + + if (string == 0) + return 0; + + for (s = string; c = *s; s++) + if (ISPRINT (c) == 0) + return 1; + + return 0; +} diff --git a/lib/sh/times.c b/lib/sh/times.c index e26e41c..7136cf2 100644 --- a/lib/sh/times.c +++ b/lib/sh/times.c @@ -30,7 +30,7 @@ # include <sys/resource.h> #endif /* HAVE_SYS_RESOURCE_H && HAVE_GETRUSAGE */ -extern long get_clk_tck(); +extern long get_clk_tck __P((void)); #define CONVTCK(r) (r.tv_sec * clk_tck + r.tv_usec / (1000000 / clk_tck)) diff --git a/lib/sh/timeval.c b/lib/sh/timeval.c index 809d411..f7f624e 100644 --- a/lib/sh/timeval.c +++ b/lib/sh/timeval.c @@ -103,7 +103,7 @@ timeval_to_cpu (rt, ut, st) void timeval_to_secs (tvp, sp, sfp) struct timeval *tvp; - long *sp; + time_t *sp; int *sfp; { int rest; @@ -131,14 +131,15 @@ print_timeval (fp, tvp) FILE *fp; struct timeval *tvp; { - int minutes, seconds_fraction; - long seconds; + time_t timestamp; + long minutes; + int seconds, seconds_fraction; - timeval_to_secs (tvp, &seconds, &seconds_fraction); + timeval_to_secs (tvp, ×tamp, &seconds_fraction); - minutes = seconds / 60; - seconds %= 60; + minutes = timestamp / 60; + seconds = timestamp % 60; - fprintf (fp, "%0dm%0ld.%03ds", minutes, seconds, seconds_fraction); + fprintf (fp, "%ldm%d.%03ds", minutes, seconds, seconds_fraction); } #endif /* HAVE_TIMEVAL */ diff --git a/lib/sh/tmpfile.c b/lib/sh/tmpfile.c index 6912e5c..d51ac2c 100644 --- a/lib/sh/tmpfile.c +++ b/lib/sh/tmpfile.c @@ -44,7 +44,7 @@ extern int errno; #define DEFAULT_TMPDIR "." /* bogus default, should be changed */ #define DEFAULT_NAMEROOT "shtmp" -extern int dollar_dollar_pid; +extern pid_t dollar_dollar_pid; static char *sys_tmpdir = (char *)NULL; static int ntmpfiles; @@ -59,6 +59,12 @@ get_sys_tmpdir () if (sys_tmpdir) return sys_tmpdir; +#ifdef P_tmpdir + sys_tmpdir = P_tmpdir; + if (stat (sys_tmpdir, &sb) == 0) + return sys_tmpdir; +#endif + sys_tmpdir = "/tmp"; if (stat (sys_tmpdir, &sb) == 0) return sys_tmpdir; @@ -71,11 +77,7 @@ get_sys_tmpdir () if (stat (sys_tmpdir, &sb) == 0) return sys_tmpdir; -#ifdef P_tmpdir - sys_tmpdir = P_tmpdir; -#else sys_tmpdir = DEFAULT_TMPDIR; -#endif return sys_tmpdir; } @@ -105,32 +107,42 @@ sh_mktmpname (nameroot, flags) char *nameroot; int flags; { - char *filename, *tdir; + char *filename, *tdir, *lroot; struct stat sb; int r, tdlen; - filename = xmalloc (PATH_MAX + 1); + filename = (char *)xmalloc (PATH_MAX + 1); tdir = get_tmpdir (flags); tdlen = strlen (tdir); - if (nameroot == 0) - nameroot = DEFAULT_NAMEROOT; + lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; +#ifdef USE_MKTEMP + sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + if (mktemp (filename) == 0) + { + free (filename); + filename = NULL; + } +#else /* !USE_MKTEMP */ while (1) { - filenum *= (int)time ((time_t *)0) * dollar_dollar_pid * - ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++); - sprintf (filename, "%s/%s-%lu", tdir, nameroot, filenum); + filenum = (filenum << 1) ^ + (unsigned long) time ((time_t *)0) ^ + (unsigned long) dollar_dollar_pid ^ + (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++); + sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum); if (tmpnamelen > 0 && tmpnamelen < 32) filename[tdlen + 1 + tmpnamelen] = '\0'; -#ifdef HAVE_LSTAT +# ifdef HAVE_LSTAT r = lstat (filename, &sb); -#else +# else r = stat (filename, &sb); -#endif +# endif if (r < 0 && errno == ENOENT) break; } +#endif /* !USE_MKTEMP */ return filename; } @@ -141,21 +153,34 @@ sh_mktmpfd (nameroot, flags, namep) int flags; char **namep; { - char *filename, *tdir; + char *filename, *tdir, *lroot; int fd, tdlen; - filename = xmalloc (PATH_MAX + 1); + filename = (char *)xmalloc (PATH_MAX + 1); tdir = get_tmpdir (flags); tdlen = strlen (tdir); - if (nameroot == 0) - nameroot = DEFAULT_NAMEROOT; + lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; +#ifdef USE_MKSTEMP + sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + fd = mkstemp (filename); + if (fd < 0 || namep == 0) + { + free (filename); + filename = NULL; + } + if (namep) + *namep = filename; + return fd; +#else /* !USE_MKSTEMP */ do { - filenum *= (int)time ((time_t *)0) * dollar_dollar_pid * - ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++); - sprintf (filename, "%s/%s-%lu", tdir, nameroot, filenum); + filenum = (filenum << 1) ^ + (unsigned long) time ((time_t *)0) ^ + (unsigned long) dollar_dollar_pid ^ + (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++); + sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum); if (tmpnamelen > 0 && tmpnamelen < 32) filename[tdlen + 1 + tmpnamelen] = '\0'; fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600); @@ -168,6 +193,7 @@ sh_mktmpfd (nameroot, flags, namep) free (filename); return fd; +#endif /* !USE_MKSTEMP */ } FILE * @@ -177,7 +203,13 @@ sh_mktmpfp (nameroot, flags, namep) char **namep; { int fd; + FILE *fp; fd = sh_mktmpfd (nameroot, flags, namep); - return ((fd >= 0) ? (fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w")) : (FILE *)NULL); + if (fd < 0) + return ((FILE *)NULL); + fp = fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w"); + if (fp == 0) + close (fd); + return fp; } diff --git a/lib/sh/zread.c b/lib/sh/zread.c index 0d5320a..2cdfb4e 100644 --- a/lib/sh/zread.c +++ b/lib/sh/zread.c @@ -36,13 +36,13 @@ extern int errno; /* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other error causes the loop to break. */ -int +ssize_t zread (fd, buf, len) int fd; char *buf; size_t len; { - int r; + ssize_t r; while ((r = read (fd, buf, len)) < 0 && errno == EINTR) ; @@ -57,13 +57,14 @@ zread (fd, buf, len) #endif #define NUM_INTR 3 -int +ssize_t zread1 (fd, buf, len) int fd; char *buf; size_t len; { - int r, nintr; + ssize_t r; + int nintr; for (nintr = 0; ; ) { @@ -84,25 +85,29 @@ zread1 (fd, buf, len) in read(2). This does some local buffering to avoid many one-character calls to read(2), like those the `read' builtin performs. */ -static unsigned char lbuf[128]; -static int lind, lused; +static char lbuf[128]; +static size_t lind, lused; -int +ssize_t zreadc (fd, cp) int fd; char *cp; { - int r; + ssize_t nr; if (lind == lused || lused == 0) { - lused = zread (fd, lbuf, sizeof (lbuf)); + nr = zread (fd, lbuf, sizeof (lbuf)); lind = 0; - if (lused <= 0) - return (lused); + if (nr <= 0) + { + lused = 0; + return nr; + } + lused = nr; } if (cp) - *cp = (char)lbuf[lind++]; + *cp = lbuf[lind++]; return 1; } @@ -118,7 +123,7 @@ void zsyncfd (fd) int fd; { - int off; + off_t off; off = lused - lind; if (off > 0) diff --git a/lib/sh/zwrite.c b/lib/sh/zwrite.c index d36ca5f..39ffbb1 100644 --- a/lib/sh/zwrite.c +++ b/lib/sh/zwrite.c @@ -36,7 +36,7 @@ extern int errno; int zwrite (fd, buf, nb) int fd; - unsigned char *buf; + char *buf; size_t nb; { int n, i, nt; diff --git a/lib/termcap/Makefile.in b/lib/termcap/Makefile.in index 1ed2c27..2f17bce 100644 --- a/lib/termcap/Makefile.in +++ b/lib/termcap/Makefile.in @@ -25,6 +25,8 @@ VPATH = .:@srcdir@ topdir = @top_srcdir@ BUILD_DIR = @BUILD_DIR@ +libdir = @libdir@ + INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ @@ -80,7 +82,7 @@ mostlyclean: clean distclean maintainer-clean: clean $(RM) Makefile -$(DESTDIR)/libtermcap.a: libtermcap.a +$(DESTDIR)$(libdir)/libtermcap.a: libtermcap.a ${INSTALL_DATA} -c -m 644 libtermcap.a $@ -test -n "$(RANLIB)" && $(RANLIB) -t $@ diff --git a/lib/tilde/ChangeLog b/lib/tilde/ChangeLog deleted file mode 100644 index 986db67..0000000 --- a/lib/tilde/ChangeLog +++ /dev/null @@ -1,6 +0,0 @@ -Mon Jul 13 12:01:51 1992 Brian Fox (bfox@cubit) - - * tilde.c: (tilde_expand_word) If there is no variable $HOME, then - look up the user's home directory in the password database. - - diff --git a/lib/tilde/Makefile.in b/lib/tilde/Makefile.in index 35543b5..f53c5d7 100644 --- a/lib/tilde/Makefile.in +++ b/lib/tilde/Makefile.in @@ -97,8 +97,8 @@ force: # always returns TRUE unless there really was an error installing the # include files. install: - $(INSTALL_DATA) -c -m 644 $(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME) - -test -n "$(RANLIB)" && $(RANLIB) -t $(bindir)/$(LIBRARY_NAME) + $(INSTALL_DATA) -c -m 644 $(LIBRARY_NAME) $(libdir)/$(LIBRARY_NAME) + -test -n "$(RANLIB)" && $(RANLIB) -t $(libdir)/$(LIBRARY_NAME) clean: $(RM) -f $(OBJECTS) $(LIBRARY_NAME) diff --git a/lib/tilde/tilde.c b/lib/tilde/tilde.c index 7f33db4..6e4f116 100644 --- a/lib/tilde/tilde.c +++ b/lib/tilde/tilde.c @@ -48,22 +48,21 @@ #include "tilde.h" #if defined (TEST) || defined (STATIC_MALLOC) -static char *xmalloc (), *xrealloc (); +static void *xmalloc (), *xrealloc (); #else -extern char *xmalloc __P((int)); -extern char *xrealloc __P((void *, int)); +# include "xmalloc.h" #endif /* TEST || STATIC_MALLOC */ #if !defined (HAVE_GETPW_DECLS) -extern struct passwd *getpwuid __P((uid_t)); -extern struct passwd *getpwnam __P((const char *)); +extern struct passwd *getpwuid PARAMS((uid_t)); +extern struct passwd *getpwnam PARAMS((const char *)); #endif /* !HAVE_GETPW_DECLS */ #if !defined (savestring) # ifndef strcpy extern char *strcpy (); # endif -#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) #endif /* !savestring */ #if !defined (NULL) @@ -77,8 +76,8 @@ extern char *strcpy (); /* If being compiled as part of bash, these will be satisfied from variables.o. If being compiled as part of readline, they will be satisfied from shell.o. */ -extern char *sh_get_home_dir __P((void)); -extern char *sh_get_env_value __P((const char *)); +extern char *sh_get_home_dir PARAMS((void)); +extern char *sh_get_env_value PARAMS((const char *)); /* The default value of tilde_additional_prefixes. This is set to whitespace preceding a tilde so that simple programs which do not @@ -114,12 +113,17 @@ char **tilde_additional_prefixes = (char **)default_prefixes; `:' and `=~'. */ char **tilde_additional_suffixes = (char **)default_suffixes; +static int tilde_find_prefix PARAMS((const char *, int *)); +static int tilde_find_suffix PARAMS((const char *)); +static char *isolate_tilde_prefix PARAMS((const char *, int *)); +static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); + /* Find the start of a tilde expansion in STRING, and return the index of the tilde which starts the expansion. Place the length of the text which identified this tilde starter in LEN, excluding the tilde itself. */ static int tilde_find_prefix (string, len) - char *string; + const char *string; int *len; { register int i, j, string_len; @@ -154,7 +158,7 @@ tilde_find_prefix (string, len) the character which ends the tilde definition. */ static int tilde_find_suffix (string) - char *string; + const char *string; { register int i, j, string_len; register char **suffixes; @@ -190,9 +194,9 @@ tilde_expand (string) result_index = result_size = 0; if (result = strchr (string, '~')) - result = xmalloc (result_size = (strlen (string) + 16)); + result = (char *)xmalloc (result_size = (strlen (string) + 16)); else - result = xmalloc (result_size = (strlen (string) + 1)); + result = (char *)xmalloc (result_size = (strlen (string) + 1)); /* Scan through STRING expanding tildes as we come to them. */ while (1) @@ -206,7 +210,7 @@ tilde_expand (string) /* Copy the skipped text into the result. */ if ((result_index + start + 1) > result_size) - result = xrealloc (result, 1 + (result_size += (start + 20))); + result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); strncpy (result + result_index, string, start); result_index += start; @@ -223,7 +227,7 @@ tilde_expand (string) break; /* Expand the entire tilde word, and copy it into RESULT. */ - tilde_word = xmalloc (1 + end); + tilde_word = (char *)xmalloc (1 + end); strncpy (tilde_word, string, end); tilde_word[end] = '\0'; string += end; @@ -239,7 +243,7 @@ tilde_expand (string) #endif { if ((result_index + len + 1) > result_size) - result = xrealloc (result, 1 + (result_size += (len + 20))); + result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); strcpy (result + result_index, expansion); result_index += len; @@ -257,13 +261,13 @@ tilde_expand (string) the location it points to. */ static char * isolate_tilde_prefix (fname, lenp) - char *fname; + const char *fname; int *lenp; { char *ret; int i; - ret = xmalloc (strlen (fname)); + ret = (char *)xmalloc (strlen (fname)); #if defined (__MSDOS__) for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) #else @@ -280,7 +284,8 @@ isolate_tilde_prefix (fname, lenp) SUFFIND. */ static char * glue_prefix_and_suffix (prefix, suffix, suffind) - char *prefix, *suffix; + char *prefix; + const char *suffix; int suffind; { char *ret; @@ -288,7 +293,7 @@ glue_prefix_and_suffix (prefix, suffix, suffind) plen = (prefix && *prefix) ? strlen (prefix) : 0; slen = strlen (suffix + suffind); - ret = xmalloc (plen + slen + 1); + ret = (char *)xmalloc (plen + slen + 1); if (plen) strcpy (ret, prefix); strcpy (ret + plen, suffix + suffind); @@ -412,28 +417,28 @@ main (argc, argv) static void memory_error_and_abort (); -static char * +static void * xmalloc (bytes) - int bytes; + size_t bytes; { - char *temp = (char *)malloc (bytes); + void *temp = (char *)malloc (bytes); if (!temp) memory_error_and_abort (); return (temp); } -static char * +static void * xrealloc (pointer, bytes) - char *pointer; + void *pointer; int bytes; { - char *temp; + void *temp; if (!pointer) - temp = (char *)malloc (bytes); + temp = malloc (bytes); else - temp = (char *)realloc (pointer, bytes); + temp = realloc (pointer, bytes); if (!temp) memory_error_and_abort (); diff --git a/lib/tilde/tilde.h b/lib/tilde/tilde.h index d3966a6..0df608b 100644 --- a/lib/tilde/tilde.h +++ b/lib/tilde/tilde.h @@ -24,35 +24,27 @@ #if !defined (_TILDE_H_) # define _TILDE_H_ +#if defined (HAVE_CONFIG_H) +# include <config.h> +#endif + #ifdef __cplusplus extern "C" { #endif /* A function can be defined using prototypes and compile on both ANSI C and traditional C compilers with something like this: - extern char *func __P((char *, char *, int)); */ + extern char *func PARAMS((char *, char *, int)); */ -#if !defined (__P) +#if !defined (PARAMS) # if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) -# define __P(protos) protos +# define PARAMS(protos) protos # else -# define __P(protos) () +# define PARAMS(protos) () # endif #endif -#if !defined (__STDC__) && !defined (__cplusplus) -# if defined (__GNUC__) /* gcc with -traditional */ -# if !defined (const) -# define const __const -# endif /* !const */ -# else /* !__GNUC__ */ -# if !defined (const) -# define const -# endif /* !const */ -# endif /* !__GNUC__ */ -#endif /* !__STDC__ && !__cplusplus */ - -typedef char *tilde_hook_func_t __P((char *)); +typedef char *tilde_hook_func_t PARAMS((char *)); /* If non-null, this contains the address of a function that the application wants called before trying the standard tilde expansions. The function @@ -77,11 +69,11 @@ extern char **tilde_additional_prefixes; extern char **tilde_additional_suffixes; /* Return a new string which is the result of tilde expanding STRING. */ -extern char *tilde_expand __P((const char *)); +extern char *tilde_expand PARAMS((const char *)); /* Do the work of tilde expansion on FILENAME. FILENAME starts with a tilde. If there is no expansion, call tilde_expansion_failure_hook. */ -extern char *tilde_expand_word __P((const char *)); +extern char *tilde_expand_word PARAMS((const char *)); #ifdef __cplusplus } |