Imported from ../bash-2.02.tar.gz.
This commit is contained in:
parent
e8ce775db8
commit
cce855bc5b
323 changed files with 33916 additions and 12321 deletions
129
lib/glob/collsyms.h
Normal file
129
lib/glob/collsyms.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
/* collsyms.h -- collating symbol names and their corresponding characters
|
||||
(in ascii) as given by POSIX.2 in table 2.8. */
|
||||
|
||||
/* Copyright (C) 1997 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef _COLLSYMS_H_
|
||||
# define _COLLSYSMS_H_
|
||||
|
||||
/* The upper-case letters, lower-case letters, and digits are omitted from
|
||||
this table. The digits are not included in the table in the POSIX.2
|
||||
spec. The upper and lower case letters are translated by the code
|
||||
in fnmatch.c:collsym(). */
|
||||
|
||||
typedef struct _collsym {
|
||||
char *name;
|
||||
char code;
|
||||
} COLLSYM;
|
||||
|
||||
static COLLSYM posix_collsyms[] =
|
||||
{
|
||||
"NUL", '\0',
|
||||
"SOH", '\001',
|
||||
"STX", '\002',
|
||||
"ETX", '\003',
|
||||
"EOT", '\004',
|
||||
"ENQ", '\005',
|
||||
"ACK", '\006',
|
||||
#ifdef __STDC__
|
||||
"alert", '\a',
|
||||
#else
|
||||
"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,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,238 +1,738 @@
|
|||
/* Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
/* fnmatch.c -- ksh-like extended pattern matching for the shell and filename
|
||||
globbing. */
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <config.h>
|
||||
|
||||
#include "fnmatch.h"
|
||||
#include "collsyms.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
|
||||
# if !defined (errno)
|
||||
extern int errno;
|
||||
# endif /* !errno */
|
||||
static int gmatch ();
|
||||
static char *brackmatch ();
|
||||
#ifdef EXTENDED_GLOB
|
||||
static int extmatch ();
|
||||
#endif
|
||||
|
||||
#if !defined (isascii)
|
||||
# define isascii(c) ((unsigned int)(c) <= 0177)
|
||||
#endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, FNM_NOMATCH if not. */
|
||||
/* Note that these evaluate C many times. */
|
||||
|
||||
#define ISUPPER(c) (isascii (c) && isupper (c))
|
||||
#define ISLOWER(c) (isascii (c) && islower (c))
|
||||
|
||||
#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
|
||||
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
|
||||
#ifndef STREQ
|
||||
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
|
||||
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STRCOLL)
|
||||
static int rangecmp (c1, c2)
|
||||
int c1, c2;
|
||||
{
|
||||
static char s1[2] = { ' ', '\0' };
|
||||
static char s2[2] = { ' ', '\0' };
|
||||
int ret;
|
||||
|
||||
/* Eight bits only. Period. */
|
||||
c1 &= 0xFF;
|
||||
c2 &= 0xFF;
|
||||
|
||||
if (c1 == c2)
|
||||
return (0);
|
||||
|
||||
s1[0] = c1;
|
||||
s2[0] = c2;
|
||||
|
||||
if ((ret = strcoll (s1, s2)) != 0)
|
||||
return ret;
|
||||
return (c1 - c2);
|
||||
}
|
||||
#else /* !HAVE_STRCOLL */
|
||||
# define rangecmp(c1, c2) ((c1) - (c2))
|
||||
#endif /* !HAVE_STRCOLL */
|
||||
|
||||
#if defined (HAVE_STRCOLL)
|
||||
static int collequiv (c1, c2)
|
||||
int c1, c2;
|
||||
{
|
||||
return (rangecmp (c1, c2) == 0);
|
||||
}
|
||||
#else
|
||||
# define collequiv(c1, c2) ((c1) == (c2))
|
||||
#endif
|
||||
|
||||
static int
|
||||
collsym (s, len)
|
||||
char *s;
|
||||
int len;
|
||||
{
|
||||
register struct _collsym *csp;
|
||||
|
||||
for (csp = posix_collsyms; csp->name; csp++)
|
||||
{
|
||||
if (STREQN(csp->name, s, len) && csp->name[len] == '\0')
|
||||
return (csp->code);
|
||||
}
|
||||
if (len == 1)
|
||||
return s[0];
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
char *pattern;
|
||||
char *string;
|
||||
int flags;
|
||||
{
|
||||
register char *p = pattern, *n = string;
|
||||
register char c;
|
||||
char *se, *pe;
|
||||
|
||||
if ((flags & ~__FNM_FLAGS) != 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (string == 0 || pattern == 0)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
se = string + strlen (string);
|
||||
pe = pattern + strlen (pattern);
|
||||
|
||||
return (gmatch (string, se, pattern, pe, flags));
|
||||
}
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, FNM_NOMATCH if not. */
|
||||
static int
|
||||
gmatch (string, se, pattern, pe, flags)
|
||||
char *string, *se;
|
||||
char *pattern, *pe;
|
||||
int flags;
|
||||
{
|
||||
register char *p, *n; /* pattern, string */
|
||||
register char c; /* current pattern character */
|
||||
register char sc; /* current string character */
|
||||
|
||||
p = pattern;
|
||||
n = string;
|
||||
|
||||
if (string == 0 || pattern == 0)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
while (p < pe)
|
||||
{
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
sc = n < se ? *n : '\0';
|
||||
|
||||
#ifdef EXTENDED_GLOB
|
||||
if ((flags & FNM_EXTMATCH) && *p == '(' &&
|
||||
(c == '+' || c == '*' || c == '?' || c == '@' || c == '!')) /* ) */
|
||||
/* extmatch () will handle recursively calling gmatch, so we can
|
||||
just return what extmatch() returns. */
|
||||
return (extmatch (c, n, se, p, pe, flags));
|
||||
#endif
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
if (*n == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
else if ((flags & FNM_PATHNAME) && *n == '/')
|
||||
case '?': /* Match single character */
|
||||
if (sc == '\0')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PATHNAME) && sc == '/')
|
||||
/* If we are matching a pathname, `?' can never match a `/'. */
|
||||
return (FNM_NOMATCH);
|
||||
else if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PERIOD) && sc == '.' &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
|
||||
/* `?' cannot match a `.' if it is the first character of the
|
||||
string or if it is the first character following a slash and
|
||||
we are matching a pathname. */
|
||||
return (FNM_NOMATCH);
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
case '\\': /* backslash escape removes special meaning */
|
||||
if (p == pe)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if ((flags & FNM_NOESCAPE) == 0)
|
||||
{
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
/* A trailing `\' cannot match. */
|
||||
if (p > pe)
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (*n != c)
|
||||
return (FNM_NOMATCH);
|
||||
if (FOLD (sc) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
case '*': /* Match zero or more characters */
|
||||
if (p == pe)
|
||||
return 0;
|
||||
|
||||
if ((flags & FNM_PERIOD) && sc == '.' &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
|
||||
/* `*' cannot match a `.' if it is the first character of the
|
||||
string or if it is the first character following a slash and
|
||||
we are matching a pathname. */
|
||||
return (FNM_NOMATCH);
|
||||
return FNM_NOMATCH;
|
||||
|
||||
/* Collapse multiple consecutive, `*' and `?', but make sure that
|
||||
one character of the string is consumed for each `?'. */
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++)
|
||||
for (c = *p++; (c == '?' || c == '*'); c = *p++)
|
||||
{
|
||||
if ((flags & FNM_PATHNAME) && *n == '/')
|
||||
if ((flags & FNM_PATHNAME) && sc == '/')
|
||||
/* A slash does not match a wildcard under FNM_PATHNAME. */
|
||||
return (FNM_NOMATCH);
|
||||
return FNM_NOMATCH;
|
||||
else if (c == '?')
|
||||
{
|
||||
if (*n == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
if (sc == '\0')
|
||||
return FNM_NOMATCH;
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
fewer than three characters. */
|
||||
n++;
|
||||
sc = n < se ? *n : '\0';
|
||||
}
|
||||
|
||||
#ifdef EXTENDED_GLOB
|
||||
/* Handle ******(patlist) */
|
||||
if ((flags & FNM_EXTMATCH) && c == '*' && *p == '(') /*)*/
|
||||
return (extmatch (c, n, se, p, pe, flags));
|
||||
#endif
|
||||
if (p == pe)
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\0')
|
||||
/* If we've hit the end of the pattern and the last character of
|
||||
the pattern was handled by the loop above, we've succeeded.
|
||||
Otherwise, we need to match that last character. */
|
||||
if (p == pe && (c == '?' || c == '*'))
|
||||
return (0);
|
||||
|
||||
/* General case, use recursion. */
|
||||
{
|
||||
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
|
||||
for (--p; *n != '\0'; ++n)
|
||||
char c1;
|
||||
|
||||
c1 = ((flags & FNM_NOESCAPE) == 0 && c == '\\') ? *p : c;
|
||||
c1 = FOLD (c1);
|
||||
for (--p; n < se; ++n)
|
||||
/* Only call fnmatch if the first character indicates a
|
||||
possible match. */
|
||||
if ((c == '[' || *n == c1) &&
|
||||
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
|
||||
if ((c == '[' || FOLD (*n) == c1) &&
|
||||
gmatch (n, se, p, pe, flags & ~FNM_PERIOD) == 0)
|
||||
return (0);
|
||||
return (FNM_NOMATCH);
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
case '[':
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
register int not;
|
||||
|
||||
if (*n == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
if (sc == '\0' || n == se)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
/* A character class cannot match a `.' if it is the first
|
||||
character of the string or if it is the first character
|
||||
following a slash and we are matching a pathname. */
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
if ((flags & FNM_PERIOD) && sc == '.' &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
/* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
|
||||
is not preceded by a backslash and is not part of a bracket
|
||||
expression produces undefined results.' This implementation
|
||||
treats the `[' as just a character to be matched if there is
|
||||
not a closing `]'. This code will have to be changed when
|
||||
POSIX.2 character classes are implemented. */
|
||||
{
|
||||
register char *np;
|
||||
|
||||
for (np = p; np && *np && *np != ']'; np++)
|
||||
;
|
||||
|
||||
if (np && !*np)
|
||||
{
|
||||
if (*n != '[')
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
not = (*p == '!' || *p == '^');
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
register char cstart, cend;
|
||||
|
||||
/* Initialize cstart and cend in case `-' is the last
|
||||
character of the pattern. */
|
||||
cstart = cend = c;
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
cstart = cend = *p++;
|
||||
}
|
||||
|
||||
if (c == '\0')
|
||||
/* [ (unterminated) loses. */
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
c = *p++;
|
||||
|
||||
if ((flags & FNM_PATHNAME) && c == '/')
|
||||
/* [/] can never match. */
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
/* This introduces a range, unless the `-' is the last
|
||||
character of the class. Find the end of the range
|
||||
and move past it. */
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if (*n >= cstart && *n <= cend)
|
||||
goto matched;
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
if (!not)
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != ']')
|
||||
{
|
||||
if (c == '\0')
|
||||
/* [... (unterminated) loses. */
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
return (FNM_NOMATCH);
|
||||
p = brackmatch (p, sc, flags);
|
||||
if (p == 0)
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c != *n)
|
||||
if (c != FOLD (sc))
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
if (*n == '\0')
|
||||
if (n == se)
|
||||
return (0);
|
||||
|
||||
if ((flags & FNM_LEADING_DIR) && *n == '/')
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find
|
||||
the value of the symbol, and move P past the collating symbol expression.
|
||||
The value is returned in *VP, if VP is not null. */
|
||||
static char *
|
||||
parse_collsym (p, vp)
|
||||
char *p;
|
||||
int *vp;
|
||||
{
|
||||
register int pc;
|
||||
int val;
|
||||
|
||||
p++; /* move past the `.' */
|
||||
|
||||
for (pc = 0; p[pc]; pc++)
|
||||
if (p[pc] == '.' && p[pc+1] == ']')
|
||||
break;
|
||||
val = collsym (p, pc);
|
||||
if (vp)
|
||||
*vp = val;
|
||||
return (p + pc + 2);
|
||||
}
|
||||
|
||||
static char *
|
||||
brackmatch (p, test, flags)
|
||||
char *p;
|
||||
unsigned char test;
|
||||
int flags;
|
||||
{
|
||||
register char cstart, cend, c;
|
||||
register int not; /* Nonzero if the sense of the character class is inverted. */
|
||||
int pc, brcnt;
|
||||
char *savep;
|
||||
|
||||
test = FOLD (test);
|
||||
|
||||
savep = p;
|
||||
|
||||
/* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
|
||||
circumflex (`^') in its role in a `nonmatching list'. A bracket
|
||||
expression starging with an unquoted circumflex character produces
|
||||
unspecified results. This implementation treats the two identically. */
|
||||
if (not = (*p == '!' || *p == '^'))
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
/* Initialize cstart and cend in case `-' is the last
|
||||
character of the pattern. */
|
||||
cstart = cend = c;
|
||||
|
||||
/* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find
|
||||
the end of the equivalence class, move the pattern pointer past
|
||||
it, and check for equivalence. XXX - this handles only
|
||||
single-character equivalence classes, which is wrong, or at
|
||||
least incomplete. */
|
||||
if (c == '[' && *p == '=' && p[2] == '=' && p[3] == ']')
|
||||
{
|
||||
pc = FOLD (p[1]);
|
||||
p += 4;
|
||||
if (collequiv (test, pc))
|
||||
goto matched;
|
||||
else
|
||||
{
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
return ((test == '[') ? savep : (char *)0);
|
||||
c = FOLD (c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */
|
||||
if (c == '[' && *p == ':')
|
||||
{
|
||||
pc = 0; /* make sure invalid char classes don't match. */
|
||||
if (STREQN (p+1, "alnum:]", 7))
|
||||
{ pc = isalnum (test); p += 8; }
|
||||
else if (STREQN (p+1, "alpha:]", 7))
|
||||
{ pc = isalpha (test); p += 8; }
|
||||
else if (STREQN (p+1, "blank:]", 7))
|
||||
{ pc = isblank (test); p += 8; }
|
||||
else if (STREQN (p+1, "cntrl:]", 7))
|
||||
{ pc = iscntrl (test); p += 8; }
|
||||
else if (STREQN (p+1, "digit:]", 7))
|
||||
{ pc = isdigit (test); p += 8; }
|
||||
else if (STREQN (p+1, "graph:]", 7))
|
||||
{ pc = isgraph (test); p += 8; }
|
||||
else if (STREQN (p+1, "lower:]", 7))
|
||||
{ pc = ISLOWER (test); p += 8; }
|
||||
else if (STREQN (p+1, "print:]", 7))
|
||||
{ pc = isprint (test); p += 8; }
|
||||
else if (STREQN (p+1, "punct:]", 7))
|
||||
{ pc = ispunct (test); p += 8; }
|
||||
else if (STREQN (p+1, "space:]", 7))
|
||||
{ pc = isspace (test); p += 8; }
|
||||
else if (STREQN (p+1, "upper:]", 7))
|
||||
{ pc = ISUPPER (test); p += 8; }
|
||||
else if (STREQN (p+1, "xdigit:]", 8))
|
||||
{ pc = isxdigit (test); p += 9; }
|
||||
else if (STREQN (p+1, "ascii:]", 7))
|
||||
{ pc = isascii (test); p += 8; }
|
||||
if (pc)
|
||||
goto matched;
|
||||
else
|
||||
{
|
||||
/* continue the loop here, since this expression can't be
|
||||
the first part of a range expression. */
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
return ((test == '[') ? savep : (char *)0);
|
||||
else if (c == ']')
|
||||
break;
|
||||
c = FOLD (c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* POSIX.2 collating symbols. See POSIX.2 2.8.3.2. Find the end of
|
||||
the symbol name, make sure it is terminated by `.]', translate
|
||||
the name to a character using the external table, and do the
|
||||
comparison. */
|
||||
if (c == '[' && *p == '.')
|
||||
{
|
||||
p = parse_collsym (p, &pc);
|
||||
/* An invalid collating symbol cannot be the first point of a
|
||||
range. If it is, we set cstart to one greater than `test',
|
||||
so any comparisons later will fail. */
|
||||
cstart = (pc == -1) ? test + 1 : pc;
|
||||
}
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return (char *)0;
|
||||
cstart = cend = *p++;
|
||||
}
|
||||
|
||||
cstart = cend = FOLD (cstart);
|
||||
|
||||
/* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
|
||||
is not preceded by a backslash and is not part of a bracket
|
||||
expression produces undefined results.' This implementation
|
||||
treats the `[' as just a character to be matched if there is
|
||||
not a closing `]'. */
|
||||
if (c == '\0')
|
||||
return ((test == '[') ? savep : (char *)0);
|
||||
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
if ((flags & FNM_PATHNAME) && c == '/')
|
||||
/* [/] can never match when matching a pathname. */
|
||||
return (char *)0;
|
||||
|
||||
/* This introduces a range, unless the `-' is the last
|
||||
character of the class. Find the end of the range
|
||||
and move past it. */
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return (char *)0;
|
||||
if (cend == '[' && *p == '.')
|
||||
{
|
||||
p = parse_collsym (p, &pc);
|
||||
/* An invalid collating symbol cannot be the second part of a
|
||||
range expression. If we get one, we set cend to one fewer
|
||||
than the test character to make sure the range test fails. */
|
||||
cend = (pc == -1) ? test - 1 : pc;
|
||||
}
|
||||
cend = FOLD (cend);
|
||||
|
||||
c = *p++;
|
||||
|
||||
/* POSIX.2 2.8.3.2: ``The ending range point shall collate
|
||||
equal to or higher than the starting range point; otherwise
|
||||
the expression shall be treated as invalid.'' Note that this
|
||||
applies to only the range expression; the rest of the bracket
|
||||
expression is still checked for matches. */
|
||||
if (rangecmp (cstart, cend) > 0)
|
||||
{
|
||||
if (c == ']')
|
||||
break;
|
||||
c = FOLD (c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (rangecmp (test, cstart) >= 0 && rangecmp (test, cend) <= 0)
|
||||
goto matched;
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
/* No match. */
|
||||
return (!not ? (char *)0 : p);
|
||||
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.'));
|
||||
while (brcnt > 0)
|
||||
{
|
||||
/* A `[' without a matching `]' is just another character to match. */
|
||||
if (c == '\0')
|
||||
return ((test == '[') ? savep : (char *)0);
|
||||
|
||||
c = *p++;
|
||||
if (c == '[' && (*p == '=' || *p == ':' || *p == '.'))
|
||||
brcnt++;
|
||||
else if (c == ']')
|
||||
brcnt--;
|
||||
else if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return (char *)0;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
}
|
||||
return (not ? (char *)0 : p);
|
||||
}
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
/* ksh-like extended pattern matching:
|
||||
|
||||
[?*+@!](pat-list)
|
||||
|
||||
where pat-list is a list of one or patterns separated by `|'. Operation
|
||||
is as follows:
|
||||
|
||||
?(patlist) match zero or one of the given patterns
|
||||
*(patlist) match zero or more of the given patterns
|
||||
+(patlist) match one or more of the given patterns
|
||||
@(patlist) match exactly one of the given patterns
|
||||
!(patlist) match anything except one of the given patterns
|
||||
*/
|
||||
|
||||
/* Scan a pattern starting at STRING and ending at END, keeping track of
|
||||
embedded () and []. If DELIM is 0, we scan until a matching `)'
|
||||
because we're scanning a `patlist'. Otherwise, we scan until we see
|
||||
DELIM. In all cases, we never scan past END. The return value is the
|
||||
first character after the matching DELIM. */
|
||||
static char *
|
||||
patscan (string, end, delim)
|
||||
char *string, *end;
|
||||
int delim;
|
||||
{
|
||||
int pnest, bnest;
|
||||
char *s, c;
|
||||
|
||||
pnest = bnest = 0;
|
||||
for (s = string; c = *s; s++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\0':
|
||||
return ((char *)0);
|
||||
case '[':
|
||||
bnest++;
|
||||
break;
|
||||
case ']':
|
||||
if (bnest)
|
||||
bnest--;
|
||||
break;
|
||||
case '(':
|
||||
if (bnest == 0)
|
||||
pnest++;
|
||||
break;
|
||||
case ')':
|
||||
if (bnest == 0)
|
||||
pnest--;
|
||||
if (pnest <= 0)
|
||||
return ++s;
|
||||
break;
|
||||
case '|':
|
||||
if (bnest == 0 && pnest == 0 && delim == '|')
|
||||
return ++s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
/* Return 0 if dequoted pattern matches S in the current locale. */
|
||||
static int
|
||||
strcompare (p, pe, s, se)
|
||||
char *p, *pe, *s, *se;
|
||||
{
|
||||
int ret;
|
||||
char c1, c2;
|
||||
|
||||
c1 = *pe;
|
||||
c2 = *se;
|
||||
|
||||
*pe = *se = '\0';
|
||||
#if defined (HAVE_STRCOLL)
|
||||
ret = strcoll (p, s);
|
||||
#else
|
||||
ret = strcmp (p, s);
|
||||
#endif
|
||||
|
||||
*pe = c1;
|
||||
*se = c2;
|
||||
|
||||
return (ret == 0 ? ret : FNM_NOMATCH);
|
||||
}
|
||||
|
||||
/* Match a ksh extended pattern specifier. Return FNM_NOMATCH on failure or
|
||||
0 on success. This is handed the entire rest of the pattern and string
|
||||
the first time an extended pattern specifier is encountered, so it calls
|
||||
gmatch recursively. */
|
||||
static int
|
||||
extmatch (xc, s, se, p, pe, flags)
|
||||
int xc; /* select which operation */
|
||||
char *s, *se;
|
||||
char *p, *pe;
|
||||
int flags;
|
||||
{
|
||||
char *prest; /* pointer to rest of pattern */
|
||||
char *psub; /* pointer to sub-pattern */
|
||||
char *pnext; /* pointer to next sub-pattern */
|
||||
char *srest; /* pointer to rest of string */
|
||||
int m1, m2;
|
||||
|
||||
switch (xc)
|
||||
{
|
||||
case '+': /* match one or more occurrences */
|
||||
case '*': /* match zero or more occurrences */
|
||||
prest = patscan (p, pe, 0);
|
||||
if (prest == 0)
|
||||
/* If PREST is 0, we failed to scan a valid pattern. In this
|
||||
case, we just want to compare the two as strings. */
|
||||
return (strcompare (p - 1, pe, s, se));
|
||||
|
||||
/* If we can get away with no matches, don't even bother. Just
|
||||
call gmatch on the rest of the pattern and return success if
|
||||
it succeeds. */
|
||||
if (xc == '*' && (gmatch (s, se, prest, pe, flags) == 0))
|
||||
return 0;
|
||||
|
||||
/* OK, we have to do this the hard way. First, we make sure one of
|
||||
the subpatterns matches, then we try to match the rest of the
|
||||
string. */
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = patscan (psub, pe, '|');
|
||||
for (srest = s; srest <= se; srest++)
|
||||
{
|
||||
/* Match this substring (S -> SREST) against this
|
||||
subpattern (psub -> pnext - 1) */
|
||||
m1 = gmatch (s, srest, psub, pnext - 1, flags) == 0;
|
||||
/* OK, we matched a subpattern, so make sure the rest of the
|
||||
string matches the rest of the pattern. Also handle
|
||||
multiple matches of the pattern. */
|
||||
if (m1)
|
||||
m2 = (gmatch (srest, se, prest, pe, flags) == 0) ||
|
||||
(s != srest && gmatch (srest, se, p - 1, pe, flags) == 0);
|
||||
if (m1 && m2)
|
||||
return (0);
|
||||
}
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
case '?': /* match zero or one of the patterns */
|
||||
case '@': /* match exactly one of the patterns */
|
||||
prest = patscan (p, pe, 0);
|
||||
if (prest == 0)
|
||||
return (strcompare (p - 1, pe, s, se));
|
||||
|
||||
/* If we can get away with no matches, don't even bother. Just
|
||||
call gmatch on the rest of the pattern and return success if
|
||||
it succeeds. */
|
||||
if (xc == '?' && (gmatch (s, se, prest, pe, flags) == 0))
|
||||
return 0;
|
||||
|
||||
/* OK, we have to do this the hard way. First, we see if one of
|
||||
the subpatterns matches, then, if it does, we try to match the
|
||||
rest of the string. */
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = patscan (psub, pe, '|');
|
||||
srest = (prest == pe) ? se : s;
|
||||
for ( ; srest <= se; srest++)
|
||||
{
|
||||
if (gmatch (s, srest, psub, pnext - 1, flags) == 0 &&
|
||||
gmatch (srest, se, prest, pe, flags) == 0)
|
||||
return (0);
|
||||
}
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
case '!': /* match anything *except* one of the patterns */
|
||||
prest = patscan (p, pe, 0);
|
||||
if (prest == 0)
|
||||
return (strcompare (p - 1, pe, s, se));
|
||||
|
||||
for (srest = s; srest <= se; srest++)
|
||||
{
|
||||
m1 = 0;
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = patscan (psub, pe, '|');
|
||||
/* If one of the patterns matches, just bail immediately. */
|
||||
if (m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0))
|
||||
break;
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0)
|
||||
return (0);
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
#endif /* EXTENDED_GLOB */
|
||||
|
||||
#ifdef TEST
|
||||
main (c, v)
|
||||
int c;
|
||||
char **v;
|
||||
{
|
||||
char *string, *pat;
|
||||
|
||||
string = v[1];
|
||||
pat = v[2];
|
||||
|
||||
if (fnmatch (pat, string, 0) == 0)
|
||||
{
|
||||
printf ("%s matches %s\n", string, pat);
|
||||
exit (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("%s does not match %s\n", string, pat);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -17,14 +17,24 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
|||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#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. */
|
||||
#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
|
||||
/* standard flags */
|
||||
#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 */
|
||||
#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. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
@ -33,4 +43,4 @@ Cambridge, MA 02139, USA. */
|
|||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch();
|
||||
|
||||
#endif /* fnmatch.h */
|
||||
#endif /* _FNMATCH_H */
|
||||
|
|
287
lib/glob/glob.c
287
lib/glob/glob.c
|
@ -25,20 +25,29 @@
|
|||
#pragma alloca
|
||||
#endif /* _AIX && RISC6000 && !__GNUC__ */
|
||||
|
||||
#if defined (SHELL)
|
||||
# include "bashtypes.h"
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#if defined (SHELL)
|
||||
# include "bashansi.h"
|
||||
#else
|
||||
# if defined (SHELL)
|
||||
# include "ansi_stdlib.h"
|
||||
# endif /* SHELL */
|
||||
# if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
# if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
# else /* !HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
# endif /* !HAVE_STRING_H */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined (HAVE_DIRENT_H)
|
||||
# include <dirent.h>
|
||||
# define D_NAMLEN(d) strlen ((d)->d_name)
|
||||
|
@ -66,27 +75,25 @@
|
|||
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
|
||||
#endif /* _POSIX_SOURCE */
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else /* !HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
#if !defined (HAVE_BCOPY)
|
||||
# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
|
||||
#endif /* !HAVE_BCOPY */
|
||||
|
||||
/* If the opendir () on your system lets you open non-directory files,
|
||||
then we consider that not robust. */
|
||||
#if defined (OPENDIR_NOT_ROBUST)
|
||||
# if defined (SHELL)
|
||||
# include "posixstat.h"
|
||||
# else /* !SHELL */
|
||||
# include <sys/stat.h>
|
||||
# endif /* !SHELL */
|
||||
#endif /* OPENDIR_NOT_ROBUST */
|
||||
#if defined (SHELL)
|
||||
# include "posixstat.h"
|
||||
#else /* !SHELL */
|
||||
# include <sys/stat.h>
|
||||
#endif /* !SHELL */
|
||||
|
||||
#include "filecntl.h"
|
||||
#if !defined (F_OK)
|
||||
# define F_OK 0
|
||||
#endif
|
||||
|
||||
#if defined (SHELL)
|
||||
# include "memalloc.h"
|
||||
#endif
|
||||
|
||||
#include "memalloc.h"
|
||||
#include "fnmatch.h"
|
||||
|
||||
#if !defined (HAVE_STDLIB_H) && !defined (SHELL)
|
||||
|
@ -104,14 +111,20 @@ extern void free ();
|
|||
|
||||
#if defined (SHELL)
|
||||
extern void throw_to_top_level ();
|
||||
extern int test_eaccess ();
|
||||
|
||||
extern int interrupt_state;
|
||||
extern int extended_glob;
|
||||
#endif /* SHELL */
|
||||
|
||||
/* Global variable which controls whether or not * matches .*.
|
||||
Non-zero means don't match .*. */
|
||||
int noglob_dot_filenames = 1;
|
||||
|
||||
/* Global variable which controls whether or not filename globbing
|
||||
is done without regard to case. */
|
||||
int glob_ignore_case = 0;
|
||||
|
||||
/* Global variable to return to signify an error in globbing. */
|
||||
char *glob_error_return;
|
||||
|
||||
|
@ -120,9 +133,12 @@ int
|
|||
glob_pattern_p (pattern)
|
||||
char *pattern;
|
||||
{
|
||||
register char *p = pattern;
|
||||
register char *p;
|
||||
register char c;
|
||||
int open = 0;
|
||||
int bopen;
|
||||
|
||||
p = pattern;
|
||||
bopen = 0;
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
switch (c)
|
||||
|
@ -132,13 +148,20 @@ glob_pattern_p (pattern)
|
|||
return (1);
|
||||
|
||||
case '[': /* Only accept an open brace if there is a close */
|
||||
open++; /* brace to match it. Bracket expressions must be */
|
||||
bopen++; /* brace to match it. Bracket expressions must be */
|
||||
continue; /* complete, according to Posix.2 */
|
||||
case ']':
|
||||
if (open)
|
||||
if (bopen)
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case '+': /* extended matching operators */
|
||||
case '@':
|
||||
case '!':
|
||||
if (*p == '(') /*) */
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case '\\':
|
||||
if (*p++ == '\0')
|
||||
return (0);
|
||||
|
@ -168,6 +191,35 @@ dequote_pathname (pathname)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* Test whether NAME exists. */
|
||||
|
||||
#if defined (HAVE_LSTAT)
|
||||
# define GLOB_TESTNAME(name) (lstat (name, &finfo))
|
||||
#else /* !HAVE_LSTAT */
|
||||
# if defined (SHELL) && !defined (AFS)
|
||||
# define GLOB_TESTNAME(name) (test_eaccess (nextname, F_OK))
|
||||
# else /* !SHELL || AFS */
|
||||
# define GLOB_TESTNAME(name) (access (nextname, F_OK))
|
||||
# endif /* !SHELL || AFS */
|
||||
#endif /* !HAVE_LSTAT */
|
||||
|
||||
/* Return 0 if DIR is a directory, -1 otherwise. */
|
||||
static int
|
||||
glob_testdir (dir)
|
||||
char *dir;
|
||||
{
|
||||
struct stat finfo;
|
||||
|
||||
if (stat (dir, &finfo) < 0)
|
||||
return (-1);
|
||||
|
||||
if (S_ISDIR (finfo.st_mode) == 0)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return a vector of names of files in directory DIR
|
||||
whose names match glob pattern PAT.
|
||||
The names are not in any particular order.
|
||||
|
@ -204,103 +256,161 @@ glob_vector (pat, dir)
|
|||
int lose, skip;
|
||||
register char **name_vector;
|
||||
register unsigned int i;
|
||||
#if defined (OPENDIR_NOT_ROBUST)
|
||||
struct stat finfo;
|
||||
|
||||
if (stat (dir, &finfo) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
if (!S_ISDIR (finfo.st_mode))
|
||||
return ((char **) &glob_error_return);
|
||||
#endif /* OPENDIR_NOT_ROBUST */
|
||||
|
||||
d = opendir (dir);
|
||||
if (d == NULL)
|
||||
return ((char **) &glob_error_return);
|
||||
int flags; /* Flags passed to fnmatch (). */
|
||||
|
||||
lastlink = 0;
|
||||
count = 0;
|
||||
lose = 0;
|
||||
skip = 0;
|
||||
count = lose = skip = 0;
|
||||
|
||||
/* If PAT is empty, skip the loop, but return one (empty) filename. */
|
||||
if (!pat || !*pat)
|
||||
if (pat == 0 || *pat == '\0')
|
||||
{
|
||||
if (glob_testdir (dir) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
nextlink->next = lastlink;
|
||||
nextlink->next = (struct globval *)0;
|
||||
nextname = (char *) malloc (1);
|
||||
if (!nextname)
|
||||
if (nextname == 0)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
nextname[0] = '\0';
|
||||
count++;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
skip = 1;
|
||||
}
|
||||
|
||||
/* Scan the directory, finding all names that match.
|
||||
For each name that matches, allocate a struct globval
|
||||
on the stack and store the name in it.
|
||||
Chain those structs together; lastlink is the front of the chain. */
|
||||
while (!skip)
|
||||
/* If the filename pattern (PAT) does not contain any globbing characters,
|
||||
we can dispense with reading the directory, and just see if there is
|
||||
a filename `DIR/PAT'. If there is, and we can access it, just make the
|
||||
vector to return and bail immediately. */
|
||||
if (skip == 0 && glob_pattern_p (pat) == 0)
|
||||
{
|
||||
int flags; /* Flags passed to fnmatch (). */
|
||||
#if defined (SHELL)
|
||||
/* Make globbing interruptible in the bash shell. */
|
||||
if (interrupt_state)
|
||||
int dirlen;
|
||||
struct stat finfo;
|
||||
|
||||
if (glob_testdir (dir) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
dirlen = strlen (dir);
|
||||
nextname = (char *)malloc (dirlen + strlen (pat) + 2);
|
||||
if (nextname == 0)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
closedir (d);
|
||||
lose = 1;
|
||||
goto lost;
|
||||
strcpy (nextname, dir);
|
||||
nextname[dirlen++] = '/';
|
||||
strcpy (nextname + dirlen, pat);
|
||||
|
||||
if (GLOB_TESTNAME (nextname) >= 0)
|
||||
{
|
||||
free (nextname);
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
nextlink->next = (struct globval *)0;
|
||||
nextname = (char *) malloc (strlen (pat) + 1);
|
||||
if (nextname == 0)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
strcpy (nextname, pat);
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
free (nextname);
|
||||
}
|
||||
#endif /* SHELL */
|
||||
|
||||
dp = readdir (d);
|
||||
if (dp == NULL)
|
||||
break;
|
||||
|
||||
/* If this directory entry is not to be used, try again. */
|
||||
if (!REAL_DIR_ENTRY (dp))
|
||||
continue;
|
||||
skip = 1;
|
||||
}
|
||||
|
||||
/* If a dot must be explicity matched, check to see if they do. */
|
||||
if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
|
||||
(pat[0] != '\\' || pat[1] != '.'))
|
||||
continue;
|
||||
if (skip == 0)
|
||||
{
|
||||
/* Open the directory, punting immediately if we cannot. If opendir
|
||||
is not robust (i.e., it opens non-directories successfully), test
|
||||
that DIR is a directory and punt if it's not. */
|
||||
#if defined (OPENDIR_NOT_ROBUST)
|
||||
if (glob_testdir (dir) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
#endif
|
||||
|
||||
d = opendir (dir);
|
||||
if (d == NULL)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
/* Compute the flags that will be passed to fnmatch(). We don't
|
||||
need to do this every time through the loop. */
|
||||
flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
|
||||
|
||||
if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
|
||||
#ifdef FNM_CASEFOLD
|
||||
if (glob_ignore_case)
|
||||
flags |= FNM_CASEFOLD;
|
||||
#endif
|
||||
|
||||
#ifdef SHELL
|
||||
if (extended_glob)
|
||||
flags |= FNM_EXTMATCH;
|
||||
#endif
|
||||
|
||||
/* Scan the directory, finding all names that match.
|
||||
For each name that matches, allocate a struct globval
|
||||
on the stack and store the name in it.
|
||||
Chain those structs together; lastlink is the front of the chain. */
|
||||
while (1)
|
||||
{
|
||||
nextlink = (struct globval *) alloca (sizeof (struct globval));
|
||||
nextlink->next = lastlink;
|
||||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextname == NULL)
|
||||
#if defined (SHELL)
|
||||
/* Make globbing interruptible in the shell. */
|
||||
if (interrupt_state)
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
(void) closedir (d);
|
||||
#endif /* SHELL */
|
||||
|
||||
dp = readdir (d);
|
||||
if (dp == NULL)
|
||||
break;
|
||||
|
||||
if (!lose)
|
||||
/* If this directory entry is not to be used, try again. */
|
||||
if (REAL_DIR_ENTRY (dp) == 0)
|
||||
continue;
|
||||
|
||||
/* If a dot must be explicity matched, check to see if they do. */
|
||||
if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
|
||||
(pat[0] != '\\' || pat[1] != '.'))
|
||||
continue;
|
||||
|
||||
if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
|
||||
{
|
||||
nextlink = (struct globval *) alloca (sizeof (struct globval));
|
||||
nextlink->next = lastlink;
|
||||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextname == NULL)
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
(void) closedir (d);
|
||||
}
|
||||
|
||||
if (lose == 0)
|
||||
{
|
||||
name_vector = (char **) malloc ((count + 1) * sizeof (char *));
|
||||
lose |= name_vector == NULL;
|
||||
}
|
||||
|
||||
/* Have we run out of memory? */
|
||||
#if defined (SHELL)
|
||||
lost:
|
||||
#endif
|
||||
if (lose)
|
||||
{
|
||||
/* Here free the strings we have got. */
|
||||
|
@ -313,7 +423,8 @@ glob_vector (pat, dir)
|
|||
if (interrupt_state)
|
||||
throw_to_top_level ();
|
||||
#endif /* SHELL */
|
||||
return (NULL);
|
||||
|
||||
return ((char **)NULL);
|
||||
}
|
||||
|
||||
/* Copy the name pointers from the linked list into the vector. */
|
||||
|
|
|
@ -26,5 +26,6 @@ extern char **glob_filename __P((char *));
|
|||
|
||||
extern char *glob_error_return;
|
||||
extern int noglob_dot_filenames;
|
||||
extern int glob_ignore_case;
|
||||
|
||||
#endif /* _GLOB_H_ */
|
||||
|
|
|
@ -16,6 +16,9 @@ along with this program; if not, write to the Free Software
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
# if defined (_SC_PAGESIZE)
|
||||
# define getpagesize() sysconf(_SC_PAGESIZE)
|
||||
|
@ -27,7 +30,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#endif
|
||||
|
||||
#if !defined (getpagesize)
|
||||
# include <sys/param.h>
|
||||
# ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if defined (PAGESIZE)
|
||||
# define getpagesize() PAGESIZE
|
||||
# else /* !PAGESIZE */
|
||||
|
|
1233
lib/malloc/gmalloc.c
1233
lib/malloc/gmalloc.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1579
lib/malloc/ogmalloc.c
Normal file
1579
lib/malloc/ogmalloc.c
Normal file
File diff suppressed because it is too large
Load diff
759
lib/malloc/omalloc.c
Normal file
759
lib/malloc/omalloc.c
Normal file
|
@ -0,0 +1,759 @@
|
|||
/* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, 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 */
|
|
@ -190,7 +190,7 @@ rltty.o: readline.h keymaps.h chardefs.h tilde.h
|
|||
search.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
search.o: readline.h keymaps.h chardefs.h tilde.h
|
||||
search.o: ansi_stdlib.h history.h
|
||||
shell.o: ${BUILD_DIR}/config.h
|
||||
shell.o: ${BUILD_DIR}/config.h ansi_stdlib.h
|
||||
signals.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
signals.o: readline.h keymaps.h chardefs.h tilde.h
|
||||
signals.o: history.h
|
||||
|
|
|
@ -70,6 +70,8 @@ extern int _rl_convert_meta_chars_to_ascii;
|
|||
extern int _rl_output_meta_chars;
|
||||
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_enable_keypad;
|
||||
#if defined (PAREN_MATCHING)
|
||||
extern int rl_blink_matching_paren;
|
||||
|
@ -105,6 +107,7 @@ Keymap rl_binding_keymap;
|
|||
/* Forward declarations */
|
||||
void rl_set_keymap_from_edit_mode ();
|
||||
|
||||
static int _rl_read_init_file ();
|
||||
static int glean_key_from_name ();
|
||||
static int substring_member_of_array ();
|
||||
|
||||
|
@ -198,6 +201,35 @@ rl_unbind_key_in_map (key, map)
|
|||
return (rl_bind_key_in_map (key, (Function *)NULL, map));
|
||||
}
|
||||
|
||||
/* Unbind all keys bound to FUNCTION in MAP. */
|
||||
int
|
||||
rl_unbind_function_in_map (func, map)
|
||||
Function *func;
|
||||
Keymap map;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < KEYMAP_SIZE; i++)
|
||||
{
|
||||
if (map[i].type == ISFUNC && map[i].function == func)
|
||||
map[i].function = (Function *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rl_unbind_command_in_map (command, map)
|
||||
char *command;
|
||||
Keymap map;
|
||||
{
|
||||
Function *func;
|
||||
register int i;
|
||||
|
||||
func = rl_named_function (command);
|
||||
if (func == 0)
|
||||
return 0;
|
||||
return (rl_unbind_function_in_map (func, map));
|
||||
}
|
||||
|
||||
/* Bind the key sequence represented by the string KEYSEQ to
|
||||
FUNCTION. This makes new keymaps as necessary. The initial
|
||||
place to do bindings is in MAP. */
|
||||
|
@ -313,7 +345,7 @@ rl_translate_keyseq (seq, array, len)
|
|||
char *seq, *array;
|
||||
int *len;
|
||||
{
|
||||
register int i, c, l;
|
||||
register int i, c, l, temp;
|
||||
|
||||
for (i = l = 0; c = seq[i]; i++)
|
||||
{
|
||||
|
@ -324,7 +356,8 @@ rl_translate_keyseq (seq, array, len)
|
|||
if (c == 0)
|
||||
break;
|
||||
|
||||
if (((c == 'C' || c == 'M') && seq[i + 1] == '-') || (c == 'e'))
|
||||
/* Handle \C- and \M- prefixes. */
|
||||
if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
|
||||
{
|
||||
/* Handle special case of backwards define. */
|
||||
if (strncmp (&seq[i], "C-\\M-", 5) == 0)
|
||||
|
@ -332,31 +365,83 @@ rl_translate_keyseq (seq, array, len)
|
|||
array[l++] = ESC;
|
||||
i += 5;
|
||||
array[l++] = CTRL (_rl_to_upper (seq[i]));
|
||||
if (!seq[i])
|
||||
if (seq[i] == '\0')
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
else if (c == 'M')
|
||||
{
|
||||
case 'M':
|
||||
i++;
|
||||
array[l++] = ESC; /* XXX */
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
}
|
||||
else if (c == 'C')
|
||||
{
|
||||
i += 2;
|
||||
/* Special hack for C-?... */
|
||||
array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
array[l++] = ESC;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Translate other backslash-escaped characters. These are the
|
||||
same escape sequences that bash's `echo' and `printf' builtins
|
||||
handle, with the addition of \d -> RUBOUT. A backslash
|
||||
preceding a character that is not special is stripped. */
|
||||
switch (c)
|
||||
{
|
||||
case 'a':
|
||||
array[l++] = '\007';
|
||||
break;
|
||||
case 'b':
|
||||
array[l++] = '\b';
|
||||
break;
|
||||
case 'd':
|
||||
array[l++] = RUBOUT; /* readline-specific */
|
||||
break;
|
||||
case 'e':
|
||||
array[l++] = ESC;
|
||||
break;
|
||||
case 'f':
|
||||
array[l++] = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
array[l++] = NEWLINE;
|
||||
break;
|
||||
case 'r':
|
||||
array[l++] = RETURN;
|
||||
break;
|
||||
case 't':
|
||||
array[l++] = TAB;
|
||||
break;
|
||||
case 'v':
|
||||
array[l++] = 0x0B;
|
||||
break;
|
||||
case '\\':
|
||||
array[l++] = '\\';
|
||||
break;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
i++;
|
||||
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);
|
||||
break;
|
||||
case 'x':
|
||||
i++;
|
||||
for (temp = 3, c = 0; isxdigit (seq[i]) && temp--; i++)
|
||||
c = (c * 16) + HEXVALUE (seq[i]);
|
||||
if (temp == 3)
|
||||
c = 'x';
|
||||
i--; /* auto-increment in for loop */
|
||||
array[l++] = c % (largest_char + 1);
|
||||
break;
|
||||
default: /* backslashes before non-special chars just add the char */
|
||||
array[l++] = c;
|
||||
break; /* the backslash is stripped */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
array[l++] = c;
|
||||
}
|
||||
|
||||
|
@ -541,8 +626,55 @@ static char *last_readline_init_file = (char *)NULL;
|
|||
|
||||
/* The file we're currently reading key bindings from. */
|
||||
static char *current_readline_init_file;
|
||||
static int current_readline_init_include_level;
|
||||
static int current_readline_init_lineno;
|
||||
|
||||
/* Read FILENAME into a locally-allocated buffer and return the buffer.
|
||||
The size of the buffer is returned in *SIZEP. Returns NULL if any
|
||||
errors were encountered. */
|
||||
static char *
|
||||
_rl_read_file (filename, sizep)
|
||||
char *filename;
|
||||
size_t *sizep;
|
||||
{
|
||||
struct stat finfo;
|
||||
size_t file_size;
|
||||
char *buffer;
|
||||
int i, file;
|
||||
|
||||
if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
|
||||
return ((char *)NULL);
|
||||
|
||||
file_size = (size_t)finfo.st_size;
|
||||
|
||||
/* check for overflow on very large files */
|
||||
if (file_size != finfo.st_size || file_size + 1 < file_size)
|
||||
{
|
||||
if (file >= 0)
|
||||
close (file);
|
||||
#if defined (EFBIG)
|
||||
errno = EFBIG;
|
||||
#endif
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
/* Read the file into BUFFER. */
|
||||
buffer = (char *)xmalloc (file_size + 1);
|
||||
i = read (file, buffer, file_size);
|
||||
close (file);
|
||||
|
||||
if (i < file_size)
|
||||
{
|
||||
free (buffer);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
buffer[file_size] = '\0';
|
||||
if (sizep)
|
||||
*sizep = file_size;
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
/* Re-read the current keybindings file. */
|
||||
int
|
||||
rl_re_read_init_file (count, ignore)
|
||||
|
@ -565,11 +697,6 @@ int
|
|||
rl_read_init_file (filename)
|
||||
char *filename;
|
||||
{
|
||||
register int i;
|
||||
char *buffer, *openname, *line, *end;
|
||||
struct stat finfo;
|
||||
int file;
|
||||
|
||||
/* Default the filename. */
|
||||
if (filename == 0)
|
||||
{
|
||||
|
@ -583,39 +710,37 @@ rl_read_init_file (filename)
|
|||
if (*filename == 0)
|
||||
filename = DEFAULT_INPUTRC;
|
||||
|
||||
return (_rl_read_init_file (filename, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_read_init_file (filename, include_level)
|
||||
char *filename;
|
||||
int include_level;
|
||||
{
|
||||
register int i;
|
||||
char *buffer, *openname, *line, *end;
|
||||
size_t file_size;
|
||||
|
||||
current_readline_init_file = filename;
|
||||
current_readline_init_include_level = include_level;
|
||||
|
||||
openname = tilde_expand (filename);
|
||||
|
||||
if ((stat (openname, &finfo) < 0) ||
|
||||
(file = open (openname, O_RDONLY, 0666)) < 0)
|
||||
buffer = _rl_read_file (openname, &file_size);
|
||||
if (buffer == 0)
|
||||
return (errno);
|
||||
|
||||
if (include_level == 0 && filename != last_readline_init_file)
|
||||
{
|
||||
free (openname);
|
||||
return (errno);
|
||||
}
|
||||
else
|
||||
free (openname);
|
||||
|
||||
if (filename != last_readline_init_file)
|
||||
{
|
||||
if (last_readline_init_file)
|
||||
free (last_readline_init_file);
|
||||
|
||||
FREE (last_readline_init_file);
|
||||
last_readline_init_file = savestring (filename);
|
||||
}
|
||||
|
||||
/* Read the file into BUFFER. */
|
||||
buffer = (char *)xmalloc ((int)finfo.st_size + 1);
|
||||
i = read (file, buffer, finfo.st_size);
|
||||
close (file);
|
||||
|
||||
if (i != finfo.st_size)
|
||||
return (errno);
|
||||
|
||||
/* Loop over the lines in the file. Lines that start with `#' are
|
||||
comments; all other lines are commands for readline initialization. */
|
||||
current_readline_init_lineno = 1;
|
||||
line = buffer;
|
||||
end = buffer + finfo.st_size;
|
||||
end = buffer + file_size;
|
||||
while (line < end)
|
||||
{
|
||||
/* Find the end of this line. */
|
||||
|
@ -639,6 +764,7 @@ rl_read_init_file (filename)
|
|||
line += i + 1;
|
||||
current_readline_init_lineno++;
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
return (0);
|
||||
}
|
||||
|
@ -697,7 +823,7 @@ parser_if (args)
|
|||
if (args[i])
|
||||
args[i++] = '\0';
|
||||
|
||||
/* Handle "if term=foo" and "if mode=emacs" constructs. If this
|
||||
/* Handle "$if term=foo" and "$if mode=emacs" constructs. If this
|
||||
isn't term=foo, or mode=emacs, then check to see if the first
|
||||
word in ARGS is the same as the value stored in rl_readline_name. */
|
||||
if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
|
||||
|
@ -749,9 +875,9 @@ parser_else (args)
|
|||
{
|
||||
register int i;
|
||||
|
||||
if (!if_stack_depth)
|
||||
if (if_stack_depth == 0)
|
||||
{
|
||||
/* Error message? */
|
||||
_rl_init_file_error ("$else found without matching $if");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -775,12 +901,36 @@ parser_endif (args)
|
|||
if (if_stack_depth)
|
||||
_rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
|
||||
else
|
||||
{
|
||||
/* *** What, no error message? *** */
|
||||
}
|
||||
_rl_init_file_error ("$endif without matching $if");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parser_include (args)
|
||||
char *args;
|
||||
{
|
||||
char *old_init_file, *e;
|
||||
int old_line_number, old_include_level, r;
|
||||
|
||||
if (_rl_parsing_conditionalized_out)
|
||||
return (0);
|
||||
|
||||
old_init_file = current_readline_init_file;
|
||||
old_line_number = current_readline_init_lineno;
|
||||
old_include_level = current_readline_init_include_level;
|
||||
|
||||
e = strchr (args, '\n');
|
||||
if (e)
|
||||
*e = '\0';
|
||||
r = _rl_read_init_file (args, old_include_level + 1);
|
||||
|
||||
current_readline_init_file = old_init_file;
|
||||
current_readline_init_lineno = old_line_number;
|
||||
current_readline_init_include_level = old_include_level;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Associate textual names with actual functions. */
|
||||
static struct {
|
||||
char *name;
|
||||
|
@ -789,6 +939,7 @@ static struct {
|
|||
{ "if", parser_if },
|
||||
{ "endif", parser_endif },
|
||||
{ "else", parser_else },
|
||||
{ "include", parser_include },
|
||||
{ (char *)0x0, (Function *)0x0 }
|
||||
};
|
||||
|
||||
|
@ -825,7 +976,8 @@ handle_parser_directive (statement)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/* *** Should an error message be output? */
|
||||
/* display an error message about the unknown parser directive */
|
||||
_rl_init_file_error ("unknown parser directive");
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
@ -940,10 +1092,9 @@ rl_parse_and_bind (string)
|
|||
the quoted string delimiter, like the shell. */
|
||||
if (*funname == '\'' || *funname == '"')
|
||||
{
|
||||
int delimiter = string[i++];
|
||||
int passc = 0;
|
||||
int delimiter = string[i++], passc;
|
||||
|
||||
for (; c = string[i]; i++)
|
||||
for (passc = 0; c = string[i]; i++)
|
||||
{
|
||||
if (passc)
|
||||
{
|
||||
|
@ -981,11 +1132,11 @@ rl_parse_and_bind (string)
|
|||
rl_set_key (). Otherwise, let the older code deal with it. */
|
||||
if (*string == '"')
|
||||
{
|
||||
char *seq = xmalloc (1 + strlen (string));
|
||||
register int j, k = 0;
|
||||
int passc = 0;
|
||||
char *seq;
|
||||
register int j, k, passc;
|
||||
|
||||
for (j = 1; string[j]; j++)
|
||||
seq = xmalloc (1 + strlen (string));
|
||||
for (j = 1, k = passc = 0; string[j]; j++)
|
||||
{
|
||||
/* Allow backslash to quote characters, but leave them in place.
|
||||
This allows a string to end with a backslash quoting another
|
||||
|
@ -1078,6 +1229,7 @@ static struct {
|
|||
#if defined (PAREN_MATCHING)
|
||||
{ "blink-matching-paren", &rl_blink_matching_paren },
|
||||
#endif
|
||||
{ "completion-ignore-case", &_rl_completion_case_fold },
|
||||
{ "convert-meta", &_rl_convert_meta_chars_to_ascii },
|
||||
{ "disable-completion", &rl_inhibit_completion },
|
||||
{ "enable-keypad", &_rl_enable_keypad },
|
||||
|
@ -1088,6 +1240,7 @@ static struct {
|
|||
{ "mark-modified-lines", &_rl_mark_modified_lines },
|
||||
{ "meta-flag", &_rl_meta_flag },
|
||||
{ "output-meta", &_rl_output_meta_chars },
|
||||
{ "print-completions-horizontally", &_rl_print_completions_horizontally },
|
||||
{ "show-all-if-ambiguous", &_rl_complete_show_all },
|
||||
#if defined (VISIBLE_STATS)
|
||||
{ "visible-stats", &rl_visible_stats },
|
||||
|
@ -1186,6 +1339,7 @@ rl_variable_bind (name, value)
|
|||
_rl_bell_preference = AUDIBLE_BELL;
|
||||
}
|
||||
|
||||
/* For the time being, unknown variable names are simply ignored. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1338,7 +1492,7 @@ _rl_get_keyname (key)
|
|||
int key;
|
||||
{
|
||||
char *keyname;
|
||||
int i, c;
|
||||
int i, c, v;
|
||||
|
||||
keyname = (char *)xmalloc (8);
|
||||
|
||||
|
@ -1383,6 +1537,18 @@ _rl_get_keyname (key)
|
|||
c = _rl_to_lower (UNCTRL (c));
|
||||
}
|
||||
|
||||
/* XXX experimental code. Turn the characters that are not ASCII or
|
||||
ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
|
||||
This changes C. */
|
||||
if (c >= 128 && c <= 159)
|
||||
{
|
||||
keyname[i++] = '\\';
|
||||
keyname[i++] = '2';
|
||||
c -= 128;
|
||||
keyname[i++] = (c / 8) + '0';
|
||||
c = (c % 8) + '0';
|
||||
}
|
||||
|
||||
/* Now, if the character needs to be quoted with a backslash, do that. */
|
||||
if (c == '\\' || c == '"')
|
||||
keyname[i++] = '\\';
|
||||
|
@ -1692,10 +1858,13 @@ rl_variable_dumper (print_readably)
|
|||
/* bell-style */
|
||||
switch (_rl_bell_preference)
|
||||
{
|
||||
case NO_BELL: kname = "none"; break;
|
||||
case VISIBLE_BELL: kname = "visible"; break;
|
||||
case NO_BELL:
|
||||
kname = "none"; break;
|
||||
case VISIBLE_BELL:
|
||||
kname = "visible"; break;
|
||||
case AUDIBLE_BELL:
|
||||
default: kname = "audible"; break;
|
||||
default:
|
||||
kname = "audible"; break;
|
||||
}
|
||||
if (print_readably)
|
||||
fprintf (rl_outstream, "set bell-style %s\n", kname);
|
||||
|
|
|
@ -55,10 +55,10 @@ extern int rl_visible_prompt_length;
|
|||
things to handle at once, and dispatches them via select(). Call
|
||||
rl_callback_handler_install() with the prompt and a function to call
|
||||
whenever a complete line of input is ready. The user must then
|
||||
call readline_char() every time some input is available, and
|
||||
readline_char() will call the user's function with the complete text
|
||||
read in at each end of line. The terminal is kept prepped and signals
|
||||
handled all the time, except during calls to the user's function. */
|
||||
call rl_callback_read_char() every time some input is available, and
|
||||
rl_callback_read_char() will call the user's function with the complete
|
||||
text read in at each end of line. The terminal is kept prepped and
|
||||
signals handled all the time, except during calls to the user's function. */
|
||||
|
||||
VFunction *rl_linefunc; /* user callback function */
|
||||
static int in_handler; /* terminal_prepped and signals set? */
|
||||
|
|
|
@ -121,7 +121,20 @@
|
|||
#ifdef ESC
|
||||
#undef ESC
|
||||
#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_ */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -72,7 +72,11 @@ extern int _rl_prefer_visible_bell;
|
|||
|
||||
/* Variables and functions imported from terminal.c */
|
||||
extern void _rl_output_some_chars ();
|
||||
#ifdef _MINIX
|
||||
extern void _rl_output_character_function ();
|
||||
#else
|
||||
extern int _rl_output_character_function ();
|
||||
#endif
|
||||
extern int _rl_backspace ();
|
||||
|
||||
extern char *term_clreol, *term_clrpag;
|
||||
|
|
|
@ -7,20 +7,25 @@
|
|||
@setchapternewpage odd
|
||||
|
||||
@ignore
|
||||
last change: Thu Mar 21 16:07:29 EST 1996
|
||||
last change: Thu Apr 2 14:38:22 EST 1998
|
||||
@end ignore
|
||||
|
||||
@set EDITION 2.1
|
||||
@set VERSION 2.1
|
||||
@set UPDATED 21 March 1996
|
||||
@set UPDATE-MONTH March 1996
|
||||
@set EDITION 2.2
|
||||
@set VERSION 2.2
|
||||
@set UPDATED 2 April 1998
|
||||
@set UPDATE-MONTH April 1998
|
||||
|
||||
@dircategory Libraries
|
||||
@direntry
|
||||
* History: (history). The GNU history library API
|
||||
@end direntry
|
||||
|
||||
@ifinfo
|
||||
This document describes the GNU History library, a programming tool that
|
||||
provides a consistent user interface for recalling lines of previously
|
||||
typed input.
|
||||
|
||||
Copyright (C) 1988, 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1991, 1993, 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
|
|
|
@ -29,7 +29,7 @@ into another language, under the above conditions for modified versions.
|
|||
@ifset BashFeatures
|
||||
This chapter describes how to use the GNU History Library interactively,
|
||||
from a user's standpoint. It should be considered a user's guide. For
|
||||
information on using the GNU History Library in your own programs,
|
||||
information on using the GNU History Library in other programs,
|
||||
see the GNU Readline Library Manual.
|
||||
@end ifset
|
||||
@ifclear BashFeatures
|
||||
|
@ -43,6 +43,8 @@ information on using the GNU History Library in your own programs,
|
|||
@menu
|
||||
* Bash History Facilities:: How Bash lets you manipulate your command
|
||||
history.
|
||||
* Bash History Builtins:: The Bash builtin commands that manipulate
|
||||
the command history.
|
||||
* History Interaction:: What it feels like using History as a user.
|
||||
@end menu
|
||||
@end ifset
|
||||
|
@ -84,11 +86,10 @@ not saved. After saving the history, the history file is truncated
|
|||
to contain no more than @code{$HISTFILESIZE}
|
||||
lines. If @code{HISTFILESIZE} is not set, no truncation is performed.
|
||||
|
||||
The builtin command @code{fc} (@pxref{Korn Shell Builtins})
|
||||
may be used to list or edit and re-execute a portion of
|
||||
the history list. The @code{history} builtin (@pxref{C Shell Builtins})
|
||||
can be used to display or modify the history list and
|
||||
manipulate the history file.
|
||||
The builtin command @code{fc} may be used to list or edit and re-execute
|
||||
a portion of the history list.
|
||||
The @code{history} builtin can be used to display or modify the history
|
||||
list and manipulate the history file.
|
||||
When using the command-line editing, search commands
|
||||
are available in each editing mode that provide access to the
|
||||
history list.
|
||||
|
@ -104,11 +105,103 @@ semicolons where necessary to preserve syntactic correctness.
|
|||
The @code{lithist}
|
||||
shell option causes the shell to save the command with embedded newlines
|
||||
instead of semicolons.
|
||||
@xref{Bash Builtins} for a description of @code{shopt}.
|
||||
@xref{Bash Builtins}, for a description of @code{shopt}.
|
||||
|
||||
@node Bash History Builtins
|
||||
@section Bash History Builtins
|
||||
@cindex history builtins
|
||||
|
||||
Bash provides two builtin commands that allow you to manipulate the
|
||||
history list and history file.
|
||||
|
||||
@table @code
|
||||
|
||||
@item fc
|
||||
@btindex fc
|
||||
@example
|
||||
@code{fc [-e @var{ename}] [-nlr] [@var{first}] [@var{last}]}
|
||||
@code{fc -s [@var{pat}=@var{rep}] [@var{command}]}
|
||||
@end example
|
||||
|
||||
Fix Command. In the first form, a range of commands from @var{first} to
|
||||
@var{last} is selected from the history list. Both @var{first} and
|
||||
@var{last} may be specified as a string (to locate the most recent
|
||||
command beginning with that string) or as a number (an index into the
|
||||
history list, where a negative number is used as an offset from the
|
||||
current command number). If @var{last} is not specified it is set to
|
||||
@var{first}. If @var{first} is not specified it is set to the previous
|
||||
command for editing and @minus{}16 for listing. If the @samp{-l} flag is
|
||||
given, the commands are listed on standard output. The @samp{-n} flag
|
||||
suppresses the command numbers when listing. The @samp{-r} flag
|
||||
reverses the order of the listing. Otherwise, the editor given by
|
||||
@var{ename} is invoked on a file containing those commands. If
|
||||
@var{ename} is not given, the value of the following variable expansion
|
||||
is used: @code{$@{FCEDIT:-$@{EDITOR:-vi@}@}}. This says to use the
|
||||
value of the @code{FCEDIT} variable if set, or the value of the
|
||||
@code{EDITOR} variable if that is set, or @code{vi} if neither is set.
|
||||
When editing is complete, the edited commands are echoed and executed.
|
||||
|
||||
In the second form, @var{command} is re-executed after each instance
|
||||
of @var{pat} in the selected command is replaced by @var{rep}.
|
||||
|
||||
A useful alias to use with the @code{fc} command is @code{r='fc -s'}, so
|
||||
that typing @samp{r cc} runs the last command beginning with @code{cc}
|
||||
and typing @samp{r} re-executes the last command (@pxref{Aliases}).
|
||||
|
||||
@item history
|
||||
@btindex history
|
||||
@example
|
||||
history [-c] [@var{n}]
|
||||
history [-anrw] [@var{filename}]
|
||||
history -ps @var{arg}
|
||||
@end example
|
||||
|
||||
Display the history list with line numbers. Lines prefixed with
|
||||
with a @samp{*} have been modified. An argument of @var{n} says
|
||||
to list only the last @var{n} lines. Options, if supplied, have
|
||||
the following meanings:
|
||||
|
||||
@table @code
|
||||
@item -w
|
||||
Write out the current history to the history file.
|
||||
|
||||
@item -r
|
||||
Read the current history file and append its contents to
|
||||
the history list.
|
||||
|
||||
@item -a
|
||||
Append the new
|
||||
history lines (history lines entered since the beginning of the
|
||||
current Bash session) to the history file.
|
||||
|
||||
@item -n
|
||||
Append the history lines not already read from the history file
|
||||
to the current history list. These are lines appended to the history
|
||||
file since the beginning of the current Bash session.
|
||||
|
||||
@item -c
|
||||
Clear the history list. This may be combined
|
||||
with the other options to replace the history list completely.
|
||||
|
||||
@item -s
|
||||
The @var{arg}s are added to the end of
|
||||
the history list as a single entry.
|
||||
|
||||
@item -p
|
||||
Perform history substitution on the @var{arg}s and display the result
|
||||
on the standard output, without storing the results in the history list.
|
||||
@end table
|
||||
|
||||
When the @samp{-w}, @samp{-r}, @samp{-a}, or @samp{-n} option is
|
||||
used, if @var{filename}
|
||||
is given, then it is used as the history file. If not, then
|
||||
the value of the @code{HISTFILE} variable is used.
|
||||
|
||||
@end table
|
||||
@end ifset
|
||||
|
||||
@node History Interaction
|
||||
@section Interactive History Expansion
|
||||
@section History Expansion
|
||||
@cindex history expansion
|
||||
|
||||
The History library provides a history expansion feature that is similar
|
||||
|
@ -121,14 +214,14 @@ arguments to a previous command into the current input line, or
|
|||
fix errors in previous commands quickly.
|
||||
|
||||
History expansion takes place in two parts. The first is to determine
|
||||
which line from the previous history should be used during substitution.
|
||||
which line from the history list should be used during substitution.
|
||||
The second is to select portions of that line for inclusion into the
|
||||
current one. The line selected from the previous history is called the
|
||||
current one. The line selected from the history is called the
|
||||
@dfn{event}, and the portions of that line that are acted upon are
|
||||
called @dfn{words}. Various @dfn{modifiers} are available to manipulate
|
||||
the selected words. The line is broken into words in the same fashion
|
||||
that Bash does, so that several English (or Unix) words
|
||||
surrounded by quotes are considered as one word.
|
||||
that Bash does, so that several words
|
||||
surrounded by quotes are considered one word.
|
||||
History expansions are introduced by the appearance of the
|
||||
history expansion character, which is @samp{!} by default.
|
||||
@ifset BashFeatures
|
||||
|
@ -153,6 +246,7 @@ may be used to see what a history expansion will do before using it.
|
|||
The @samp{-s} option to the @code{history} builtin may be used to
|
||||
add commands to the end of the history list without actually executing
|
||||
them, so that they are available for subsequent recall.
|
||||
This is most useful in conjunction with Readline.
|
||||
|
||||
The shell allows control of the various characters used by the
|
||||
history expansion mechanism with the @code{histchars} variable.
|
||||
|
@ -176,7 +270,7 @@ history list.
|
|||
|
||||
@item @code{!}
|
||||
Start a history substitution, except when followed by a space, tab,
|
||||
the end of the line, @key{=} or @key{(}.
|
||||
the end of the line, @samp{=} or @samp{(}.
|
||||
|
||||
@item @code{!@var{n}}
|
||||
Refer to command line @var{n}.
|
||||
|
@ -210,7 +304,7 @@ The entire command line typed so far.
|
|||
|
||||
Word designators are used to select desired words from the event.
|
||||
A @samp{:} separates the event specification from the word designator. It
|
||||
can be omitted if the word designator begins with a @samp{^}, @samp{$},
|
||||
may be omitted if the word designator begins with a @samp{^}, @samp{$},
|
||||
@samp{*}, @samp{-}, or @samp{%}. Words are numbered from the beginning
|
||||
of the line, with the first word being denoted by 0 (zero). Words are
|
||||
inserted into the current line separated by single spaces.
|
||||
|
|
|
@ -7,20 +7,25 @@
|
|||
@setchapternewpage odd
|
||||
|
||||
@ignore
|
||||
last change: Thu Mar 21 16:06:39 EST 1996
|
||||
last change: Thu Apr 2 14:39:03 EST 1998
|
||||
@end ignore
|
||||
|
||||
@set EDITION 2.1
|
||||
@set VERSION 2.1
|
||||
@set UPDATED 21 March 1996
|
||||
@set UPDATE-MONTH March 1996
|
||||
@set EDITION 2.2
|
||||
@set VERSION 2.2
|
||||
@set UPDATED 2 April 1998
|
||||
@set UPDATE-MONTH April 1998
|
||||
|
||||
@dircategory Libraries
|
||||
@direntry
|
||||
* Readline: (readline). The GNU readline library API
|
||||
@end direntry
|
||||
|
||||
@ifinfo
|
||||
This document describes the GNU Readline Library, a utility which aids
|
||||
in the consistency of user interface across discrete programs that need
|
||||
to provide a command line interface.
|
||||
|
||||
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1991, 1993, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
|
|
|
@ -454,6 +454,14 @@ Bind @var{key} to the null function in @var{map}.
|
|||
Returns non-zero in case of error.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int rl_unbind_function_in_map (Function *function, Keymap map)
|
||||
Unbind all keys that execute @var{function} in @var{map}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int rl_unbind_command_in_map (char *command, Keymap map)
|
||||
Unbind all keys that are bound to @var{command} in @var{map}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int rl_generic_bind (int type, char *keyseq, char *data, Keymap map)
|
||||
Bind the key sequence represented by the string @var{keyseq} to the arbitrary
|
||||
pointer @var{data}. @var{type} says what kind of data is pointed to by
|
||||
|
@ -1034,7 +1042,7 @@ unless they also appear within this list.
|
|||
|
||||
@deftypevar {char *} rl_filename_quote_characters
|
||||
A list of characters that cause a filename to be quoted by the completer
|
||||
when they appear in a completed filename. The default is empty.
|
||||
when they appear in a completed filename. The default is the null string.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {char *} rl_special_prefixes
|
||||
|
|
|
@ -135,7 +135,7 @@ Delete the character underneath the cursor.
|
|||
@item @w{Printing characters}
|
||||
Insert the character into the line at the cursor.
|
||||
@item @key{C-_}
|
||||
Undo the last thing that you did. You can undo all the way back to an
|
||||
Undo the last editing command. You can undo all the way back to an
|
||||
empty line.
|
||||
@end table
|
||||
|
||||
|
@ -155,7 +155,7 @@ Move to the start of the line.
|
|||
@item C-e
|
||||
Move to the end of the line.
|
||||
@item M-f
|
||||
Move forward a word.
|
||||
Move forward a word, where a word is composed of letters and digits.
|
||||
@item M-b
|
||||
Move backward a word.
|
||||
@item C-l
|
||||
|
@ -207,7 +207,7 @@ Kill from the cursor to the previous whitespace. This is different than
|
|||
|
||||
@end table
|
||||
|
||||
And, here is how to @dfn{yank} the text back into the line. Yanking
|
||||
Here is how to @dfn{yank} the text back into the line. Yanking
|
||||
means to copy the most-recently-killed text from the kill buffer.
|
||||
|
||||
@table @key
|
||||
|
@ -227,10 +227,10 @@ argument acts as a repeat count, other times it is the @i{sign} of the
|
|||
argument that is significant. If you pass a negative argument to a
|
||||
command which normally acts in a forward direction, that command will
|
||||
act in a backward direction. For example, to kill text back to the
|
||||
start of the line, you might type @w{@kbd{M-- C-k}}.
|
||||
start of the line, you might type @samp{M-- C-k}.
|
||||
|
||||
The general way to pass numeric arguments to a command is to type meta
|
||||
digits before the command. If the first `digit' you type is a minus
|
||||
digits before the command. If the first `digit' typed is a minus
|
||||
sign (@key{-}), then the sign of the argument will be negative. Once
|
||||
you have typed one meta digit to get the argument started, you can type
|
||||
the remainder of the digits, and then the command. For example, to give
|
||||
|
@ -248,38 +248,38 @@ There are two search modes: @var{incremental} and @var{non-incremental}.
|
|||
|
||||
Incremental searches begin before the user has finished typing the
|
||||
search string.
|
||||
As each character of the search string is typed, readline displays
|
||||
As each character of the search string is typed, Readline displays
|
||||
the next entry from the history matching the string typed so far.
|
||||
An incremental search requires only as many characters as needed to
|
||||
find the desired history entry.
|
||||
The Escape character is used to terminate an incremental search.
|
||||
Control-J will also terminate the search.
|
||||
Control-G will abort an incremental search and restore the original
|
||||
line.
|
||||
The @key{ESC} character is used to terminate an incremental search.
|
||||
@key{C-j} will also terminate the search.
|
||||
@key{C-g} will abort an incremental search and restore the original line.
|
||||
When the search is terminated, the history entry containing the
|
||||
search string becomes the current line.
|
||||
To find other matching entries in the history list, type Control-S or
|
||||
Control-R as appropriate.
|
||||
To find other matching entries in the history list, type @key{C-s} or
|
||||
@key{C-r} as appropriate.
|
||||
This will search backward or forward in the history for the next
|
||||
entry matching the search string typed so far.
|
||||
Any other key sequence bound to a readline command will terminate
|
||||
Any other key sequence bound to a Readline command will terminate
|
||||
the search and execute that command.
|
||||
For instance, a @code{newline} will terminate the search and accept
|
||||
For instance, a @key{RET} will terminate the search and accept
|
||||
the line, thereby executing the command from the history list.
|
||||
|
||||
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 part of the contents of the current line.
|
||||
typed by the user or be part of the contents of the current line.
|
||||
|
||||
@node Readline Init File
|
||||
@section Readline Init File
|
||||
@cindex initialization file, readline
|
||||
|
||||
Although the Readline library comes with a set of @code{emacs}-like
|
||||
keybindings installed by default,
|
||||
it is possible that you would like to use a different set
|
||||
of keybindings. You can customize programs that use Readline by putting
|
||||
commands in an @dfn{inputrc} file in your home directory. The name of this
|
||||
keybindings installed by default, it is possible to use a different set
|
||||
of keybindings.
|
||||
Any user can customize programs that use Readline by putting
|
||||
commands in an @dfn{inputrc} file in his home directory.
|
||||
The name of this
|
||||
@ifset BashFeatures
|
||||
file is taken from the value of the shell variable @code{INPUTRC}. If
|
||||
@end ifset
|
||||
|
@ -314,16 +314,18 @@ denote variable settings and key bindings.
|
|||
|
||||
@table @asis
|
||||
@item Variable Settings
|
||||
You can change the state of a few variables in Readline by
|
||||
using the @code{set} command within the init file. Here is how you
|
||||
would specify that you wish to use @code{vi} line editing commands:
|
||||
You can modify the run-time behavior of Readline by
|
||||
altering the values of variables in Readline
|
||||
using the @code{set} command within the init file. Here is how to
|
||||
change from the default Emacs-like key binding to use
|
||||
@code{vi} line editing commands:
|
||||
|
||||
@example
|
||||
set editing-mode vi
|
||||
@end example
|
||||
|
||||
Right now, there are only a few variables which can be set;
|
||||
so few, in fact, that we just list them here:
|
||||
A great deal of run-time behavior is changeable with the following
|
||||
variables.
|
||||
|
||||
@table @code
|
||||
|
||||
|
@ -341,6 +343,11 @@ The string to insert at the beginning of the line when the
|
|||
@code{insert-comment} command is executed. The default value
|
||||
is @code{"#"}.
|
||||
|
||||
@item completion-ignore-case
|
||||
If set to @samp{on}, Readline performs filename matching and completion
|
||||
in a case-insensitive fashion.
|
||||
The default value is @samp{off}.
|
||||
|
||||
@item completion-query-items
|
||||
@vindex completion-query-items
|
||||
The number of possible completions that determines when the user is
|
||||
|
@ -353,26 +360,26 @@ them; otherwise, they are simply listed. The default limit is
|
|||
@item convert-meta
|
||||
@vindex convert-meta
|
||||
If set to @samp{on}, Readline will convert characters with the
|
||||
eigth bit set to an ASCII key sequence by stripping the eigth
|
||||
eighth bit set to an ASCII key sequence by stripping the eighth
|
||||
bit and prepending an @key{ESC} character, converting them to a
|
||||
meta-prefixed key sequence. The default value is @samp{on}.
|
||||
|
||||
@item disable-completion
|
||||
@vindex disable-completion
|
||||
If set to @samp{On}, readline will inhibit word completion.
|
||||
If set to @samp{On}, Readline will inhibit word completion.
|
||||
Completion characters will be inserted into the line as if they had
|
||||
been mapped to @code{self-insert}. The default is @samp{off}.
|
||||
|
||||
@item editing-mode
|
||||
@vindex editing-mode
|
||||
The @code{editing-mode} variable controls which editing mode you are
|
||||
using. By default, Readline starts up in Emacs editing mode, where
|
||||
the keystrokes are most similar to Emacs. This variable can be
|
||||
The @code{editing-mode} variable controls which default set of
|
||||
key bindings is used. By default, Readline starts up in Emacs editing
|
||||
mode, where the keystrokes are most similar to Emacs. This variable can be
|
||||
set to either @samp{emacs} or @samp{vi}.
|
||||
|
||||
@item enable-keypad
|
||||
@vindex enable-keypad
|
||||
When set to @samp{on}, readline will try to enable the application
|
||||
When set to @samp{on}, Readline will try to enable the application
|
||||
keypad when it is called. Some systems need this to enable the
|
||||
arrow keys. The default is @samp{off}.
|
||||
|
||||
|
@ -384,7 +391,7 @@ attempts word completion. The default is @samp{off}.
|
|||
@item horizontal-scroll-mode
|
||||
@vindex horizontal-scroll-mode
|
||||
This variable can be set to either @samp{on} or @samp{off}. Setting it
|
||||
to @samp{on} means that the text of the lines that you edit will scroll
|
||||
to @samp{on} means that the text of the lines being edited will scroll
|
||||
horizontally on a single screen line when they are longer than the width
|
||||
of the screen, instead of wrapping onto a new screen line. By default,
|
||||
this variable is set to @samp{off}.
|
||||
|
@ -411,8 +418,8 @@ appended. The default is @samp{on}.
|
|||
|
||||
@item mark-modified-lines
|
||||
@vindex mark-modified-lines
|
||||
This variable, when set to @samp{on}, says to display an asterisk
|
||||
(@samp{*}) at the start of history lines which have been modified.
|
||||
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 input-meta
|
||||
|
@ -430,6 +437,11 @@ If set to @samp{on}, Readline will display characters with the
|
|||
eighth bit set directly rather than as a meta-prefixed escape
|
||||
sequence. The default is @samp{off}.
|
||||
|
||||
@item print-completions-horizontally
|
||||
If set to @samp{on}, Readline will display completions with matches
|
||||
sorted horizontally in alphabetical order, rather than down the screen.
|
||||
The default is @samp{off}.
|
||||
|
||||
@item show-all-if-ambiguous
|
||||
@vindex show-all-if-ambiguous
|
||||
This alters the default behavior of the completion functions. If
|
||||
|
@ -449,9 +461,9 @@ completions. The default is @samp{off}.
|
|||
@item Key Bindings
|
||||
The syntax for controlling key bindings in the init file is
|
||||
simple. First you have to know the name of the command that you
|
||||
want to change. The following pages contain tables of the command name,
|
||||
the default keybinding, and a short description of what the command
|
||||
does.
|
||||
want to change. The following sections contain tables of the command
|
||||
name, the default keybinding, if any, and a short description of what
|
||||
the command does.
|
||||
|
||||
Once you know the name of the command, simply place the name of the key
|
||||
you wish to bind the command to, a colon, and then the name of the
|
||||
|
@ -468,8 +480,8 @@ Meta-Rubout: backward-kill-word
|
|||
Control-o: "> output"
|
||||
@end example
|
||||
|
||||
In the above example, @samp{C-u} is bound to the function
|
||||
@code{universal-argument}, and @samp{C-o} is bound to run the macro
|
||||
In the above example, @key{C-u} is bound to the function
|
||||
@code{universal-argument}, and @key{C-o} is bound to run the macro
|
||||
expressed on the right hand side (that is, to insert the text
|
||||
@samp{> output} into the line).
|
||||
|
||||
|
@ -486,12 +498,16 @@ special character names are not recognized.
|
|||
"\e[11~": "Function Key 1"
|
||||
@end example
|
||||
|
||||
In the above example, @samp{C-u} is bound to the function
|
||||
In the above example, @key{C-u} is bound to the function
|
||||
@code{universal-argument} (just as it was in the first example),
|
||||
@samp{C-x C-r} is bound to the function @code{re-read-init-file}, and
|
||||
@samp{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}.
|
||||
The following escape sequences are available when specifying key
|
||||
sequences:
|
||||
@samp{@key{C-x} @key{C-r}} is bound to the function @code{re-read-init-file},
|
||||
and @samp{@key{ESC} @key{[} @key{1} @key{1} @key{~}} is bound to insert
|
||||
the text @samp{Function Key 1}.
|
||||
|
||||
@end table
|
||||
|
||||
The following GNU Emacs style escape sequences are available when
|
||||
specifying key sequences:
|
||||
|
||||
@table @code
|
||||
@item @kbd{\C-}
|
||||
|
@ -508,18 +524,46 @@ backslash
|
|||
@key{'}
|
||||
@end table
|
||||
|
||||
When entering the text of a macro, single or double quotes should
|
||||
be used to indicate a macro definition. Unquoted text
|
||||
is assumed to be a function name. Backslash
|
||||
will quote any character in the macro text, including @samp{"}
|
||||
and @samp{'}.
|
||||
In addition to the GNU Emacs style escape sequences, a second
|
||||
set of backslash escapes is available:
|
||||
|
||||
@table @code
|
||||
@item \a
|
||||
alert (bell)
|
||||
@item \b
|
||||
backspace
|
||||
@item \d
|
||||
delete
|
||||
@item \f
|
||||
form feed
|
||||
@item \n
|
||||
newline
|
||||
@item \r
|
||||
carriage return
|
||||
@item \t
|
||||
horizontal tab
|
||||
@item \v
|
||||
vertical tab
|
||||
@item \@var{nnn}
|
||||
the character whose ASCII code is the octal value @var{nnn}
|
||||
(one to three digits)
|
||||
@item \x@var{nnn}
|
||||
the character whose ASCII code is the hexadecimal value @var{nnn}
|
||||
(one to three digits)
|
||||
@end table
|
||||
|
||||
When entering the text of a macro, single or double quotes must
|
||||
be used to indicate a macro definition.
|
||||
Unquoted text is assumed to be a function name.
|
||||
In the macro body, the backslash escapes described above are expanded.
|
||||
Backslash will quote any other character in the macro text,
|
||||
including @samp{"} and @samp{'}.
|
||||
For example, the following binding will make @samp{C-x \}
|
||||
insert a single @samp{\} into the line:
|
||||
@example
|
||||
"\C-x\\": "\\"
|
||||
@end example
|
||||
|
||||
@end table
|
||||
@end table
|
||||
|
||||
@node Conditional Init Constructs
|
||||
|
@ -528,7 +572,7 @@ insert a single @samp{\} into the line:
|
|||
Readline implements a facility similar in spirit to the conditional
|
||||
compilation features of the C preprocessor which allows key
|
||||
bindings and variable settings to be performed as the result
|
||||
of tests. There are three parser directives used.
|
||||
of tests. There are four parser directives used.
|
||||
|
||||
@table @code
|
||||
@item $if
|
||||
|
@ -550,8 +594,8 @@ Readline is starting out in @code{emacs} mode.
|
|||
The @code{term=} form may be used to include terminal-specific
|
||||
key bindings, perhaps to bind the key sequences output by the
|
||||
terminal's function keys. The word on the right side of the
|
||||
@samp{=} is tested against the full name of the terminal and the
|
||||
portion of the terminal name before the first @samp{-}. This
|
||||
@samp{=} is tested against both the full name of the terminal and
|
||||
the portion of the terminal name before the first @samp{-}. This
|
||||
allows @code{sun} to match both @code{sun} and @code{sun-cmd},
|
||||
for instance.
|
||||
|
||||
|
@ -571,12 +615,19 @@ $endif
|
|||
@end table
|
||||
|
||||
@item $endif
|
||||
This command, as you saw in the previous example, terminates an
|
||||
This command, as seen in the previous example, terminates an
|
||||
@code{$if} command.
|
||||
|
||||
@item $else
|
||||
Commands in this branch of the @code{$if} directive are executed if
|
||||
the test fails.
|
||||
|
||||
@item $include
|
||||
This directive takes a single filename as an argument and reads commands
|
||||
and bindings from that file.
|
||||
@example
|
||||
$include /etc/inputrc
|
||||
@end example
|
||||
@end table
|
||||
|
||||
@node Sample Init File
|
||||
|
@ -593,6 +644,11 @@ binding, variable assignment, and conditional syntax.
|
|||
#
|
||||
# You can re-read the inputrc file with C-x C-r.
|
||||
# Lines beginning with '#' are comments.
|
||||
#
|
||||
# First, include any systemwide bindings and variable assignments from
|
||||
# /etc/Inputrc
|
||||
$include /etc/Inputrc
|
||||
|
||||
#
|
||||
# Set various bindings for emacs mode.
|
||||
|
||||
|
@ -738,8 +794,9 @@ Refresh the current line. By default, this is unbound.
|
|||
@ifset BashFeatures
|
||||
Accept the line regardless of where the cursor is. If this line is
|
||||
non-empty, add it to the history list according to the setting of
|
||||
the @code{HISTCONTROL} variable. If this line was a history
|
||||
line, then restore the history line to its original state.
|
||||
the @code{HISTCONTROL} and @code{HISTIGNORE} variables.
|
||||
If this line was a history line, then restore the history line to its
|
||||
original state.
|
||||
@end ifset
|
||||
@ifclear BashFeatures
|
||||
Accept the line regardless of where the cursor is. If this line is
|
||||
|
@ -757,7 +814,8 @@ Move `down' through the history list.
|
|||
Move to the first line in the history.
|
||||
|
||||
@item end-of-history (M->)
|
||||
Move to the end of the input history, i.e., the line you are entering.
|
||||
Move to the end of the input history, i.e., the line currently
|
||||
being entered.
|
||||
|
||||
@item reverse-search-history (C-r)
|
||||
Search backward starting at the current line and moving `up' through
|
||||
|
@ -780,7 +838,7 @@ for a string supplied by the user.
|
|||
@item history-search-forward ()
|
||||
Search forward through the history for the string of characters
|
||||
between the start of the current line and the current cursor
|
||||
position (the `point'). This is a non-incremental search. By
|
||||
position (the @var{point}). This is a non-incremental search. By
|
||||
default, this command is unbound.
|
||||
|
||||
@item history-search-backward ()
|
||||
|
@ -799,6 +857,8 @@ inserts the @var{n}th word from the end of the previous command.
|
|||
Insert last argument to the previous command (the last word of the
|
||||
previous history entry). With an
|
||||
argument, behave exactly like @code{yank-nth-arg}.
|
||||
Successive calls to @code{yank-last-arg} move back through the history
|
||||
list, inserting the last argument of each line in turn.
|
||||
|
||||
@end ftable
|
||||
|
||||
|
@ -809,18 +869,21 @@ argument, behave exactly like @code{yank-nth-arg}.
|
|||
@item delete-char (C-d)
|
||||
Delete the character under the cursor. If the cursor is at the
|
||||
beginning of the line, there are no characters in the line, and
|
||||
the last character typed was not @kbd{C-d}, then return @code{EOF}.
|
||||
the last character typed was not bound to @code{delete-char}, then
|
||||
return @code{EOF}.
|
||||
|
||||
@item backward-delete-char (Rubout)
|
||||
Delete the character behind the cursor. A numeric arg says to kill
|
||||
the characters instead of deleting them.
|
||||
Delete the character behind the cursor. A numeric argument means
|
||||
to kill the characters instead of deleting them.
|
||||
|
||||
@item quoted-insert (C-q, C-v)
|
||||
Add the next character that you type to the line verbatim. This is
|
||||
Add the next character typed to the line verbatim. This is
|
||||
how to insert key sequences like @key{C-q}, for example.
|
||||
|
||||
@ifclear BashFeatures
|
||||
@item tab-insert (M-TAB)
|
||||
Insert a tab character.
|
||||
@end ifclear
|
||||
|
||||
@item self-insert (a, b, A, 1, !, ...)
|
||||
Insert yourself.
|
||||
|
@ -831,7 +894,7 @@ the character at the cursor, moving the
|
|||
cursor forward as well. If the insertion point
|
||||
is at the end of the line, then this
|
||||
transposes the last two characters of the line.
|
||||
Negative argumentss don't work.
|
||||
Negative arguments don't work.
|
||||
|
||||
@item transpose-words (M-t)
|
||||
Drag the word behind the cursor past the word in front of the cursor
|
||||
|
@ -839,15 +902,15 @@ moving the cursor over that word as well.
|
|||
|
||||
@item upcase-word (M-u)
|
||||
Uppercase the current (or following) word. With a negative argument,
|
||||
do the previous word, but do not move the cursor.
|
||||
uppercase the previous word, but do not move the cursor.
|
||||
|
||||
@item downcase-word (M-l)
|
||||
Lowercase the current (or following) word. With a negative argument,
|
||||
do the previous word, but do not move the cursor.
|
||||
lowercase the previous word, but do not move the cursor.
|
||||
|
||||
@item capitalize-word (M-c)
|
||||
Capitalize the current (or following) word. With a negative argument,
|
||||
do the previous word, but do not move the cursor.
|
||||
capitalize the previous word, but do not move the cursor.
|
||||
|
||||
@end ftable
|
||||
|
||||
|
@ -864,7 +927,7 @@ Kill backward to the beginning of the line.
|
|||
|
||||
@item unix-line-discard (C-u)
|
||||
Kill backward from the cursor to the beginning of the current line.
|
||||
Save the killed text on the kill-ring.
|
||||
The killed text is saved on the kill-ring.
|
||||
|
||||
@item kill-whole-line ()
|
||||
Kill all characters on the current line, no matter where the
|
||||
|
@ -888,19 +951,21 @@ Delete all spaces and tabs around point. By default, this is unbound.
|
|||
|
||||
@item kill-region ()
|
||||
Kill the text between the point and the @emph{mark} (saved
|
||||
cursor position. This text is referred to as the @var{region}.
|
||||
cursor position). This text is referred to as the @var{region}.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item copy-region-as-kill ()
|
||||
Copy the text in the region to the kill buffer, so you can yank it
|
||||
Copy the text in the region to the kill buffer, so it can be yanked
|
||||
right away. By default, this command is unbound.
|
||||
|
||||
@item copy-backward-word ()
|
||||
Copy the word before point to the kill buffer.
|
||||
The word boundaries are the same as @code{backward-word}.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item copy-forward-word ()
|
||||
Copy the word following point to the kill buffer.
|
||||
The word boundaries are the same as @code{forward-word}.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item yank (C-y)
|
||||
|
@ -943,8 +1008,8 @@ By default, this is not bound to a key.
|
|||
Attempt to do completion on the text before the cursor. This is
|
||||
application-specific. Generally, if you are typing a filename
|
||||
argument, you can do filename completion; if you are typing a command,
|
||||
you can do command completion, if you are typing in a symbol to GDB, you
|
||||
can do symbol name completion, if you are typing in a variable to Bash,
|
||||
you can do command completion; if you are typing in a symbol to GDB, you
|
||||
can do symbol name completion; if you are typing in a variable to Bash,
|
||||
you can do variable name completion, and so on.
|
||||
@ifset BashFeatures
|
||||
Bash attempts completion treating the text as a variable (if the
|
||||
|
@ -961,6 +1026,19 @@ List the possible completions of the text before the cursor.
|
|||
Insert all completions of the text before point that would have
|
||||
been generated by @code{possible-completions}.
|
||||
|
||||
@item menu-complete ()
|
||||
Similar to @code{complete}, but replaces the word to be completed
|
||||
with a single match from the list of possible completions.
|
||||
Repeated execution of @code{menu-complete} steps through the list
|
||||
of possible completions, inserting each match in turn.
|
||||
At the end of the list of completions, the bell is rung and the
|
||||
original text is restored.
|
||||
An argument of @var{n} moves @var{n} positions forward in the list
|
||||
of matches; a negative argument may be used to move backward
|
||||
through the list.
|
||||
This command is intended to be bound to @code{TAB}, but is unbound
|
||||
by default.
|
||||
|
||||
@ifset BashFeatures
|
||||
@item complete-filename (M-/)
|
||||
Attempt filename completion on the text before point.
|
||||
|
@ -997,7 +1075,7 @@ treating it as a hostname.
|
|||
Attempt completion on the text before point, treating
|
||||
it as a command name. Command completion attempts to
|
||||
match the text against aliases, reserved words, shell
|
||||
functions, builtins, and finally executable filenames,
|
||||
functions, shell builtins, and finally executable filenames,
|
||||
in that order.
|
||||
|
||||
@item possible-command-completions (C-x !)
|
||||
|
@ -1052,7 +1130,7 @@ If the metafied character @var{x} is lowercase, run the command
|
|||
that is bound to the corresponding uppercase character.
|
||||
|
||||
@item prefix-meta (ESC)
|
||||
Make the next character that you type be metafied. This is for people
|
||||
Make the next character typed be metafied. This is for keyboards
|
||||
without a meta key. Typing @samp{ESC f} is equivalent to typing
|
||||
@samp{M-f}.
|
||||
|
||||
|
@ -1060,7 +1138,7 @@ without a meta key. Typing @samp{ESC f} is equivalent to typing
|
|||
Incremental undo, separately remembered for each line.
|
||||
|
||||
@item revert-line (M-r)
|
||||
Undo all changes made to this line. This is like typing the @code{undo}
|
||||
Undo all changes made to this line. This is like executing the @code{undo}
|
||||
command enough times to get back to the beginning.
|
||||
|
||||
@item tilde-expand (M-~)
|
||||
|
@ -1093,18 +1171,18 @@ This makes the current line a shell comment.
|
|||
|
||||
@item dump-functions ()
|
||||
Print all of the functions and their key bindings to the
|
||||
readline output stream. If a numeric argument is supplied,
|
||||
Readline output stream. If a numeric argument is supplied,
|
||||
the output is formatted in such a way that it can be made part
|
||||
of an @var{inputrc} file. This command is unbound by default.
|
||||
|
||||
@item dump-variables ()
|
||||
Print all of the settable variables and their values to the
|
||||
readline output stream. If a numeric argument is supplied,
|
||||
Readline output stream. If a numeric argument is supplied,
|
||||
the output is formatted in such a way that it can be made part
|
||||
of an @var{inputrc} file. This command is unbound by default.
|
||||
|
||||
@item dump-macros ()
|
||||
Print all of the readline key sequences bound to macros and the
|
||||
Print all of the Readline key sequences bound to macros and the
|
||||
strings they ouput. If a numeric argument is supplied,
|
||||
the output is formatted in such a way that it can be made part
|
||||
of an @var{inputrc} file. This command is unbound by default.
|
||||
|
@ -1116,24 +1194,27 @@ and the list of matching file names is inserted, replacing the word.
|
|||
|
||||
@item glob-list-expansions (C-x g)
|
||||
The list of expansions that would have been generated by
|
||||
@code{glob-expand-word}
|
||||
is inserted into the line, replacing the word before point.
|
||||
@code{glob-expand-word} is displayed, and the line is redrawn.
|
||||
|
||||
@item display-shell-version (C-x C-v)
|
||||
Display version information about the current instance of Bash.
|
||||
|
||||
@item shell-expand-line (M-C-e)
|
||||
Expand the line the way the shell does when it reads it. This
|
||||
performs alias and history expansion as well as all of the shell
|
||||
word expansions.
|
||||
Expand the line as the shell does.
|
||||
This performs alias and history expansion as well as all of the shell
|
||||
word expansions (@pxref{Shell Expansions}).
|
||||
|
||||
@item history-expand-line (M-^)
|
||||
Perform history expansion on the current line.
|
||||
|
||||
@item alias-expand-line
|
||||
@item magic-space ()
|
||||
Perform history expansion on the current line and insert a space
|
||||
(@pxref{History Interaction}).
|
||||
|
||||
@item alias-expand-line ()
|
||||
Perform alias expansion on the current line (@pxref{Aliases}).
|
||||
|
||||
@item history-and-alias-expand-line
|
||||
@item history-and-alias-expand-line ()
|
||||
Perform history and alias expansion on the current line.
|
||||
|
||||
@item insert-last-argument (M-., M-_)
|
||||
|
|
|
@ -19,12 +19,16 @@
|
|||
#include "readline.h"
|
||||
#include "history.h"
|
||||
|
||||
extern HIST_ENTRY **history_list ();
|
||||
|
||||
main ()
|
||||
{
|
||||
HIST_ENTRY **history_list ();
|
||||
char *temp = (char *)NULL;
|
||||
char *prompt = "readline$ ";
|
||||
int done = 0;
|
||||
char *temp, *prompt;
|
||||
int done;
|
||||
|
||||
temp = (char *)NULL;
|
||||
prompt = "readline$ ";
|
||||
done = 0;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
|
@ -47,18 +51,17 @@ main ()
|
|||
|
||||
if (strcmp (temp, "list") == 0)
|
||||
{
|
||||
HIST_ENTRY **list = history_list ();
|
||||
HIST_ENTRY **list;
|
||||
register int i;
|
||||
|
||||
list = history_list ();
|
||||
if (list)
|
||||
{
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
|
||||
free (list[i]->line);
|
||||
}
|
||||
free (list);
|
||||
fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
|
||||
}
|
||||
}
|
||||
free (temp);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
|
|
@ -94,11 +94,15 @@ static FUNMAP default_funmap[] = {
|
|||
{ "kill-line", rl_kill_line },
|
||||
{ "kill-region", rl_kill_region },
|
||||
{ "kill-word", rl_kill_word },
|
||||
{ "menu-complete", rl_menu_complete },
|
||||
{ "next-history", rl_get_next_history },
|
||||
{ "non-incremental-forward-search-history", rl_noninc_forward_search },
|
||||
{ "non-incremental-reverse-search-history", rl_noninc_reverse_search },
|
||||
{ "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
|
||||
{ "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
|
||||
#ifdef __CYGWIN32__
|
||||
{ "paste-from-clipboard", rl_paste_from_clipboard },
|
||||
#endif
|
||||
{ "possible-completions", rl_possible_completions },
|
||||
{ "previous-history", rl_get_previous_history },
|
||||
{ "quoted-insert", rl_quoted_insert },
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifndef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
@ -47,6 +50,9 @@
|
|||
#include "history.h"
|
||||
#include "histlib.h"
|
||||
|
||||
#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
|
||||
#define HISTORY_QUOTE_CHARACTERS "\"'`"
|
||||
|
||||
static char error_pointer;
|
||||
|
||||
static char *subst_lhs;
|
||||
|
@ -823,8 +829,8 @@ history_expand (hstring, output)
|
|||
only_printing = modified = 0;
|
||||
l = strlen (hstring);
|
||||
|
||||
/* Grovel the string. Only backslash can quote the history escape
|
||||
character. We also handle arg specifiers. */
|
||||
/* Grovel the string. Only backslash and single quotes can quote the
|
||||
history escape character. We also handle arg specifiers. */
|
||||
|
||||
/* Before we grovel forever, see if the history_expansion_char appears
|
||||
anywhere within the text. */
|
||||
|
@ -852,7 +858,18 @@ history_expand (hstring, output)
|
|||
for (i = 0; string[i]; i++)
|
||||
{
|
||||
cc = string[i + 1];
|
||||
if (string[i] == history_expansion_char)
|
||||
/* The history_comment_char, if set, appearing that the beginning
|
||||
of a word signifies that the rest of the line should not have
|
||||
history expansion performed on it.
|
||||
Skip the rest of the line and break out of the loop. */
|
||||
if (history_comment_char && string[i] == history_comment_char &&
|
||||
(i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS)))
|
||||
{
|
||||
while (string[i])
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
else if (string[i] == history_expansion_char)
|
||||
{
|
||||
if (!cc || member (cc, history_no_expand_chars))
|
||||
continue;
|
||||
|
@ -867,6 +884,8 @@ history_expand (hstring, output)
|
|||
else
|
||||
break;
|
||||
}
|
||||
/* XXX - at some point, might want to extend this to handle
|
||||
double quotes as well. */
|
||||
else if (history_quotes_inhibit_expansion && string[i] == '\'')
|
||||
{
|
||||
/* If this is bash, single quotes inhibit history expansion. */
|
||||
|
@ -904,6 +923,8 @@ history_expand (hstring, output)
|
|||
|
||||
if (tchar == history_expansion_char)
|
||||
tchar = -3;
|
||||
else if (tchar == history_comment_char)
|
||||
tchar = -2;
|
||||
|
||||
switch (tchar)
|
||||
{
|
||||
|
@ -939,6 +960,19 @@ history_expand (hstring, output)
|
|||
break;
|
||||
}
|
||||
|
||||
case -2: /* history_comment_char */
|
||||
if (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS))
|
||||
{
|
||||
temp = xmalloc (l - i + 1);
|
||||
strcpy (temp, string + i);
|
||||
ADD_STRING (temp);
|
||||
free (temp);
|
||||
i = l;
|
||||
}
|
||||
else
|
||||
ADD_CHAR (string[i]);
|
||||
break;
|
||||
|
||||
case -3: /* history_expansion_char */
|
||||
cc = string[i + 1];
|
||||
|
||||
|
@ -1238,7 +1272,7 @@ history_tokenize_internal (string, wind, indp)
|
|||
|
||||
/* Get word from string + i; */
|
||||
|
||||
if (member (string[i], "\"'`"))
|
||||
if (member (string[i], HISTORY_QUOTE_CHARACTERS))
|
||||
delimiter = string[i++];
|
||||
|
||||
for (; string[i]; i++)
|
||||
|
@ -1262,10 +1296,10 @@ history_tokenize_internal (string, wind, indp)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!delimiter && (member (string[i], " \t\n;&()|<>")))
|
||||
if (!delimiter && (member (string[i], HISTORY_WORD_DELIMITERS)))
|
||||
break;
|
||||
|
||||
if (!delimiter && member (string[i], "\"'`"))
|
||||
if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
|
||||
delimiter = string[i];
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#ifndef _MINIX
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
@ -129,19 +131,31 @@ read_history_range (filename, from, to)
|
|||
int from, to;
|
||||
{
|
||||
register int line_start, line_end;
|
||||
char *input, *buffer = (char *)NULL;
|
||||
char *input, *buffer;
|
||||
int file, current_line;
|
||||
struct stat finfo;
|
||||
size_t file_size;
|
||||
|
||||
buffer = (char *)NULL;
|
||||
input = history_filename (filename);
|
||||
file = open (input, O_RDONLY|O_BINARY, 0666);
|
||||
|
||||
if ((file < 0) || (fstat (file, &finfo) == -1))
|
||||
goto error_and_exit;
|
||||
|
||||
buffer = xmalloc ((int)finfo.st_size + 1);
|
||||
file_size = (size_t)finfo.st_size;
|
||||
|
||||
if (read (file, buffer, finfo.st_size) != finfo.st_size)
|
||||
/* check for overflow on very large files */
|
||||
if (file_size != finfo.st_size || file_size + 1 < file_size)
|
||||
{
|
||||
#if defined (EFBIG)
|
||||
errno = EFBIG;
|
||||
#endif
|
||||
goto error_and_exit;
|
||||
}
|
||||
|
||||
buffer = xmalloc (file_size + 1);
|
||||
if (read (file, buffer, file_size) != file_size)
|
||||
{
|
||||
error_and_exit:
|
||||
if (file >= 0)
|
||||
|
@ -157,15 +171,15 @@ read_history_range (filename, from, to)
|
|||
|
||||
/* Set TO to larger than end of file if negative. */
|
||||
if (to < 0)
|
||||
to = finfo.st_size;
|
||||
to = file_size;
|
||||
|
||||
/* Start at beginning of file, work to end. */
|
||||
line_start = line_end = current_line = 0;
|
||||
|
||||
/* Skip lines until we are at FROM. */
|
||||
while (line_start < finfo.st_size && current_line < from)
|
||||
while (line_start < file_size && current_line < from)
|
||||
{
|
||||
for (line_end = line_start; line_end < finfo.st_size; line_end++)
|
||||
for (line_end = line_start; line_end < file_size; line_end++)
|
||||
if (buffer[line_end] == '\n')
|
||||
{
|
||||
current_line++;
|
||||
|
@ -176,7 +190,7 @@ read_history_range (filename, from, to)
|
|||
}
|
||||
|
||||
/* If there are lines left to gobble, then gobble them now. */
|
||||
for (line_end = line_start; line_end < finfo.st_size; line_end++)
|
||||
for (line_end = line_start; line_end < file_size; line_end++)
|
||||
if (buffer[line_end] == '\n')
|
||||
{
|
||||
buffer[line_end] = '\0';
|
||||
|
@ -209,6 +223,7 @@ history_truncate_file (fname, lines)
|
|||
int file, chars_read;
|
||||
char *buffer, *filename;
|
||||
struct stat finfo;
|
||||
size_t file_size;
|
||||
|
||||
buffer = (char *)NULL;
|
||||
filename = history_filename (fname);
|
||||
|
@ -217,8 +232,20 @@ history_truncate_file (fname, lines)
|
|||
if (file == -1 || fstat (file, &finfo) == -1)
|
||||
goto truncate_exit;
|
||||
|
||||
buffer = xmalloc ((int)finfo.st_size + 1);
|
||||
chars_read = read (file, buffer, finfo.st_size);
|
||||
file_size = (size_t)finfo.st_size;
|
||||
|
||||
/* check for overflow on very large files */
|
||||
if (file_size != finfo.st_size || file_size + 1 < file_size)
|
||||
{
|
||||
close (file);
|
||||
#if defined (EFBIG)
|
||||
errno = EFBIG;
|
||||
#endif
|
||||
goto truncate_exit;
|
||||
}
|
||||
|
||||
buffer = xmalloc (file_size + 1);
|
||||
chars_read = read (file, buffer, file_size);
|
||||
close (file);
|
||||
|
||||
if (chars_read <= 0)
|
||||
|
@ -248,7 +275,7 @@ history_truncate_file (fname, lines)
|
|||
truncate to. */
|
||||
if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
|
||||
{
|
||||
write (file, buffer + i, finfo.st_size - i);
|
||||
write (file, buffer + i, file_size - i);
|
||||
close (file);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if defined (HAVE_STRING_H)
|
||||
|
|
|
@ -262,7 +262,7 @@ rl_search_history (direction, invoking_key)
|
|||
break;
|
||||
}
|
||||
|
||||
if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('g'))
|
||||
if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G'))
|
||||
{
|
||||
rl_execute_next (c);
|
||||
break;
|
||||
|
@ -298,6 +298,21 @@ rl_search_history (direction, invoking_key)
|
|||
free (lines);
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
/* delete character from search string. */
|
||||
case -3:
|
||||
if (search_string_index == 0)
|
||||
ding ();
|
||||
else
|
||||
{
|
||||
search_string[--search_string_index] = '\0';
|
||||
/* This is tricky. To do this right, we need to keep a
|
||||
stack of search positions for the current search, with
|
||||
sentinels marking the beginning and end. */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
/* Add character to search string and continue search. */
|
||||
if (search_string_index + 2 >= search_string_size)
|
||||
|
|
|
@ -39,9 +39,9 @@ typedef char **CPPFunction ();
|
|||
|
||||
/* A keymap contains one entry for each key in the ASCII set.
|
||||
Each entry consists of a type and a pointer.
|
||||
POINTER is the address of a function to run, or the
|
||||
FUNCTION is the address of a function to run, or the
|
||||
address of a keymap to indirect through.
|
||||
TYPE says which kind of thing POINTER is. */
|
||||
TYPE says which kind of thing FUNCTION is. */
|
||||
typedef struct _keymap_entry {
|
||||
char type;
|
||||
Function *function;
|
||||
|
|
|
@ -495,17 +495,32 @@ rl_yank_pop (count, key)
|
|||
}
|
||||
}
|
||||
|
||||
/* Yank the COUNTth argument from the previous history line. */
|
||||
int
|
||||
rl_yank_nth_arg (count, ignore)
|
||||
int count, ignore;
|
||||
/* Yank the COUNTh argument from the previous history line, skipping
|
||||
HISTORY_SKIP lines before looking for the `previous line'. */
|
||||
static int
|
||||
rl_yank_nth_arg_internal (count, ignore, history_skip)
|
||||
int count, ignore, history_skip;
|
||||
{
|
||||
register HIST_ENTRY *entry;
|
||||
char *arg;
|
||||
int i;
|
||||
|
||||
if (history_skip)
|
||||
{
|
||||
for (i = 0; i < history_skip; i++)
|
||||
entry = previous_history ();
|
||||
}
|
||||
|
||||
entry = previous_history ();
|
||||
if (entry)
|
||||
next_history ();
|
||||
{
|
||||
if (history_skip)
|
||||
{
|
||||
for (i = 0; i < history_skip; i++)
|
||||
next_history ();
|
||||
}
|
||||
next_history ();
|
||||
}
|
||||
else
|
||||
{
|
||||
ding ();
|
||||
|
@ -538,6 +553,14 @@ rl_yank_nth_arg (count, ignore)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Yank the COUNTth argument from the previous history line. */
|
||||
int
|
||||
rl_yank_nth_arg (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
return (rl_yank_nth_arg_internal (count, ignore, 0));
|
||||
}
|
||||
|
||||
/* Yank the last argument from the previous history line. This `knows'
|
||||
how rl_yank_nth_arg treats a count of `$'. With an argument, this
|
||||
behaves the same as rl_yank_nth_arg. */
|
||||
|
@ -545,8 +568,67 @@ int
|
|||
rl_yank_last_arg (count, key)
|
||||
int count, key;
|
||||
{
|
||||
if (rl_explicit_arg)
|
||||
return (rl_yank_nth_arg (count, key));
|
||||
static int history_skip = 0;
|
||||
static int explicit_arg_p = 0;
|
||||
static int count_passed = 1;
|
||||
static int direction = 1;
|
||||
|
||||
if (rl_last_func != rl_yank_last_arg)
|
||||
{
|
||||
history_skip = 0;
|
||||
explicit_arg_p = rl_explicit_arg;
|
||||
count_passed = count;
|
||||
direction = 1;
|
||||
}
|
||||
else
|
||||
return (rl_yank_nth_arg ('$', key));
|
||||
{
|
||||
rl_do_undo ();
|
||||
if (count < 1)
|
||||
direction = -direction;
|
||||
history_skip += direction;
|
||||
if (history_skip < 0)
|
||||
history_skip = 0;
|
||||
count_passed = count;
|
||||
}
|
||||
|
||||
if (explicit_arg_p)
|
||||
return (rl_yank_nth_arg_internal (count, key, history_skip));
|
||||
else
|
||||
return (rl_yank_nth_arg_internal ('$', key, history_skip));
|
||||
}
|
||||
|
||||
/* A special paste command for users of Cygnus's cygwin32. */
|
||||
#if defined (__CYGWIN32__)
|
||||
#include <windows.h>
|
||||
|
||||
int
|
||||
rl_paste_from_clipboard (count, key)
|
||||
int count, key;
|
||||
{
|
||||
char *data, *ptr;
|
||||
int len;
|
||||
|
||||
if (OpenClipboard (NULL) == 0)
|
||||
return (0);
|
||||
|
||||
data = (char *)GetClipboardData (CF_TEXT);
|
||||
if (data)
|
||||
{
|
||||
ptr = strchr (data, '\r');
|
||||
if (ptr)
|
||||
{
|
||||
len = ptr - data;
|
||||
ptr = xmalloc (len + 1);
|
||||
ptr[len] = '\0';
|
||||
strncpy (ptr, data, len);
|
||||
}
|
||||
else
|
||||
ptr = data;
|
||||
rl_insert_text (ptr);
|
||||
if (ptr != data)
|
||||
free (ptr);
|
||||
CloseClipboard ();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif /* __CYGWIN32__ */
|
||||
|
|
|
@ -69,7 +69,8 @@ static char *legal_lang_values[] =
|
|||
"iso88598",
|
||||
"iso88599",
|
||||
"iso885910",
|
||||
"koi8r",
|
||||
"koi8r",
|
||||
"koi8-r",
|
||||
0
|
||||
};
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ rl_insert_close (count, invoking_key)
|
|||
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (fileno (rl_instream), &readfds);
|
||||
timer.tv_sec = 1;
|
||||
timer.tv_sec = 0;
|
||||
timer.tv_usec = 500;
|
||||
|
||||
orig_point = rl_point;
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
#include "history.h"
|
||||
|
||||
#ifndef RL_LIBRARY_VERSION
|
||||
# define RL_LIBRARY_VERSION "2.1-bash"
|
||||
# define RL_LIBRARY_VERSION "2.2-bash"
|
||||
#endif
|
||||
|
||||
/* Evaluates its arguments multiple times. */
|
||||
|
@ -78,7 +78,11 @@
|
|||
/* Variables and functions imported from terminal.c */
|
||||
extern int _rl_init_terminal_io ();
|
||||
extern void _rl_enable_meta_key ();
|
||||
#ifdef _MINIX
|
||||
extern void _rl_output_character_function ();
|
||||
#else
|
||||
extern int _rl_output_character_function ();
|
||||
#endif
|
||||
extern void _rl_get_screen_size ();
|
||||
|
||||
extern int _rl_enable_meta;
|
||||
|
@ -1027,6 +1031,18 @@ _rl_fix_point (fix_mark_too)
|
|||
}
|
||||
#undef _RL_FIX_POINT
|
||||
|
||||
void
|
||||
_rl_replace_text (text, start, end)
|
||||
char *text;
|
||||
int start, end;
|
||||
{
|
||||
rl_begin_undo_group ();
|
||||
rl_delete_text (start, end + 1);
|
||||
rl_point = start;
|
||||
rl_insert_text (text);
|
||||
rl_end_undo_group ();
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Readline character functions */
|
||||
|
|
|
@ -73,6 +73,7 @@ extern int
|
|||
rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
|
||||
rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words (),
|
||||
rl_complete (), rl_possible_completions (), rl_insert_completions (),
|
||||
rl_menu_complete (),
|
||||
rl_do_lowercase_version (), rl_kill_full_line (),
|
||||
rl_digit_argument (), rl_universal_argument (), rl_abort (),
|
||||
rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
|
||||
|
@ -93,13 +94,19 @@ extern void rl_callback_handler_install ();
|
|||
extern void rl_callback_read_char ();
|
||||
extern void rl_callback_handler_remove ();
|
||||
|
||||
/* Not available unless __CYGWIN32__ is defined. */
|
||||
#ifdef __CYGWIN32__
|
||||
extern int rl_paste_from_clipboard ();
|
||||
#endif
|
||||
|
||||
/* These are *both* defined even when VI_MODE is not. */
|
||||
extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
|
||||
|
||||
/* Non incremental history searching. */
|
||||
extern int
|
||||
rl_noninc_forward_search (), rl_noninc_reverse_search (),
|
||||
rl_noninc_forward_search_again (), rl_noninc_reverse_search_again ();
|
||||
extern int rl_noninc_forward_search ();
|
||||
extern int rl_noninc_reverse_search ();
|
||||
extern int rl_noninc_forward_search_again ();
|
||||
extern int rl_noninc_reverse_search_again ();
|
||||
|
||||
/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
|
||||
extern int rl_vi_check ();
|
||||
|
@ -153,6 +160,7 @@ extern char *rl_get_keymap_name ();
|
|||
|
||||
extern int rl_bind_key (), rl_bind_key_in_map ();
|
||||
extern int rl_unbind_key (), rl_unbind_key_in_map ();
|
||||
extern int rl_unbind_function_in_map (), rl_unbind_command_in_map ();
|
||||
extern int rl_set_key ();
|
||||
extern int rl_generic_bind ();
|
||||
extern int rl_parse_and_bind ();
|
||||
|
|
|
@ -42,17 +42,7 @@
|
|||
# include <sgtty.h>
|
||||
#endif
|
||||
|
||||
/* Stuff for `struct winsize' on various systems. */
|
||||
#if defined (HAVE_SYS_STREAM_H)
|
||||
# include <sys/stream.h>
|
||||
#endif /* HAVE_SYS_STREAM_H */
|
||||
#if defined (HAVE_SYS_PTEM_H)
|
||||
# include <sys/ptem.h>
|
||||
# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
|
||||
#endif /* HAVE_SYS_PTEM_H */
|
||||
#if defined (HAVE_SYS_PTE_H)
|
||||
# include <sys/pte.h>
|
||||
#endif /* HAVE_SYS_PTE_H */
|
||||
#include "rlwinsize.h"
|
||||
|
||||
/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
|
||||
it is not already defined. It is used both to determine if a
|
||||
|
|
58
lib/readline/rlwinsize.h
Normal file
58
lib/readline/rlwinsize.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* rlwinsize.h -- an attempt to isolate some of the system-specific defines
|
||||
for `struct winsize' and TIOCGWINSZ. */
|
||||
|
||||
/* Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the Readline Library (the Library), a set of
|
||||
routines for providing Emacs style line input to programs that ask
|
||||
for it.
|
||||
|
||||
The 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
The 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#if !defined (_RLWINSIZE_H_)
|
||||
#define _RLWINSIZE_H_
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
|
||||
|
||||
#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
|
||||
# include <sys/ioctl.h>
|
||||
#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
|
||||
|
||||
#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
|
||||
# include <termios.h>
|
||||
#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
|
||||
|
||||
/* Not in either of the standard places, look around. */
|
||||
#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
|
||||
# if defined (HAVE_SYS_STREAM_H)
|
||||
# include <sys/stream.h>
|
||||
# endif /* HAVE_SYS_STREAM_H */
|
||||
# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
|
||||
# include <sys/ptem.h>
|
||||
# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
|
||||
# endif /* HAVE_SYS_PTEM_H */
|
||||
# if defined (HAVE_SYS_PTE_H) /* ??? */
|
||||
# include <sys/pte.h>
|
||||
# endif /* HAVE_SYS_PTE_H */
|
||||
#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
|
||||
|
||||
#endif /* _RL_WINSIZE_H */
|
||||
|
||||
|
|
@ -27,6 +27,9 @@
|
|||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
|
@ -36,6 +39,12 @@
|
|||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
extern char *xmalloc (), *xrealloc ();
|
||||
|
||||
#if !defined (SHELL)
|
||||
|
|
|
@ -434,13 +434,21 @@ rl_reset_terminal (terminal_name)
|
|||
}
|
||||
|
||||
/* A function for the use of tputs () */
|
||||
#ifdef _MINIX
|
||||
void
|
||||
_rl_output_character_function (c)
|
||||
int c;
|
||||
{
|
||||
putc (c, _rl_out_stream);
|
||||
}
|
||||
#else /* !_MINIX */
|
||||
int
|
||||
_rl_output_character_function (c)
|
||||
int c;
|
||||
{
|
||||
return putc (c, _rl_out_stream);
|
||||
}
|
||||
|
||||
#endif /* !_MINIX */
|
||||
/* Write COUNT characters from STRING to the output stream. */
|
||||
void
|
||||
_rl_output_some_chars (string, count)
|
||||
|
@ -519,18 +527,11 @@ ding ()
|
|||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static int
|
||||
outchar (c)
|
||||
int c;
|
||||
{
|
||||
return putc (c, rl_outstream);
|
||||
}
|
||||
|
||||
void
|
||||
_rl_enable_meta_key ()
|
||||
{
|
||||
if (term_has_meta && term_mm)
|
||||
tputs (term_mm, 1, outchar);
|
||||
tputs (term_mm, 1, _rl_output_character_function);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -538,7 +539,7 @@ _rl_control_keypad (on)
|
|||
int on;
|
||||
{
|
||||
if (on && term_ks)
|
||||
tputs (term_ks, 1, outchar);
|
||||
tputs (term_ks, 1, _rl_output_character_function);
|
||||
else if (!on && term_ke)
|
||||
tputs (term_ke, 1, outchar);
|
||||
tputs (term_ke, 1, _rl_output_character_function);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -166,6 +166,58 @@ rl_extend_line_buffer (len)
|
|||
_rl_set_the_line ();
|
||||
}
|
||||
|
||||
|
||||
/* A function for simple tilde expansion. */
|
||||
int
|
||||
rl_tilde_expand (ignore, key)
|
||||
int ignore, key;
|
||||
{
|
||||
register int start, end;
|
||||
char *homedir, *temp;
|
||||
int len;
|
||||
|
||||
end = rl_point;
|
||||
start = end - 1;
|
||||
|
||||
if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
|
||||
{
|
||||
homedir = tilde_expand ("~");
|
||||
_rl_replace_text (homedir, start, end);
|
||||
return (0);
|
||||
}
|
||||
else if (rl_line_buffer[start] != '~')
|
||||
{
|
||||
for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
|
||||
;
|
||||
start++;
|
||||
}
|
||||
|
||||
end = start;
|
||||
do
|
||||
end++;
|
||||
while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
|
||||
|
||||
if (whitespace (rl_line_buffer[end]) || end >= rl_end)
|
||||
end--;
|
||||
|
||||
/* If the first character of the current word is a tilde, perform
|
||||
tilde expansion and insert the result. If not a tilde, do
|
||||
nothing. */
|
||||
if (rl_line_buffer[start] == '~')
|
||||
{
|
||||
len = end - start + 1;
|
||||
temp = xmalloc (len + 1);
|
||||
strncpy (temp, rl_line_buffer + start, len);
|
||||
temp[len] = '\0';
|
||||
homedir = tilde_expand (temp);
|
||||
free (temp);
|
||||
|
||||
_rl_replace_text (homedir, start, end);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* String Utility Functions */
|
||||
|
@ -300,3 +352,13 @@ _rl_digit_value (c)
|
|||
{
|
||||
return (isdigit (c) ? c - '0' : c);
|
||||
}
|
||||
|
||||
/* Backwards compatibility, now that savestring has been removed from
|
||||
all `public' readline header files. */
|
||||
#undef _rl_savestring
|
||||
char *
|
||||
_rl_savestring (s)
|
||||
char *s;
|
||||
{
|
||||
return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s)));
|
||||
}
|
||||
|
|
|
@ -615,6 +615,13 @@ _rl_vi_save_insert (up)
|
|||
{
|
||||
int len, start, end;
|
||||
|
||||
if (up == 0)
|
||||
{
|
||||
if (vi_insert_buffer_size >= 1)
|
||||
vi_insert_buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
start = up->start;
|
||||
end = up->end;
|
||||
len = end - start + 1;
|
||||
|
|
164
lib/sh/Makefile.in
Normal file
164
lib/sh/Makefile.in
Normal file
|
@ -0,0 +1,164 @@
|
|||
#
|
||||
# Makefile for the Bash library
|
||||
#
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
POSIX_INC = ${topdir}/lib/posixheaders
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
|
||||
|
||||
PROFILE_FLAGS = @PROFILE_FLAGS@
|
||||
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(POSIX_INC) -I$(srcdir)
|
||||
|
||||
CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \
|
||||
$(CFLAGS) $(CPPFLAGS)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CCFLAGS) $<
|
||||
|
||||
# The name of the library target.
|
||||
LIBRARY_NAME = libsh.a
|
||||
|
||||
# The C code source files for this library.
|
||||
CSOURCES = clktck.c getcwd.c getenv.c oslib.c setlinebuf.c \
|
||||
strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
|
||||
vprint.c itos.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES =
|
||||
|
||||
# The object files contained in $(LIBRARY_NAME)
|
||||
OBJECTS = clktck.o getcwd.o getenv.o oslib.o setlinebuf.o \
|
||||
strcasecmp.o strerror.o strtod.o strtol.o strtoul.o \
|
||||
vprint.o itos.o
|
||||
|
||||
SUPPORT = Makefile
|
||||
|
||||
all: $(LIBRARY_NAME)
|
||||
|
||||
$(LIBRARY_NAME): $(OBJECTS)
|
||||
$(RM) $@
|
||||
$(AR) cr $@ $(OBJECTS)
|
||||
-test -n "$(RANLIB)" && $(RANLIB) $@
|
||||
|
||||
force:
|
||||
|
||||
# The rule for 'includes' is written funny so that the if statement
|
||||
# always returns TRUE unless there really was an error installing the
|
||||
# include files.
|
||||
install:
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJECTS) $(LIBRARY_NAME)
|
||||
|
||||
realclean distclean maintainer-clean: clean
|
||||
$(RM) Makefile
|
||||
|
||||
mostlyclean: clean
|
||||
|
||||
# Dependencies
|
||||
|
||||
# rules for losing makes, like SunOS
|
||||
clktck.o: clktck.c
|
||||
getcwd.o: getcwd.c
|
||||
getenv.o: getenv.c
|
||||
itos.o: itos.c
|
||||
oslib.o: oslib.c
|
||||
setlinebuf.o: setlinebuf.c
|
||||
strcasecmp.o: strcasecmp.c
|
||||
strerror.o: strerror.c
|
||||
strtod.o: strtod.c
|
||||
strtol.o: strtol.c
|
||||
strtoul.o: strtoul.c
|
||||
vprint.o: vprint.c
|
||||
|
||||
# all files in the library depend on config.h
|
||||
clktck.o: ${BUILD_DIR}/config.h
|
||||
getcwd.o: ${BUILD_DIR}/config.h
|
||||
getenv.o: ${BUILD_DIR}/config.h
|
||||
itos.o: ${BUILD_DIR}/config.h
|
||||
oslib.o: ${BUILD_DIR}/config.h
|
||||
setlinebuf.o: ${BUILD_DIR}/config.h
|
||||
strcasecmp.o: ${BUILD_DIR}/config.h
|
||||
strerror.o: ${BUILD_DIR}/config.h
|
||||
strtod.o: ${BUILD_DIR}/config.h
|
||||
strtol.o: ${BUILD_DIR}/config.h
|
||||
strtoul.o: ${BUILD_DIR}/config.h
|
||||
vprint.o: ${BUILD_DIR}/config.h
|
||||
|
||||
clktck.o: ${topdir}/bashtypes.h
|
||||
|
||||
getcwd.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${topdir}/maxpath.h
|
||||
getcwd.o: ${POSIX_INC}/posixstat.h ${POSIX_INC}/posixdir.h
|
||||
getcwd.o: ${POSIX_INC}/memalloc.h ${POSIX_INC}/ansi_stdlib.h
|
||||
|
||||
getenv.o: ${topdir}/bashansi.h ${topdir}/ansi_stdlib.h
|
||||
getenv.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h
|
||||
getenv.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h
|
||||
getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.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
|
||||
getenv.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
|
||||
itos.o: ${topdir}/bashansi.h ${topdir}/ansi_stdlib.h
|
||||
itos.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h
|
||||
itos.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h
|
||||
itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.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
|
||||
itos.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
|
||||
oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${topdir}/maxpath.h
|
||||
oslib.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h
|
||||
oslib.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h
|
||||
oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.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: ${POSIX_INC}/posixstat.h ${POSIX_INC}/filecntl.h
|
||||
oslib.o: ${POSIX_INC}/ansi_stdlib.h
|
||||
|
||||
strcasecmp.o: ${topdir}/stdc.h ${topdir}/bashansi.h ${topdir}/ansi_stdlib.h
|
||||
|
||||
strerror.o: ${topdir}/bashtypes.h
|
||||
strerror.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h
|
||||
strerror.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h
|
||||
strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.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
|
||||
|
||||
strtod.o: ${topdir}/bashansi.h
|
||||
strtod.o: ${POSIX_INC}/ansi_stdlib.h
|
||||
|
||||
strtol.o: ${topdir}/bashansi.h
|
||||
strtol.o: ${POSIX_INC}/ansi_stdlib.h
|
||||
|
||||
strtoul.o: ${topdir}/bashansi.h
|
||||
strtoul.o: ${POSIX_INC}/ansi_stdlib.h
|
55
lib/sh/clktck.c
Normal file
55
lib/sh/clktck.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* clktck.c - get the value of CLK_TCK. */
|
||||
|
||||
/* Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK)
|
||||
# if !defined (CLK_TCK)
|
||||
# if defined (HZ)
|
||||
# define CLK_TCK HZ
|
||||
# else
|
||||
# define CLK_TCK 60
|
||||
# endif
|
||||
# endif /* !CLK_TCK */
|
||||
#endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */
|
||||
|
||||
long
|
||||
get_clk_tck ()
|
||||
{
|
||||
static long retval = 0;
|
||||
|
||||
if (retval != 0)
|
||||
return (retval);
|
||||
|
||||
#if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK)
|
||||
retval = sysconf (_SC_CLK_TCK);
|
||||
#else /* !SYSCONF || !_SC_CLK_TCK */
|
||||
retval = CLK_TCK;
|
||||
#endif /* !SYSCONF || !_SC_CLK_TCK */
|
||||
|
||||
return (retval);
|
||||
}
|
319
lib/sh/getcwd.c
Normal file
319
lib/sh/getcwd.c
Normal file
|
@ -0,0 +1,319 @@
|
|||
/* getcwd.c -- stolen from the GNU C library and modified to work with bash. */
|
||||
|
||||
/* Copyright (C) 1991 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 Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (HAVE_GETCWD)
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <posixdir.h>
|
||||
#include <posixstat.h>
|
||||
#include <maxpath.h>
|
||||
#include <memalloc.h>
|
||||
|
||||
#include <bashansi.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
|
||||
|
||||
/* Get the pathname of the current working directory,
|
||||
and put it in SIZE bytes of BUF. Returns NULL if the
|
||||
directory couldn't be determined or SIZE was too small.
|
||||
If successful, returns BUF. In GNU, if BUF is NULL,
|
||||
an array is allocated with `malloc'; the array is SIZE
|
||||
bytes long, unless SIZE <= 0, in which case it is as
|
||||
big as necessary. */
|
||||
#if defined (__STDC__)
|
||||
char *
|
||||
getcwd (char *buf, size_t size)
|
||||
#else /* !__STDC__ */
|
||||
char *
|
||||
getcwd (buf, size)
|
||||
char *buf;
|
||||
size_t size;
|
||||
#endif /* !__STDC__ */
|
||||
{
|
||||
static CONST char dots[]
|
||||
= "../../../../../../../../../../../../../../../../../../../../../../../\
|
||||
../../../../../../../../../../../../../../../../../../../../../../../../../../\
|
||||
../../../../../../../../../../../../../../../../../../../../../../../../../..";
|
||||
CONST char *dotp, *dotlist;
|
||||
size_t dotsize;
|
||||
dev_t rootdev, thisdev;
|
||||
ino_t rootino, thisino;
|
||||
char path[PATH_MAX + 1];
|
||||
register char *pathp;
|
||||
char *pathbuf;
|
||||
size_t pathsize;
|
||||
struct stat st;
|
||||
int saved_errno;
|
||||
|
||||
if (buf != NULL && size == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
pathsize = sizeof (path);
|
||||
pathp = &path[pathsize];
|
||||
*--pathp = '\0';
|
||||
pathbuf = path;
|
||||
|
||||
if (stat (".", &st) < 0)
|
||||
return ((char *)NULL);
|
||||
thisdev = st.st_dev;
|
||||
thisino = st.st_ino;
|
||||
|
||||
if (stat ("/", &st) < 0)
|
||||
return ((char *)NULL);
|
||||
rootdev = st.st_dev;
|
||||
rootino = st.st_ino;
|
||||
|
||||
saved_errno = 0;
|
||||
|
||||
dotsize = sizeof (dots) - 1;
|
||||
dotp = &dots[sizeof (dots)];
|
||||
dotlist = dots;
|
||||
while (!(thisdev == rootdev && thisino == rootino))
|
||||
{
|
||||
register DIR *dirstream;
|
||||
register struct dirent *d;
|
||||
dev_t dotdev;
|
||||
ino_t dotino;
|
||||
char mount_point;
|
||||
int namlen;
|
||||
|
||||
/* Look at the parent directory. */
|
||||
if (dotp == dotlist)
|
||||
{
|
||||
/* My, what a deep directory tree you have, Grandma. */
|
||||
char *new;
|
||||
if (dotlist == dots)
|
||||
{
|
||||
new = malloc (dotsize * 2 + 1);
|
||||
if (new == NULL)
|
||||
goto lose;
|
||||
memcpy (new, dots, dotsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
new = realloc ((PTR) dotlist, dotsize * 2 + 1);
|
||||
if (new == NULL)
|
||||
goto lose;
|
||||
}
|
||||
memcpy (&new[dotsize], new, dotsize);
|
||||
dotp = &new[dotsize];
|
||||
dotsize *= 2;
|
||||
new[dotsize] = '\0';
|
||||
dotlist = new;
|
||||
}
|
||||
|
||||
dotp -= 3;
|
||||
|
||||
/* Figure out if this directory is a mount point. */
|
||||
if (stat (dotp, &st) < 0)
|
||||
goto lose;
|
||||
dotdev = st.st_dev;
|
||||
dotino = st.st_ino;
|
||||
mount_point = dotdev != thisdev;
|
||||
|
||||
/* Search for the last directory. */
|
||||
dirstream = opendir (dotp);
|
||||
if (dirstream == NULL)
|
||||
goto lose;
|
||||
while ((d = readdir (dirstream)) != NULL)
|
||||
{
|
||||
if (d->d_name[0] == '.' &&
|
||||
(d->d_name[1] == '\0' ||
|
||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||
continue;
|
||||
if (mount_point || d->d_fileno == thisino)
|
||||
{
|
||||
char *name;
|
||||
|
||||
namlen = D_NAMLEN(d);
|
||||
name = (char *)
|
||||
alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
|
||||
memcpy (name, dotp, dotlist + dotsize - dotp);
|
||||
name[dotlist + dotsize - dotp] = '/';
|
||||
memcpy (&name[dotlist + dotsize - dotp + 1],
|
||||
d->d_name, namlen + 1);
|
||||
if (lstat (name, &st) < 0)
|
||||
{
|
||||
#if 0
|
||||
int save = errno;
|
||||
(void) closedir (dirstream);
|
||||
errno = save;
|
||||
goto lose;
|
||||
#else
|
||||
saved_errno = errno;
|
||||
#endif
|
||||
}
|
||||
if (st.st_dev == thisdev && st.st_ino == thisino)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d == NULL)
|
||||
{
|
||||
#if 0
|
||||
int save = errno;
|
||||
#else
|
||||
int save = errno ? errno : saved_errno;
|
||||
#endif
|
||||
(void) closedir (dirstream);
|
||||
errno = save;
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t space;
|
||||
|
||||
while ((space = pathp - pathbuf) <= namlen)
|
||||
{
|
||||
char *new;
|
||||
|
||||
if (pathbuf == path)
|
||||
{
|
||||
new = malloc (pathsize * 2);
|
||||
if (!new)
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
new = realloc ((PTR) pathbuf, (pathsize * 2));
|
||||
if (!new)
|
||||
goto lose;
|
||||
pathp = new + space;
|
||||
}
|
||||
(void) memcpy (new + pathsize + space, pathp, pathsize - space);
|
||||
pathp = new + pathsize + space;
|
||||
pathbuf = new;
|
||||
pathsize *= 2;
|
||||
}
|
||||
|
||||
pathp -= namlen;
|
||||
(void) memcpy (pathp, d->d_name, namlen);
|
||||
*--pathp = '/';
|
||||
(void) closedir (dirstream);
|
||||
}
|
||||
|
||||
thisdev = dotdev;
|
||||
thisino = dotino;
|
||||
}
|
||||
|
||||
if (pathp == &path[sizeof(path) - 1])
|
||||
*--pathp = '/';
|
||||
|
||||
if (dotlist != dots)
|
||||
free ((PTR) dotlist);
|
||||
|
||||
{
|
||||
size_t len = pathbuf + pathsize - pathp;
|
||||
if (buf == NULL)
|
||||
{
|
||||
if (len < (size_t) size)
|
||||
len = size;
|
||||
buf = (char *) malloc (len);
|
||||
if (buf == NULL)
|
||||
goto lose2;
|
||||
}
|
||||
else if ((size_t) size < len)
|
||||
{
|
||||
errno = ERANGE;
|
||||
goto lose2;
|
||||
}
|
||||
(void) memcpy((PTR) buf, (PTR) pathp, len);
|
||||
}
|
||||
|
||||
if (pathbuf != path)
|
||||
free (pathbuf);
|
||||
|
||||
return (buf);
|
||||
|
||||
lose:
|
||||
if ((dotlist != dots) && dotlist)
|
||||
{
|
||||
int e = errno;
|
||||
free ((PTR) dotlist);
|
||||
errno = e;
|
||||
}
|
||||
|
||||
lose2:
|
||||
if ((pathbuf != path) && pathbuf)
|
||||
{
|
||||
int e = errno;
|
||||
free ((PTR) pathbuf);
|
||||
errno = e;
|
||||
}
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
#if defined (TEST)
|
||||
# include <stdio.h>
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char b[PATH_MAX];
|
||||
|
||||
if (getcwd(b, sizeof(b)))
|
||||
{
|
||||
printf ("%s\n", b);
|
||||
exit (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
perror ("cwd: getcwd");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#endif /* TEST */
|
||||
#endif /* !HAVE_GETCWD */
|
99
lib/sh/getenv.c
Normal file
99
lib/sh/getenv.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* getenv.c - get environment variable value from the shell's variable
|
||||
list. */
|
||||
|
||||
/* Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (CAN_REDEFINE_GETENV)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <bashansi.h>
|
||||
#include <shell.h>
|
||||
|
||||
extern char **environ;
|
||||
|
||||
/* We supply our own version of getenv () because we want library
|
||||
routines to get the changed values of exported variables. */
|
||||
|
||||
/* The NeXT C library has getenv () defined and used in the same file.
|
||||
This screws our scheme. However, Bash will run on the NeXT using
|
||||
the C library getenv (), since right now the only environment variable
|
||||
that we care about is HOME, and that is already defined. */
|
||||
static char *last_tempenv_value = (char *)NULL;
|
||||
|
||||
char *
|
||||
getenv (name)
|
||||
#if defined (__linux__) || defined (__bsdi__) || defined (convex)
|
||||
const char *name;
|
||||
#else
|
||||
char const *name;
|
||||
#endif /* !__linux__ && !__bsdi__ && !convex */
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = find_tempenv_variable ((char *)name);
|
||||
if (var)
|
||||
{
|
||||
FREE (last_tempenv_value);
|
||||
|
||||
last_tempenv_value = savestring (value_cell (var));
|
||||
dispose_variable (var);
|
||||
return (last_tempenv_value);
|
||||
}
|
||||
else if (shell_variables)
|
||||
{
|
||||
var = find_variable ((char *)name);
|
||||
if (var && exported_p (var))
|
||||
return (value_cell (var));
|
||||
}
|
||||
else
|
||||
{
|
||||
register int i, len;
|
||||
|
||||
/* In some cases, s5r3 invokes getenv() before main(); BSD systems
|
||||
using gprof also exhibit this behavior. This means that
|
||||
shell_variables will be 0 when this is invoked. We look up the
|
||||
variable in the real environment in that case. */
|
||||
|
||||
for (i = 0, len = strlen (name); environ[i]; i++)
|
||||
{
|
||||
if ((STREQN (environ[i], name, len)) && (environ[i][len] == '='))
|
||||
return (environ[i] + len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
/* Some versions of Unix use _getenv instead. */
|
||||
char *
|
||||
_getenv (name)
|
||||
#if defined (__linux__) || defined (__bsdi__) || defined (convex)
|
||||
const char *name;
|
||||
#else
|
||||
char const *name;
|
||||
#endif /* !__linux__ && !__bsdi__ && !convex */
|
||||
{
|
||||
return (getenv (name));
|
||||
}
|
||||
#endif /* CAN_REDEFINE_GETENV */
|
64
lib/sh/itos.c
Normal file
64
lib/sh/itos.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* itos.c -- Convert integer 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.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. This conses the string; the
|
||||
caller should free it. */
|
||||
char *
|
||||
itos (i)
|
||||
int i;
|
||||
{
|
||||
char buf[MAX_INT_LEN], *p, *ret;
|
||||
int negative = 0;
|
||||
unsigned int ui;
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
negative++;
|
||||
i = -i;
|
||||
}
|
||||
|
||||
ui = (unsigned int) i;
|
||||
|
||||
p = buf + MAX_INT_LEN - 2;
|
||||
p[1] = '\0';
|
||||
|
||||
do
|
||||
*p-- = (ui % 10) + '0';
|
||||
while (ui /= 10);
|
||||
|
||||
if (negative)
|
||||
*p-- = '-';
|
||||
|
||||
ret = savestring (p + 1);
|
||||
return (ret);
|
||||
}
|
233
lib/sh/oslib.c
Normal file
233
lib/sh/oslib.c
Normal file
|
@ -0,0 +1,233 @@
|
|||
/* oslib.c - functions present only in some unix versions. */
|
||||
|
||||
/* Copyright (C) 1995 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <posixstat.h>
|
||||
#include <filecntl.h>
|
||||
#include <bashansi.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <shell.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
/* Make the functions strchr and strrchr if they do not exist. */
|
||||
#if !defined (HAVE_STRCHR)
|
||||
char *
|
||||
strchr (string, c)
|
||||
char *string;
|
||||
int c;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
for (s = string; s && *s; s++)
|
||||
if (*s == c)
|
||||
return (s);
|
||||
|
||||
return ((char *) NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
strrchr (string, c)
|
||||
char *string;
|
||||
int c;
|
||||
{
|
||||
register char *s, *t;
|
||||
|
||||
for (s = string, t = (char *)NULL; s && *s; s++)
|
||||
if (*s == c)
|
||||
t = s;
|
||||
return (t);
|
||||
}
|
||||
#endif /* !HAVE_STRCHR */
|
||||
|
||||
#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
|
||||
/* Replacement for dup2 (), for those systems which either don't have it,
|
||||
or supply one with broken behaviour. */
|
||||
int
|
||||
dup2 (fd1, fd2)
|
||||
int fd1, fd2;
|
||||
{
|
||||
int saved_errno, r;
|
||||
|
||||
/* If FD1 is not a valid file descriptor, then return immediately with
|
||||
an error. */
|
||||
if (fcntl (fd1, F_GETFL, 0) == -1)
|
||||
return (-1);
|
||||
|
||||
if (fd2 < 0 || fd2 >= getdtablesize ())
|
||||
{
|
||||
errno = EBADF;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (fd1 == fd2)
|
||||
return (0);
|
||||
|
||||
saved_errno = errno;
|
||||
|
||||
(void) close (fd2);
|
||||
r = fcntl (fd1, F_DUPFD, fd2);
|
||||
|
||||
if (r >= 0)
|
||||
errno = saved_errno;
|
||||
else
|
||||
if (errno == EINVAL)
|
||||
errno = EBADF;
|
||||
|
||||
/* Force the new file descriptor to remain open across exec () calls. */
|
||||
SET_OPEN_ON_EXEC (fd2);
|
||||
return (r);
|
||||
}
|
||||
#endif /* !HAVE_DUP2 */
|
||||
|
||||
/*
|
||||
* Return the total number of available file descriptors.
|
||||
*
|
||||
* On some systems, like 4.2BSD and its descendents, there is a system call
|
||||
* that returns the size of the descriptor table: getdtablesize(). There are
|
||||
* lots of ways to emulate this on non-BSD systems.
|
||||
*
|
||||
* On System V.3, this can be obtained via a call to ulimit:
|
||||
* return (ulimit(4, 0L));
|
||||
*
|
||||
* On other System V systems, NOFILE is defined in /usr/include/sys/param.h
|
||||
* (this is what we assume below), so we can simply use it:
|
||||
* return (NOFILE);
|
||||
*
|
||||
* On POSIX systems, there are specific functions for retrieving various
|
||||
* configuration parameters:
|
||||
* return (sysconf(_SC_OPEN_MAX));
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined (HAVE_GETDTABLESIZE)
|
||||
int
|
||||
getdtablesize ()
|
||||
{
|
||||
# if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
|
||||
return (sysconf(_SC_OPEN_MAX)); /* Posix systems use sysconf */
|
||||
# else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */
|
||||
# if defined (ULIMIT_MAXFDS)
|
||||
return (ulimit (4, 0L)); /* System V.3 systems use ulimit(4, 0L) */
|
||||
# else /* !ULIMIT_MAXFDS */
|
||||
# if defined (NOFILE) /* Other systems use NOFILE */
|
||||
return (NOFILE);
|
||||
# else /* !NOFILE */
|
||||
return (20); /* XXX - traditional value is 20 */
|
||||
# endif /* !NOFILE */
|
||||
# endif /* !ULIMIT_MAXFDS */
|
||||
# endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
|
||||
}
|
||||
#endif /* !HAVE_GETDTABLESIZE */
|
||||
|
||||
#if !defined (HAVE_BCOPY)
|
||||
void
|
||||
bcopy (s,d,n)
|
||||
char *d, *s;
|
||||
int n;
|
||||
{
|
||||
FASTCOPY (s, d, n);
|
||||
}
|
||||
#endif /* !HAVE_BCOPY */
|
||||
|
||||
#if !defined (HAVE_BZERO)
|
||||
void
|
||||
bzero (s, n)
|
||||
char *s;
|
||||
int n;
|
||||
{
|
||||
register int i;
|
||||
register char *r;
|
||||
|
||||
for (i = 0, r = s; i < n; i++)
|
||||
*r++ = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_GETHOSTNAME)
|
||||
# if defined (HAVE_UNAME)
|
||||
# include <sys/utsname.h>
|
||||
int
|
||||
gethostname (name, namelen)
|
||||
char *name;
|
||||
int namelen;
|
||||
{
|
||||
int i;
|
||||
struct utsname ut;
|
||||
|
||||
--namelen;
|
||||
|
||||
uname (&ut);
|
||||
i = strlen (ut.nodename) + 1;
|
||||
strncpy (name, ut.nodename, i < namelen ? i : namelen);
|
||||
name[namelen] = '\0';
|
||||
return (0);
|
||||
}
|
||||
# else /* !HAVE_UNAME */
|
||||
int
|
||||
gethostname (name, namelen)
|
||||
int name, namelen;
|
||||
{
|
||||
strncpy (name, "unknown", namelen);
|
||||
name[namelen] = '\0';
|
||||
return 0;
|
||||
}
|
||||
# endif /* !HAVE_UNAME */
|
||||
#endif /* !HAVE_GETHOSTNAME */
|
||||
|
||||
#if !defined (HAVE_KILLPG)
|
||||
int
|
||||
killpg (pgrp, sig)
|
||||
pid_t pgrp;
|
||||
int sig;
|
||||
{
|
||||
return (kill (-pgrp, sig));
|
||||
}
|
||||
#endif /* !HAVE_KILLPG */
|
||||
|
||||
#if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION)
|
||||
int
|
||||
mkfifo (path, mode)
|
||||
char *path;
|
||||
int mode;
|
||||
{
|
||||
#if defined (S_IFIFO)
|
||||
return (mknod (path, (mode | S_IFIFO), 0));
|
||||
#else /* !S_IFIFO */
|
||||
return (-1);
|
||||
#endif /* !S_IFIFO */
|
||||
}
|
||||
#endif /* !HAVE_MKFIFO && PROCESS_SUBSTITUTION */
|
41
lib/sh/setlinebuf.c
Normal file
41
lib/sh/setlinebuf.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* setlinebuf.c - line-buffer a stdio stream. */
|
||||
|
||||
/* Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (HAVE_SETLINEBUF)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Cause STREAM to buffer lines as opposed to characters or blocks. */
|
||||
int
|
||||
setlinebuf (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
#if defined (_IOLBF)
|
||||
# if defined (SETVBUF_REVERSED)
|
||||
setvbuf (stream, _IOLBF, (char *)NULL, BUFSIZ);
|
||||
# else /* !SETVBUF_REVERSED */
|
||||
setvbuf (stream, (char *)NULL, _IOLBF, BUFSIZ);
|
||||
# endif /* !SETVBUF_REVERSED */
|
||||
#endif /* _IOLBF */
|
||||
return (0);
|
||||
}
|
||||
#endif /* !HAVE_SETLINEBUF */
|
88
lib/sh/strcasecmp.c
Normal file
88
lib/sh/strcasecmp.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* strcasecmp.c - functions for case-insensitive string comparison. */
|
||||
|
||||
/* Copyright (C) 1995 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (HAVE_STRCASECMP)
|
||||
|
||||
#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 */
|
||||
|
||||
/* Compare at most COUNT characters from string1 to string2. Case
|
||||
doesn't matter. */
|
||||
int
|
||||
strncasecmp (string1, string2, count)
|
||||
const char *string1;
|
||||
const char *string2;
|
||||
int count;
|
||||
{
|
||||
register const char *s1;
|
||||
register const char *s2;
|
||||
register int r;
|
||||
|
||||
if (count <= 0 || (string1 == string2))
|
||||
return 0;
|
||||
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
do
|
||||
{
|
||||
if ((r = to_lower (*s1) - to_lower (*s2)) != 0)
|
||||
return r;
|
||||
if (*s1++ == '\0')
|
||||
break;
|
||||
s2++;
|
||||
}
|
||||
while (--count != 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* strcmp (), but caseless. */
|
||||
int
|
||||
strcasecmp (string1, string2)
|
||||
const char *string1;
|
||||
const char *string2;
|
||||
{
|
||||
register const char *s1;
|
||||
register const char *s2;
|
||||
register int r;
|
||||
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
|
||||
if (s1 == s2)
|
||||
return (0);
|
||||
|
||||
while ((r = to_lower (*s1) - to_lower (*s2)) == 0)
|
||||
{
|
||||
if (*s1++ == '\0')
|
||||
return 0;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
#endif /* !HAVE_STRCASECMP */
|
74
lib/sh/strerror.c
Normal file
74
lib/sh/strerror.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* strerror.c - string corresponding to a particular value of errno. */
|
||||
|
||||
/* Copyright (C) 1995 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (HAVE_STRERROR)
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <shell.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
/* Return a string corresponding to the error number E. From
|
||||
the ANSI C spec. */
|
||||
#if defined (strerror)
|
||||
# undef strerror
|
||||
#endif
|
||||
|
||||
static char *errbase = "Unknown system error ";
|
||||
|
||||
char *
|
||||
strerror (e)
|
||||
int e;
|
||||
{
|
||||
static char emsg[40];
|
||||
#if defined (HAVE_SYS_ERRLIST)
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
if (e > 0 && e < sys_nerr)
|
||||
return (sys_errlist[e]);
|
||||
else
|
||||
#endif /* HAVE_SYS_ERRLIST */
|
||||
{
|
||||
char *z;
|
||||
|
||||
z = itos (e);
|
||||
strcpy (emsg, errbase);
|
||||
strcat (emsg, z);
|
||||
free (z);
|
||||
return (&emsg[0]);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_STRERROR */
|
197
lib/sh/strtod.c
Normal file
197
lib/sh/strtod.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* Copyright (C) 1991, 1992 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. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRTOD
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_FLOAT_H
|
||||
# include <float.h>
|
||||
#else
|
||||
# define DBL_MAX 1.7976931348623159e+308
|
||||
# define DBL_MIN 2.2250738585072010e-308
|
||||
#endif
|
||||
|
||||
#include <bashansi.h>
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef HUGE_VAL
|
||||
# define HUGE_VAL HUGE
|
||||
#endif
|
||||
|
||||
/* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the
|
||||
character after the last one used in the number is put in *ENDPTR. */
|
||||
double
|
||||
strtod (nptr, endptr)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
{
|
||||
register const char *s;
|
||||
short sign;
|
||||
|
||||
/* The number so far. */
|
||||
double num;
|
||||
|
||||
int got_dot; /* Found a decimal point. */
|
||||
int got_digit; /* Seen any digits. */
|
||||
|
||||
/* The exponent of the number. */
|
||||
long int exponent;
|
||||
|
||||
if (nptr == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
goto noconv;
|
||||
}
|
||||
|
||||
s = nptr;
|
||||
|
||||
/* Eat whitespace. */
|
||||
while (isspace (*s))
|
||||
++s;
|
||||
|
||||
/* Get the sign. */
|
||||
sign = *s == '-' ? -1 : 1;
|
||||
if (*s == '-' || *s == '+')
|
||||
++s;
|
||||
|
||||
num = 0.0;
|
||||
got_dot = 0;
|
||||
got_digit = 0;
|
||||
exponent = 0;
|
||||
for (;; ++s)
|
||||
{
|
||||
if (isdigit (*s))
|
||||
{
|
||||
got_digit = 1;
|
||||
|
||||
/* Make sure that multiplication by 10 will not overflow. */
|
||||
if (num > DBL_MAX * 0.1)
|
||||
/* The value of the digit doesn't matter, since we have already
|
||||
gotten as many digits as can be represented in a `double'.
|
||||
This doesn't necessarily mean the result will overflow.
|
||||
The exponent may reduce it to within range.
|
||||
|
||||
We just need to record that there was another
|
||||
digit so that we can multiply by 10 later. */
|
||||
++exponent;
|
||||
else
|
||||
num = (num * 10.0) + (*s - '0');
|
||||
|
||||
/* Keep track of the number of digits after the decimal point.
|
||||
If we just divided by 10 here, we would lose precision. */
|
||||
if (got_dot)
|
||||
--exponent;
|
||||
}
|
||||
else if (!got_dot && *s == '.')
|
||||
/* Record that we have found the decimal point. */
|
||||
got_dot = 1;
|
||||
else
|
||||
/* Any other character terminates the number. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!got_digit)
|
||||
goto noconv;
|
||||
|
||||
if (tolower (*s) == 'e')
|
||||
{
|
||||
/* Get the exponent specified after the `e' or `E'. */
|
||||
int save = errno;
|
||||
char *end;
|
||||
long int exp;
|
||||
|
||||
errno = 0;
|
||||
++s;
|
||||
exp = strtol (s, &end, 10);
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
/* The exponent overflowed a `long int'. It is probably a safe
|
||||
assumption that an exponent that cannot be represented by
|
||||
a `long int' exceeds the limits of a `double'. */
|
||||
if (endptr != NULL)
|
||||
*endptr = end;
|
||||
if (exp < 0)
|
||||
goto underflow;
|
||||
else
|
||||
goto overflow;
|
||||
}
|
||||
else if (end == s)
|
||||
/* There was no exponent. Reset END to point to
|
||||
the 'e' or 'E', so *ENDPTR will be set there. */
|
||||
end = (char *) s - 1;
|
||||
errno = save;
|
||||
s = end;
|
||||
exponent += exp;
|
||||
}
|
||||
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) s;
|
||||
|
||||
if (num == 0.0)
|
||||
return 0.0;
|
||||
|
||||
/* Multiply NUM by 10 to the EXPONENT power,
|
||||
checking for overflow and underflow. */
|
||||
|
||||
if (exponent < 0)
|
||||
{
|
||||
if (num < DBL_MIN * pow (10.0, (double) -exponent))
|
||||
goto underflow;
|
||||
}
|
||||
else if (exponent > 0)
|
||||
{
|
||||
if (num > DBL_MAX * pow (10.0, (double) -exponent))
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
num *= pow (10.0, (double) exponent);
|
||||
|
||||
return num * sign;
|
||||
|
||||
overflow:
|
||||
/* Return an overflow error. */
|
||||
errno = ERANGE;
|
||||
return HUGE_VAL * sign;
|
||||
|
||||
underflow:
|
||||
/* Return an underflow error. */
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) nptr;
|
||||
errno = ERANGE;
|
||||
return 0.0;
|
||||
|
||||
noconv:
|
||||
/* There was no number. */
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) nptr;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_STRTOD */
|
213
lib/sh/strtol.c
Normal file
213
lib/sh/strtol.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/* strtol - Convert string representation of a number into an integer value.
|
||||
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_STRTOL)
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#ifndef __set_errno
|
||||
# define __set_errno(Val) errno = (Val)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include <bashansi.h>
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
/* Nonzero if we are defining `strtoul', operating on unsigned integers. */
|
||||
#ifndef UNSIGNED
|
||||
# define UNSIGNED 0
|
||||
# define RETTYPE long
|
||||
#else
|
||||
# define RETTYPE unsigned long
|
||||
#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)
|
||||
#endif
|
||||
|
||||
#ifndef LONG_MAX
|
||||
# define LONG_MAX ((long) (ULONG_MAX >> 1))
|
||||
# define LONG_MIN ((long) (0 - LONG_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 ENDPTR is not NULL, a pointer to the character after the last
|
||||
one converted is stored in *ENDPTR. */
|
||||
|
||||
RETTYPE
|
||||
strtol (nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
int base;
|
||||
{
|
||||
int negative;
|
||||
register unsigned long cutoff, i;
|
||||
register unsigned int cutlim;
|
||||
register const char *s;
|
||||
register unsigned char c;
|
||||
const char *save, *end;
|
||||
int overflow;
|
||||
|
||||
if (base < 0 || base == 1 || base > 36)
|
||||
base = 10;
|
||||
|
||||
save = s = nptr;
|
||||
|
||||
/* Skip white space. */
|
||||
while (isspace (*s))
|
||||
++s;
|
||||
if (*s == '\0')
|
||||
goto noconv;
|
||||
|
||||
/* Check for a sign. */
|
||||
if (*s == '-' || *s == '+')
|
||||
{
|
||||
negative = (*s == '-');
|
||||
++s;
|
||||
}
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
overflow = 0;
|
||||
i = 0;
|
||||
for (c = *s; c != '\0'; c = *++s)
|
||||
{
|
||||
if (s == end)
|
||||
break;
|
||||
|
||||
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
|
||||
{
|
||||
i *= (unsigned long int) base;
|
||||
i += c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if anything actually happened. */
|
||||
if (s == save)
|
||||
goto noconv;
|
||||
|
||||
/* Store in ENDPTR the address of one character
|
||||
past the last character we converted. */
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) s;
|
||||
|
||||
#if !UNSIGNED
|
||||
/* Check for a value that is within the range of
|
||||
`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))
|
||||
overflow = 1;
|
||||
#endif
|
||||
|
||||
if (overflow)
|
||||
{
|
||||
__set_errno (ERANGE);
|
||||
#if UNSIGNED
|
||||
return ULONG_MAX;
|
||||
#else
|
||||
return negative ? LONG_MIN : LONG_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the result with 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'. */
|
||||
if (endptr != NULL)
|
||||
{
|
||||
if (save - nptr >= 2 && toupper (save[-1]) == 'X' && save[-2] == '0')
|
||||
*endptr = (char *) &save[-1];
|
||||
else
|
||||
/* There was no number to convert. */
|
||||
*endptr = (char *) nptr;
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_STRTOL */
|
26
lib/sh/strtoul.c
Normal file
26
lib/sh/strtoul.c
Normal file
|
@ -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>
|
||||
|
||||
#ifndef HAVE_STRTOUL
|
||||
|
||||
#define UNSIGNED 1
|
||||
#undef HAVE_STRTOL
|
||||
|
||||
#include <strtol.c>
|
||||
|
||||
#endif /* !HAVE_STRTOUL */
|
85
lib/sh/vprint.c
Normal file
85
lib/sh/vprint.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* vprint.c -- v[fs]printf() for 4.[23] BSD systems. */
|
||||
|
||||
/* Copyright (C) 1987,1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (USE_VFPRINTF_EMULATION)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined (NULL)
|
||||
# if defined (__STDC__)
|
||||
# define NULL ((void *)0)
|
||||
# else
|
||||
# define NULL 0x0
|
||||
# endif /* __STDC__ */
|
||||
#endif /* !NULL */
|
||||
|
||||
/*
|
||||
* Beware! Don't trust the value returned by either of these functions; it
|
||||
* seems that pre-4.3-tahoe implementations of _doprnt () return the first
|
||||
* argument, i.e. a char *.
|
||||
*/
|
||||
#include <varargs.h>
|
||||
|
||||
int
|
||||
vfprintf (iop, fmt, ap)
|
||||
FILE *iop;
|
||||
char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
int len;
|
||||
char localbuf[BUFSIZ];
|
||||
|
||||
if (iop->_flag & _IONBF)
|
||||
{
|
||||
iop->_flag &= ~_IONBF;
|
||||
iop->_ptr = iop->_base = localbuf;
|
||||
len = _doprnt (fmt, ap, iop);
|
||||
(void) fflush (iop);
|
||||
iop->_flag |= _IONBF;
|
||||
iop->_base = NULL;
|
||||
iop->_bufsiz = 0;
|
||||
iop->_cnt = 0;
|
||||
}
|
||||
else
|
||||
len = _doprnt (fmt, ap, iop);
|
||||
return (ferror (iop) ? EOF : len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ditto for vsprintf
|
||||
*/
|
||||
int
|
||||
vsprintf (str, fmt, ap)
|
||||
char *str, *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
FILE f;
|
||||
int len;
|
||||
|
||||
f._flag = _IOWRT|_IOSTRG;
|
||||
f._ptr = str;
|
||||
f._cnt = 32767;
|
||||
len = _doprnt (fmt, ap, &f);
|
||||
*f._ptr = 0;
|
||||
return (len);
|
||||
}
|
||||
#endif /* USE_VFPRINTF_EMULATION */
|
|
@ -21,11 +21,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include <config.h>
|
||||
|
||||
/* Get the O_* definitions for open et al. */
|
||||
#ifndef _MINIX
|
||||
#include <sys/file.h>
|
||||
#ifdef USG5
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#else /* not HAVE_CONFIG_H */
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
|
@ -777,4 +778,3 @@ tprint (cap)
|
|||
}
|
||||
|
||||
#endif /* TEST */
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue