Merge remote-tracking branch 'origin/master' into feature/bignum
This commit is contained in:
commit
accb7b7ecc
220 changed files with 20431 additions and 5091 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -57,6 +57,7 @@ lib/execinfo.h
|
|||
lib/fcntl.h
|
||||
lib/getopt.h
|
||||
lib/getopt-cdefs.h
|
||||
lib/ieee754.h
|
||||
lib/inttypes.h
|
||||
lib/libgnu.a
|
||||
lib/limits.h
|
||||
|
|
|
@ -37,7 +37,7 @@ Kenichi Handa
|
|||
Mule
|
||||
|
||||
Stefan Monnier
|
||||
src/regex.c
|
||||
src/regex-emacs.c
|
||||
src/syntax.c
|
||||
src/keymap.c
|
||||
font-lock/jit-lock/syntax
|
||||
|
@ -61,7 +61,7 @@ Michael Albinus
|
|||
lisp/net/tramp*.el
|
||||
lisp/url/url-tramp.el
|
||||
doc/misc/tramp*.texi
|
||||
test/lisp/net/tramp-tests.el
|
||||
test/lisp/net/tramp*-tests.el
|
||||
test/lisp/url/url-tramp-tests.el
|
||||
|
||||
D-Bus
|
||||
|
@ -210,11 +210,21 @@ Paul Eggert
|
|||
Michael Albinus
|
||||
src/inotify.c
|
||||
lisp/autorevert.el
|
||||
lisp/files.el (file-name-non-special)
|
||||
lisp/eshell/em-tramp.el
|
||||
lisp/net/ange-ftp.el
|
||||
lisp/notifications.el
|
||||
lisp/shadowfile.el
|
||||
test/lisp/autorevert-tests.el
|
||||
test/lisp/files-tests.el (file-name-non-special)
|
||||
test/lisp/shadowfile-tests.el
|
||||
test/src/inotify-test.el
|
||||
|
||||
Secret Service API in
|
||||
lisp/auth-source.el
|
||||
doc/misc/auth.texi
|
||||
test/lisp/auth-source-tests.el
|
||||
|
||||
Nicolas Petton
|
||||
lisp/emacs-lisp/subr-x.el
|
||||
lisp/arc-mode.el
|
||||
|
|
|
@ -57,7 +57,7 @@ Each entry has the form (FUNCTION . FUNCTIONS-IT-CALLS).")
|
|||
"keymap.c" "sysdep.c" "buffer.c" "filelock.c"
|
||||
"insdel.c" "marker.c" "minibuf.c" "fileio.c"
|
||||
"dired.c" "cmds.c" "casefiddle.c"
|
||||
"indent.c" "search.c" "regex.c" "undo.c"
|
||||
"indent.c" "search.c" "regex-emacs.c" "undo.c"
|
||||
"alloc.c" "data.c" "doc.c" "editfns.c"
|
||||
"callint.c" "eval.c" "fns.c" "print.c" "lread.c"
|
||||
"syntax.c" "unexcoff.c"
|
||||
|
|
|
@ -35,9 +35,9 @@ GNULIB_MODULES='
|
|||
fcntl fcntl-h fdatasync fdopendir
|
||||
filemode filevercmp flexmember fpieee fstatat fsusage fsync
|
||||
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
|
||||
ignore-value intprops largefile lstat
|
||||
ieee754-h ignore-value intprops largefile lstat
|
||||
manywarnings memrchr minmax mkostemp mktime nstrftime
|
||||
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
||||
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat regex
|
||||
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
|
||||
stpcpy strtoimax symlink sys_stat sys_time
|
||||
tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
|
||||
|
@ -46,11 +46,12 @@ GNULIB_MODULES='
|
|||
'
|
||||
|
||||
AVOIDED_MODULES='
|
||||
close dup fchdir fstat
|
||||
malloc-posix msvc-inval msvc-nothrow
|
||||
btowc close dup fchdir fstat langinfo lock
|
||||
malloc-posix mbrtowc mbsinit msvc-inval msvc-nothrow nl_langinfo
|
||||
openat-die opendir raise
|
||||
save-cwd select setenv sigprocmask stat stdarg stdbool
|
||||
threadlib tzset unsetenv utime utime-h
|
||||
wchar wcrtomb wctype-h
|
||||
'
|
||||
|
||||
GNULIB_TOOL_FLAGS='
|
||||
|
|
114
build-aux/config.guess
vendored
114
build-aux/config.guess
vendored
|
@ -2,7 +2,7 @@
|
|||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2018 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2018-07-06'
|
||||
timestamp='2018-08-02'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
|
@ -84,8 +84,6 @@ if test $# != 0; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
|
||||
# compiler to aid in system detection is discouraged as it requires
|
||||
# temporary files to be created and, as you can see below, it is a
|
||||
|
@ -96,34 +94,39 @@ trap 'exit 1' 1 2 15
|
|||
|
||||
# Portable tmp directory creation inspired by the Autoconf team.
|
||||
|
||||
set_cc_for_build='
|
||||
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
|
||||
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
|
||||
: ${TMPDIR=/tmp} ;
|
||||
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
|
||||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } ||
|
||||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
|
||||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
|
||||
dummy=$tmp/dummy ;
|
||||
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
|
||||
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
|
||||
,,) echo "int x;" > "$dummy.c" ;
|
||||
for c in cc gcc c89 c99 ; do
|
||||
if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
|
||||
CC_FOR_BUILD="$c"; break ;
|
||||
fi ;
|
||||
done ;
|
||||
if test x"$CC_FOR_BUILD" = x ; then
|
||||
CC_FOR_BUILD=no_compiler_found ;
|
||||
fi
|
||||
;;
|
||||
,,*) CC_FOR_BUILD=$CC ;;
|
||||
,*,*) CC_FOR_BUILD=$HOST_CC ;;
|
||||
esac ; set_cc_for_build= ;'
|
||||
tmp=
|
||||
# shellcheck disable=SC2172
|
||||
trap 'test -z "$tmp" || rm -fr "$tmp"' 1 2 13 15
|
||||
trap 'exitcode=$?; test -z "$tmp" || rm -fr "$tmp"; exit $exitcode' 0
|
||||
|
||||
set_cc_for_build() {
|
||||
: "${TMPDIR=/tmp}"
|
||||
# shellcheck disable=SC2039
|
||||
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
|
||||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
|
||||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
|
||||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
|
||||
dummy=$tmp/dummy
|
||||
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
|
||||
,,) echo "int x;" > "$dummy.c"
|
||||
for driver in cc gcc c89 c99 ; do
|
||||
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
|
||||
CC_FOR_BUILD="$driver"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test x"$CC_FOR_BUILD" = x ; then
|
||||
CC_FOR_BUILD=no_compiler_found
|
||||
fi
|
||||
;;
|
||||
,,*) CC_FOR_BUILD=$CC ;;
|
||||
,*,*) CC_FOR_BUILD=$HOST_CC ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
|
||||
# (ghazi@noc.rutgers.edu 1994-08-24)
|
||||
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
|
||||
if test -f /.attbin/uname ; then
|
||||
PATH=$PATH:/.attbin ; export PATH
|
||||
fi
|
||||
|
||||
|
@ -138,7 +141,7 @@ Linux|GNU|GNU/*)
|
|||
# We could probably try harder.
|
||||
LIBC=gnu
|
||||
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
cat <<-EOF > "$dummy.c"
|
||||
#include <features.h>
|
||||
#if defined(__UCLIBC__)
|
||||
|
@ -199,7 +202,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
|||
os=netbsdelf
|
||||
;;
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ELF__
|
||||
then
|
||||
|
@ -389,20 +392,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
|||
echo i386-pc-auroraux"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
eval "$set_cc_for_build"
|
||||
SUN_ARCH=i386
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
SUN_ARCH=x86_64
|
||||
fi
|
||||
fi
|
||||
echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
|
||||
UNAME_REL="`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
|
||||
case `isainfo -b` in
|
||||
32)
|
||||
echo i386-pc-solaris2"$UNAME_REL"
|
||||
;;
|
||||
64)
|
||||
echo x86_64-pc-solaris2"$UNAME_REL"
|
||||
;;
|
||||
esac
|
||||
exit ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
# According to config.sub, this is the proper way to canonicalize
|
||||
|
@ -482,7 +480,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
|||
echo clipper-intergraph-clix"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
mips:*:*:UMIPS | mips:*:*:RISCos)
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
#ifdef __cplusplus
|
||||
#include <stdio.h> /* for printf() prototype */
|
||||
|
@ -579,7 +577,7 @@ EOF
|
|||
exit ;;
|
||||
*:AIX:2:3)
|
||||
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
|
@ -660,7 +658,7 @@ EOF
|
|||
esac
|
||||
fi
|
||||
if [ "$HP_ARCH" = "" ]; then
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
|
||||
#define _HPUX_SOURCE
|
||||
|
@ -700,7 +698,7 @@ EOF
|
|||
esac
|
||||
if [ "$HP_ARCH" = hppa2.0w ]
|
||||
then
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
|
||||
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
|
||||
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
|
||||
|
@ -726,7 +724,7 @@ EOF
|
|||
echo ia64-hp-hpux"$HPUX_REV"
|
||||
exit ;;
|
||||
3050*:HI-UX:*:*)
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
#include <unistd.h>
|
||||
int
|
||||
|
@ -840,6 +838,17 @@ EOF
|
|||
*:BSD/OS:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
arm*:FreeBSD:*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
set_cc_for_build
|
||||
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_PCS_VFP
|
||||
then
|
||||
echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
|
||||
else
|
||||
echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
|
||||
fi
|
||||
exit ;;
|
||||
*:FreeBSD:*:*)
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
case "$UNAME_PROCESSOR" in
|
||||
|
@ -922,7 +931,7 @@ EOF
|
|||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
arm*:Linux:*:*)
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_EABI__
|
||||
then
|
||||
|
@ -971,7 +980,7 @@ EOF
|
|||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
mips:Linux:*:* | mips64:Linux:*:*)
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
#undef CPU
|
||||
#undef ${UNAME_MACHINE}
|
||||
|
@ -1285,7 +1294,7 @@ EOF
|
|||
exit ;;
|
||||
*:Darwin:*:*)
|
||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||
eval "$set_cc_for_build"
|
||||
set_cc_for_build
|
||||
if test "$UNAME_PROCESSOR" = unknown ; then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
|
@ -1358,6 +1367,7 @@ EOF
|
|||
# "uname -m" is not consistent, so use $cputype instead. 386
|
||||
# is converted to i386 for consistency with other x86
|
||||
# operating systems.
|
||||
# shellcheck disable=SC2154
|
||||
if test "$cputype" = 386; then
|
||||
UNAME_MACHINE=i386
|
||||
else
|
||||
|
|
10
build-aux/config.sub
vendored
10
build-aux/config.sub
vendored
|
@ -2,7 +2,7 @@
|
|||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2018 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2018-07-03'
|
||||
timestamp='2018-07-25'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
|
@ -307,7 +307,7 @@ case $1 in
|
|||
os=mach
|
||||
;;
|
||||
vsta)
|
||||
basic_machine=i386-unknown
|
||||
basic_machine=i386-pc
|
||||
os=vsta
|
||||
;;
|
||||
isi68 | isi)
|
||||
|
@ -371,7 +371,7 @@ case $1 in
|
|||
os=sysv4
|
||||
;;
|
||||
netbsd386)
|
||||
basic_machine=i386-unknown
|
||||
basic_machine=i386-pc
|
||||
os=netbsd
|
||||
;;
|
||||
netwinder)
|
||||
|
@ -739,6 +739,7 @@ case $basic_machine in
|
|||
| mipsr5900-* | mipsr5900el-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| moxie-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
|
@ -1263,9 +1264,6 @@ case $basic_machine in
|
|||
pmac | pmac-mpw)
|
||||
basic_machine=powerpc-apple
|
||||
;;
|
||||
*-unknown)
|
||||
# Make sure to match an already-canonicalized machine name.
|
||||
;;
|
||||
*)
|
||||
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
|
||||
exit 1
|
||||
|
|
|
@ -5483,9 +5483,10 @@ echo
|
|||
|
||||
if test "$HAVE_NS" = "yes"; then
|
||||
echo
|
||||
AS_ECHO(["You must run \"${MAKE-make} install\" in order to test the built application.
|
||||
The installed application will go to nextstep/Emacs.app and can be
|
||||
run or moved from there."])
|
||||
AS_ECHO(["Run '${MAKE-make}' to build Emacs, then run 'src/emacs' to test it.
|
||||
Run '${MAKE-make} install' in order to build an application bundle.
|
||||
The application will go to nextstep/Emacs.app and can be run or moved
|
||||
from there."])
|
||||
if test "$EN_NS_SELF_CONTAINED" = "yes"; then
|
||||
echo "The application will be fully self-contained."
|
||||
else
|
||||
|
|
|
@ -1468,6 +1468,11 @@ rotation is lossless, and uses an external utility called
|
|||
directory's name, and creates that directory. It signals an error if
|
||||
the directory already exists.
|
||||
|
||||
@findex dired-create-empty-file
|
||||
The command (@code{dired-create-empty-file}) reads a
|
||||
file name, and creates that file. It signals an error if
|
||||
the file already exists.
|
||||
|
||||
@cindex searching multiple files via Dired
|
||||
@kindex M-s a C-s @r{(Dired)}
|
||||
@kindex M-s a M-C-s @r{(Dired)}
|
||||
|
|
|
@ -881,6 +881,8 @@ You can answer ``no'' to bypass copying of this file, this time. If
|
|||
you want to cancel the shadowing permanently for a certain file, use
|
||||
@w{@kbd{M-x shadow-cancel}} to eliminate or change the shadow file group.
|
||||
|
||||
File Shadowing is not available on MS Windows.
|
||||
|
||||
@node Time Stamps
|
||||
@subsection Updating Time Stamps Automatically
|
||||
@cindex time stamps
|
||||
|
|
|
@ -427,11 +427,15 @@ dictionary.
|
|||
@cindex mode, Flyspell
|
||||
@findex flyspell-mode
|
||||
Flyspell mode is a minor mode that performs automatic spell-checking
|
||||
as you type. When it finds a word that it does not recognize, it
|
||||
highlights that word. Type @kbd{M-x flyspell-mode} to toggle Flyspell
|
||||
mode in the current buffer. To enable Flyspell mode in all text mode
|
||||
buffers, add @code{flyspell-mode} to @code{text-mode-hook}.
|
||||
@xref{Hooks}.
|
||||
of the text you type as you type it. When it finds a word that it
|
||||
does not recognize, it highlights that word. Type @kbd{M-x
|
||||
flyspell-mode} to toggle Flyspell mode in the current buffer. To
|
||||
enable Flyspell mode in all text mode buffers, add
|
||||
@code{flyspell-mode} to @code{text-mode-hook}. @xref{Hooks}. Note
|
||||
that, as Flyspell mode needs to check each word across which you move,
|
||||
it will slow down cursor motion and scrolling commands. It also
|
||||
doesn't automatically check the text you didn't type or move across;
|
||||
use @code{flyspell-region} or @code{flyspell-buffer} for that.
|
||||
|
||||
@findex flyspell-correct-word
|
||||
@findex flyspell-auto-correct-word
|
||||
|
|
|
@ -60,9 +60,9 @@ repositioned to the first non-whitespace character on the line.
|
|||
@node Indentation Commands
|
||||
@section Indentation Commands
|
||||
|
||||
Apart from the @key{TAB} (@code{indent-for-tab-command}) command,
|
||||
Emacs provides a variety of commands to perform indentation in other
|
||||
ways.
|
||||
Apart from the @kbd{@key{TAB}} (@code{indent-for-tab-command})
|
||||
command, Emacs provides a variety of commands to perform indentation
|
||||
in other ways.
|
||||
|
||||
@table @kbd
|
||||
@item C-M-o
|
||||
|
@ -113,8 +113,8 @@ appears after the newline that is deleted. @xref{Fill Prefix}.
|
|||
@item C-M-\
|
||||
@kindex C-M-\
|
||||
@findex indent-region
|
||||
Indent all the lines in the region, as though you had typed @key{TAB}
|
||||
at the beginning of each line (@code{indent-region}).
|
||||
Indent all the lines in the region, as though you had typed
|
||||
@kbd{@key{TAB}} at the beginning of each line (@code{indent-region}).
|
||||
|
||||
If a numeric argument is supplied, indent every line in the region to
|
||||
that column number.
|
||||
|
@ -128,11 +128,12 @@ in the region, moving the affected lines as a rigid unit.
|
|||
|
||||
If called with no argument, the command activates a transient mode for
|
||||
adjusting the indentation of the affected lines interactively. While
|
||||
this transient mode is active, typing @key{LEFT} or @key{RIGHT}
|
||||
indents leftward and rightward, respectively, by one space. You can
|
||||
also type @kbd{S-@key{LEFT}} or @kbd{S-@key{RIGHT}} to indent leftward
|
||||
or rightward to the next tab stop (@pxref{Tab Stops}). Typing any
|
||||
other key disables the transient mode, and resumes normal editing.
|
||||
this transient mode is active, typing @kbd{@key{LEFT}} or
|
||||
@kbd{@key{RIGHT}} indents leftward and rightward, respectively, by one
|
||||
space. You can also type @kbd{S-@key{LEFT}} or @kbd{S-@key{RIGHT}} to
|
||||
indent leftward or rightward to the next tab stop (@pxref{Tab Stops}).
|
||||
Typing any other key disables the transient mode, and resumes normal
|
||||
editing.
|
||||
|
||||
If called with a prefix argument @var{n}, this command indents the
|
||||
lines forward by @var{n} spaces (without enabling the transient mode).
|
||||
|
|
|
@ -1655,10 +1655,20 @@ not just to the next change log entry. You can also use
|
|||
log files into a buffer in Change Log Mode, preserving the date
|
||||
ordering of entries.
|
||||
|
||||
@vindex add-log-dont-create-changelog-file
|
||||
Version control systems are another way to keep track of changes in
|
||||
your program and keep a change log. In the VC log buffer, typing
|
||||
@kbd{C-c C-a} (@code{log-edit-insert-changelog}) inserts the relevant
|
||||
change log entry, if one exists. @xref{Log Buffer}.
|
||||
your program and keep a change log. Many projects that use a VCS don't
|
||||
keep a separate versioned change log file nowadays, so you may wish to
|
||||
avoid having such a file in the repository. If the value of
|
||||
@code{add-log-dont-create-changelog-file} is non-@code{nil}, commands
|
||||
like @kbd{C-x 4 a} (@code{add-change-log-entry-other-window}) will
|
||||
record changes in a suitably named temporary buffer instead of a file,
|
||||
if such a file does not already exist.
|
||||
|
||||
Whether you have a change log file or use a temporary buffer for
|
||||
change logs, you can type @kbd{C-c C-a}
|
||||
(@code{log-edit-insert-changelog}) in the VC Log buffer to insert the
|
||||
relevant change log entries, if they exist. @xref{Log Buffer}.
|
||||
|
||||
@node Format of ChangeLog
|
||||
@subsection Format of ChangeLog
|
||||
|
|
|
@ -1026,8 +1026,8 @@ Move backward across one shell command, but not beyond the current line
|
|||
Ask the shell for its working directory, and update the Shell buffer's
|
||||
default directory. @xref{Directory Tracking}.
|
||||
|
||||
@item M-x send-invisible @key{RET} @var{text} @key{RET}
|
||||
@findex send-invisible
|
||||
@item M-x comint-send-invisible @key{RET} @var{text} @key{RET}
|
||||
@findex comint-send-invisible
|
||||
Send @var{text} as input to the shell, after reading it without
|
||||
echoing. This is useful when a shell command runs a program that asks
|
||||
for a password.
|
||||
|
|
|
@ -156,12 +156,19 @@ system encodes the character safely and with a single byte
|
|||
(@pxref{Coding Systems}). If the character's encoding is longer than
|
||||
one byte, Emacs shows @samp{file ...}.
|
||||
|
||||
As a special case, if the character lies in the range 128 (0200
|
||||
octal) through 159 (0237 octal), it stands for a raw byte that
|
||||
does not correspond to any specific displayable character. Such a
|
||||
character lies within the @code{eight-bit-control} character set,
|
||||
and is displayed as an escaped octal character code. In this case,
|
||||
@kbd{C-x =} shows @samp{part of display ...} instead of @samp{file}.
|
||||
@cindex eight-bit character set
|
||||
@cindex raw bytes
|
||||
On rare occasions, Emacs encounters @dfn{raw bytes}: single bytes
|
||||
whose values are in the range 128 (0200 octal) through 255 (0377
|
||||
octal), which Emacs cannot interpret as part of a known encoding of
|
||||
some non-ASCII character. Such raw bytes are treated as if they
|
||||
belonged to a special character set @code{eight-bit}; Emacs displays
|
||||
them as escaped octal codes (this can be customized; @pxref{Display
|
||||
Custom}). In this case, @kbd{C-x =} shows @samp{raw-byte} instead of
|
||||
@samp{file}. In addition, @kbd{C-x =} shows the character codes of
|
||||
raw bytes as if they were in the range @code{#x3FFF80..#x3FFFFF},
|
||||
which is where Emacs maps them to distinguish them from Unicode
|
||||
characters in the range @code{#x0080..#x00FF}.
|
||||
|
||||
@cindex character set of character at point
|
||||
@cindex font of character at point
|
||||
|
|
|
@ -80,7 +80,9 @@ information until you store something else in it.
|
|||
@kindex C-x r j
|
||||
@findex jump-to-register
|
||||
The command @kbd{C-x r j @var{r}} switches to the buffer recorded in
|
||||
register @var{r}, and moves point to the recorded position. The
|
||||
register @var{r}, pushes a mark, and moves point to the recorded
|
||||
position. (The mark is not pushed if point was already at the
|
||||
recorded position, or in successive calls to the command.) The
|
||||
contents of the register are not changed, so you can jump to the saved
|
||||
position any number of times.
|
||||
|
||||
|
|
|
@ -81,7 +81,8 @@ debugger recursively. @xref{Recursive Editing}.
|
|||
* Function Debugging:: Entering it when a certain function is called.
|
||||
* Variable Debugging:: Entering it when a variable is modified.
|
||||
* Explicit Debug:: Entering it at a certain point in the program.
|
||||
* Using Debugger:: What the debugger does; what you see while in it.
|
||||
* Using Debugger:: What the debugger does.
|
||||
* Backtraces:: What you see while in the debugger.
|
||||
* Debugger Commands:: Commands used while in the debugger.
|
||||
* Invoking the Debugger:: How to call the function @code{debug}.
|
||||
* Internals of Debugger:: Subroutines of the debugger, and global variables.
|
||||
|
@ -392,32 +393,82 @@ this is not what you want, you can either set
|
|||
@code{eval-expression-debug-on-error} to @code{nil}, or set
|
||||
@code{debug-on-error} to @code{nil} in @code{debugger-mode-hook}.
|
||||
|
||||
@cindex current stack frame
|
||||
The backtrace buffer shows you the functions that are executing and
|
||||
their argument values. It also allows you to specify a stack frame by
|
||||
moving point to the line describing that frame. (A stack frame is the
|
||||
place where the Lisp interpreter records information about a particular
|
||||
invocation of a function.) The frame whose line point is on is
|
||||
considered the @dfn{current frame}. Some of the debugger commands
|
||||
operate on the current frame. If a line starts with a star, that means
|
||||
that exiting that frame will call the debugger again. This is useful
|
||||
for examining the return value of a function.
|
||||
|
||||
If a function name is underlined, that means the debugger knows
|
||||
where its source code is located. You can click with the mouse on
|
||||
that name, or move to it and type @key{RET}, to visit the source code.
|
||||
|
||||
The debugger itself must be run byte-compiled, since it makes
|
||||
assumptions about how many stack frames are used for the debugger
|
||||
itself. These assumptions are false if the debugger is running
|
||||
interpreted.
|
||||
assumptions about the state of the Lisp interpreter. These
|
||||
assumptions are false if the debugger is running interpreted.
|
||||
|
||||
@node Backtraces
|
||||
@subsection Backtraces
|
||||
@cindex backtrace buffer
|
||||
|
||||
Debugger mode is derived from Backtrace mode, which is also used to
|
||||
show backtraces by Edebug and ERT. (@pxref{Edebug}, and @ref{Top,the
|
||||
ERT manual,, ert, ERT: Emacs Lisp Regression Testing}.)
|
||||
|
||||
@cindex stack frame
|
||||
The backtrace buffer shows you the functions that are executing and
|
||||
their argument values. When a backtrace buffer is created, it shows
|
||||
each stack frame on one, possibly very long, line. (A stack frame is
|
||||
the place where the Lisp interpreter records information about a
|
||||
particular invocation of a function.) The most recently called
|
||||
function will be at the top.
|
||||
|
||||
@cindex current stack frame
|
||||
In a backtrace you can specify a stack frame by moving point to a line
|
||||
describing that frame. The frame whose line point is on is considered
|
||||
the @dfn{current frame}.
|
||||
|
||||
If a function name is underlined, that means Emacs knows where its
|
||||
source code is located. You can click with the mouse on that name, or
|
||||
move to it and type @key{RET}, to visit the source code. You can also
|
||||
type @key{RET} while point is on any name of a function or variable
|
||||
which is not underlined, to see help information for that symbol in a
|
||||
help buffer, if any exists. The @code{xref-find-definitions} command,
|
||||
bound to @key{M-.}, can also be used on any identifier in a backtrace
|
||||
(@pxref{Looking Up Identifiers,,,emacs, The GNU Emacs Manual}).
|
||||
|
||||
In backtraces, the tails of long lists and the ends of long strings,
|
||||
vectors or structures, as well as objects which are deeply nested,
|
||||
will be printed as underlined ``...''. You can click with the mouse
|
||||
on a ``...'', or type @key{RET} while point is on it, to show the part
|
||||
of the object that was hidden. To control how much abbreviation is
|
||||
done, customize @code{backtrace-line-length}.
|
||||
|
||||
Here is a list of commands for navigating and viewing backtraces:
|
||||
|
||||
@table @kbd
|
||||
@item v
|
||||
Toggle the display of local variables of the current stack frame.
|
||||
|
||||
@item p
|
||||
Move to the beginning of the frame, or to the beginning
|
||||
of the previous frame.
|
||||
|
||||
@item n
|
||||
Move to the beginning of the next frame.
|
||||
|
||||
@item +
|
||||
Add line breaks and indentation to the top-level Lisp form at point to
|
||||
make it more readable.
|
||||
|
||||
@item -
|
||||
Collapse the top-level Lisp form at point back to a single line.
|
||||
|
||||
@item #
|
||||
Toggle @code{print-circle} for the frame at point.
|
||||
|
||||
@item .
|
||||
Expand all the forms abbreviated with ``...'' in the frame at point.
|
||||
|
||||
@end table
|
||||
|
||||
@node Debugger Commands
|
||||
@subsection Debugger Commands
|
||||
@cindex debugger command list
|
||||
|
||||
The debugger buffer (in Debugger mode) provides special commands in
|
||||
addition to the usual Emacs commands. The most important use of
|
||||
addition to the usual Emacs commands and to the Backtrace mode commands
|
||||
described in the previous section. The most important use of
|
||||
debugger commands is for stepping through code, so that you can see
|
||||
how control flows. The debugger can step through the control
|
||||
structures of an interpreted function, but cannot do so in a
|
||||
|
@ -427,6 +478,11 @@ the same function. (To do this, visit the source for the function and
|
|||
type @kbd{C-M-x} on its definition.) You cannot use the Lisp debugger
|
||||
to step through a primitive function.
|
||||
|
||||
Some of the debugger commands operate on the current frame. If a
|
||||
frame starts with a star, that means that exiting that frame will call the
|
||||
debugger again. This is useful for examining the return value of a
|
||||
function.
|
||||
|
||||
@c FIXME: Add @findex for the following commands? --xfq
|
||||
Here is a list of Debugger mode commands:
|
||||
|
||||
|
@ -502,8 +558,6 @@ Display a list of functions that will invoke the debugger when called.
|
|||
This is a list of functions that are set to break on entry by means of
|
||||
@code{debug-on-entry}.
|
||||
|
||||
@item v
|
||||
Toggle the display of local variables of the current stack frame.
|
||||
@end table
|
||||
|
||||
@node Invoking the Debugger
|
||||
|
@ -624,20 +678,19 @@ of @code{debug} (@pxref{Invoking the Debugger}).
|
|||
@cindex run time stack
|
||||
@cindex call stack
|
||||
This function prints a trace of Lisp function calls currently active.
|
||||
This is the function used by @code{debug} to fill up the
|
||||
@file{*Backtrace*} buffer. It is written in C, since it must have access
|
||||
to the stack to determine which function calls are active. The return
|
||||
value is always @code{nil}.
|
||||
The trace is identical to the one that @code{debug} would show in the
|
||||
@file{*Backtrace*} buffer. The return value is always nil.
|
||||
|
||||
In the following example, a Lisp expression calls @code{backtrace}
|
||||
explicitly. This prints the backtrace to the stream
|
||||
@code{standard-output}, which, in this case, is the buffer
|
||||
@samp{backtrace-output}.
|
||||
|
||||
Each line of the backtrace represents one function call. The line shows
|
||||
the values of the function's arguments if they are all known; if they
|
||||
are still being computed, the line says so. The arguments of special
|
||||
forms are elided.
|
||||
Each line of the backtrace represents one function call. The line
|
||||
shows the function followed by a list of the values of the function's
|
||||
arguments if they are all known; if they are still being computed, the
|
||||
line consists of a list containing the function and its unevaluated
|
||||
arguments. Long lists or deeply nested structures may be elided.
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
|
@ -654,7 +707,7 @@ forms are elided.
|
|||
@group
|
||||
----------- Buffer: backtrace-output ------------
|
||||
backtrace()
|
||||
(list ...computing arguments...)
|
||||
(list 'testing (backtrace))
|
||||
@end group
|
||||
(progn ...)
|
||||
eval((progn (1+ var) (list 'testing (backtrace))))
|
||||
|
@ -685,7 +738,7 @@ example would look as follows:
|
|||
@group
|
||||
----------- Buffer: backtrace-output ------------
|
||||
(backtrace)
|
||||
(list ...computing arguments...)
|
||||
(list 'testing (backtrace))
|
||||
@end group
|
||||
(progn ...)
|
||||
(eval (progn (1+ var) (list 'testing (backtrace))))
|
||||
|
|
|
@ -442,8 +442,16 @@ Redisplay the most recently known expression result in the echo area
|
|||
Display a backtrace, excluding Edebug's own functions for clarity
|
||||
(@code{edebug-backtrace}).
|
||||
|
||||
You cannot use debugger commands in the backtrace buffer in Edebug as
|
||||
you would in the standard debugger.
|
||||
@xref{Backtraces}, for a description of backtraces
|
||||
and the commands which work on them.
|
||||
|
||||
If you would like to see Edebug's functions in the backtrace,
|
||||
use @kbd{M-x edebug-backtrace-show-instrumentation}. To hide them
|
||||
again use @kbd{M-x edebug-backtrace-hide-instrumentation}.
|
||||
|
||||
If a backtrace frame starts with @samp{>} that means that Edebug knows
|
||||
where the source code for the frame is located. Use @kbd{s} to jump
|
||||
to the source code for the current frame.
|
||||
|
||||
The backtrace buffer is killed automatically when you continue
|
||||
execution.
|
||||
|
|
|
@ -507,9 +507,6 @@ Emacs Lisp with a reference to where each is described.
|
|||
@item setq-default
|
||||
@pxref{Creating Buffer-Local}
|
||||
|
||||
@item track-mouse
|
||||
@pxref{Mouse Tracking}
|
||||
|
||||
@item unwind-protect
|
||||
@pxref{Nonlocal Exits}
|
||||
|
||||
|
|
|
@ -3005,10 +3005,16 @@ This command creates a directory named @var{dirname}. If
|
|||
@var{parents} is non-@code{nil}, as is always the case in an
|
||||
interactive call, that means to create the parent directories first,
|
||||
if they don't already exist.
|
||||
|
||||
@code{mkdir} is an alias for this.
|
||||
@end deffn
|
||||
|
||||
@deffn Command make-empty-file filename &optional parents
|
||||
This command creates an empty file named @var{filename}.
|
||||
As @code{make-directory}, this command creates parent directories
|
||||
if @var{parents} is non-@code{nil}.
|
||||
If @var{filename} already exists, this command signals an error.
|
||||
@end deffn
|
||||
|
||||
@deffn Command copy-directory dirname newname &optional keep-time parents copy-contents
|
||||
This command copies the directory named @var{dirname} to
|
||||
@var{newname}. If @var{newname} is a directory name,
|
||||
|
|
|
@ -3373,10 +3373,10 @@ occur. That is useful, because normally you don't want to track the
|
|||
mouse forever---only until some other event, such as the release of a
|
||||
button.
|
||||
|
||||
@defspec track-mouse body@dots{}
|
||||
This special form executes @var{body}, with generation of mouse motion
|
||||
events enabled. Typically, @var{body} would use @code{read-event} to
|
||||
read the motion events and modify the display accordingly. @xref{Motion
|
||||
@defmac track-mouse body@dots{}
|
||||
This macro executes @var{body}, with generation of mouse motion events
|
||||
enabled. Typically, @var{body} would use @code{read-event} to read
|
||||
the motion events and modify the display accordingly. @xref{Motion
|
||||
Events}, for the format of mouse motion events.
|
||||
|
||||
The value of @code{track-mouse} is that of the last form in @var{body}.
|
||||
|
@ -3396,7 +3396,7 @@ on (@pxref{Pointer Shape}). Therefore, Lisp programs that need the
|
|||
mouse pointer to retain its original shape during dragging should bind
|
||||
@code{track-mouse} to the value @code{dragging} at the beginning of
|
||||
their @var{body}.
|
||||
@end defspec
|
||||
@end defmac
|
||||
|
||||
The usual purpose of tracking mouse motion is to indicate on the screen
|
||||
the consequences of pushing or releasing a button at the current
|
||||
|
|
|
@ -50,16 +50,19 @@ convention; at the level of cons cells, the @sc{car} and @sc{cdr}
|
|||
slots have similar properties). Hence, the @sc{cdr} slot of each cons
|
||||
cell in a list refers to the following cons cell.
|
||||
|
||||
@cindex proper list
|
||||
@cindex true list
|
||||
Also by convention, the @sc{cdr} of the last cons cell in a list is
|
||||
@code{nil}. We call such a @code{nil}-terminated structure a
|
||||
@dfn{true list}. In Emacs Lisp, the symbol @code{nil} is both a
|
||||
symbol and a list with no elements. For convenience, the symbol
|
||||
@code{nil} is considered to have @code{nil} as its @sc{cdr} (and also
|
||||
as its @sc{car}).
|
||||
@dfn{proper list}@footnote{It is sometimes also referred to as a
|
||||
@dfn{true list}, but we generally do not use this terminology in this
|
||||
manual.}. In Emacs Lisp, the symbol @code{nil} is both a symbol and a
|
||||
list with no elements. For convenience, the symbol @code{nil} is
|
||||
considered to have @code{nil} as its @sc{cdr} (and also as its
|
||||
@sc{car}).
|
||||
|
||||
Hence, the @sc{cdr} of a true list is always a true list. The
|
||||
@sc{cdr} of a nonempty true list is a true list containing all the
|
||||
Hence, the @sc{cdr} of a proper list is always a proper list. The
|
||||
@sc{cdr} of a nonempty proper list is a proper list containing all the
|
||||
elements except the first.
|
||||
|
||||
@cindex dotted list
|
||||
|
@ -71,10 +74,10 @@ Pair Notation}). There is one other possibility: some cons cell's
|
|||
@sc{cdr} could point to one of the previous cons cells in the list.
|
||||
We call that structure a @dfn{circular list}.
|
||||
|
||||
For some purposes, it does not matter whether a list is true,
|
||||
For some purposes, it does not matter whether a list is proper,
|
||||
circular or dotted. If a program doesn't look far enough down the
|
||||
list to see the @sc{cdr} of the final cons cell, it won't care.
|
||||
However, some functions that operate on lists demand true lists and
|
||||
However, some functions that operate on lists demand proper lists and
|
||||
signal errors if given a dotted list. Most functions that try to find
|
||||
the end of a list enter infinite loops if given a circular list.
|
||||
|
||||
|
@ -538,7 +541,7 @@ object. The final argument is not copied or converted; it becomes the
|
|||
is itself a list, then its elements become in effect elements of the
|
||||
result list. If the final element is not a list, the result is a
|
||||
dotted list since its final @sc{cdr} is not @code{nil} as required
|
||||
in a true list.
|
||||
in a proper list (@pxref{Cons Cells}).
|
||||
@end defun
|
||||
|
||||
Here is an example of using @code{append}:
|
||||
|
|
|
@ -2199,7 +2199,7 @@ function @code{read-passwd}.
|
|||
@defun read-passwd prompt &optional confirm default
|
||||
This function reads a password, prompting with @var{prompt}. It does
|
||||
not echo the password as the user types it; instead, it echoes
|
||||
@samp{.} for each character in the password. If you want to apply
|
||||
@samp{*} for each character in the password. If you want to apply
|
||||
another character to hide the password, let-bind the variable
|
||||
@code{read-hide-char} with that character.
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ least one digit after any decimal point in a floating-point number;
|
|||
@samp{1500.} is an integer, not a floating-point number.
|
||||
|
||||
Emacs Lisp treats @code{-0.0} as numerically equal to ordinary zero
|
||||
with respect to @code{equal} and @code{=}. This follows the
|
||||
with respect to numeric comparisons like @code{=}. This follows the
|
||||
@acronym{IEEE} floating-point standard, which says @code{-0.0} and
|
||||
@code{0.0} are numerically equal even though other operations can
|
||||
distinguish them.
|
||||
|
@ -227,8 +227,20 @@ infinity and negative infinity as floating-point values. It also
|
|||
provides for a class of values called NaN, or ``not a number'';
|
||||
numerical functions return such values in cases where there is no
|
||||
correct answer. For example, @code{(/ 0.0 0.0)} returns a NaN@.
|
||||
Although NaN values carry a sign, for practical purposes there is no other
|
||||
significant difference between different NaN values in Emacs Lisp.
|
||||
A NaN is never numerically equal to any value, not even to itself.
|
||||
NaNs carry a sign and a significand, and non-numeric functions treat
|
||||
two NaNs as equal when their
|
||||
signs and significands agree. Significands of NaNs are
|
||||
machine-dependent, as are the digits in their string representation.
|
||||
|
||||
When NaNs and signed zeros are involved, non-numeric functions like
|
||||
@code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and
|
||||
@code{gethash} determine whether values are indistinguishable, not
|
||||
whether they are numerically equal. For example, when @var{x} and
|
||||
@var{y} are the same NaN, @code{(equal x y)} returns @code{t} whereas
|
||||
@code{(= x y)} uses numeric comparison and returns @code{nil};
|
||||
conversely, @code{(equal 0.0 -0.0)} returns @code{nil} whereas
|
||||
@code{(= 0.0 -0.0)} returns @code{t}.
|
||||
|
||||
Here are read syntaxes for these special floating-point values:
|
||||
|
||||
|
@ -358,11 +370,15 @@ if so, @code{nil} otherwise. The argument must be a number.
|
|||
@cindex comparing numbers
|
||||
|
||||
To test numbers for numerical equality, you should normally use
|
||||
@code{=}, not @code{eq}. There can be many distinct floating-point
|
||||
and large integer objects with the same numeric value. If you use
|
||||
@code{eq} to compare them, then you test whether two values are the
|
||||
same @emph{object}. By contrast, @code{=} compares only the numeric
|
||||
values of the objects.
|
||||
@code{=} instead of non-numeric comparison predicates like @code{eq},
|
||||
@code{eql} and @code{equal}. Distinct floating-point and large
|
||||
integer objects can be numerically equal. If you use @code{eq} to
|
||||
compare them, you test whether they are the same @emph{object}; if you
|
||||
use @code{eql} or @code{equal}, you test whether their values are
|
||||
@emph{indistinguishable}. In contrast, @code{=} uses numeric
|
||||
comparison, and sometimes returns @code{t} when a non-numeric
|
||||
comparison would return @code{nil} and vice versa. @xref{Float
|
||||
Basics}.
|
||||
|
||||
In Emacs Lisp, each small integer is a unique Lisp object.
|
||||
Therefore, @code{eq} is equivalent to @code{=} where small integers are
|
||||
|
@ -829,7 +845,7 @@ reproducing the same pattern moved over.
|
|||
bits in @var{integer1} to the left @var{count} places, or to the right
|
||||
if @var{count} is negative, bringing zeros into the vacated bits. If
|
||||
@var{count} is negative, @code{lsh} shifts zeros into the leftmost
|
||||
(most-significant) bit, producing a positive result even if
|
||||
(most-significant) bit, producing a nonnegative result even if
|
||||
@var{integer1} is negative. Contrast this with @code{ash}, below.
|
||||
|
||||
Here are two examples of @code{lsh}, shifting a pattern of bits one
|
||||
|
@ -1167,7 +1183,7 @@ returns a NaN.
|
|||
|
||||
@defun expt x y
|
||||
This function returns @var{x} raised to power @var{y}. If both
|
||||
arguments are integers and @var{y} is positive, the result is an
|
||||
arguments are integers and @var{y} is nonnegative, the result is an
|
||||
integer; in this case, overflow causes truncation, so watch out.
|
||||
If @var{x} is a finite negative number and @var{y} is a finite
|
||||
non-integer, @code{expt} returns a NaN.
|
||||
|
|
|
@ -63,7 +63,8 @@ But it is possible to add elements to the list, or remove elements.
|
|||
|
||||
@defun sequencep object
|
||||
This function returns @code{t} if @var{object} is a list, vector,
|
||||
string, bool-vector, or char-table, @code{nil} otherwise.
|
||||
string, bool-vector, or char-table, @code{nil} otherwise. See also
|
||||
@code{seqp} below.
|
||||
@end defun
|
||||
|
||||
@defun length sequence
|
||||
|
@ -479,7 +480,8 @@ built-in sequence types, @code{seq-length} behaves like @code{length}.
|
|||
@defun seqp object
|
||||
This function returns non-@code{nil} if @var{object} is a sequence
|
||||
(a list or array), or any additional type of sequence defined via
|
||||
@file{seq.el} generic functions.
|
||||
@file{seq.el} generic functions. This is an extensible variant of
|
||||
@code{sequencep}.
|
||||
|
||||
@example
|
||||
@group
|
||||
|
@ -1355,7 +1357,7 @@ each initialized to @var{object}.
|
|||
@defun vconcat &rest sequences
|
||||
@cindex copying vectors
|
||||
This function returns a new vector containing all the elements of
|
||||
@var{sequences}. The arguments @var{sequences} may be true lists,
|
||||
@var{sequences}. The arguments @var{sequences} may be proper lists,
|
||||
vectors, strings or bool-vectors. If no @var{sequences} are given,
|
||||
the empty vector is returned.
|
||||
|
||||
|
|
|
@ -922,7 +922,8 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and
|
|||
@item %o
|
||||
@cindex integer to octal
|
||||
Replace the specification with the base-eight representation of an
|
||||
unsigned integer. The object can also be a nonnegative floating-point
|
||||
integer. Negative integers are formatted in a platform-dependent
|
||||
way. The object can also be a nonnegative floating-point
|
||||
number that is formatted as an integer, dropping any fraction, if the
|
||||
integer does not exceed machine limits.
|
||||
|
||||
|
@ -935,7 +936,8 @@ formatted as an integer, dropping any fraction.
|
|||
@itemx %X
|
||||
@cindex integer to hexadecimal
|
||||
Replace the specification with the base-sixteen representation of an
|
||||
unsigned integer. @samp{%x} uses lower case and @samp{%X} uses upper
|
||||
integer. Negative integers are formatted in a platform-dependent
|
||||
way. @samp{%x} uses lower case and @samp{%X} uses upper
|
||||
case. The object can also be a nonnegative floating-point number that
|
||||
is formatted as an integer, dropping any fraction, if the integer does
|
||||
not exceed machine limits.
|
||||
|
@ -1015,17 +1017,17 @@ numbered or unnumbered format specifications but not both, except that
|
|||
After the @samp{%} and any field number, you can put certain
|
||||
@dfn{flag characters}.
|
||||
|
||||
The flag @samp{+} inserts a plus sign before a positive number, so
|
||||
The flag @samp{+} inserts a plus sign before a nonnegative number, so
|
||||
that it always has a sign. A space character as flag inserts a space
|
||||
before a positive number. (Otherwise, positive numbers start with the
|
||||
first digit.) These flags are useful for ensuring that positive
|
||||
numbers and negative numbers use the same number of columns. They are
|
||||
before a nonnegative number. (Otherwise, nonnegative numbers start with the
|
||||
first digit.) These flags are useful for ensuring that nonnegative
|
||||
and negative numbers use the same number of columns. They are
|
||||
ignored except for @samp{%d}, @samp{%e}, @samp{%f}, @samp{%g}, and if
|
||||
both flags are used, @samp{+} takes precedence.
|
||||
|
||||
The flag @samp{#} specifies an alternate form which depends on
|
||||
the format in use. For @samp{%o}, it ensures that the result begins
|
||||
with a @samp{0}. For @samp{%x} and @samp{%X}, it prefixes the result
|
||||
with a @samp{0}. For @samp{%x} and @samp{%X}, it prefixes nonzero results
|
||||
with @samp{0x} or @samp{0X}. For @samp{%e} and @samp{%f}, the
|
||||
@samp{#} flag means include a decimal point even if the precision is
|
||||
zero. For @samp{%g}, it always includes a decimal point, and also
|
||||
|
@ -1108,6 +1110,17 @@ shows only the first three characters of the representation for
|
|||
precision is what the local library functions of the @code{printf}
|
||||
family produce.
|
||||
|
||||
@cindex formatting numbers for rereading later
|
||||
If you plan to use @code{read} later on the formatted string to
|
||||
retrieve a copy of the formatted value, use a specification that lets
|
||||
@code{read} reconstruct the value. To format numbers in this
|
||||
reversible way you can use @samp{%s} and @samp{%S}, to format just
|
||||
integers you can also use @samp{%d}, and to format just nonnegative
|
||||
integers you can also use @samp{#x%x} and @samp{#o%o}. Other formats
|
||||
may be problematic; for example, @samp{%d} and @samp{%g} can mishandle
|
||||
NaNs and can lose precision and type, and @samp{#x%x} and @samp{#o%o}
|
||||
can mishandle negative integers. @xref{Input Functions}.
|
||||
|
||||
@node Case Conversion
|
||||
@section Case Conversion in Lisp
|
||||
@cindex upper case
|
||||
|
|
|
@ -75,8 +75,8 @@ thread, @code{nil} otherwise.
|
|||
|
||||
@defun thread-join thread
|
||||
Block until @var{thread} exits, or until the current thread is
|
||||
signaled. If @var{thread} has already exited, this returns
|
||||
immediately.
|
||||
signaled. It returns the result of the @var{thread} function. If
|
||||
@var{thread} has already exited, this returns immediately.
|
||||
@end defun
|
||||
|
||||
@defun thread-signal thread error-symbol data
|
||||
|
@ -87,6 +87,15 @@ thread, then this just calls @code{signal} immediately. Otherwise,
|
|||
If @var{thread} was blocked by a call to @code{mutex-lock},
|
||||
@code{condition-wait}, or @code{thread-join}; @code{thread-signal}
|
||||
will unblock it.
|
||||
|
||||
Since signal handlers in Emacs are located in the main thread, a
|
||||
signal must be propagated there in order to become visible. The
|
||||
second @code{signal} call let the thread die:
|
||||
|
||||
@example
|
||||
(thread-signal main-thread 'error data)
|
||||
(signal 'error data)
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
@defun thread-yield
|
||||
|
@ -127,15 +136,21 @@ Return a list of all the live thread objects. A new list is returned
|
|||
by each invocation.
|
||||
@end defun
|
||||
|
||||
@defvar main-thread
|
||||
This variable keeps the main thread Emacs is running, or @code{nil} if
|
||||
Emacs is compiled without thread support.
|
||||
@end defvar
|
||||
|
||||
When code run by a thread signals an error that is unhandled, the
|
||||
thread exits. Other threads can access the error form which caused
|
||||
the thread to exit using the following function.
|
||||
|
||||
@defun thread-last-error
|
||||
@defun thread-last-error &optional cleanup
|
||||
This function returns the last error form recorded when a thread
|
||||
exited due to an error. Each thread that exits abnormally overwrites
|
||||
the form stored by the previous thread's error with a new value, so
|
||||
only the last one can be accessed.
|
||||
only the last one can be accessed. If @var{cleanup} is
|
||||
non-@code{nil}, the stored form is reset to @code{nil}.
|
||||
@end defun
|
||||
|
||||
@node Mutexes
|
||||
|
|
|
@ -2988,7 +2988,7 @@ Emacs compiled on a 64-bit machine can handle much larger buffers.
|
|||
@cindex Shell buffer, echoed commands and @samp{^M} in
|
||||
@cindex Echoed commands in @code{shell-mode}
|
||||
|
||||
Try typing @kbd{M-x shell-strip-ctrl-m @key{RET}} while in @code{shell-mode} to
|
||||
Try typing @kbd{M-x comint-strip-ctrl-m @key{RET}} while in @code{shell-mode} to
|
||||
make them go away. If that doesn't work, you have several options:
|
||||
|
||||
For @code{tcsh}, put this in your @file{.cshrc} (or @file{.tcshrc})
|
||||
|
@ -3041,7 +3041,7 @@ characters from the buffer by adding this to your @file{.emacs} init
|
|||
file:
|
||||
|
||||
@smalllisp
|
||||
(add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m)
|
||||
(add-hook 'comint-output-filter-functions #'comint-strip-ctrl-m)
|
||||
@end smalllisp
|
||||
|
||||
On a related note: if your shell is echoing your input line in the shell
|
||||
|
|
|
@ -273,9 +273,11 @@ moving point to it and typing @kbd{@key{RET}} jumps to its definition.
|
|||
@cindex backtrace of a failed test
|
||||
Pressing @kbd{r} re-runs the test near point on its own. Pressing
|
||||
@kbd{d} re-runs it with the debugger enabled. @kbd{.} jumps to the
|
||||
definition of the test near point (@kbd{@key{RET}} has the same effect if
|
||||
point is on the name of the test). On a failed test, @kbd{b} shows
|
||||
the backtrace of the failure.
|
||||
definition of the test near point (@kbd{@key{RET}} has the same effect
|
||||
if point is on the name of the test). On a failed test, @kbd{b} shows
|
||||
the backtrace of the failure. @xref{Debugging,, Backtraces, elisp,
|
||||
GNU Emacs Lisp Reference Manual}, for more information about
|
||||
backtraces.
|
||||
|
||||
@kindex l@r{, in ert results buffer}
|
||||
@kbd{l} shows the list of @code{should} forms executed in the test.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
@set VERSION 1.0
|
||||
@set UPDATED June 2018
|
||||
@settitle GNU Flymake @value{VERSION}
|
||||
@include ../emacs/docstyle.texi
|
||||
@include docstyle.texi
|
||||
@syncodeindex pg cp
|
||||
@syncodeindex vr cp
|
||||
@syncodeindex fn cp
|
||||
|
|
|
@ -544,9 +544,9 @@ file system), @file{@trampfn{dav,user@@host,/path/to/file}} and
|
|||
@cindex method @option{gdrive}
|
||||
@cindex @option{gdrive} method
|
||||
@cindex google drive
|
||||
@cindex method @option{owncloud}
|
||||
@cindex @option{owncloud} method
|
||||
@cindex nextcloud
|
||||
@cindex method @option{nextcloud}
|
||||
@cindex @option{nextcloud} method
|
||||
@cindex owncloud
|
||||
|
||||
GVFS-based methods include also @acronym{GNOME} Online Accounts, which
|
||||
support the @option{Files} service. These are the Google Drive file
|
||||
|
@ -554,7 +554,7 @@ system, and the OwnCloud/NextCloud file system. The file name syntax
|
|||
is here always
|
||||
@file{@trampfn{gdrive,john.doe@@gmail.com,/path/to/file}}
|
||||
(@samp{john.doe@@gmail.com} stands here for your Google Drive
|
||||
account), or @file{@trampfn{owncloud,user@@host#8081,/path/to/file}}
|
||||
account), or @file{@trampfn{nextcloud,user@@host#8081,/path/to/file}}
|
||||
(@samp{8081} stands for the port number) for OwnCloud/NextCloud files.
|
||||
|
||||
|
||||
|
@ -1094,6 +1094,10 @@ syntax requires a leading volume (share) name, for example:
|
|||
based on standard protocols, such as HTTP@. @option{davs} does the same
|
||||
but with SSL encryption. Both methods support the port numbers.
|
||||
|
||||
Paths being part of the WebDAV volume to be mounted by GVFS, as it is
|
||||
common for OwnCloud or NextCloud file names, are not supported by
|
||||
these methods. See method @option{nextcloud} for handling them.
|
||||
|
||||
@item @option{gdrive}
|
||||
@cindex method @option{gdrive}
|
||||
@cindex @option{gdrive} method
|
||||
|
@ -1110,13 +1114,13 @@ Since Google Drive uses cryptic blob file names internally,
|
|||
could produce unexpected behavior in case two files in the same
|
||||
directory have the same @code{display-name}, such a situation must be avoided.
|
||||
|
||||
@item @option{owncloud}
|
||||
@item @option{nextcloud}
|
||||
@cindex @acronym{GNOME} Online Accounts
|
||||
@cindex method @option{owncloud}
|
||||
@cindex @option{owncloud} method
|
||||
@cindex nextcloud
|
||||
@cindex method @option{nextcloud}
|
||||
@cindex @option{nextcloud} method
|
||||
@cindex owncloud
|
||||
|
||||
As the name indicates, the method @option{owncloud} allows you to
|
||||
As the name indicates, the method @option{nextcloud} allows you to
|
||||
access OwnCloud or NextCloud hosted files and directories. Like the
|
||||
@option{gdrive} method, your credentials must be populated in your
|
||||
@command{Online Accounts} application outside Emacs. The method
|
||||
|
@ -1135,7 +1139,7 @@ that for security reasons refuse @command{ssh} connections.
|
|||
@defopt tramp-gvfs-methods
|
||||
This user option is a list of external methods for GVFS@. By default,
|
||||
this list includes @option{afp}, @option{dav}, @option{davs},
|
||||
@option{gdrive}, @option{owncloud} and @option{sftp}. Other methods
|
||||
@option{gdrive}, @option{nextcloud} and @option{sftp}. Other methods
|
||||
to include are @option{ftp}, @option{http}, @option{https} and
|
||||
@option{smb}. These methods are not intended to be used directly as
|
||||
GVFS based method. Instead, they are added here for the benefit of
|
||||
|
@ -1238,7 +1242,7 @@ improvement is not always true.
|
|||
@cindex default user
|
||||
|
||||
@defopt tramp-default-user
|
||||
@value{tramp} file name can omit the user name part since
|
||||
A @value{tramp} file name can omit the user name part since
|
||||
@value{tramp} substitutes the currently logged-in user name. However
|
||||
this substitution can be overridden with @code{tramp-default-user}.
|
||||
For example:
|
||||
|
@ -1453,7 +1457,7 @@ support this command.
|
|||
|
||||
@subsection Tunneling with ssh
|
||||
|
||||
With ssh, you could use the @code{ProxyCommand} entry in the
|
||||
With ssh, you could use the @code{ProxyCommand} entry in
|
||||
@file{~/.ssh/config}:
|
||||
|
||||
@example
|
||||
|
@ -1589,12 +1593,12 @@ A function dedicated to @file{/etc/hosts} for host names.
|
|||
@item @code{tramp-parse-passwd}
|
||||
@findex tramp-parse-passwd
|
||||
|
||||
A function which parses @file{/etc/passwd} files for user names.
|
||||
A function which parses @file{/etc/passwd} for user names.
|
||||
|
||||
@item @code{tramp-parse-etc-group}
|
||||
@findex tramp-parse-etc-group
|
||||
|
||||
A function which parses @file{/etc/group} files for group names.
|
||||
A function which parses @file{/etc/group} for group names.
|
||||
|
||||
@item @code{tramp-parse-netrc}
|
||||
@findex tramp-parse-netrc
|
||||
|
@ -2194,7 +2198,7 @@ of the secretfile is now owned by the user logged in from
|
|||
When @code{backup-directory-alist} is @code{nil} (the default), such
|
||||
problems do not occur.
|
||||
|
||||
To ``turn off'' the backup feature for @value{tramp} files and stop
|
||||
To ``turn off'' the backup feature for remote files and stop
|
||||
@value{tramp} from saving to the backup directory, use this:
|
||||
|
||||
@lisp
|
||||
|
@ -2256,12 +2260,11 @@ The backup file name of
|
|||
|
||||
@vindex auto-save-file-name-transforms
|
||||
Just as for backup files, similar issues of file naming affect
|
||||
auto-saving @value{tramp} files. Auto-saved files are saved in the
|
||||
directory specified by the user option
|
||||
@code{auto-save-file-name-transforms}. By default this is set to
|
||||
the local temporary directory. But in some versions of Debian
|
||||
GNU/Linux, this points to the source directory where the Emacs was
|
||||
compiled. Reset such values to a valid directory.
|
||||
auto-saving remote files. Auto-saved files are saved in the directory
|
||||
specified by the user option @code{auto-save-file-name-transforms}.
|
||||
By default this is set to the local temporary directory. But in some
|
||||
versions of Debian GNU/Linux, this points to the source directory
|
||||
where the Emacs was compiled. Reset such values to a valid directory.
|
||||
|
||||
Set @code{auto-save-file-name-transforms} to @code{nil} to save
|
||||
auto-saved files to the same directory as the original file.
|
||||
|
@ -2765,8 +2768,8 @@ hard-coded, fixed name. Note that using @code{:0} for X11 display name
|
|||
here will not work as expected.
|
||||
|
||||
An alternate approach is specify @code{ForwardX11 yes} or
|
||||
@code{ForwardX11Trusted yes} in the file @file{~/.ssh/config} on the
|
||||
local host.
|
||||
@code{ForwardX11Trusted yes} in @file{~/.ssh/config} on the local
|
||||
host.
|
||||
|
||||
|
||||
@subsection Running @code{shell} on a remote host
|
||||
|
@ -3446,6 +3449,19 @@ source "$@{HOME@}/.iterm2_shell_integration.bash"
|
|||
@end group
|
||||
@end example
|
||||
|
||||
And finally, bash's readline should not use key bindings like
|
||||
@samp{C-j} to commands. Disable this in your @file{~/.inputrc}:
|
||||
|
||||
@example
|
||||
@group
|
||||
$if term=dumb
|
||||
# Don't bind Control-J or it messes up @value{tramp}.
|
||||
$else
|
||||
"\C-j": next-history
|
||||
$endif
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@item
|
||||
Echoed characters after login
|
||||
|
||||
|
@ -3582,13 +3598,13 @@ When testing, ensure the remote shell is the same shell
|
|||
How to get notified after @value{tramp} completes file transfers?
|
||||
|
||||
Make Emacs beep after reading from or writing to the remote host with
|
||||
the following code in @file{~/.emacs} file.
|
||||
the following code in @file{~/.emacs}.
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(defadvice tramp-handle-write-region
|
||||
(after tramp-write-beep-advice activate)
|
||||
"Make tramp beep after writing a file."
|
||||
"Make @value{tramp} beep after writing a file."
|
||||
(interactive)
|
||||
(beep))
|
||||
@end group
|
||||
|
@ -3596,7 +3612,7 @@ the following code in @file{~/.emacs} file.
|
|||
@group
|
||||
(defadvice tramp-handle-do-copy-or-rename-file
|
||||
(after tramp-copy-beep-advice activate)
|
||||
"Make tramp beep after copying a file."
|
||||
"Make @value{tramp} beep after copying a file."
|
||||
(interactive)
|
||||
(beep))
|
||||
@end group
|
||||
|
@ -3604,7 +3620,7 @@ the following code in @file{~/.emacs} file.
|
|||
@group
|
||||
(defadvice tramp-handle-insert-file-contents
|
||||
(after tramp-insert-beep-advice activate)
|
||||
"Make tramp beep after inserting a file."
|
||||
"Make @value{tramp} beep after inserting a file."
|
||||
(interactive)
|
||||
(beep))
|
||||
@end group
|
||||
|
@ -3642,7 +3658,7 @@ then set them with a hook as follows:
|
|||
|
||||
|
||||
@item
|
||||
Why is @file{~/.sh_history} file on the remote host growing?
|
||||
Why is @file{~/.sh_history} on the remote host growing?
|
||||
|
||||
@vindex tramp-histfile-override
|
||||
@vindex HISTFILE@r{, environment variable}
|
||||
|
@ -3663,7 +3679,7 @@ undesired results when using @command{bash} as remote shell.
|
|||
Another approach is to disable @value{tramp}'s handling of the
|
||||
@env{HISTFILE} at all by setting @code{tramp-histfile-override} to
|
||||
@code{nil}. In this case, saving history could be turned off by
|
||||
putting this shell code in the @file{.bashrc} or @file{.kshrc} file:
|
||||
putting this shell code in @file{.bashrc} or @file{.kshrc}:
|
||||
|
||||
@example
|
||||
@group
|
||||
|
@ -3680,7 +3696,7 @@ fi
|
|||
@end example
|
||||
|
||||
For @option{ssh}-based method, add the following line to your
|
||||
@file{~/.ssh/environment} file:
|
||||
@file{~/.ssh/environment}:
|
||||
|
||||
@example
|
||||
HISTFILE=/dev/null
|
||||
|
|
155
etc/NEWS
155
etc/NEWS
|
@ -34,6 +34,13 @@ functions 'json-serialize', 'json-insert', 'json-parse-string', and
|
|||
'json-parse-buffer' are typically much faster than their Lisp
|
||||
counterparts from json.el.
|
||||
|
||||
** The etags program now uses the C library's regular expression matcher
|
||||
when possible, and a compatible regex substitute otherwise. This will
|
||||
let developers maintain Emacs's own regex code without having to also
|
||||
support other programs. The new configure option '--without-included-regex'
|
||||
forces etags to use the C library's regex matcher even if the regex
|
||||
substitute ordinarily would be used to work around compatibility problems.
|
||||
|
||||
** Emacs has been ported to the -fcheck-pointer-bounds option of GCC.
|
||||
This causes Emacs to check bounds of some arrays addressed by its
|
||||
internal pointers, which can be helpful when debugging the Emacs
|
||||
|
@ -84,14 +91,24 @@ work right without some adjustment:
|
|||
- you can use the new 'package-quickstart' so activation of packages does not
|
||||
need to pay attention to 'package-load-list' or 'package-user-dir' any more.
|
||||
|
||||
---
|
||||
** Emacs now notifies systemd when startup finishes or shutdown begins.
|
||||
Units that are ordered after 'emacs.service' will only be started
|
||||
after Emacs has finished initialization and is ready for use.
|
||||
(If your Emacs is installed in a non-standard location and you copied the
|
||||
emacs.service file to eg ~/.config/systemd/user/, you will need to copy
|
||||
the new version of the file again.)
|
||||
|
||||
|
||||
* Changes in Emacs 27.1
|
||||
|
||||
+++
|
||||
** The function 'read-passwd' uses '*' as default character to hide passwords.
|
||||
|
||||
---
|
||||
** New variable 'xft-ignore-color-fonts'.
|
||||
Default t means don't try to load color fonts when using Xft, as they
|
||||
often cause crashes. Set it to nil if you really need those fonts.
|
||||
(Bug#30874)
|
||||
|
||||
---
|
||||
** The new option 'tooltip-resize-echo-area' avoids truncating tooltip text
|
||||
|
@ -178,6 +195,9 @@ This triggers to search the program on the remote host as indicated by
|
|||
|
||||
* Editing Changes in Emacs 27.1
|
||||
|
||||
+++
|
||||
** New command 'make-empty-file'.
|
||||
|
||||
---
|
||||
** New variable 'x-wait-for-event-timeout'.
|
||||
This controls how long Emacs will wait for updates to the graphical
|
||||
|
@ -215,6 +235,29 @@ navigation and editing of large files.
|
|||
|
||||
* Changes in Specialized Modes and Packages in Emacs 27.1
|
||||
|
||||
+++
|
||||
** Dired
|
||||
|
||||
*** New command 'dired-create-empty-file'.
|
||||
|
||||
** Change Logs and VC
|
||||
|
||||
*** Recording ChangeLog entries doesn't require an actual file.
|
||||
If a ChangeLog file doesn't exist, and if the new variable
|
||||
'add-log-dont-create-changelog-file' is non-nil (which is the
|
||||
default), commands such as 'C-x 4 a' will add log entries to a
|
||||
suitable named temporary buffer. (An existing ChangeLog file will
|
||||
still be used if it exists.) Set the variable to nil to get the
|
||||
previous behavior of always creating a buffer that visits a ChangeLog
|
||||
file.
|
||||
|
||||
** diff-mode
|
||||
*** Hunks are now automatically refined by default
|
||||
To disable it, set the new defcustom 'diff-font-lock-refine' to nil.
|
||||
|
||||
*** File headers can be shortened, mimicking Magit's diff format
|
||||
To enable it, set the new defcustom 'diff-font-lock-prettify to t.
|
||||
|
||||
** Browse-url
|
||||
|
||||
*** The function 'browse-url-emacs' can now visit a URL in selected window.
|
||||
|
@ -223,6 +266,10 @@ shown in the currently selected window.
|
|||
|
||||
** Comint
|
||||
|
||||
+++
|
||||
*** 'send-invisible' is now an obsolete alias for `comint-send-invisible'
|
||||
Also, 'shell-strip-ctrl-m' is declared obsolete.
|
||||
|
||||
+++
|
||||
*** 'C-c .' (comint-insert-previous-argument) no longer interprets '&'.
|
||||
This feature caused problems when '&&' was present in the previous
|
||||
|
@ -240,6 +287,11 @@ better emulate 'M-.' in both Bash and zsh, since the former counts
|
|||
from the beginning of the arguments, while the latter counts from the
|
||||
end.
|
||||
|
||||
** Term
|
||||
|
||||
---
|
||||
*** 'term-read-noecho' is now obsolete, use 'read-passwd' instead.
|
||||
|
||||
** Flymake
|
||||
|
||||
+++
|
||||
|
@ -371,6 +423,13 @@ bound to 'C-c C-f'.
|
|||
when escaping text and in addition all numeric entities when
|
||||
unescaping text.
|
||||
|
||||
** Python mode
|
||||
|
||||
---
|
||||
*** Python mode supports three different font lock decoration levels.
|
||||
The maximum level is used by default; customize
|
||||
'font-lock-maximum-decoration' to tone down the decoration.
|
||||
|
||||
** Dired
|
||||
|
||||
+++
|
||||
|
@ -417,6 +476,14 @@ the shift key.
|
|||
*** Isearch now remembers the regexp-based search mode for words/symbols
|
||||
and case-sensitivity together with search strings in the search ring.
|
||||
|
||||
** Debugger
|
||||
|
||||
+++
|
||||
*** The Lisp Debugger is now based on 'backtrace-mode'.
|
||||
Backtrace mode adds fontification and commands for changing the
|
||||
appearance of backtrace frames. See the node "Backtraces" in the Elisp
|
||||
manual for documentation of the new mode and its commands.
|
||||
|
||||
** Edebug
|
||||
|
||||
+++
|
||||
|
@ -426,14 +493,27 @@ using the new variables 'edebug-behavior-alist',
|
|||
'edebug-new-definition-function'. Edebug's behavior can be changed
|
||||
globally or for individual definitions.
|
||||
|
||||
+++
|
||||
*** Edebug's backtrace buffer now uses 'backtrace-mode'.
|
||||
Backtrace mode adds fontification, links and commands for changing the
|
||||
appearance of backtrace frames. See the node "Backtraces" in the Elisp
|
||||
manual for documentation of the new mode and its commands.
|
||||
|
||||
The binding of 'd' in Edebug's keymap is now 'edebug-pop-to-backtrace'
|
||||
which replaces 'edebug-backtrace'. Consequently Edebug's backtrace
|
||||
windows now behave like those of the Lisp Debugger and of ERT, in that
|
||||
when they appear they will be the selected window.
|
||||
|
||||
The new 'backtrace-goto-source' command, bound to 's', works in
|
||||
Edebug's backtraces on backtrace frames whose source code has
|
||||
been instrumented by Edebug.
|
||||
|
||||
** Enhanced xterm support
|
||||
|
||||
*** New variable 'xterm-set-window-title' controls whether Emacs sets
|
||||
the XTerm window title. This feature is experimental and is disabled
|
||||
by default.
|
||||
|
||||
** Gamegrid
|
||||
|
||||
** grep
|
||||
|
||||
+++
|
||||
|
@ -450,6 +530,14 @@ The abbreviation can be disabled by the new option
|
|||
*** New variable 'ert-quiet' allows to make ERT output in batch mode
|
||||
less verbose by removing non-essential information.
|
||||
|
||||
+++
|
||||
*** ERT's backtrace buffer now uses 'backtrace-mode'.
|
||||
Backtrace mode adds fontification and commands for changing the
|
||||
appearance of backtrace frames. See the node "Backtraces" in the Elisp
|
||||
manual for documentation of the new mode and its commands.
|
||||
|
||||
** Gamegrid
|
||||
|
||||
---
|
||||
*** Gamegrid now determines its default glyph size based on display
|
||||
dimensions, instead of always using 16 pixels. As a result, Tetris,
|
||||
|
@ -520,7 +608,7 @@ process. It now accepts signals specified either by name or by its number.
|
|||
** Tramp
|
||||
|
||||
+++
|
||||
*** New connection method "owncloud", which allows to access OwnCloud
|
||||
*** New connection method "nextcloud", which allows to access OwnCloud
|
||||
or NextCloud hosted files and directories.
|
||||
|
||||
+++
|
||||
|
@ -534,6 +622,11 @@ are obsoleted in GVFS.
|
|||
*** The user option 'tramp-ignored-file-name-regexp' allows to disable
|
||||
Tramp for some look-alike remote file names.
|
||||
|
||||
** Register
|
||||
---
|
||||
*** The return value of method 'register-val-describe' includes the
|
||||
names of buffers shown by the windows of a window configuration.
|
||||
|
||||
---
|
||||
** The options.el library has been removed.
|
||||
It was obsolete since Emacs 22.1, replaced by customize.
|
||||
|
@ -542,7 +635,6 @@ It was obsolete since Emacs 22.1, replaced by customize.
|
|||
Use of built-in libgnutls based functionality (described in the Emacs
|
||||
GnuTLS manual) is recommended instead.
|
||||
|
||||
|
||||
** Message
|
||||
|
||||
+++
|
||||
|
@ -588,6 +680,17 @@ If this option is non-nil, messages appended to an output file by the
|
|||
selects the messages to summarize with a regexp that matches the
|
||||
sender of the current message.
|
||||
|
||||
** Threads
|
||||
|
||||
+++
|
||||
*** New variable 'main-thread' holds Emacs's main thread.
|
||||
This is handy in Lisp programs that run on a non-main thread and want
|
||||
to signal the main thread, e.g., when they encounter an error.
|
||||
|
||||
+++
|
||||
*** 'thread-join' returns the result of the finished thread now.
|
||||
|
||||
|
||||
* New Modes and Packages in Emacs 27.1
|
||||
|
||||
+++
|
||||
|
@ -605,6 +708,13 @@ transport strategies as well as a separate API to use them. A
|
|||
transport implementation for process-based communication, such as is
|
||||
used by the Language Server Protocol (LSP), is readily available.
|
||||
|
||||
+++
|
||||
** Backtrace mode improves viewing of Elisp backtraces.
|
||||
Backtrace mode adds pretty printing, fontification and ellipsis
|
||||
expansion to backtrace buffers produced by the Lisp debugger, Edebug
|
||||
and ERT. See the node "Backtraces" in the Elisp manual for
|
||||
documentation of the new mode and its commands.
|
||||
|
||||
|
||||
* Incompatible Lisp Changes in Emacs 27.1
|
||||
|
||||
|
@ -645,7 +755,7 @@ as new-style, bind the new variable 'force-new-style-backquotes' to t.
|
|||
|
||||
** When formatting a floating-point number as an octal or hexadecimal
|
||||
integer, Emacs now signals an error if the number is too large for the
|
||||
implementation to format (Bug#30408).
|
||||
implementation to format.
|
||||
|
||||
---
|
||||
** Some functions and variables obsolete since Emacs 22 have been removed:
|
||||
|
@ -694,13 +804,15 @@ however applications should instead call 'display-buffer-in-side-window'
|
|||
is backwards-compatible with versions of Emacs in which the old function
|
||||
exists. See the node "Displaying Buffers in Side Windows" in the ELisp
|
||||
manual for more details.
|
||||
|
||||
|
||||
* Lisp Changes in Emacs 27.1
|
||||
|
||||
+++
|
||||
** New function 'proper-list-p'.
|
||||
Given a proper list as argument, this predicate returns its length;
|
||||
otherwise, it returns nil.
|
||||
otherwise, it returns nil. 'format-proper-list-p' is now an obsolete
|
||||
alias for the new function.
|
||||
|
||||
+++
|
||||
** Emacs Lisp integers can be of arbitrary precision. The new
|
||||
|
@ -758,6 +870,15 @@ between two strings.
|
|||
** 'print-quoted' now defaults to t, so if you want to see
|
||||
(quote x) instead of 'x you will have to bind it to nil where applicable.
|
||||
|
||||
+++
|
||||
** Numbers formatted via %o or %x may now be formatted as signed integers.
|
||||
This avoids problems in calls like (read (format "#x%x" -1)), and is
|
||||
more compatible with bignums, a planned feature. To get this
|
||||
behavior, set the experimental variable binary-as-unsigned to nil,
|
||||
and if the new behavior breaks your code please email
|
||||
32252@debbugs.gnu.org. Because %o and %x can now format signed
|
||||
integers, they now support the + and space flags.
|
||||
|
||||
** To avoid confusion caused by "smart quotes", the reader signals an
|
||||
error when reading Lisp symbols which begin with one of the following
|
||||
quotation characters: ‘’‛“”‟〞"'. A symbol beginning with such a
|
||||
|
@ -782,12 +903,12 @@ The new variable 'comment-use-syntax-ppss' can be set to nil to recover the old
|
|||
behavior if needed.
|
||||
|
||||
** The 'server-name' and 'server-socket-dir' variables are set when a
|
||||
socket has been passed to Emacs (Bug#24218).
|
||||
socket has been passed to Emacs.
|
||||
|
||||
---
|
||||
** The 'file-system-info' function is now available on all platforms.
|
||||
instead of just Microsoft platforms. This fixes a 'get-free-disk-space'
|
||||
bug on OS X 10.8 and later (Bug#28639).
|
||||
bug on OS X 10.8 and later.
|
||||
|
||||
+++
|
||||
** 'memory-limit' now returns a better estimate of memory consumption.
|
||||
|
@ -803,13 +924,23 @@ changes and the change hooks are time consuming.
|
|||
** The function 'get-free-disk-space' returns now a non-nil value for
|
||||
remote systems, which support this check.
|
||||
|
||||
+++
|
||||
** 'eql', 'make-hash-table', etc. now treat NaNs consistently.
|
||||
Formerly, some of these functions ignored signs and significands of
|
||||
NaNs. Now, all these functions treat NaN signs and significands as
|
||||
significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil
|
||||
because the two NaNs have different signs; formerly it returned t.
|
||||
Also, Emacs now reads and prints NaN significands; e.g., if X is a
|
||||
NaN, (format "%s" X) now returns "0.0e+NaN", "1.0e+NaN", etc.,
|
||||
depending on X's significand.
|
||||
|
||||
+++
|
||||
** The function 'make-string' accepts an additional optional argument.
|
||||
If the optional third argument is non-nil, 'make-string' will produce
|
||||
a multibyte string even if its second argument is an ASCII character.
|
||||
|
||||
** (format "%d" X) no longer mishandles a floating-point number X that
|
||||
does not fit in a machine integer (Bug#30408).
|
||||
does not fit in a machine integer.
|
||||
|
||||
** New JSON parsing and serialization functions 'json-serialize',
|
||||
'json-insert', 'json-parse-string', and 'json-parse-buffer'. These
|
||||
|
@ -844,10 +975,6 @@ higher-level functions.
|
|||
some years back. It now respects 'imagemagick-types-inhibit' as a way
|
||||
to disable that.
|
||||
|
||||
+++
|
||||
** The new function 'read-answer' accepts either long or short answers
|
||||
depending on the new customizable variable 'read-answer-short'.
|
||||
|
||||
** The function 'load' now behaves correctly when loading modules.
|
||||
Specifically, it puts the module name into 'load-history', prints
|
||||
loading messages if requested, and protects against recursive loads.
|
||||
|
|
|
@ -85,12 +85,20 @@ it now shows the global revision number, in the form of its changeset
|
|||
hash value. To get back the previous behavior, customize the new
|
||||
option 'vc-hg-symbolic-revision-styles' to the value '("{rev}")'.
|
||||
|
||||
---
|
||||
** shadowfile.el has been rewritten to support Tramp file names.
|
||||
|
||||
|
||||
* New Modes and Packages in Emacs 26.2
|
||||
|
||||
|
||||
* Incompatible Lisp Changes in Emacs 26.2
|
||||
|
||||
---
|
||||
** shadowfile config files have changed their syntax.
|
||||
Existing files "~/.emacs.d/shadows" and "~/.emacs.d/shadow_todo" must
|
||||
be removed prior using the changed 'shadow-*' commands.
|
||||
|
||||
|
||||
* Lisp Changes in Emacs 26.2
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Description=Emacs text editor
|
|||
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Type=notify
|
||||
ExecStart=emacs --fg-daemon
|
||||
ExecStop=emacsclient --eval "(kill-emacs)"
|
||||
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
|
||||
|
|
|
@ -99,8 +99,4 @@ default look of the Gnome 3 desktop.")
|
|||
`(diff-added ((,class (:bold t :foreground "#4E9A06"))))
|
||||
`(diff-removed ((,class (:bold t :foreground "#F5666D"))))))
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; adwaita-theme.el ends here
|
||||
|
|
|
@ -110,8 +110,4 @@
|
|||
|
||||
(provide-theme 'deeper-blue)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; deeper-blue-theme.el ends here
|
||||
|
|
|
@ -122,8 +122,4 @@ Ansi-Color faces are included.")
|
|||
|
||||
(provide-theme 'dichromacy)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; dichromacy-theme.el ends here
|
||||
|
|
|
@ -708,7 +708,6 @@ Semantic, and Ansi-Color faces are included -- and much more...")
|
|||
;; time-stamp-format: "%:y%02m%02d.%02H%02M"
|
||||
;; time-stamp-start: "Version: "
|
||||
;; time-stamp-end: "$"
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; leuven-theme.el ends here
|
||||
|
|
|
@ -61,8 +61,4 @@
|
|||
|
||||
(provide-theme 'light-blue)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; light-blue-theme.el ends here
|
||||
|
|
|
@ -700,8 +700,4 @@ jarring angry fruit salad look to reduce eye fatigue.")
|
|||
|
||||
(provide-theme 'manoj-dark)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; manoj-dark.el ends here
|
||||
|
|
|
@ -103,8 +103,4 @@
|
|||
|
||||
(provide-theme 'misterioso)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; misterioso-theme.el ends here
|
||||
|
|
|
@ -170,8 +170,4 @@ Semantic, and Ansi-Color faces are included.")
|
|||
|
||||
(provide-theme 'tango-dark)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; tango-dark-theme.el ends here
|
||||
|
|
|
@ -154,8 +154,4 @@ Semantic, and Ansi-Color faces are included.")
|
|||
|
||||
(provide-theme 'tango)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; tango-theme.el ends here
|
||||
|
|
|
@ -144,8 +144,4 @@
|
|||
|
||||
(provide-theme 'tsdh-dark)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; tsdh-dark-theme.el ends here
|
||||
|
|
|
@ -106,9 +106,4 @@ Used and created by Tassilo Horn.")
|
|||
|
||||
(provide-theme 'tsdh-light)
|
||||
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; tsdh-light-theme.el ends here
|
||||
|
|
|
@ -83,8 +83,4 @@ of green, brown, and blue.")
|
|||
|
||||
(provide-theme 'wheatgrass)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; wheatgrass-theme.el ends here
|
||||
|
|
|
@ -100,8 +100,4 @@
|
|||
|
||||
(provide-theme 'whiteboard)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; whiteboard-theme.el ends here
|
||||
|
|
|
@ -102,8 +102,4 @@ are included.")
|
|||
|
||||
(provide-theme 'wombat)
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; wombat-theme.el ends here
|
||||
|
|
|
@ -361,13 +361,9 @@ TAGS: etags${EXEEXT} ${tagsfiles}
|
|||
../lib/libgnu.a: $(config_h)
|
||||
$(MAKE) -C ../lib all
|
||||
|
||||
regex.o: $(srcdir)/../src/regex.c $(srcdir)/../src/regex.h $(config_h)
|
||||
$(AM_V_CC)$(CC) -c $(CPP_CFLAGS) $<
|
||||
|
||||
|
||||
etags_deps = ${srcdir}/etags.c regex.o $(NTLIB) $(config_h)
|
||||
etags_deps = ${srcdir}/etags.c $(NTLIB) $(config_h)
|
||||
etags_cflags = -DEMACS_NAME="\"GNU Emacs\"" -DVERSION="\"${version}\"" -o $@
|
||||
etags_libs = regex.o $(NTLIB) $(LOADLIBES)
|
||||
etags_libs = $(NTLIB) $(LOADLIBES)
|
||||
|
||||
etags${EXEEXT}: ${etags_deps}
|
||||
$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $(etags_cflags) $< $(etags_libs)
|
||||
|
|
|
@ -6401,7 +6401,7 @@ add_regex (char *regexp_pattern, language *lang)
|
|||
*patbuf = zeropattern;
|
||||
if (ignore_case)
|
||||
{
|
||||
static char lc_trans[UCHAR_MAX + 1];
|
||||
static unsigned char lc_trans[UCHAR_MAX + 1];
|
||||
int i;
|
||||
for (i = 0; i < UCHAR_MAX + 1; i++)
|
||||
lc_trans[i] = c_tolower (i);
|
||||
|
|
|
@ -31,6 +31,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <ctype.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <mbstring.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <nl_types.h>
|
||||
#include <langinfo.h>
|
||||
|
||||
#include "ntlib.h"
|
||||
|
||||
|
@ -423,3 +427,66 @@ sys_open (const char * path, int oflag, int mode)
|
|||
{
|
||||
return _open (path, oflag, mode);
|
||||
}
|
||||
|
||||
/* Emulation of nl_langinfo that supports only CODESET.
|
||||
Used in Gnulib regex.c. */
|
||||
char *
|
||||
nl_langinfo (nl_item item)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case CODESET:
|
||||
{
|
||||
/* Shamelessly stolen from Gnulib's nl_langinfo.c, modulo
|
||||
CPP directives. */
|
||||
static char buf[2 + 10 + 1];
|
||||
char const *locale = setlocale (LC_CTYPE, NULL);
|
||||
char *codeset = buf;
|
||||
size_t codesetlen;
|
||||
codeset[0] = '\0';
|
||||
|
||||
if (locale && locale[0])
|
||||
{
|
||||
/* If the locale name contains an encoding after the
|
||||
dot, return it. */
|
||||
char *dot = strchr (locale, '.');
|
||||
|
||||
if (dot)
|
||||
{
|
||||
/* Look for the possible @... trailer and remove it,
|
||||
if any. */
|
||||
char *codeset_start = dot + 1;
|
||||
char const *modifier = strchr (codeset_start, '@');
|
||||
|
||||
if (! modifier)
|
||||
codeset = codeset_start;
|
||||
else
|
||||
{
|
||||
codesetlen = modifier - codeset_start;
|
||||
if (codesetlen < sizeof buf)
|
||||
{
|
||||
codeset = memcpy (buf, codeset_start, codesetlen);
|
||||
codeset[codesetlen] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If setlocale is successful, it returns the number of the
|
||||
codepage, as a string. Otherwise, fall back on Windows
|
||||
API GetACP, which returns the locale's codepage as a
|
||||
number (although this doesn't change according to what
|
||||
the 'setlocale' call specified). Either way, prepend
|
||||
"CP" to make it a valid codeset name. */
|
||||
codesetlen = strlen (codeset);
|
||||
if (0 < codesetlen && codesetlen < sizeof buf - 2)
|
||||
memmove (buf + 2, codeset, codesetlen + 1);
|
||||
else
|
||||
sprintf (buf + 2, "%u", GetACP ());
|
||||
codeset = memcpy (buf, "CP", 2);
|
||||
|
||||
return codeset;
|
||||
}
|
||||
default:
|
||||
return (char *) "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "ntlib.h"
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501 /* for getaddrinfo stuff */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#if defined __MINGW32_VERSION && __MINGW32_VERSION >= 5000002L
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
# include <ws2tcpip.h>
|
||||
#undef getaddrinfo
|
||||
#define getaddrinfo sys_getaddrinfo
|
||||
#undef freeaddrinfo
|
||||
|
|
|
@ -79,9 +79,15 @@ endif
|
|||
Makefile: ../config.status $(srcdir)/Makefile.in
|
||||
$(MAKE) -C .. src/$@
|
||||
|
||||
# Object modules that need not be built for Emacs.
|
||||
# Emacs does not need e-regex.o (it has its own regex-emacs.c),
|
||||
# and building it would just waste time.
|
||||
not_emacs_OBJECTS = regex.o
|
||||
|
||||
libgnu_a_OBJECTS = $(gl_LIBOBJS) \
|
||||
$(patsubst %.c,%.o,$(filter %.c,$(libgnu_a_SOURCES)))
|
||||
libegnu_a_OBJECTS = $(patsubst %.o,e-%.o,$(libgnu_a_OBJECTS))
|
||||
for_emacs_OBJECTS = $(filter-out $(not_emacs_OBJECTS),$(libgnu_a_OBJECTS))
|
||||
libegnu_a_OBJECTS = $(patsubst %.o,e-%.o,$(for_emacs_OBJECTS))
|
||||
|
||||
$(libegnu_a_OBJECTS) $(libgnu_a_OBJECTS): $(BUILT_SOURCES)
|
||||
|
||||
|
|
170
lib/gnulib.mk.in
170
lib/gnulib.mk.in
|
@ -20,7 +20,134 @@
|
|||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5-buffer crypto/sha1-buffer crypto/sha256-buffer crypto/sha512-buffer d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fpieee fstatat fsusage fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings
|
||||
# Reproduce by:
|
||||
# gnulib-tool --import \
|
||||
# --lib=libgnu \
|
||||
# --source-base=lib \
|
||||
# --m4-base=m4 \
|
||||
# --doc-base=doc \
|
||||
# --tests-base=tests \
|
||||
# --aux-dir=build-aux \
|
||||
# --gnu-make \
|
||||
# --makefile-name=gnulib.mk.in \
|
||||
# --conditional-dependencies \
|
||||
# --no-libtool \
|
||||
# --macro-prefix=gl \
|
||||
# --no-vc-files \
|
||||
# --avoid=btowc \
|
||||
# --avoid=close \
|
||||
# --avoid=dup \
|
||||
# --avoid=fchdir \
|
||||
# --avoid=fstat \
|
||||
# --avoid=langinfo \
|
||||
# --avoid=lock \
|
||||
# --avoid=malloc-posix \
|
||||
# --avoid=mbrtowc \
|
||||
# --avoid=mbsinit \
|
||||
# --avoid=msvc-inval \
|
||||
# --avoid=msvc-nothrow \
|
||||
# --avoid=nl_langinfo \
|
||||
# --avoid=openat-die \
|
||||
# --avoid=opendir \
|
||||
# --avoid=raise \
|
||||
# --avoid=save-cwd \
|
||||
# --avoid=select \
|
||||
# --avoid=setenv \
|
||||
# --avoid=sigprocmask \
|
||||
# --avoid=stat \
|
||||
# --avoid=stdarg \
|
||||
# --avoid=stdbool \
|
||||
# --avoid=threadlib \
|
||||
# --avoid=tzset \
|
||||
# --avoid=unsetenv \
|
||||
# --avoid=utime \
|
||||
# --avoid=utime-h \
|
||||
# --avoid=wchar \
|
||||
# --avoid=wcrtomb \
|
||||
# --avoid=wctype-h \
|
||||
# alloca-opt \
|
||||
# binary-io \
|
||||
# byteswap \
|
||||
# c-ctype \
|
||||
# c-strcase \
|
||||
# careadlinkat \
|
||||
# close-stream \
|
||||
# count-leading-zeros \
|
||||
# count-one-bits \
|
||||
# count-trailing-zeros \
|
||||
# crypto/md5-buffer \
|
||||
# crypto/sha1-buffer \
|
||||
# crypto/sha256-buffer \
|
||||
# crypto/sha512-buffer \
|
||||
# d-type \
|
||||
# diffseq \
|
||||
# dtoastr \
|
||||
# dtotimespec \
|
||||
# dup2 \
|
||||
# environ \
|
||||
# execinfo \
|
||||
# explicit_bzero \
|
||||
# faccessat \
|
||||
# fcntl \
|
||||
# fcntl-h \
|
||||
# fdatasync \
|
||||
# fdopendir \
|
||||
# filemode \
|
||||
# filevercmp \
|
||||
# flexmember \
|
||||
# fpieee \
|
||||
# fstatat \
|
||||
# fsusage \
|
||||
# fsync \
|
||||
# getloadavg \
|
||||
# getopt-gnu \
|
||||
# gettime \
|
||||
# gettimeofday \
|
||||
# gitlog-to-changelog \
|
||||
# ieee754-h \
|
||||
# ignore-value \
|
||||
# intprops \
|
||||
# largefile \
|
||||
# lstat \
|
||||
# manywarnings \
|
||||
# memrchr \
|
||||
# minmax \
|
||||
# mkostemp \
|
||||
# mktime \
|
||||
# nstrftime \
|
||||
# pipe2 \
|
||||
# pselect \
|
||||
# pthread_sigmask \
|
||||
# putenv \
|
||||
# qcopy-acl \
|
||||
# readlink \
|
||||
# readlinkat \
|
||||
# regex \
|
||||
# sig2str \
|
||||
# socklen \
|
||||
# stat-time \
|
||||
# std-gnu11 \
|
||||
# stdalign \
|
||||
# stddef \
|
||||
# stdio \
|
||||
# stpcpy \
|
||||
# strtoimax \
|
||||
# symlink \
|
||||
# sys_stat \
|
||||
# sys_time \
|
||||
# tempname \
|
||||
# time \
|
||||
# time_r \
|
||||
# time_rz \
|
||||
# timegm \
|
||||
# timer-time \
|
||||
# timespec-add \
|
||||
# timespec-sub \
|
||||
# unlocked-io \
|
||||
# update-copyright \
|
||||
# utimens \
|
||||
# vla \
|
||||
# warnings
|
||||
|
||||
|
||||
MOSTLYCLEANFILES += core *.stackdump
|
||||
|
@ -99,11 +226,13 @@ GETOPT_CDEFS_H = @GETOPT_CDEFS_H@
|
|||
GETOPT_H = @GETOPT_H@
|
||||
GFILENOTIFY_CFLAGS = @GFILENOTIFY_CFLAGS@
|
||||
GFILENOTIFY_LIBS = @GFILENOTIFY_LIBS@
|
||||
GLIBC21 = @GLIBC21@
|
||||
GL_COND_LIBTOOL = @GL_COND_LIBTOOL@
|
||||
GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
|
||||
GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
|
||||
GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
|
||||
GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
|
||||
GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@
|
||||
GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
|
||||
GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
|
||||
GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
|
||||
|
@ -530,6 +659,7 @@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
|
|||
HAVE_XSERVER = @HAVE_XSERVER@
|
||||
HAVE__EXIT = @HAVE__EXIT@
|
||||
HYBRID_MALLOC = @HYBRID_MALLOC@
|
||||
IEEE754_H = @IEEE754_H@
|
||||
IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
|
||||
IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
|
||||
INCLUDE_NEXT = @INCLUDE_NEXT@
|
||||
|
@ -905,6 +1035,7 @@ gameuser = @gameuser@
|
|||
gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@
|
||||
gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9 = @gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9@
|
||||
gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@
|
||||
gl_GNULIB_ENABLED_37f71b604aa9c54446783d80f42fe547 = @gl_GNULIB_ENABLED_37f71b604aa9c54446783d80f42fe547@
|
||||
gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@
|
||||
gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@
|
||||
gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec@
|
||||
|
@ -1671,6 +1802,32 @@ EXTRA_libgnu_a_SOURCES += group-member.c
|
|||
endif
|
||||
## end gnulib module group-member
|
||||
|
||||
## begin gnulib module ieee754-h
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_ieee754-h))
|
||||
|
||||
BUILT_SOURCES += $(IEEE754_H)
|
||||
|
||||
# We need the following in order to create <ieee754.h> when the system
|
||||
# doesn't have one that works with the given compiler.
|
||||
ifneq (,$(GL_GENERATE_IEEE754_H))
|
||||
ieee754.h: ieee754.in.h $(top_builddir)/config.status
|
||||
$(AM_V_GEN)rm -f $@-t && \
|
||||
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
|
||||
sed -e 's/ifndef _GL_GNULIB_HEADER/if 0/g' \
|
||||
$(srcdir)/ieee754.in.h; \
|
||||
} > $@-t && \
|
||||
mv -f $@-t $@
|
||||
else
|
||||
ieee754.h: $(top_builddir)/config.status
|
||||
rm -f $@
|
||||
endif
|
||||
MOSTLYCLEANFILES += ieee754.h ieee754.h-t
|
||||
|
||||
EXTRA_DIST += ieee754.in.h
|
||||
|
||||
endif
|
||||
## end gnulib module ieee754-h
|
||||
|
||||
## begin gnulib module ignore-value
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_ignore-value))
|
||||
|
||||
|
@ -1950,6 +2107,17 @@ EXTRA_libgnu_a_SOURCES += at-func.c readlinkat.c
|
|||
endif
|
||||
## end gnulib module readlinkat
|
||||
|
||||
## begin gnulib module regex
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_regex))
|
||||
|
||||
|
||||
EXTRA_DIST += regcomp.c regex.c regex.h regex_internal.c regex_internal.h regexec.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c
|
||||
|
||||
endif
|
||||
## end gnulib module regex
|
||||
|
||||
## begin gnulib module root-uid
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_root-uid))
|
||||
|
||||
|
|
222
lib/ieee754.in.h
Normal file
222
lib/ieee754.in.h
Normal file
|
@ -0,0 +1,222 @@
|
|||
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IEEE754_H
|
||||
|
||||
#define _IEEE754_H 1
|
||||
|
||||
#ifndef _GL_GNULIB_HEADER
|
||||
/* Ordinary glibc usage. */
|
||||
# include <features.h>
|
||||
# include <endian.h>
|
||||
#else
|
||||
/* Gnulib usage. */
|
||||
# ifndef __BEGIN_DECLS
|
||||
# ifdef __cplusplus
|
||||
# define __BEGIN_DECLS extern "C" {
|
||||
# define __END_DECLS }
|
||||
# else
|
||||
# define __BEGIN_DECLS
|
||||
# define __END_DECLS
|
||||
# endif
|
||||
# endif
|
||||
# ifndef __FLOAT_WORD_ORDER
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define __BIG_ENDIAN 4321
|
||||
# ifdef WORDS_BIGENDIAN
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
# else
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
# endif
|
||||
# define __FLOAT_WORD_ORDER __BYTE_ORDER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
union ieee754_float
|
||||
{
|
||||
float f;
|
||||
|
||||
/* This is the IEEE 754 single-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int mantissa:23;
|
||||
#endif /* Big endian. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned int mantissa:23;
|
||||
unsigned int exponent:8;
|
||||
unsigned int negative:1;
|
||||
#endif /* Little endian. */
|
||||
} ieee;
|
||||
|
||||
/* This format makes it easier to see if a NaN is a signalling NaN. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int mantissa:22;
|
||||
#endif /* Big endian. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned int mantissa:22;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int negative:1;
|
||||
#endif /* Little endian. */
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
|
||||
|
||||
|
||||
union ieee754_double
|
||||
{
|
||||
double d;
|
||||
|
||||
/* This is the IEEE 754 double-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int mantissa1:32;
|
||||
#endif /* Big endian. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
# endif
|
||||
#endif /* Little endian. */
|
||||
} ieee;
|
||||
|
||||
/* This format makes it easier to see if a NaN is a signalling NaN. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int quiet_nan:1;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
# endif
|
||||
#endif
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
|
||||
|
||||
|
||||
union ieee854_long_double
|
||||
{
|
||||
long double d;
|
||||
|
||||
/* This is the IEEE 854 double-extended-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:15;
|
||||
unsigned int empty:16;
|
||||
unsigned int mantissa0:32;
|
||||
unsigned int mantissa1:32;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
unsigned int mantissa0:32;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:32;
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
# endif
|
||||
#endif
|
||||
} ieee;
|
||||
|
||||
/* This is for NaNs in the IEEE 854 double-extended-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:15;
|
||||
unsigned int empty:16;
|
||||
unsigned int one:1;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int mantissa0:30;
|
||||
unsigned int mantissa1:32;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
unsigned int mantissa0:30;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int one:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:30;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int one:1;
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
# endif
|
||||
#endif
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ieee754.h */
|
3944
lib/regcomp.c
Normal file
3944
lib/regcomp.c
Normal file
File diff suppressed because it is too large
Load diff
81
lib/regex.c
Normal file
81
lib/regex.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Extended regular expression matching and search library.
|
||||
Copyright (C) 2002-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
|
||||
# if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
|
||||
# endif
|
||||
# if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wold-style-definition"
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Make sure no one compiles this code with a C++ compiler. */
|
||||
#if defined __cplusplus && defined _LIBC
|
||||
# error "This is C code, use a C compiler"
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
/* We have to keep the namespace clean. */
|
||||
# define regfree(preg) __regfree (preg)
|
||||
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
|
||||
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
|
||||
# define regerror(errcode, preg, errbuf, errbuf_size) \
|
||||
__regerror(errcode, preg, errbuf, errbuf_size)
|
||||
# define re_set_registers(bu, re, nu, st, en) \
|
||||
__re_set_registers (bu, re, nu, st, en)
|
||||
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
|
||||
__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
|
||||
# define re_match(bufp, string, size, pos, regs) \
|
||||
__re_match (bufp, string, size, pos, regs)
|
||||
# define re_search(bufp, string, size, startpos, range, regs) \
|
||||
__re_search (bufp, string, size, startpos, range, regs)
|
||||
# define re_compile_pattern(pattern, length, bufp) \
|
||||
__re_compile_pattern (pattern, length, bufp)
|
||||
# define re_set_syntax(syntax) __re_set_syntax (syntax)
|
||||
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
|
||||
__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
|
||||
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
|
||||
|
||||
# include "../locale/localeinfo.h"
|
||||
#endif
|
||||
|
||||
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
|
||||
GNU regex allows. Include it before <regex.h>, which correctly
|
||||
#undefs RE_DUP_MAX and sets it to the right value. */
|
||||
#include <limits.h>
|
||||
|
||||
#include <regex.h>
|
||||
#include "regex_internal.h"
|
||||
|
||||
#include "regex_internal.c"
|
||||
#include "regcomp.c"
|
||||
#include "regexec.c"
|
||||
|
||||
/* Binary backward compatibility. */
|
||||
#if _LIBC
|
||||
# include <shlib-compat.h>
|
||||
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
|
||||
link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
|
||||
int re_max_failures = 2000;
|
||||
# endif
|
||||
#endif
|
658
lib/regex.h
Normal file
658
lib/regex.h
Normal file
|
@ -0,0 +1,658 @@
|
|||
/* Definitions for data structures and routines for the regular
|
||||
expression library.
|
||||
Copyright (C) 1985, 1989-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _REGEX_H
|
||||
#define _REGEX_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Allow the use in C++ code. */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Define __USE_GNU to declare GNU extensions that violate the
|
||||
POSIX name space rules. */
|
||||
#ifdef _GNU_SOURCE
|
||||
# define __USE_GNU 1
|
||||
#endif
|
||||
|
||||
#ifdef _REGEX_LARGE_OFFSETS
|
||||
|
||||
/* Use types and values that are wide enough to represent signed and
|
||||
unsigned byte offsets in memory. This currently works only when
|
||||
the regex code is used outside of the GNU C library; it is not yet
|
||||
supported within glibc itself, and glibc users should not define
|
||||
_REGEX_LARGE_OFFSETS. */
|
||||
|
||||
/* The type of object sizes. */
|
||||
typedef size_t __re_size_t;
|
||||
|
||||
/* The type of object sizes, in places where the traditional code
|
||||
uses unsigned long int. */
|
||||
typedef size_t __re_long_size_t;
|
||||
|
||||
#else
|
||||
|
||||
/* The traditional GNU regex implementation mishandles strings longer
|
||||
than INT_MAX. */
|
||||
typedef unsigned int __re_size_t;
|
||||
typedef unsigned long int __re_long_size_t;
|
||||
|
||||
#endif
|
||||
|
||||
/* The following two types have to be signed and unsigned integer type
|
||||
wide enough to hold a value of a pointer. For most ANSI compilers
|
||||
ptrdiff_t and size_t should be likely OK. Still size of these two
|
||||
types is 2 for Microsoft C. Ugh... */
|
||||
typedef long int s_reg_t;
|
||||
typedef unsigned long int active_reg_t;
|
||||
|
||||
/* The following bits are used to determine the regexp syntax we
|
||||
recognize. The set/not-set meanings are chosen so that Emacs syntax
|
||||
remains the value 0. The bits are given in alphabetical order, and
|
||||
the definitions shifted by one from the previous bit; thus, when we
|
||||
add or remove a bit, only one other definition need change. */
|
||||
typedef unsigned long int reg_syntax_t;
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* If this bit is not set, then \ inside a bracket expression is literal.
|
||||
If set, then such a \ quotes the following character. */
|
||||
# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
|
||||
|
||||
/* If this bit is not set, then + and ? are operators, and \+ and \? are
|
||||
literals.
|
||||
If set, then \+ and \? are operators and + and ? are literals. */
|
||||
# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
|
||||
|
||||
/* If this bit is set, then character classes are supported. They are:
|
||||
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
|
||||
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
|
||||
If not set, then character classes are not supported. */
|
||||
# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
|
||||
|
||||
/* If this bit is set, then ^ and $ are always anchors (outside bracket
|
||||
expressions, of course).
|
||||
If this bit is not set, then it depends:
|
||||
^ is an anchor if it is at the beginning of a regular
|
||||
expression or after an open-group or an alternation operator;
|
||||
$ is an anchor if it is at the end of a regular expression, or
|
||||
before a close-group or an alternation operator.
|
||||
|
||||
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
|
||||
POSIX draft 11.2 says that * etc. in leading positions is undefined.
|
||||
We already implemented a previous draft which made those constructs
|
||||
invalid, though, so we haven't changed the code back. */
|
||||
# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
|
||||
|
||||
/* If this bit is set, then special characters are always special
|
||||
regardless of where they are in the pattern.
|
||||
If this bit is not set, then special characters are special only in
|
||||
some contexts; otherwise they are ordinary. Specifically,
|
||||
* + ? and intervals are only special when not after the beginning,
|
||||
open-group, or alternation operator. */
|
||||
# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
|
||||
|
||||
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
|
||||
immediately after an alternation or begin-group operator. */
|
||||
# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
|
||||
|
||||
/* If this bit is set, then . matches newline.
|
||||
If not set, then it doesn't. */
|
||||
# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
|
||||
|
||||
/* If this bit is set, then . doesn't match NUL.
|
||||
If not set, then it does. */
|
||||
# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
|
||||
|
||||
/* If this bit is set, nonmatching lists [^...] do not match newline.
|
||||
If not set, they do. */
|
||||
# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
|
||||
|
||||
/* If this bit is set, either \{...\} or {...} defines an
|
||||
interval, depending on RE_NO_BK_BRACES.
|
||||
If not set, \{, \}, {, and } are literals. */
|
||||
# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
|
||||
|
||||
/* If this bit is set, +, ? and | aren't recognized as operators.
|
||||
If not set, they are. */
|
||||
# define RE_LIMITED_OPS (RE_INTERVALS << 1)
|
||||
|
||||
/* If this bit is set, newline is an alternation operator.
|
||||
If not set, newline is literal. */
|
||||
# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
|
||||
|
||||
/* If this bit is set, then '{...}' defines an interval, and \{ and \}
|
||||
are literals.
|
||||
If not set, then '\{...\}' defines an interval. */
|
||||
# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
|
||||
|
||||
/* If this bit is set, (...) defines a group, and \( and \) are literals.
|
||||
If not set, \(...\) defines a group, and ( and ) are literals. */
|
||||
# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
|
||||
|
||||
/* If this bit is set, then \<digit> matches <digit>.
|
||||
If not set, then \<digit> is a back-reference. */
|
||||
# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
|
||||
|
||||
/* If this bit is set, then | is an alternation operator, and \| is literal.
|
||||
If not set, then \| is an alternation operator, and | is literal. */
|
||||
# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
|
||||
|
||||
/* If this bit is set, then an ending range point collating higher
|
||||
than the starting range point, as in [z-a], is invalid.
|
||||
If not set, then when ending range point collates higher than the
|
||||
starting range point, the range is ignored. */
|
||||
# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
|
||||
|
||||
/* If this bit is set, then an unmatched ) is ordinary.
|
||||
If not set, then an unmatched ) is invalid. */
|
||||
# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
|
||||
|
||||
/* If this bit is set, succeed as soon as we match the whole pattern,
|
||||
without further backtracking. */
|
||||
# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
|
||||
|
||||
/* If this bit is set, do not process the GNU regex operators.
|
||||
If not set, then the GNU regex operators are recognized. */
|
||||
# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
|
||||
|
||||
/* If this bit is set, turn on internal regex debugging.
|
||||
If not set, and debugging was on, turn it off.
|
||||
This only works if regex.c is compiled -DDEBUG.
|
||||
We define this bit always, so that all that's needed to turn on
|
||||
debugging is to recompile regex.c; the calling code can always have
|
||||
this bit set, and it won't affect anything in the normal case. */
|
||||
# define RE_DEBUG (RE_NO_GNU_OPS << 1)
|
||||
|
||||
/* If this bit is set, a syntactically invalid interval is treated as
|
||||
a string of ordinary characters. For example, the ERE 'a{1' is
|
||||
treated as 'a\{1'. */
|
||||
# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
|
||||
|
||||
/* If this bit is set, then ignore case when matching.
|
||||
If not set, then case is significant. */
|
||||
# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
|
||||
|
||||
/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
|
||||
for ^, because it is difficult to scan the regex backwards to find
|
||||
whether ^ should be special. */
|
||||
# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
|
||||
|
||||
/* If this bit is set, then \{ cannot be first in a regex or
|
||||
immediately after an alternation, open-group or \} operator. */
|
||||
# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
|
||||
|
||||
/* If this bit is set, then no_sub will be set to 1 during
|
||||
re_compile_pattern. */
|
||||
# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
|
||||
#endif
|
||||
|
||||
/* This global variable defines the particular regexp syntax to use (for
|
||||
some interfaces). When a regexp is compiled, the syntax used is
|
||||
stored in the pattern buffer, so changing this does not affect
|
||||
already-compiled regexps. */
|
||||
extern reg_syntax_t re_syntax_options;
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Define combinations of the above bits for the standard possibilities.
|
||||
(The [[[ comments delimit what gets put into the Texinfo file, so
|
||||
don't delete them!) */
|
||||
/* [[[begin syntaxes]]] */
|
||||
# define RE_SYNTAX_EMACS 0
|
||||
|
||||
# define RE_SYNTAX_AWK \
|
||||
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
|
||||
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
|
||||
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CHAR_CLASSES \
|
||||
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
|
||||
|
||||
# define RE_SYNTAX_GNU_AWK \
|
||||
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
|
||||
| RE_INVALID_INTERVAL_ORD) \
|
||||
& ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \
|
||||
| RE_CONTEXT_INVALID_OPS ))
|
||||
|
||||
# define RE_SYNTAX_POSIX_AWK \
|
||||
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
|
||||
| RE_INTERVALS | RE_NO_GNU_OPS \
|
||||
| RE_INVALID_INTERVAL_ORD)
|
||||
|
||||
# define RE_SYNTAX_GREP \
|
||||
((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \
|
||||
& ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL))
|
||||
|
||||
# define RE_SYNTAX_EGREP \
|
||||
((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \
|
||||
& ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL))
|
||||
|
||||
/* POSIX grep -E behavior is no longer incompatible with GNU. */
|
||||
# define RE_SYNTAX_POSIX_EGREP \
|
||||
RE_SYNTAX_EGREP
|
||||
|
||||
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
|
||||
# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
|
||||
|
||||
# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
|
||||
|
||||
/* Syntax bits common to both basic and extended POSIX regex syntax. */
|
||||
# define _RE_SYNTAX_POSIX_COMMON \
|
||||
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
|
||||
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
|
||||
|
||||
# define RE_SYNTAX_POSIX_BASIC \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
|
||||
|
||||
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
|
||||
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
|
||||
isn't minimal, since other operators, such as \`, aren't disabled. */
|
||||
# define RE_SYNTAX_POSIX_MINIMAL_BASIC \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
|
||||
|
||||
# define RE_SYNTAX_POSIX_EXTENDED \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
|
||||
| RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
|
||||
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
|
||||
removed and RE_NO_BK_REFS is added. */
|
||||
# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
|
||||
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
/* [[[end syntaxes]]] */
|
||||
|
||||
/* Maximum number of duplicates an interval can allow. POSIX-conforming
|
||||
systems might define this in <limits.h>, but we want our
|
||||
value, so remove any previous define. */
|
||||
# ifdef _REGEX_INCLUDE_LIMITS_H
|
||||
# include <limits.h>
|
||||
# endif
|
||||
# ifdef RE_DUP_MAX
|
||||
# undef RE_DUP_MAX
|
||||
# endif
|
||||
|
||||
/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored
|
||||
the counter as a 2-byte signed integer. This is no longer true, so
|
||||
RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to
|
||||
((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined.
|
||||
However, there would be a huge performance problem if someone
|
||||
actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains
|
||||
its historical value. */
|
||||
# define RE_DUP_MAX (0x7fff)
|
||||
#endif
|
||||
|
||||
|
||||
/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */
|
||||
|
||||
/* If this bit is set, then use extended regular expression syntax.
|
||||
If not set, then use basic regular expression syntax. */
|
||||
#define REG_EXTENDED 1
|
||||
|
||||
/* If this bit is set, then ignore case when matching.
|
||||
If not set, then case is significant. */
|
||||
#define REG_ICASE (1 << 1)
|
||||
|
||||
/* If this bit is set, then anchors do not match at newline
|
||||
characters in the string.
|
||||
If not set, then anchors do match at newlines. */
|
||||
#define REG_NEWLINE (1 << 2)
|
||||
|
||||
/* If this bit is set, then report only success or fail in regexec.
|
||||
If not set, then returns differ between not matching and errors. */
|
||||
#define REG_NOSUB (1 << 3)
|
||||
|
||||
|
||||
/* POSIX 'eflags' bits (i.e., information for regexec). */
|
||||
|
||||
/* If this bit is set, then the beginning-of-line operator doesn't match
|
||||
the beginning of the string (presumably because it's not the
|
||||
beginning of a line).
|
||||
If not set, then the beginning-of-line operator does match the
|
||||
beginning of the string. */
|
||||
#define REG_NOTBOL 1
|
||||
|
||||
/* Like REG_NOTBOL, except for the end-of-line. */
|
||||
#define REG_NOTEOL (1 << 1)
|
||||
|
||||
/* Use PMATCH[0] to delimit the start and end of the search in the
|
||||
buffer. */
|
||||
#define REG_STARTEND (1 << 2)
|
||||
|
||||
|
||||
/* If any error codes are removed, changed, or added, update the
|
||||
'__re_error_msgid' table in regcomp.c. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
_REG_ENOSYS = -1, /* This will never happen for this implementation. */
|
||||
_REG_NOERROR = 0, /* Success. */
|
||||
_REG_NOMATCH, /* Didn't find a match (for regexec). */
|
||||
|
||||
/* POSIX regcomp return error codes. (In the order listed in the
|
||||
standard.) */
|
||||
_REG_BADPAT, /* Invalid pattern. */
|
||||
_REG_ECOLLATE, /* Invalid collating element. */
|
||||
_REG_ECTYPE, /* Invalid character class name. */
|
||||
_REG_EESCAPE, /* Trailing backslash. */
|
||||
_REG_ESUBREG, /* Invalid back reference. */
|
||||
_REG_EBRACK, /* Unmatched left bracket. */
|
||||
_REG_EPAREN, /* Parenthesis imbalance. */
|
||||
_REG_EBRACE, /* Unmatched \{. */
|
||||
_REG_BADBR, /* Invalid contents of \{\}. */
|
||||
_REG_ERANGE, /* Invalid range end. */
|
||||
_REG_ESPACE, /* Ran out of memory. */
|
||||
_REG_BADRPT, /* No preceding re for repetition op. */
|
||||
|
||||
/* Error codes we've added. */
|
||||
_REG_EEND, /* Premature end. */
|
||||
_REG_ESIZE, /* Too large (e.g., repeat count too large). */
|
||||
_REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
|
||||
} reg_errcode_t;
|
||||
|
||||
#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
|
||||
# define REG_ENOSYS _REG_ENOSYS
|
||||
#endif
|
||||
#define REG_NOERROR _REG_NOERROR
|
||||
#define REG_NOMATCH _REG_NOMATCH
|
||||
#define REG_BADPAT _REG_BADPAT
|
||||
#define REG_ECOLLATE _REG_ECOLLATE
|
||||
#define REG_ECTYPE _REG_ECTYPE
|
||||
#define REG_EESCAPE _REG_EESCAPE
|
||||
#define REG_ESUBREG _REG_ESUBREG
|
||||
#define REG_EBRACK _REG_EBRACK
|
||||
#define REG_EPAREN _REG_EPAREN
|
||||
#define REG_EBRACE _REG_EBRACE
|
||||
#define REG_BADBR _REG_BADBR
|
||||
#define REG_ERANGE _REG_ERANGE
|
||||
#define REG_ESPACE _REG_ESPACE
|
||||
#define REG_BADRPT _REG_BADRPT
|
||||
#define REG_EEND _REG_EEND
|
||||
#define REG_ESIZE _REG_ESIZE
|
||||
#define REG_ERPAREN _REG_ERPAREN
|
||||
|
||||
/* This data structure represents a compiled pattern. Before calling
|
||||
the pattern compiler, the fields 'buffer', 'allocated', 'fastmap',
|
||||
and 'translate' can be set. After the pattern has been compiled,
|
||||
the fields 're_nsub', 'not_bol' and 'not_eol' are available. All
|
||||
other fields are private to the regex routines. */
|
||||
|
||||
#ifndef RE_TRANSLATE_TYPE
|
||||
# define __RE_TRANSLATE_TYPE unsigned char *
|
||||
# ifdef __USE_GNU
|
||||
# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __USE_GNU
|
||||
# define __REPB_PREFIX(name) name
|
||||
#else
|
||||
# define __REPB_PREFIX(name) __##name
|
||||
#endif
|
||||
|
||||
struct re_pattern_buffer
|
||||
{
|
||||
/* Space that holds the compiled pattern. The type
|
||||
'struct re_dfa_t' is private and is not declared here. */
|
||||
struct re_dfa_t *__REPB_PREFIX(buffer);
|
||||
|
||||
/* Number of bytes to which 'buffer' points. */
|
||||
__re_long_size_t __REPB_PREFIX(allocated);
|
||||
|
||||
/* Number of bytes actually used in 'buffer'. */
|
||||
__re_long_size_t __REPB_PREFIX(used);
|
||||
|
||||
/* Syntax setting with which the pattern was compiled. */
|
||||
reg_syntax_t __REPB_PREFIX(syntax);
|
||||
|
||||
/* Pointer to a fastmap, if any, otherwise zero. re_search uses the
|
||||
fastmap, if there is one, to skip over impossible starting points
|
||||
for matches. */
|
||||
char *__REPB_PREFIX(fastmap);
|
||||
|
||||
/* Either a translate table to apply to all characters before
|
||||
comparing them, or zero for no translation. The translation is
|
||||
applied to a pattern when it is compiled and to a string when it
|
||||
is matched. */
|
||||
__RE_TRANSLATE_TYPE __REPB_PREFIX(translate);
|
||||
|
||||
/* Number of subexpressions found by the compiler. */
|
||||
size_t re_nsub;
|
||||
|
||||
/* Zero if this pattern cannot match the empty string, one else.
|
||||
Well, in truth it's used only in 're_search_2', to see whether or
|
||||
not we should use the fastmap, so we don't set this absolutely
|
||||
perfectly; see 're_compile_fastmap' (the "duplicate" case). */
|
||||
unsigned __REPB_PREFIX(can_be_null) : 1;
|
||||
|
||||
/* If REGS_UNALLOCATED, allocate space in the 'regs' structure
|
||||
for 'max (RE_NREGS, re_nsub + 1)' groups.
|
||||
If REGS_REALLOCATE, reallocate space if necessary.
|
||||
If REGS_FIXED, use what's there. */
|
||||
#ifdef __USE_GNU
|
||||
# define REGS_UNALLOCATED 0
|
||||
# define REGS_REALLOCATE 1
|
||||
# define REGS_FIXED 2
|
||||
#endif
|
||||
unsigned __REPB_PREFIX(regs_allocated) : 2;
|
||||
|
||||
/* Set to zero when 're_compile_pattern' compiles a pattern; set to
|
||||
one by 're_compile_fastmap' if it updates the fastmap. */
|
||||
unsigned __REPB_PREFIX(fastmap_accurate) : 1;
|
||||
|
||||
/* If set, 're_match_2' does not return information about
|
||||
subexpressions. */
|
||||
unsigned __REPB_PREFIX(no_sub) : 1;
|
||||
|
||||
/* If set, a beginning-of-line anchor doesn't match at the beginning
|
||||
of the string. */
|
||||
unsigned __REPB_PREFIX(not_bol) : 1;
|
||||
|
||||
/* Similarly for an end-of-line anchor. */
|
||||
unsigned __REPB_PREFIX(not_eol) : 1;
|
||||
|
||||
/* If true, an anchor at a newline matches. */
|
||||
unsigned __REPB_PREFIX(newline_anchor) : 1;
|
||||
};
|
||||
|
||||
typedef struct re_pattern_buffer regex_t;
|
||||
|
||||
/* Type for byte offsets within the string. POSIX mandates this. */
|
||||
#ifdef _REGEX_LARGE_OFFSETS
|
||||
/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as
|
||||
ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t
|
||||
is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not
|
||||
visible here, so use ssize_t. */
|
||||
typedef ssize_t regoff_t;
|
||||
#else
|
||||
/* The traditional GNU regex implementation mishandles strings longer
|
||||
than INT_MAX. */
|
||||
typedef int regoff_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* This is the structure we store register match data in. See
|
||||
regex.texinfo for a full description of what registers match. */
|
||||
struct re_registers
|
||||
{
|
||||
__re_size_t num_regs;
|
||||
regoff_t *start;
|
||||
regoff_t *end;
|
||||
};
|
||||
|
||||
|
||||
/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
|
||||
're_match_2' returns information about at least this many registers
|
||||
the first time a 'regs' structure is passed. */
|
||||
# ifndef RE_NREGS
|
||||
# define RE_NREGS 30
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* POSIX specification for registers. Aside from the different names than
|
||||
're_registers', POSIX uses an array of structures, instead of a
|
||||
structure of arrays. */
|
||||
typedef struct
|
||||
{
|
||||
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
|
||||
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
|
||||
} regmatch_t;
|
||||
|
||||
/* Declarations for routines. */
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Sets the current default syntax to SYNTAX, and return the old syntax.
|
||||
You can also simply assign to the 're_syntax_options' variable. */
|
||||
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
|
||||
|
||||
/* Compile the regular expression PATTERN, with length LENGTH
|
||||
and syntax given by the global 're_syntax_options', into the buffer
|
||||
BUFFER. Return NULL if successful, and an error string if not.
|
||||
|
||||
To free the allocated storage, you must call 'regfree' on BUFFER.
|
||||
Note that the translate table must either have been initialized by
|
||||
'regcomp', with a malloc'ed value, or set to NULL before calling
|
||||
'regfree'. */
|
||||
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
|
||||
struct re_pattern_buffer *__buffer);
|
||||
|
||||
|
||||
/* Compile a fastmap for the compiled pattern in BUFFER; used to
|
||||
accelerate searches. Return 0 if successful and -2 if was an
|
||||
internal error. */
|
||||
extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
|
||||
|
||||
|
||||
/* Search in the string STRING (with length LENGTH) for the pattern
|
||||
compiled into BUFFER. Start searching at position START, for RANGE
|
||||
characters. Return the starting position of the match, -1 for no
|
||||
match, or -2 for an internal error. Also return register
|
||||
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
|
||||
extern regoff_t re_search (struct re_pattern_buffer *__buffer,
|
||||
const char *__String, regoff_t __length,
|
||||
regoff_t __start, regoff_t __range,
|
||||
struct re_registers *__regs);
|
||||
|
||||
|
||||
/* Like 're_search', but search in the concatenation of STRING1 and
|
||||
STRING2. Also, stop searching at index START + STOP. */
|
||||
extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
|
||||
const char *__string1, regoff_t __length1,
|
||||
const char *__string2, regoff_t __length2,
|
||||
regoff_t __start, regoff_t __range,
|
||||
struct re_registers *__regs,
|
||||
regoff_t __stop);
|
||||
|
||||
|
||||
/* Like 're_search', but return how many characters in STRING the regexp
|
||||
in BUFFER matched, starting at position START. */
|
||||
extern regoff_t re_match (struct re_pattern_buffer *__buffer,
|
||||
const char *__String, regoff_t __length,
|
||||
regoff_t __start, struct re_registers *__regs);
|
||||
|
||||
|
||||
/* Relates to 're_match' as 're_search_2' relates to 're_search'. */
|
||||
extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
|
||||
const char *__string1, regoff_t __length1,
|
||||
const char *__string2, regoff_t __length2,
|
||||
regoff_t __start, struct re_registers *__regs,
|
||||
regoff_t __stop);
|
||||
|
||||
|
||||
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
|
||||
ENDS. Subsequent matches using BUFFER and REGS will use this memory
|
||||
for recording register information. STARTS and ENDS must be
|
||||
allocated with malloc, and must each be at least 'NUM_REGS * sizeof
|
||||
(regoff_t)' bytes long.
|
||||
|
||||
If NUM_REGS == 0, then subsequent matches should allocate their own
|
||||
register data.
|
||||
|
||||
Unless this function is called, the first search or match using
|
||||
BUFFER will allocate its own register data, without
|
||||
freeing the old data. */
|
||||
extern void re_set_registers (struct re_pattern_buffer *__buffer,
|
||||
struct re_registers *__regs,
|
||||
__re_size_t __num_regs,
|
||||
regoff_t *__starts, regoff_t *__ends);
|
||||
#endif /* Use GNU */
|
||||
|
||||
#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC)
|
||||
# ifndef _CRAY
|
||||
/* 4.2 bsd compatibility. */
|
||||
extern char *re_comp (const char *);
|
||||
extern int re_exec (const char *);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For plain 'restrict', use glibc's __restrict if defined.
|
||||
Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have
|
||||
"restrict", and "configure" may have defined "restrict".
|
||||
Other compilers use __restrict, __restrict__, and _Restrict, and
|
||||
'configure' might #define 'restrict' to those words, so pick a
|
||||
different name. */
|
||||
#ifndef _Restrict_
|
||||
# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
|
||||
# define _Restrict_ __restrict
|
||||
# elif 199901L <= __STDC_VERSION__ || defined restrict
|
||||
# define _Restrict_ restrict
|
||||
# else
|
||||
# define _Restrict_
|
||||
# endif
|
||||
#endif
|
||||
/* For [restrict], use glibc's __restrict_arr if available.
|
||||
Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */
|
||||
#ifndef _Restrict_arr_
|
||||
# ifdef __restrict_arr
|
||||
# define _Restrict_arr_ __restrict_arr
|
||||
# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
|
||||
&& !defined __GNUG__)
|
||||
# define _Restrict_arr_ _Restrict_
|
||||
# else
|
||||
# define _Restrict_arr_
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* POSIX compatibility. */
|
||||
extern int regcomp (regex_t *_Restrict_ __preg,
|
||||
const char *_Restrict_ __pattern,
|
||||
int __cflags);
|
||||
|
||||
extern int regexec (const regex_t *_Restrict_ __preg,
|
||||
const char *_Restrict_ __String, size_t __nmatch,
|
||||
regmatch_t __pmatch[_Restrict_arr_],
|
||||
int __eflags);
|
||||
|
||||
extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg,
|
||||
char *_Restrict_ __errbuf, size_t __errbuf_size);
|
||||
|
||||
extern void regfree (regex_t *__preg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* C++ */
|
||||
|
||||
#endif /* regex.h */
|
1740
lib/regex_internal.c
Normal file
1740
lib/regex_internal.c
Normal file
File diff suppressed because it is too large
Load diff
911
lib/regex_internal.h
Normal file
911
lib/regex_internal.h
Normal file
|
@ -0,0 +1,911 @@
|
|||
/* Extended regular expression matching and search library.
|
||||
Copyright (C) 2002-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _REGEX_INTERNAL_H
|
||||
#define _REGEX_INTERNAL_H 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Properties of integers. Although Gnulib has intprops.h, glibc does
|
||||
without for now. */
|
||||
#ifndef _LIBC
|
||||
# include "intprops.h"
|
||||
#else
|
||||
/* True if the real type T is signed. */
|
||||
# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* True if adding the nonnegative Idx values A and B would overflow.
|
||||
If false, set *R to A + B. A, B, and R may be evaluated more than
|
||||
once, or zero times. Although this is not a full implementation of
|
||||
Gnulib INT_ADD_WRAPV, it is good enough for glibc regex code.
|
||||
FIXME: This implementation is a fragile stopgap, and this file would
|
||||
be simpler and more robust if intprops.h were migrated into glibc. */
|
||||
# define INT_ADD_WRAPV(a, b, r) \
|
||||
(IDX_MAX - (a) < (b) ? true : (*(r) = (a) + (b), false))
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libc-lock.h>
|
||||
# define lock_define(name) __libc_lock_define (, name)
|
||||
# define lock_init(lock) (__libc_lock_init (lock), 0)
|
||||
# define lock_fini(lock) ((void) 0)
|
||||
# define lock_lock(lock) __libc_lock_lock (lock)
|
||||
# define lock_unlock(lock) __libc_lock_unlock (lock)
|
||||
#elif defined GNULIB_LOCK && !defined USE_UNLOCKED_IO
|
||||
# include "glthread/lock.h"
|
||||
/* Use gl_lock_define if empty macro arguments are known to work.
|
||||
Otherwise, fall back on less-portable substitutes. */
|
||||
# if ((defined __GNUC__ && !defined __STRICT_ANSI__) \
|
||||
|| (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__))
|
||||
# define lock_define(name) gl_lock_define (, name)
|
||||
# elif USE_POSIX_THREADS
|
||||
# define lock_define(name) pthread_mutex_t name;
|
||||
# elif USE_PTH_THREADS
|
||||
# define lock_define(name) pth_mutex_t name;
|
||||
# elif USE_SOLARIS_THREADS
|
||||
# define lock_define(name) mutex_t name;
|
||||
# elif USE_WINDOWS_THREADS
|
||||
# define lock_define(name) gl_lock_t name;
|
||||
# else
|
||||
# define lock_define(name)
|
||||
# endif
|
||||
# define lock_init(lock) glthread_lock_init (&(lock))
|
||||
# define lock_fini(lock) glthread_lock_destroy (&(lock))
|
||||
# define lock_lock(lock) glthread_lock_lock (&(lock))
|
||||
# define lock_unlock(lock) glthread_lock_unlock (&(lock))
|
||||
#elif defined GNULIB_PTHREAD && !defined USE_UNLOCKED_IO
|
||||
# include <pthread.h>
|
||||
# define lock_define(name) pthread_mutex_t name;
|
||||
# define lock_init(lock) pthread_mutex_init (&(lock), 0)
|
||||
# define lock_fini(lock) pthread_mutex_destroy (&(lock))
|
||||
# define lock_lock(lock) pthread_mutex_lock (&(lock))
|
||||
# define lock_unlock(lock) pthread_mutex_unlock (&(lock))
|
||||
#else
|
||||
# define lock_define(name)
|
||||
# define lock_init(lock) 0
|
||||
# define lock_fini(lock) ((void) 0)
|
||||
/* The 'dfa' avoids an "unused variable 'dfa'" warning from GCC. */
|
||||
# define lock_lock(lock) ((void) dfa)
|
||||
# define lock_unlock(lock) ((void) 0)
|
||||
#endif
|
||||
|
||||
/* In case that the system doesn't have isblank(). */
|
||||
#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
|
||||
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
|
||||
# define _RE_DEFINE_LOCALE_FUNCTIONS 1
|
||||
# include <locale/localeinfo.h>
|
||||
# include <locale/coll-lookup.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is for other GNU distributions with internationalized messages. */
|
||||
#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
|
||||
# include <libintl.h>
|
||||
# ifdef _LIBC
|
||||
# undef gettext
|
||||
# define gettext(msgid) \
|
||||
__dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES)
|
||||
# endif
|
||||
#else
|
||||
# undef gettext
|
||||
# define gettext(msgid) (msgid)
|
||||
#endif
|
||||
|
||||
#ifndef gettext_noop
|
||||
/* This define is so xgettext can find the internationalizable
|
||||
strings. */
|
||||
# define gettext_noop(String) String
|
||||
#endif
|
||||
|
||||
#if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE) || _LIBC
|
||||
# define RE_ENABLE_I18N
|
||||
#endif
|
||||
|
||||
#define BE(expr, val) __builtin_expect (expr, val)
|
||||
|
||||
/* Number of ASCII characters. */
|
||||
#define ASCII_CHARS 0x80
|
||||
|
||||
/* Number of single byte characters. */
|
||||
#define SBC_MAX (UCHAR_MAX + 1)
|
||||
|
||||
#define COLL_ELEM_LEN_MAX 8
|
||||
|
||||
/* The character which represents newline. */
|
||||
#define NEWLINE_CHAR '\n'
|
||||
#define WIDE_NEWLINE_CHAR L'\n'
|
||||
|
||||
/* Rename to standard API for using out of glibc. */
|
||||
#ifndef _LIBC
|
||||
# undef __wctype
|
||||
# undef __iswctype
|
||||
# define __wctype wctype
|
||||
# define __iswalnum iswalnum
|
||||
# define __iswctype iswctype
|
||||
# define __towlower towlower
|
||||
# define __towupper towupper
|
||||
# define __btowc btowc
|
||||
# define __mbrtowc mbrtowc
|
||||
# define __wcrtomb wcrtomb
|
||||
# define __regfree regfree
|
||||
# define attribute_hidden
|
||||
#endif /* not _LIBC */
|
||||
|
||||
#if __GNUC__ < 3 + (__GNUC_MINOR__ < 1)
|
||||
# define __attribute__(arg)
|
||||
#endif
|
||||
|
||||
#ifndef SSIZE_MAX
|
||||
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
|
||||
#endif
|
||||
|
||||
/* The type of indexes into strings. This is signed, not size_t,
|
||||
since the API requires indexes to fit in regoff_t anyway, and using
|
||||
signed integers makes the code a bit smaller and presumably faster.
|
||||
The traditional GNU regex implementation uses int for indexes.
|
||||
The POSIX-compatible implementation uses a possibly-wider type.
|
||||
The name 'Idx' is three letters to minimize the hassle of
|
||||
reindenting a lot of regex code that formerly used 'int'. */
|
||||
typedef regoff_t Idx;
|
||||
#ifdef _REGEX_LARGE_OFFSETS
|
||||
# define IDX_MAX SSIZE_MAX
|
||||
#else
|
||||
# define IDX_MAX INT_MAX
|
||||
#endif
|
||||
|
||||
/* A hash value, suitable for computing hash tables. */
|
||||
typedef __re_size_t re_hashval_t;
|
||||
|
||||
/* An integer used to represent a set of bits. It must be unsigned,
|
||||
and must be at least as wide as unsigned int. */
|
||||
typedef unsigned long int bitset_word_t;
|
||||
/* All bits set in a bitset_word_t. */
|
||||
#define BITSET_WORD_MAX ULONG_MAX
|
||||
|
||||
/* Number of bits in a bitset_word_t. For portability to hosts with
|
||||
padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)';
|
||||
instead, deduce it directly from BITSET_WORD_MAX. Avoid
|
||||
greater-than-32-bit integers and unconditional shifts by more than
|
||||
31 bits, as they're not portable. */
|
||||
#if BITSET_WORD_MAX == 0xffffffffUL
|
||||
# define BITSET_WORD_BITS 32
|
||||
#elif BITSET_WORD_MAX >> 31 >> 4 == 1
|
||||
# define BITSET_WORD_BITS 36
|
||||
#elif BITSET_WORD_MAX >> 31 >> 16 == 1
|
||||
# define BITSET_WORD_BITS 48
|
||||
#elif BITSET_WORD_MAX >> 31 >> 28 == 1
|
||||
# define BITSET_WORD_BITS 60
|
||||
#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1
|
||||
# define BITSET_WORD_BITS 64
|
||||
#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1
|
||||
# define BITSET_WORD_BITS 72
|
||||
#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1
|
||||
# define BITSET_WORD_BITS 128
|
||||
#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1
|
||||
# define BITSET_WORD_BITS 256
|
||||
#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1
|
||||
# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */
|
||||
# if BITSET_WORD_BITS <= SBC_MAX
|
||||
# error "Invalid SBC_MAX"
|
||||
# endif
|
||||
#else
|
||||
# error "Add case for new bitset_word_t size"
|
||||
#endif
|
||||
|
||||
/* Number of bitset_word_t values in a bitset_t. */
|
||||
#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
|
||||
|
||||
typedef bitset_word_t bitset_t[BITSET_WORDS];
|
||||
typedef bitset_word_t *re_bitset_ptr_t;
|
||||
typedef const bitset_word_t *re_const_bitset_ptr_t;
|
||||
|
||||
#define PREV_WORD_CONSTRAINT 0x0001
|
||||
#define PREV_NOTWORD_CONSTRAINT 0x0002
|
||||
#define NEXT_WORD_CONSTRAINT 0x0004
|
||||
#define NEXT_NOTWORD_CONSTRAINT 0x0008
|
||||
#define PREV_NEWLINE_CONSTRAINT 0x0010
|
||||
#define NEXT_NEWLINE_CONSTRAINT 0x0020
|
||||
#define PREV_BEGBUF_CONSTRAINT 0x0040
|
||||
#define NEXT_ENDBUF_CONSTRAINT 0x0080
|
||||
#define WORD_DELIM_CONSTRAINT 0x0100
|
||||
#define NOT_WORD_DELIM_CONSTRAINT 0x0200
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
|
||||
WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
|
||||
WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
|
||||
INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
|
||||
LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
|
||||
LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
|
||||
BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
|
||||
BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
|
||||
WORD_DELIM = WORD_DELIM_CONSTRAINT,
|
||||
NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
|
||||
} re_context_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Idx alloc;
|
||||
Idx nelem;
|
||||
Idx *elems;
|
||||
} re_node_set;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NON_TYPE = 0,
|
||||
|
||||
/* Node type, These are used by token, node, tree. */
|
||||
CHARACTER = 1,
|
||||
END_OF_RE = 2,
|
||||
SIMPLE_BRACKET = 3,
|
||||
OP_BACK_REF = 4,
|
||||
OP_PERIOD = 5,
|
||||
#ifdef RE_ENABLE_I18N
|
||||
COMPLEX_BRACKET = 6,
|
||||
OP_UTF8_PERIOD = 7,
|
||||
#endif /* RE_ENABLE_I18N */
|
||||
|
||||
/* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
|
||||
when the debugger shows values of this enum type. */
|
||||
#define EPSILON_BIT 8
|
||||
OP_OPEN_SUBEXP = EPSILON_BIT | 0,
|
||||
OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
|
||||
OP_ALT = EPSILON_BIT | 2,
|
||||
OP_DUP_ASTERISK = EPSILON_BIT | 3,
|
||||
ANCHOR = EPSILON_BIT | 4,
|
||||
|
||||
/* Tree type, these are used only by tree. */
|
||||
CONCAT = 16,
|
||||
SUBEXP = 17,
|
||||
|
||||
/* Token type, these are used only by token. */
|
||||
OP_DUP_PLUS = 18,
|
||||
OP_DUP_QUESTION,
|
||||
OP_OPEN_BRACKET,
|
||||
OP_CLOSE_BRACKET,
|
||||
OP_CHARSET_RANGE,
|
||||
OP_OPEN_DUP_NUM,
|
||||
OP_CLOSE_DUP_NUM,
|
||||
OP_NON_MATCH_LIST,
|
||||
OP_OPEN_COLL_ELEM,
|
||||
OP_CLOSE_COLL_ELEM,
|
||||
OP_OPEN_EQUIV_CLASS,
|
||||
OP_CLOSE_EQUIV_CLASS,
|
||||
OP_OPEN_CHAR_CLASS,
|
||||
OP_CLOSE_CHAR_CLASS,
|
||||
OP_WORD,
|
||||
OP_NOTWORD,
|
||||
OP_SPACE,
|
||||
OP_NOTSPACE,
|
||||
BACK_SLASH
|
||||
|
||||
} re_token_type_t;
|
||||
|
||||
#ifdef RE_ENABLE_I18N
|
||||
typedef struct
|
||||
{
|
||||
/* Multibyte characters. */
|
||||
wchar_t *mbchars;
|
||||
|
||||
/* Collating symbols. */
|
||||
# ifdef _LIBC
|
||||
int32_t *coll_syms;
|
||||
# endif
|
||||
|
||||
/* Equivalence classes. */
|
||||
# ifdef _LIBC
|
||||
int32_t *equiv_classes;
|
||||
# endif
|
||||
|
||||
/* Range expressions. */
|
||||
# ifdef _LIBC
|
||||
uint32_t *range_starts;
|
||||
uint32_t *range_ends;
|
||||
# else /* not _LIBC */
|
||||
wchar_t *range_starts;
|
||||
wchar_t *range_ends;
|
||||
# endif /* not _LIBC */
|
||||
|
||||
/* Character classes. */
|
||||
wctype_t *char_classes;
|
||||
|
||||
/* If this character set is the non-matching list. */
|
||||
unsigned int non_match : 1;
|
||||
|
||||
/* # of multibyte characters. */
|
||||
Idx nmbchars;
|
||||
|
||||
/* # of collating symbols. */
|
||||
Idx ncoll_syms;
|
||||
|
||||
/* # of equivalence classes. */
|
||||
Idx nequiv_classes;
|
||||
|
||||
/* # of range expressions. */
|
||||
Idx nranges;
|
||||
|
||||
/* # of character classes. */
|
||||
Idx nchar_classes;
|
||||
} re_charset_t;
|
||||
#endif /* RE_ENABLE_I18N */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned char c; /* for CHARACTER */
|
||||
re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
|
||||
#ifdef RE_ENABLE_I18N
|
||||
re_charset_t *mbcset; /* for COMPLEX_BRACKET */
|
||||
#endif /* RE_ENABLE_I18N */
|
||||
Idx idx; /* for BACK_REF */
|
||||
re_context_type ctx_type; /* for ANCHOR */
|
||||
} opr;
|
||||
#if __GNUC__ >= 2 && !defined __STRICT_ANSI__
|
||||
re_token_type_t type : 8;
|
||||
#else
|
||||
re_token_type_t type;
|
||||
#endif
|
||||
unsigned int constraint : 10; /* context constraint */
|
||||
unsigned int duplicated : 1;
|
||||
unsigned int opt_subexp : 1;
|
||||
#ifdef RE_ENABLE_I18N
|
||||
unsigned int accept_mb : 1;
|
||||
/* These 2 bits can be moved into the union if needed (e.g. if running out
|
||||
of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
|
||||
unsigned int mb_partial : 1;
|
||||
#endif
|
||||
unsigned int word_char : 1;
|
||||
} re_token_t;
|
||||
|
||||
#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
|
||||
|
||||
struct re_string_t
|
||||
{
|
||||
/* Indicate the raw buffer which is the original string passed as an
|
||||
argument of regexec(), re_search(), etc.. */
|
||||
const unsigned char *raw_mbs;
|
||||
/* Store the multibyte string. In case of "case insensitive mode" like
|
||||
REG_ICASE, upper cases of the string are stored, otherwise MBS points
|
||||
the same address that RAW_MBS points. */
|
||||
unsigned char *mbs;
|
||||
#ifdef RE_ENABLE_I18N
|
||||
/* Store the wide character string which is corresponding to MBS. */
|
||||
wint_t *wcs;
|
||||
Idx *offsets;
|
||||
mbstate_t cur_state;
|
||||
#endif
|
||||
/* Index in RAW_MBS. Each character mbs[i] corresponds to
|
||||
raw_mbs[raw_mbs_idx + i]. */
|
||||
Idx raw_mbs_idx;
|
||||
/* The length of the valid characters in the buffers. */
|
||||
Idx valid_len;
|
||||
/* The corresponding number of bytes in raw_mbs array. */
|
||||
Idx valid_raw_len;
|
||||
/* The length of the buffers MBS and WCS. */
|
||||
Idx bufs_len;
|
||||
/* The index in MBS, which is updated by re_string_fetch_byte. */
|
||||
Idx cur_idx;
|
||||
/* length of RAW_MBS array. */
|
||||
Idx raw_len;
|
||||
/* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
|
||||
Idx len;
|
||||
/* End of the buffer may be shorter than its length in the cases such
|
||||
as re_match_2, re_search_2. Then, we use STOP for end of the buffer
|
||||
instead of LEN. */
|
||||
Idx raw_stop;
|
||||
/* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
|
||||
Idx stop;
|
||||
|
||||
/* The context of mbs[0]. We store the context independently, since
|
||||
the context of mbs[0] may be different from raw_mbs[0], which is
|
||||
the beginning of the input string. */
|
||||
unsigned int tip_context;
|
||||
/* The translation passed as a part of an argument of re_compile_pattern. */
|
||||
RE_TRANSLATE_TYPE trans;
|
||||
/* Copy of re_dfa_t's word_char. */
|
||||
re_const_bitset_ptr_t word_char;
|
||||
/* true if REG_ICASE. */
|
||||
unsigned char icase;
|
||||
unsigned char is_utf8;
|
||||
unsigned char map_notascii;
|
||||
unsigned char mbs_allocated;
|
||||
unsigned char offsets_needed;
|
||||
unsigned char newline_anchor;
|
||||
unsigned char word_ops_used;
|
||||
int mb_cur_max;
|
||||
};
|
||||
typedef struct re_string_t re_string_t;
|
||||
|
||||
|
||||
struct re_dfa_t;
|
||||
typedef struct re_dfa_t re_dfa_t;
|
||||
|
||||
#ifndef _LIBC
|
||||
# define IS_IN(libc) false
|
||||
#endif
|
||||
|
||||
#define re_string_peek_byte(pstr, offset) \
|
||||
((pstr)->mbs[(pstr)->cur_idx + offset])
|
||||
#define re_string_fetch_byte(pstr) \
|
||||
((pstr)->mbs[(pstr)->cur_idx++])
|
||||
#define re_string_first_byte(pstr, idx) \
|
||||
((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
|
||||
#define re_string_is_single_byte_char(pstr, idx) \
|
||||
((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
|
||||
|| (pstr)->wcs[(idx) + 1] != WEOF))
|
||||
#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
|
||||
#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
|
||||
#define re_string_get_buffer(pstr) ((pstr)->mbs)
|
||||
#define re_string_length(pstr) ((pstr)->len)
|
||||
#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
|
||||
#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
|
||||
#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
|
||||
|
||||
#if defined _LIBC || HAVE_ALLOCA
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
#ifndef _LIBC
|
||||
# if HAVE_ALLOCA
|
||||
/* The OS usually guarantees only one guard page at the bottom of the stack,
|
||||
and a page size can be as small as 4096 bytes. So we cannot safely
|
||||
allocate anything larger than 4096 bytes. Also care for the possibility
|
||||
of a few compiler-allocated temporary stack slots. */
|
||||
# define __libc_use_alloca(n) ((n) < 4032)
|
||||
# else
|
||||
/* alloca is implemented with malloc, so just use malloc. */
|
||||
# define __libc_use_alloca(n) 0
|
||||
# undef alloca
|
||||
# define alloca(n) malloc (n)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# define MALLOC_0_IS_NONNULL 1
|
||||
#elif !defined MALLOC_0_IS_NONNULL
|
||||
# define MALLOC_0_IS_NONNULL 0
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
#endif
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
|
||||
#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
|
||||
#define re_free(p) free (p)
|
||||
|
||||
struct bin_tree_t
|
||||
{
|
||||
struct bin_tree_t *parent;
|
||||
struct bin_tree_t *left;
|
||||
struct bin_tree_t *right;
|
||||
struct bin_tree_t *first;
|
||||
struct bin_tree_t *next;
|
||||
|
||||
re_token_t token;
|
||||
|
||||
/* 'node_idx' is the index in dfa->nodes, if 'type' == 0.
|
||||
Otherwise 'type' indicate the type of this node. */
|
||||
Idx node_idx;
|
||||
};
|
||||
typedef struct bin_tree_t bin_tree_t;
|
||||
|
||||
#define BIN_TREE_STORAGE_SIZE \
|
||||
((1024 - sizeof (void *)) / sizeof (bin_tree_t))
|
||||
|
||||
struct bin_tree_storage_t
|
||||
{
|
||||
struct bin_tree_storage_t *next;
|
||||
bin_tree_t data[BIN_TREE_STORAGE_SIZE];
|
||||
};
|
||||
typedef struct bin_tree_storage_t bin_tree_storage_t;
|
||||
|
||||
#define CONTEXT_WORD 1
|
||||
#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
|
||||
#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
|
||||
#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
|
||||
|
||||
#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
|
||||
#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
|
||||
#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
|
||||
#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
|
||||
#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
|
||||
|
||||
#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
|
||||
#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
|
||||
#define IS_WIDE_WORD_CHAR(ch) (__iswalnum (ch) || (ch) == L'_')
|
||||
#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
|
||||
|
||||
#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
|
||||
((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
|
||||
|| ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
|
||||
|| ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
|
||||
|| ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
|
||||
|
||||
#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
|
||||
((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
|
||||
|| (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
|
||||
|| (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
|
||||
|| (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
|
||||
|
||||
struct re_dfastate_t
|
||||
{
|
||||
re_hashval_t hash;
|
||||
re_node_set nodes;
|
||||
re_node_set non_eps_nodes;
|
||||
re_node_set inveclosure;
|
||||
re_node_set *entrance_nodes;
|
||||
struct re_dfastate_t **trtable, **word_trtable;
|
||||
unsigned int context : 4;
|
||||
unsigned int halt : 1;
|
||||
/* If this state can accept "multi byte".
|
||||
Note that we refer to multibyte characters, and multi character
|
||||
collating elements as "multi byte". */
|
||||
unsigned int accept_mb : 1;
|
||||
/* If this state has backreference node(s). */
|
||||
unsigned int has_backref : 1;
|
||||
unsigned int has_constraint : 1;
|
||||
};
|
||||
typedef struct re_dfastate_t re_dfastate_t;
|
||||
|
||||
struct re_state_table_entry
|
||||
{
|
||||
Idx num;
|
||||
Idx alloc;
|
||||
re_dfastate_t **array;
|
||||
};
|
||||
|
||||
/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Idx next_idx;
|
||||
Idx alloc;
|
||||
re_dfastate_t **array;
|
||||
} state_array_t;
|
||||
|
||||
/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Idx node;
|
||||
Idx str_idx; /* The position NODE match at. */
|
||||
state_array_t path;
|
||||
} re_sub_match_last_t;
|
||||
|
||||
/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
|
||||
And information about the node, whose type is OP_CLOSE_SUBEXP,
|
||||
corresponding to NODE is stored in LASTS. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Idx str_idx;
|
||||
Idx node;
|
||||
state_array_t *path;
|
||||
Idx alasts; /* Allocation size of LASTS. */
|
||||
Idx nlasts; /* The number of LASTS. */
|
||||
re_sub_match_last_t **lasts;
|
||||
} re_sub_match_top_t;
|
||||
|
||||
struct re_backref_cache_entry
|
||||
{
|
||||
Idx node;
|
||||
Idx str_idx;
|
||||
Idx subexp_from;
|
||||
Idx subexp_to;
|
||||
char more;
|
||||
char unused;
|
||||
unsigned short int eps_reachable_subexps_map;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* The string object corresponding to the input string. */
|
||||
re_string_t input;
|
||||
#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
|
||||
const re_dfa_t *const dfa;
|
||||
#else
|
||||
const re_dfa_t *dfa;
|
||||
#endif
|
||||
/* EFLAGS of the argument of regexec. */
|
||||
int eflags;
|
||||
/* Where the matching ends. */
|
||||
Idx match_last;
|
||||
Idx last_node;
|
||||
/* The state log used by the matcher. */
|
||||
re_dfastate_t **state_log;
|
||||
Idx state_log_top;
|
||||
/* Back reference cache. */
|
||||
Idx nbkref_ents;
|
||||
Idx abkref_ents;
|
||||
struct re_backref_cache_entry *bkref_ents;
|
||||
int max_mb_elem_len;
|
||||
Idx nsub_tops;
|
||||
Idx asub_tops;
|
||||
re_sub_match_top_t **sub_tops;
|
||||
} re_match_context_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
re_dfastate_t **sifted_states;
|
||||
re_dfastate_t **limited_states;
|
||||
Idx last_node;
|
||||
Idx last_str_idx;
|
||||
re_node_set limits;
|
||||
} re_sift_context_t;
|
||||
|
||||
struct re_fail_stack_ent_t
|
||||
{
|
||||
Idx idx;
|
||||
Idx node;
|
||||
regmatch_t *regs;
|
||||
re_node_set eps_via_nodes;
|
||||
};
|
||||
|
||||
struct re_fail_stack_t
|
||||
{
|
||||
Idx num;
|
||||
Idx alloc;
|
||||
struct re_fail_stack_ent_t *stack;
|
||||
};
|
||||
|
||||
struct re_dfa_t
|
||||
{
|
||||
re_token_t *nodes;
|
||||
size_t nodes_alloc;
|
||||
size_t nodes_len;
|
||||
Idx *nexts;
|
||||
Idx *org_indices;
|
||||
re_node_set *edests;
|
||||
re_node_set *eclosures;
|
||||
re_node_set *inveclosures;
|
||||
struct re_state_table_entry *state_table;
|
||||
re_dfastate_t *init_state;
|
||||
re_dfastate_t *init_state_word;
|
||||
re_dfastate_t *init_state_nl;
|
||||
re_dfastate_t *init_state_begbuf;
|
||||
bin_tree_t *str_tree;
|
||||
bin_tree_storage_t *str_tree_storage;
|
||||
re_bitset_ptr_t sb_char;
|
||||
int str_tree_storage_idx;
|
||||
|
||||
/* number of subexpressions 're_nsub' is in regex_t. */
|
||||
re_hashval_t state_hash_mask;
|
||||
Idx init_node;
|
||||
Idx nbackref; /* The number of backreference in this dfa. */
|
||||
|
||||
/* Bitmap expressing which backreference is used. */
|
||||
bitset_word_t used_bkref_map;
|
||||
bitset_word_t completed_bkref_map;
|
||||
|
||||
unsigned int has_plural_match : 1;
|
||||
/* If this dfa has "multibyte node", which is a backreference or
|
||||
a node which can accept multibyte character or multi character
|
||||
collating element. */
|
||||
unsigned int has_mb_node : 1;
|
||||
unsigned int is_utf8 : 1;
|
||||
unsigned int map_notascii : 1;
|
||||
unsigned int word_ops_used : 1;
|
||||
int mb_cur_max;
|
||||
bitset_t word_char;
|
||||
reg_syntax_t syntax;
|
||||
Idx *subexp_map;
|
||||
#ifdef DEBUG
|
||||
char* re_str;
|
||||
#endif
|
||||
lock_define (lock)
|
||||
};
|
||||
|
||||
#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
|
||||
#define re_node_set_remove(set,id) \
|
||||
(re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
|
||||
#define re_node_set_empty(p) ((p)->nelem = 0)
|
||||
#define re_node_set_free(set) re_free ((set)->elems)
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SB_CHAR,
|
||||
MB_CHAR,
|
||||
EQUIV_CLASS,
|
||||
COLL_SYM,
|
||||
CHAR_CLASS
|
||||
} bracket_elem_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bracket_elem_type type;
|
||||
union
|
||||
{
|
||||
unsigned char ch;
|
||||
unsigned char *name;
|
||||
wchar_t wch;
|
||||
} opr;
|
||||
} bracket_elem_t;
|
||||
|
||||
|
||||
/* Functions for bitset_t operation. */
|
||||
|
||||
static inline void
|
||||
bitset_set (bitset_t set, Idx i)
|
||||
{
|
||||
set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_clear (bitset_t set, Idx i)
|
||||
{
|
||||
set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitset_contain (const bitset_t set, Idx i)
|
||||
{
|
||||
return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_empty (bitset_t set)
|
||||
{
|
||||
memset (set, '\0', sizeof (bitset_t));
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_set_all (bitset_t set)
|
||||
{
|
||||
memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS));
|
||||
if (SBC_MAX % BITSET_WORD_BITS != 0)
|
||||
set[BITSET_WORDS - 1] =
|
||||
((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_copy (bitset_t dest, const bitset_t src)
|
||||
{
|
||||
memcpy (dest, src, sizeof (bitset_t));
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_not (bitset_t set)
|
||||
{
|
||||
int bitset_i;
|
||||
for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i)
|
||||
set[bitset_i] = ~set[bitset_i];
|
||||
if (SBC_MAX % BITSET_WORD_BITS != 0)
|
||||
set[BITSET_WORDS - 1] =
|
||||
((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1)
|
||||
& ~set[BITSET_WORDS - 1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_merge (bitset_t dest, const bitset_t src)
|
||||
{
|
||||
int bitset_i;
|
||||
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
|
||||
dest[bitset_i] |= src[bitset_i];
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitset_mask (bitset_t dest, const bitset_t src)
|
||||
{
|
||||
int bitset_i;
|
||||
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
|
||||
dest[bitset_i] &= src[bitset_i];
|
||||
}
|
||||
|
||||
#ifdef RE_ENABLE_I18N
|
||||
/* Functions for re_string. */
|
||||
static int
|
||||
__attribute__ ((pure, unused))
|
||||
re_string_char_size_at (const re_string_t *pstr, Idx idx)
|
||||
{
|
||||
int byte_idx;
|
||||
if (pstr->mb_cur_max == 1)
|
||||
return 1;
|
||||
for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
|
||||
if (pstr->wcs[idx + byte_idx] != WEOF)
|
||||
break;
|
||||
return byte_idx;
|
||||
}
|
||||
|
||||
static wint_t
|
||||
__attribute__ ((pure, unused))
|
||||
re_string_wchar_at (const re_string_t *pstr, Idx idx)
|
||||
{
|
||||
if (pstr->mb_cur_max == 1)
|
||||
return (wint_t) pstr->mbs[idx];
|
||||
return (wint_t) pstr->wcs[idx];
|
||||
}
|
||||
|
||||
# ifdef _LIBC
|
||||
# include <locale/weight.h>
|
||||
# endif
|
||||
|
||||
static int
|
||||
__attribute__ ((pure, unused))
|
||||
re_string_elem_size_at (const re_string_t *pstr, Idx idx)
|
||||
{
|
||||
# ifdef _LIBC
|
||||
const unsigned char *p, *extra;
|
||||
const int32_t *table, *indirect;
|
||||
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
|
||||
|
||||
if (nrules != 0)
|
||||
{
|
||||
table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
|
||||
extra = (const unsigned char *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
|
||||
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
|
||||
_NL_COLLATE_INDIRECTMB);
|
||||
p = pstr->mbs + idx;
|
||||
findidx (table, indirect, extra, &p, pstr->len - idx);
|
||||
return p - pstr->mbs - idx;
|
||||
}
|
||||
else
|
||||
# endif /* _LIBC */
|
||||
return 1;
|
||||
}
|
||||
#endif /* RE_ENABLE_I18N */
|
||||
|
||||
#ifndef __GNUC_PREREQ
|
||||
# if defined __GNUC__ && defined __GNUC_MINOR__
|
||||
# define __GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
# else
|
||||
# define __GNUC_PREREQ(maj, min) 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if __GNUC_PREREQ (3,4)
|
||||
# undef __attribute_warn_unused_result__
|
||||
# define __attribute_warn_unused_result__ \
|
||||
__attribute__ ((__warn_unused_result__))
|
||||
#else
|
||||
# define __attribute_warn_unused_result__ /* empty */
|
||||
#endif
|
||||
|
||||
#ifndef FALLTHROUGH
|
||||
# if __GNUC__ < 7
|
||||
# define FALLTHROUGH ((void) 0)
|
||||
# else
|
||||
# define FALLTHROUGH __attribute__ ((__fallthrough__))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _REGEX_INTERNAL_H */
|
4324
lib/regexec.c
Normal file
4324
lib/regexec.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -432,12 +432,12 @@ extern char **environ;
|
|||
#elif defined GNULIB_POSIXCHECK
|
||||
# if HAVE_RAW_DECL_ENVIRON
|
||||
_GL_UNISTD_INLINE char ***
|
||||
_GL_WARN_ON_USE_ATTRIBUTE ("environ is unportable - "
|
||||
"use gnulib module environ for portability")
|
||||
rpl_environ (void)
|
||||
{
|
||||
return &environ;
|
||||
}
|
||||
_GL_WARN_ON_USE (rpl_environ, "environ is unportable - "
|
||||
"use gnulib module environ for portability");
|
||||
# undef environ
|
||||
# define environ (*rpl_environ ())
|
||||
# endif
|
||||
|
|
|
@ -20,23 +20,32 @@
|
|||
supported by the compiler. If the compiler does not support this
|
||||
feature, the macro expands to an unused extern declaration.
|
||||
|
||||
This macro is useful for marking a function as a potential
|
||||
_GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the
|
||||
attribute used in _GL_WARN_ON_USE. If the compiler does not support
|
||||
this feature, it expands to empty.
|
||||
|
||||
These macros are useful for marking a function as a potential
|
||||
portability trap, with the intent that "literal string" include
|
||||
instructions on the replacement function that should be used
|
||||
instead. However, one of the reasons that a function is a
|
||||
portability trap is if it has the wrong signature. Declaring
|
||||
FUNCTION with a different signature in C is a compilation error, so
|
||||
this macro must use the same type as any existing declaration so
|
||||
that programs that avoid the problematic FUNCTION do not fail to
|
||||
compile merely because they included a header that poisoned the
|
||||
function. But this implies that _GL_WARN_ON_USE is only safe to
|
||||
use if FUNCTION is known to already have a declaration. Use of
|
||||
this macro implies that there must not be any other macro hiding
|
||||
the declaration of FUNCTION; but undefining FUNCTION first is part
|
||||
of the poisoning process anyway (although for symbols that are
|
||||
provided only via a macro, the result is a compilation error rather
|
||||
than a warning containing "literal string"). Also note that in
|
||||
C++, it is only safe to use if FUNCTION has no overloads.
|
||||
instead.
|
||||
_GL_WARN_ON_USE is for functions with 'extern' linkage.
|
||||
_GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline'
|
||||
linkage.
|
||||
|
||||
However, one of the reasons that a function is a portability trap is
|
||||
if it has the wrong signature. Declaring FUNCTION with a different
|
||||
signature in C is a compilation error, so this macro must use the
|
||||
same type as any existing declaration so that programs that avoid
|
||||
the problematic FUNCTION do not fail to compile merely because they
|
||||
included a header that poisoned the function. But this implies that
|
||||
_GL_WARN_ON_USE is only safe to use if FUNCTION is known to already
|
||||
have a declaration. Use of this macro implies that there must not
|
||||
be any other macro hiding the declaration of FUNCTION; but
|
||||
undefining FUNCTION first is part of the poisoning process anyway
|
||||
(although for symbols that are provided only via a macro, the result
|
||||
is a compilation error rather than a warning containing
|
||||
"literal string"). Also note that in C++, it is only safe to use if
|
||||
FUNCTION has no overloads.
|
||||
|
||||
For an example, it is possible to poison 'getline' by:
|
||||
- adding a call to gl_WARN_ON_USE_PREPARE([[#include <stdio.h>]],
|
||||
|
@ -54,12 +63,21 @@
|
|||
(less common usage, like &environ, will cause a compilation error
|
||||
rather than issue the nice warning, but the end result of informing
|
||||
the developer about their portability problem is still achieved):
|
||||
#if HAVE_RAW_DECL_ENVIRON
|
||||
static char ***rpl_environ (void) { return &environ; }
|
||||
_GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
|
||||
# undef environ
|
||||
# define environ (*rpl_environ ())
|
||||
#endif
|
||||
#if HAVE_RAW_DECL_ENVIRON
|
||||
static char ***
|
||||
rpl_environ (void) { return &environ; }
|
||||
_GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
|
||||
# undef environ
|
||||
# define environ (*rpl_environ ())
|
||||
#endif
|
||||
or better (avoiding contradictory use of 'static' and 'extern'):
|
||||
#if HAVE_RAW_DECL_ENVIRON
|
||||
static char ***
|
||||
_GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared")
|
||||
rpl_environ (void) { return &environ; }
|
||||
# undef environ
|
||||
# define environ (*rpl_environ ())
|
||||
#endif
|
||||
*/
|
||||
#ifndef _GL_WARN_ON_USE
|
||||
|
||||
|
@ -67,13 +85,17 @@
|
|||
/* A compiler attribute is available in gcc versions 4.3.0 and later. */
|
||||
# define _GL_WARN_ON_USE(function, message) \
|
||||
extern __typeof__ (function) function __attribute__ ((__warning__ (message)))
|
||||
# define _GL_WARN_ON_USE_ATTRIBUTE(message) \
|
||||
__attribute__ ((__warning__ (message)))
|
||||
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
|
||||
/* Verify the existence of the function. */
|
||||
# define _GL_WARN_ON_USE(function, message) \
|
||||
extern __typeof__ (function) function
|
||||
# define _GL_WARN_ON_USE_ATTRIBUTE(message)
|
||||
# else /* Unsupported. */
|
||||
# define _GL_WARN_ON_USE(function, message) \
|
||||
_GL_WARN_EXTERN_C int _gl_warn_on_use
|
||||
# define _GL_WARN_ON_USE_ATTRIBUTE(message)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -779,7 +779,7 @@ Calls `auth-source-search' with the :delete property in SPEC set to t.
|
|||
The backend may not actually delete the entries.
|
||||
|
||||
Returns the deleted entries."
|
||||
(auth-source-search (plist-put spec :delete t)))
|
||||
(apply #'auth-source-search (plist-put spec :delete t)))
|
||||
|
||||
(defun auth-source-search-collection (collection value)
|
||||
"Returns t is VALUE is t or COLLECTION is t or COLLECTION contains VALUE."
|
||||
|
|
|
@ -1102,7 +1102,7 @@ BOOKMARK is usually a bookmark name (a string). It can also be a
|
|||
bookmark record, but this is usually only done by programmatic callers.
|
||||
|
||||
If DISPLAY-FUNC is non-nil, it is a function to invoke to display the
|
||||
bookmark. It defaults to `switch-to-buffer'. A typical value for
|
||||
bookmark. It defaults to `pop-to-buffer-same-window'. A typical value for
|
||||
DISPLAY-FUNC would be `switch-to-buffer-other-window'."
|
||||
(interactive
|
||||
(list (bookmark-completing-read "Jump to bookmark"
|
||||
|
@ -1110,7 +1110,10 @@ DISPLAY-FUNC would be `switch-to-buffer-other-window'."
|
|||
(unless bookmark
|
||||
(error "No bookmark specified"))
|
||||
(bookmark-maybe-historicize-string bookmark)
|
||||
(bookmark--jump-via bookmark (or display-func 'switch-to-buffer)))
|
||||
;; Don't use `switch-to-buffer' because it would let the
|
||||
;; window-point override the bookmark's point when
|
||||
;; `switch-to-buffer-preserve-window-point' is non-nil.
|
||||
(bookmark--jump-via bookmark (or display-func 'pop-to-buffer-same-window)))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
|
|
|
@ -853,17 +853,18 @@ category. With non-nil argument BACK, visit the numerically
|
|||
previous category (the highest numbered one, if the current
|
||||
category is the first)."
|
||||
(interactive)
|
||||
(setq todo-category-number
|
||||
(1+ (mod (- todo-category-number (if back 2 0))
|
||||
(length todo-categories))))
|
||||
(when todo-skip-archived-categories
|
||||
(while (and (zerop (todo-get-count 'todo))
|
||||
(zerop (todo-get-count 'done))
|
||||
(not (zerop (todo-get-count 'archived))))
|
||||
(setq todo-category-number
|
||||
(funcall (if back #'1- #'1+) todo-category-number))))
|
||||
(todo-category-select)
|
||||
(goto-char (point-min)))
|
||||
(let ((setcatnum (lambda () (1+ (mod (- todo-category-number
|
||||
(if back 2 0))
|
||||
(length todo-categories))))))
|
||||
(setq todo-category-number (funcall setcatnum))
|
||||
(when todo-skip-archived-categories
|
||||
(while (and (zerop (todo-get-count 'todo))
|
||||
(zerop (todo-get-count 'done))
|
||||
(not (zerop (todo-get-count 'archived))))
|
||||
(setq todo-category-number (funcall setcatnum))))
|
||||
(todo-category-select)
|
||||
(if transient-mark-mode (deactivate-mark))
|
||||
(goto-char (point-min))))
|
||||
|
||||
(defun todo-backward-category ()
|
||||
"Visit the numerically previous category in this todo file.
|
||||
|
@ -928,11 +929,13 @@ Categories mode."
|
|||
(when goto-archive (todo-archive-mode))
|
||||
(set-window-buffer (selected-window)
|
||||
(set-buffer (find-buffer-visiting file0)))
|
||||
(if transient-mark-mode (deactivate-mark))
|
||||
(unless todo-global-current-todo-file
|
||||
(setq todo-global-current-todo-file todo-current-todo-file))
|
||||
(todo-category-number category)
|
||||
(todo-category-select)
|
||||
(goto-char (point-min))
|
||||
(if (bound-and-true-p hl-line-mode) (hl-line-highlight))
|
||||
(when add-item (todo-insert-item--basic))))))
|
||||
|
||||
(defun todo-next-item (&optional count)
|
||||
|
@ -1018,15 +1021,17 @@ empty line above the done items separator."
|
|||
(setq shown (progn
|
||||
(goto-char (point-min))
|
||||
(re-search-forward todo-done-string-start nil t)))
|
||||
(if (not (pos-visible-in-window-p shown))
|
||||
(recenter)
|
||||
(goto-char opoint)))))))
|
||||
(if (pos-visible-in-window-p shown)
|
||||
(goto-char opoint)
|
||||
(recenter)
|
||||
(if transient-mark-mode (deactivate-mark))))))))
|
||||
|
||||
(defun todo-toggle-view-done-only ()
|
||||
"Switch between displaying only done or only todo items."
|
||||
(interactive)
|
||||
(setq todo-show-done-only (not todo-show-done-only))
|
||||
(todo-category-select))
|
||||
(todo-category-select)
|
||||
(if transient-mark-mode (deactivate-mark)))
|
||||
|
||||
(defun todo-toggle-item-highlighting ()
|
||||
"Highlight or unhighlight the todo item the cursor is on."
|
||||
|
@ -1860,15 +1865,18 @@ their associated keys and their effects."
|
|||
(region (eq where 'region))
|
||||
(here (eq where 'here))
|
||||
diary-item)
|
||||
(when copy
|
||||
(cond
|
||||
((not (eq major-mode 'todo-mode))
|
||||
(user-error "You must be in Todo mode to copy a todo item"))
|
||||
((todo-done-item-p)
|
||||
(user-error "You cannot copy a done item as a new todo item"))
|
||||
((looking-at "^$")
|
||||
(user-error "Point must be on a todo item to copy it")))
|
||||
(setq diary-item (todo-diary-item-p)))
|
||||
(when (and arg here)
|
||||
(user-error "Here insertion only valid in current category"))
|
||||
(when (and (or copy here)
|
||||
(or (not (eq major-mode 'todo-mode)) (todo-done-item-p)
|
||||
(when copy (looking-at "^$"))
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
;; Point is on done items separator.
|
||||
(looking-at todo-category-done))))
|
||||
(user-error (concat "Item " (if copy "copying" "insertion")
|
||||
" is not valid here")))
|
||||
(when copy (setq diary-item (todo-diary-item-p)))
|
||||
(when region
|
||||
(let (use-empty-active-region)
|
||||
(unless (and todo-use-only-highlighted-region (use-region-p))
|
||||
|
@ -1876,7 +1884,6 @@ their associated keys and their effects."
|
|||
(let* ((obuf (current-buffer))
|
||||
(ocat (todo-current-category))
|
||||
(opoint (point))
|
||||
(todo-mm (eq major-mode 'todo-mode))
|
||||
(cat+file (cond ((equal arg '(4))
|
||||
(todo-read-category "Insert in category: "))
|
||||
((equal arg '(16))
|
||||
|
@ -1894,7 +1901,10 @@ their associated keys and their effects."
|
|||
(new-item (cond (copy (todo-item-string))
|
||||
(region (buffer-substring-no-properties
|
||||
(region-beginning) (region-end)))
|
||||
(t (read-from-minibuffer "Todo item: "))))
|
||||
(t (if (eq major-mode 'todo-archive-mode)
|
||||
(user-error (concat "Cannot insert a new Todo"
|
||||
" item in an archive"))
|
||||
(read-from-minibuffer "Todo item: ")))))
|
||||
(date-string (cond
|
||||
((eq date-type 'date)
|
||||
(todo-read-date))
|
||||
|
@ -1931,7 +1941,6 @@ their associated keys and their effects."
|
|||
(unless todo-global-current-todo-file
|
||||
(setq todo-global-current-todo-file todo-current-todo-file))
|
||||
(let ((buffer-read-only nil)
|
||||
(called-from-outside (not (and todo-mm (equal cat ocat))))
|
||||
done-only item-added)
|
||||
(unless copy
|
||||
(setq new-item
|
||||
|
@ -1955,14 +1964,8 @@ their associated keys and their effects."
|
|||
"\n\t" new-item nil nil 1)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
;; Make sure the correct category is selected. There
|
||||
;; are two cases: (i) we just visited the file, so no
|
||||
;; category is selected yet, or (ii) we invoked
|
||||
;; insertion "here" from outside the category we want
|
||||
;; to insert in (with priority insertion, category
|
||||
;; selection is done by todo-set-item-priority).
|
||||
(when (or (= (- (point-max) (point-min)) (buffer-size))
|
||||
(and here called-from-outside))
|
||||
;; If we just visited the file, no category is selected yet.
|
||||
(when (= (- (point-max) (point-min)) (buffer-size))
|
||||
(todo-category-number cat)
|
||||
(todo-category-select))
|
||||
;; If only done items are displayed in category,
|
||||
|
@ -1973,16 +1976,7 @@ their associated keys and their effects."
|
|||
(setq done-only t)
|
||||
(todo-toggle-view-done-only))
|
||||
(if here
|
||||
(progn
|
||||
;; If command was invoked with point in done
|
||||
;; items section or outside of the current
|
||||
;; category, can't insert "here", so to be
|
||||
;; useful give new item top priority.
|
||||
(when (or (todo-done-item-section-p)
|
||||
called-from-outside
|
||||
done-only)
|
||||
(goto-char (point-min)))
|
||||
(todo-insert-with-overlays new-item))
|
||||
(todo-insert-with-overlays new-item)
|
||||
(todo-set-item-priority new-item cat t))
|
||||
(setq item-added t))
|
||||
;; If user cancels before setting priority, restore
|
||||
|
@ -2097,7 +2091,14 @@ the item at point."
|
|||
(setq todo-categories-with-marks
|
||||
(assq-delete-all cat todo-categories-with-marks)))
|
||||
(todo-update-categories-sexp)
|
||||
(todo-prefix-overlays)))
|
||||
(todo-prefix-overlays)
|
||||
(when (and (zerop (todo-get-count 'diary))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(re-search-forward
|
||||
(concat "^" (regexp-quote todo-category-done))
|
||||
nil t)))
|
||||
(let (todo-show-with-done) (todo-category-select)))))
|
||||
(if ov (delete-overlay ov)))))
|
||||
|
||||
(defvar todo-edit-item--param-key-alist)
|
||||
|
@ -2233,7 +2234,8 @@ made in the number or names of categories."
|
|||
(insert item))
|
||||
(kill-buffer)
|
||||
(unless (eq (current-buffer) buf)
|
||||
(set-window-buffer (selected-window) (set-buffer buf))))
|
||||
(set-window-buffer (selected-window) (set-buffer buf)))
|
||||
(if transient-mark-mode (deactivate-mark)))
|
||||
;; We got here via `F e'.
|
||||
(when (todo-check-format)
|
||||
;; FIXME: separate out sexp check?
|
||||
|
@ -2340,7 +2342,7 @@ made in the number or names of categories."
|
|||
((or (string= omonth "*") (= mm 13))
|
||||
(user-error "Cannot increment *"))
|
||||
(t
|
||||
(let ((mminc (+ mm inc)))
|
||||
(let ((mminc (+ mm inc (if (< inc 0) 12 0))))
|
||||
;; Increment or decrement month by INC
|
||||
;; modulo 12.
|
||||
(setq mm (% mminc 12))
|
||||
|
@ -2549,7 +2551,11 @@ whose value can be either of the symbols `raise' or `lower',
|
|||
meaning to raise or lower the item's priority by one."
|
||||
(interactive)
|
||||
(unless (and (or (called-interactively-p 'any) (memq arg '(raise lower)))
|
||||
(or (todo-done-item-p) (looking-at "^$")))
|
||||
;; Noop if point is not on a todo (i.e. not done) item.
|
||||
(or (todo-done-item-p) (looking-at "^$")
|
||||
;; On done items separator.
|
||||
(save-excursion (beginning-of-line)
|
||||
(looking-at todo-category-done))))
|
||||
(let* ((item (or item (todo-item-string)))
|
||||
(marked (todo-marked-item-p))
|
||||
(cat (or cat (cond ((eq major-mode 'todo-mode)
|
||||
|
@ -2697,9 +2703,13 @@ section in the category moved to."
|
|||
(interactive "P")
|
||||
(let* ((cat1 (todo-current-category))
|
||||
(marked (assoc cat1 todo-categories-with-marks)))
|
||||
;; Noop if point is not on an item and there are no marked items.
|
||||
(unless (and (looking-at "^$")
|
||||
(not marked))
|
||||
(unless
|
||||
;; Noop if point is not on an item and there are no marked items.
|
||||
(and (or (looking-at "^$")
|
||||
;; On done items separator.
|
||||
(save-excursion (beginning-of-line)
|
||||
(looking-at todo-category-done)))
|
||||
(not marked))
|
||||
(let* ((buffer-read-only)
|
||||
(file1 todo-current-todo-file)
|
||||
(item (todo-item-string))
|
||||
|
@ -2856,10 +2866,14 @@ visible."
|
|||
(let* ((cat (todo-current-category))
|
||||
(marked (assoc cat todo-categories-with-marks)))
|
||||
(when marked (todo--user-error-if-marked-done-item))
|
||||
(unless (and (not marked)
|
||||
(or (todo-done-item-p)
|
||||
;; Point is between todo and done items.
|
||||
(looking-at "^$")))
|
||||
(unless
|
||||
;; Noop if point is not on a todo (i.e. not done) item and
|
||||
;; there are no marked items.
|
||||
(and (or (todo-done-item-p) (looking-at "^$")
|
||||
;; On done items separator.
|
||||
(save-excursion (beginning-of-line)
|
||||
(looking-at todo-category-done)))
|
||||
(not marked))
|
||||
(let* ((date-string (calendar-date-string (calendar-current-date) t t))
|
||||
(time-string (if todo-always-add-time-string
|
||||
(concat " " (substring (current-time-string)
|
||||
|
@ -3830,6 +3844,7 @@ face."
|
|||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(setq match (re-search-forward regex nil t))
|
||||
(if (and match transient-mark-mode) (deactivate-mark))
|
||||
(goto-char (line-beginning-position))
|
||||
(unless (or (equal (point) 1)
|
||||
(looking-at (concat "^" (regexp-quote todo-category-beg))))
|
||||
|
@ -4028,19 +4043,22 @@ regexp items."
|
|||
(interactive "P")
|
||||
(todo-filter-items 'regexp arg t))
|
||||
|
||||
(defvar todo--fifiles-history nil
|
||||
"List of short file names used by todo-find-filtered-items-file.")
|
||||
|
||||
(defun todo-find-filtered-items-file ()
|
||||
"Choose a filtered items file and visit it."
|
||||
(interactive)
|
||||
(let ((files (directory-files todo-directory t "\\.tod[rty]$" t))
|
||||
falist file)
|
||||
(dolist (f files)
|
||||
(let ((type (cond ((equal (file-name-extension f) "todr") "regexp")
|
||||
(let ((sf-name (todo-short-file-name f))
|
||||
(type (cond ((equal (file-name-extension f) "todr") "regexp")
|
||||
((equal (file-name-extension f) "todt") "top")
|
||||
((equal (file-name-extension f) "tody") "diary"))))
|
||||
(push (cons (concat (todo-short-file-name f) " (" type ")") f)
|
||||
falist)))
|
||||
(setq file (completing-read "Choose a filtered items file: "
|
||||
falist nil t nil nil (car falist)))
|
||||
(push (cons (concat sf-name " (" type ")") f) falist)))
|
||||
(setq file (completing-read "Choose a filtered items file: " falist nil t nil
|
||||
'todo--fifiles-history (caar falist)))
|
||||
(setq file (cdr (assoc-string file falist)))
|
||||
(find-file file)
|
||||
(unless (derived-mode-p 'todo-filtered-items-mode)
|
||||
|
@ -4050,25 +4068,27 @@ regexp items."
|
|||
(defun todo-go-to-source-item ()
|
||||
"Display the file and category of the filtered item at point."
|
||||
(interactive)
|
||||
(let* ((str (todo-item-string))
|
||||
(buf (current-buffer))
|
||||
(res (todo-find-item str))
|
||||
(found (nth 0 res))
|
||||
(file (nth 1 res))
|
||||
(cat (nth 2 res)))
|
||||
(if (not found)
|
||||
(message "Category %s does not contain this item." cat)
|
||||
(kill-buffer buf)
|
||||
(set-window-buffer (selected-window)
|
||||
(set-buffer (find-buffer-visiting file)))
|
||||
(setq todo-current-todo-file file)
|
||||
(setq todo-category-number (todo-category-number cat))
|
||||
(let ((todo-show-with-done (if (or todo-filter-done-items
|
||||
(eq (cdr found) 'done))
|
||||
t
|
||||
todo-show-with-done)))
|
||||
(todo-category-select))
|
||||
(goto-char (car found)))))
|
||||
(unless (looking-at "^$") ; Empty line at EOB.
|
||||
(let* ((str (todo-item-string))
|
||||
(buf (current-buffer))
|
||||
(res (todo-find-item str))
|
||||
(found (nth 0 res))
|
||||
(file (nth 1 res))
|
||||
(cat (nth 2 res)))
|
||||
(if (not found)
|
||||
(message "Category %s does not contain this item." cat)
|
||||
(kill-buffer buf)
|
||||
(set-window-buffer (selected-window)
|
||||
(set-buffer (find-buffer-visiting file)))
|
||||
(setq todo-current-todo-file file)
|
||||
(setq todo-category-number (todo-category-number cat))
|
||||
(let ((todo-show-with-done (if (or todo-filter-done-items
|
||||
(eq (cdr found) 'done))
|
||||
t
|
||||
todo-show-with-done)))
|
||||
(todo-category-select))
|
||||
(if transient-mark-mode (deactivate-mark))
|
||||
(goto-char (car found))))))
|
||||
|
||||
(defvar todo-multiple-filter-files nil
|
||||
"List of files selected from `todo-multiple-filter-files' widget.")
|
||||
|
@ -4520,8 +4540,11 @@ its priority has changed, and `same' otherwise."
|
|||
(defun todo-save-filtered-items-buffer ()
|
||||
"Save current Filtered Items buffer to a file.
|
||||
If the file already exists, overwrite it only on confirmation."
|
||||
(let ((filename (or (buffer-file-name) (todo-filter-items-filename))))
|
||||
(write-file filename t)))
|
||||
(let ((filename (or (buffer-file-name) (todo-filter-items-filename)))
|
||||
(bufname (buffer-name)))
|
||||
(write-file filename t)
|
||||
(setq buffer-read-only t)
|
||||
(rename-buffer bufname)))
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
;;; Printing Todo mode buffers
|
||||
|
@ -5132,6 +5155,8 @@ but the categories sexp differs from the current value of
|
|||
(forward-line)
|
||||
(looking-at (concat "^"
|
||||
(regexp-quote todo-category-done))))))
|
||||
;; Point is on done items separator.
|
||||
(save-excursion (beginning-of-line) (looking-at todo-category-done))
|
||||
;; Buffer is widened.
|
||||
(looking-at (regexp-quote todo-category-beg)))
|
||||
(goto-char (line-beginning-position))
|
||||
|
@ -5141,8 +5166,11 @@ but the categories sexp differs from the current value of
|
|||
|
||||
(defun todo-item-end ()
|
||||
"Move to end of current todo item and return its position."
|
||||
;; Items cannot end with a blank line.
|
||||
(unless (looking-at "^$")
|
||||
(unless (or
|
||||
;; Items cannot end with a blank line.
|
||||
(looking-at "^$")
|
||||
;; Point is on done items separator.
|
||||
(save-excursion (beginning-of-line) (looking-at todo-category-done)))
|
||||
(let* ((done (todo-done-item-p))
|
||||
(to-lim nil)
|
||||
;; For todo items, end is before the done items section, for done
|
||||
|
@ -5293,6 +5321,7 @@ Overrides `diary-goto-entry'."
|
|||
nil t)
|
||||
(todo-category-number (match-string 1))
|
||||
(todo-category-select)
|
||||
(if transient-mark-mode (deactivate-mark))
|
||||
(goto-char opoint))))))
|
||||
|
||||
(add-function :override diary-goto-entry-function #'todo-diary-goto-entry)
|
||||
|
@ -6419,9 +6448,6 @@ Filtered Items mode following todo (not done) items."
|
|||
("N" todo-toggle-prefix-numbers)
|
||||
("PB" todo-print-buffer)
|
||||
("PF" todo-print-buffer-to-file)
|
||||
("b" todo-backward-category)
|
||||
("d" todo-item-done)
|
||||
("f" todo-forward-category)
|
||||
("j" todo-jump-to-category)
|
||||
("n" todo-next-item)
|
||||
("p" todo-previous-item)
|
||||
|
@ -6436,6 +6462,8 @@ Filtered Items mode following todo (not done) items."
|
|||
("Fc" todo-show-categories-table)
|
||||
("S" todo-search)
|
||||
("X" todo-clear-matches)
|
||||
("b" todo-backward-category)
|
||||
("f" todo-forward-category)
|
||||
("*" todo-toggle-mark-item)
|
||||
)
|
||||
"List of key bindings for Todo and Todo Archive modes.")
|
||||
|
|
|
@ -214,7 +214,7 @@ from which to start."
|
|||
(when (> spaces 0)
|
||||
(push (char-fold--make-space-string spaces) out))
|
||||
(let ((regexp (apply #'concat (nreverse out))))
|
||||
;; Limited by `MAX_BUF_SIZE' in `regex.c'.
|
||||
;; Limited by `MAX_BUF_SIZE' in `regex-emacs.c'.
|
||||
(if (> (length regexp) 5000)
|
||||
(regexp-quote string)
|
||||
regexp))))
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
;;
|
||||
;; Not bound by default in comint-mode (some are in shell mode)
|
||||
;; comint-run Run a program under comint-mode
|
||||
;; send-invisible Read a line w/o echo, and send to proc
|
||||
;; comint-send-invisible Read a line w/o echo, and send to proc
|
||||
;; comint-dynamic-complete-filename Complete filename at point.
|
||||
;; comint-dynamic-list-filename-completions List completions in help buffer.
|
||||
;; comint-replace-by-expanded-filename Expand and complete filename at point;
|
||||
|
@ -632,7 +632,7 @@ Input ring history expansion can be achieved with the commands
|
|||
Input ring expansion is controlled by the variable `comint-input-autoexpand',
|
||||
and addition is controlled by the variable `comint-input-ignoredups'.
|
||||
|
||||
Commands with no default key bindings include `send-invisible',
|
||||
Commands with no default key bindings include `comint-send-invisible',
|
||||
`completion-at-point', `comint-dynamic-list-filename-completions', and
|
||||
`comint-magic-space'.
|
||||
|
||||
|
@ -2247,7 +2247,7 @@ This function could be on `comint-output-filter-functions' or bound to a key."
|
|||
(error nil))
|
||||
(while (re-search-forward "\r+$" pmark t)
|
||||
(replace-match "" t t)))))
|
||||
(defalias 'shell-strip-ctrl-m 'comint-strip-ctrl-m)
|
||||
(define-obsolete-function-alias 'shell-strip-ctrl-m #'comint-strip-ctrl-m "27.1")
|
||||
|
||||
(defun comint-show-maximum-output ()
|
||||
"Put the end of the buffer at the bottom of the window."
|
||||
|
@ -2357,9 +2357,9 @@ a buffer local variable."
|
|||
|
||||
;; These three functions are for entering text you don't want echoed or
|
||||
;; saved -- typically passwords to ftp, telnet, or somesuch.
|
||||
;; Just enter m-x send-invisible and type in your line.
|
||||
;; Just enter m-x comint-send-invisible and type in your line.
|
||||
|
||||
(defun send-invisible (&optional prompt)
|
||||
(defun comint-send-invisible (&optional prompt)
|
||||
"Read a string without echoing.
|
||||
Then send it to the process running in the current buffer.
|
||||
The string is sent using `comint-input-sender'.
|
||||
|
@ -2382,18 +2382,19 @@ Security bug: your string can still be temporarily recovered with
|
|||
(message "Warning: text will be echoed")))
|
||||
(error "Buffer %s has no process" (current-buffer)))))
|
||||
|
||||
(define-obsolete-function-alias 'send-invisible #'comint-send-invisible "27.1")
|
||||
|
||||
(defun comint-watch-for-password-prompt (string)
|
||||
"Prompt in the minibuffer for password and send without echoing.
|
||||
This function uses `send-invisible' to read and send a password to the buffer's
|
||||
process if STRING contains a password prompt defined by
|
||||
`comint-password-prompt-regexp'.
|
||||
Looks for a match to `comint-password-prompt-regexp' in order
|
||||
to detect the need to (prompt and) send a password.
|
||||
|
||||
This function could be in the list `comint-output-filter-functions'."
|
||||
(when (let ((case-fold-search t))
|
||||
(string-match comint-password-prompt-regexp string))
|
||||
(when (string-match "^[ \n\r\t\v\f\b\a]+" string)
|
||||
(setq string (replace-match "" t t string)))
|
||||
(send-invisible string)))
|
||||
(comint-send-invisible string)))
|
||||
|
||||
;; Low-level process communication
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
;;; cus-theme.el -- custom theme creation user interface
|
||||
;;; cus-theme.el -- custom theme creation user interface -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; Copyright (C) 2001-2018 Free Software Foundation, Inc.
|
||||
;;
|
||||
|
@ -47,7 +47,7 @@
|
|||
Do not call this mode function yourself. It is meant for internal use."
|
||||
(use-local-map custom-new-theme-mode-map)
|
||||
(custom--initialize-widget-variables)
|
||||
(set (make-local-variable 'revert-buffer-function) 'custom-theme-revert))
|
||||
(setq-local revert-buffer-function #'custom-theme-revert))
|
||||
(put 'custom-new-theme-mode 'mode-class 'special)
|
||||
|
||||
(defvar custom-theme-name nil)
|
||||
|
@ -93,15 +93,14 @@ named *Custom Theme*."
|
|||
(switch-to-buffer (get-buffer-create (or buffer "*Custom Theme*")))
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(dolist (ov (overlays-in (point-min) (point-max)))
|
||||
(delete-overlay ov)))
|
||||
(delete-all-overlays))
|
||||
(custom-new-theme-mode)
|
||||
(make-local-variable 'custom-theme-name)
|
||||
(set (make-local-variable 'custom-theme--save-name) theme)
|
||||
(set (make-local-variable 'custom-theme-faces) nil)
|
||||
(set (make-local-variable 'custom-theme-variables) nil)
|
||||
(set (make-local-variable 'custom-theme-description) "")
|
||||
(set (make-local-variable 'custom-theme--migrate-settings) nil)
|
||||
(setq-local custom-theme--save-name theme)
|
||||
(setq-local custom-theme-faces nil)
|
||||
(setq-local custom-theme-variables nil)
|
||||
(setq-local custom-theme-description "")
|
||||
(setq-local custom-theme--migrate-settings nil)
|
||||
(make-local-variable 'custom-theme-insert-face-marker)
|
||||
(make-local-variable 'custom-theme-insert-variable-marker)
|
||||
(make-local-variable 'custom-theme--listed-faces)
|
||||
|
@ -118,13 +117,13 @@ remove them from your saved Custom file.\n\n"))
|
|||
:tag " Visit Theme "
|
||||
:help-echo "Insert the settings of a pre-defined theme."
|
||||
:action (lambda (_widget &optional _event)
|
||||
(call-interactively 'custom-theme-visit-theme)))
|
||||
(call-interactively #'custom-theme-visit-theme)))
|
||||
(widget-insert " ")
|
||||
(widget-create 'push-button
|
||||
:tag " Merge Theme "
|
||||
:help-echo "Merge in the settings of a pre-defined theme."
|
||||
:action (lambda (_widget &optional _event)
|
||||
(call-interactively 'custom-theme-merge-theme)))
|
||||
(call-interactively #'custom-theme-merge-theme)))
|
||||
(widget-insert " ")
|
||||
(widget-create 'push-button
|
||||
:tag " Revert "
|
||||
|
@ -142,7 +141,7 @@ remove them from your saved Custom file.\n\n"))
|
|||
(widget-create 'text
|
||||
:value (format-time-string "Created %Y-%m-%d.")))
|
||||
(widget-create 'push-button
|
||||
:notify (function custom-theme-write)
|
||||
:notify #'custom-theme-write
|
||||
" Save Theme ")
|
||||
(when (eq theme 'user)
|
||||
(setq custom-theme--migrate-settings t)
|
||||
|
@ -188,7 +187,7 @@ remove them from your saved Custom file.\n\n"))
|
|||
:mouse-face 'highlight
|
||||
:pressed-face 'highlight
|
||||
:action (lambda (_widget &optional _event)
|
||||
(call-interactively 'custom-theme-add-face)))
|
||||
(call-interactively #'custom-theme-add-face)))
|
||||
|
||||
;; If THEME is non-nil, insert all of that theme's variables.
|
||||
(widget-insert "\n\n Theme variables:\n ")
|
||||
|
@ -207,7 +206,7 @@ remove them from your saved Custom file.\n\n"))
|
|||
:mouse-face 'highlight
|
||||
:pressed-face 'highlight
|
||||
:action (lambda (_widget &optional _event)
|
||||
(call-interactively 'custom-theme-add-variable)))
|
||||
(call-interactively #'custom-theme-add-variable)))
|
||||
(widget-insert ?\n)
|
||||
(widget-setup)
|
||||
(goto-char (point-min))
|
||||
|
@ -254,7 +253,7 @@ interactively, this defaults to the current value of VAR."
|
|||
:tag (custom-unlispify-tag-name symbol)
|
||||
:value symbol
|
||||
:shown-value (list val)
|
||||
:notify 'ignore
|
||||
:notify #'ignore
|
||||
:custom-level 0
|
||||
:custom-state 'hidden
|
||||
:custom-style 'simple))
|
||||
|
@ -313,7 +312,7 @@ SPEC, if non-nil, should be a face spec to which to set the widget."
|
|||
(interactive
|
||||
(list
|
||||
(intern (completing-read "Find custom theme: "
|
||||
(mapcar 'symbol-name
|
||||
(mapcar #'symbol-name
|
||||
(custom-available-themes))))))
|
||||
(unless (custom-theme-name-valid-p theme)
|
||||
(error "No valid theme named `%s'" theme))
|
||||
|
@ -328,7 +327,7 @@ SPEC, if non-nil, should be a face spec to which to set the widget."
|
|||
(interactive
|
||||
(list
|
||||
(intern (completing-read "Merge custom theme: "
|
||||
(mapcar 'symbol-name
|
||||
(mapcar #'symbol-name
|
||||
(custom-available-themes))))))
|
||||
(unless (eq theme 'user)
|
||||
(unless (custom-theme-name-valid-p theme)
|
||||
|
@ -343,8 +342,8 @@ SPEC, if non-nil, should be a face spec to which to set the widget."
|
|||
(memq name '(custom-enabled-themes
|
||||
custom-safe-themes)))
|
||||
(funcall (if option
|
||||
'custom-theme-add-variable
|
||||
'custom-theme-add-face)
|
||||
#'custom-theme-add-variable
|
||||
#'custom-theme-add-face)
|
||||
name value)))))
|
||||
theme)
|
||||
|
||||
|
@ -475,7 +474,7 @@ It includes all faces in list FACES."
|
|||
(interactive
|
||||
(list
|
||||
(intern (completing-read "Describe custom theme: "
|
||||
(mapcar 'symbol-name
|
||||
(mapcar #'symbol-name
|
||||
(custom-available-themes))))))
|
||||
(unless (custom-theme-name-valid-p theme)
|
||||
(error "Invalid theme name `%s'" theme))
|
||||
|
@ -513,8 +512,7 @@ It includes all faces in list FACES."
|
|||
(condition-case nil
|
||||
(read (current-buffer))
|
||||
(end-of-file nil)))))
|
||||
(and sexp (listp sexp)
|
||||
(eq (car sexp) 'deftheme)
|
||||
(and (eq (car-safe sexp) 'deftheme)
|
||||
(setq doc (nth 2 sexp)))))))
|
||||
(princ "\n\nDocumentation:\n")
|
||||
(princ (if (stringp doc)
|
||||
|
@ -552,10 +550,10 @@ It includes all faces in list FACES."
|
|||
Do not call this mode function yourself. It is meant for internal use."
|
||||
(use-local-map custom-theme-choose-mode-map)
|
||||
(custom--initialize-widget-variables)
|
||||
(set (make-local-variable 'revert-buffer-function)
|
||||
(lambda (_ignore-auto noconfirm)
|
||||
(when (or noconfirm (y-or-n-p "Discard current choices? "))
|
||||
(customize-themes (current-buffer))))))
|
||||
(setq-local revert-buffer-function
|
||||
(lambda (_ignore-auto noconfirm)
|
||||
(when (or noconfirm (y-or-n-p "Discard current choices? "))
|
||||
(customize-themes (current-buffer))))))
|
||||
(put 'custom-theme-choose-mode 'mode-class 'special)
|
||||
|
||||
;;;###autoload
|
||||
|
@ -568,7 +566,7 @@ omitted, a buffer named *Custom Themes* is used."
|
|||
(let ((inhibit-read-only t))
|
||||
(erase-buffer))
|
||||
(custom-theme-choose-mode)
|
||||
(set (make-local-variable 'custom--listed-themes) nil)
|
||||
(setq-local custom--listed-themes nil)
|
||||
(make-local-variable 'custom-theme-allow-multiple-selections)
|
||||
(and (null custom-theme-allow-multiple-selections)
|
||||
(> (length custom-enabled-themes) 1)
|
||||
|
@ -616,11 +614,11 @@ Theme files are named *-theme.el in `"))
|
|||
(widget-create 'push-button
|
||||
:tag " Save Theme Settings "
|
||||
:help-echo "Save the selected themes for future sessions."
|
||||
:action 'custom-theme-save)
|
||||
:action #'custom-theme-save)
|
||||
(widget-insert ?\n)
|
||||
(widget-create 'checkbox
|
||||
:value custom-theme-allow-multiple-selections
|
||||
:action 'custom-theme-selections-toggle)
|
||||
:action #'custom-theme-selections-toggle)
|
||||
(widget-insert (propertize " Select more than one theme at a time"
|
||||
'face '(variable-pitch (:height 0.9))))
|
||||
|
||||
|
@ -632,13 +630,13 @@ Theme files are named *-theme.el in `"))
|
|||
:value (custom-theme-enabled-p theme)
|
||||
:theme-name theme
|
||||
:help-echo help-echo
|
||||
:action 'custom-theme-checkbox-toggle))
|
||||
:action #'custom-theme-checkbox-toggle))
|
||||
(push (cons theme widget) custom--listed-themes)
|
||||
(widget-create-child-and-convert widget 'push-button
|
||||
:button-face-get 'ignore
|
||||
:mouse-face-get 'ignore
|
||||
:value (format " %s" theme)
|
||||
:action 'widget-parent-action
|
||||
:action #'widget-parent-action
|
||||
:help-echo help-echo)
|
||||
(widget-insert " -- "
|
||||
(propertize (custom-theme-summary theme)
|
||||
|
@ -662,8 +660,7 @@ Theme files are named *-theme.el in `"))
|
|||
(condition-case nil
|
||||
(read (current-buffer))
|
||||
(end-of-file nil)))))
|
||||
(and sexp (listp sexp)
|
||||
(eq (car sexp) 'deftheme)
|
||||
(and (eq (car-safe sexp) 'deftheme)
|
||||
(setq doc (nth 2 sexp))))))))
|
||||
(cond ((null doc)
|
||||
"(no documentation available)")
|
||||
|
|
257
lisp/custom.el
257
lisp/custom.el
|
@ -1,4 +1,4 @@
|
|||
;;; custom.el --- tools for declaring and initializing options
|
||||
;;; custom.el --- tools for declaring and initializing options -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; Copyright (C) 1996-1997, 1999, 2001-2018 Free Software Foundation,
|
||||
;; Inc.
|
||||
|
@ -150,7 +150,7 @@ set to nil, as the value is no longer rogue."
|
|||
(put symbol 'force-value nil))
|
||||
(if (keywordp doc)
|
||||
(error "Doc string is missing"))
|
||||
(let ((initialize 'custom-initialize-reset)
|
||||
(let ((initialize #'custom-initialize-reset)
|
||||
(requests nil))
|
||||
(unless (memq :group args)
|
||||
(custom-add-to-group (custom-current-group) symbol 'custom-variable))
|
||||
|
@ -426,7 +426,7 @@ information."
|
|||
(defun custom-declare-group (symbol members doc &rest args)
|
||||
"Like `defgroup', but SYMBOL is evaluated as a normal argument."
|
||||
(while members
|
||||
(apply 'custom-add-to-group symbol (car members))
|
||||
(apply #'custom-add-to-group symbol (car members))
|
||||
(setq members (cdr members)))
|
||||
(when doc
|
||||
;; This text doesn't get into DOC.
|
||||
|
@ -618,11 +618,8 @@ VARIABLE is a symbol that names a user option.
|
|||
The result is that the change is treated as having been made through Custom."
|
||||
(put variable 'customized-value (list (custom-quote (eval variable)))))
|
||||
|
||||
|
||||
;;; Custom Themes
|
||||
|
||||
;;; Loading files needed to customize a symbol.
|
||||
;;; This is in custom.el because menu-bar.el needs it for toggle cmds.
|
||||
;; Loading files needed to customize a symbol.
|
||||
;; This is in custom.el because menu-bar.el needs it for toggle cmds.
|
||||
|
||||
(defvar custom-load-recursion nil
|
||||
"Hack to avoid recursive dependencies.")
|
||||
|
@ -633,14 +630,12 @@ The result is that the change is treated as having been made through Custom."
|
|||
(let ((custom-load-recursion t))
|
||||
;; Load these files if not already done,
|
||||
;; to make sure we know all the dependencies of SYMBOL.
|
||||
(condition-case nil
|
||||
(require 'cus-load)
|
||||
(error nil))
|
||||
(condition-case nil
|
||||
(require 'cus-start)
|
||||
(error nil))
|
||||
(ignore-errors
|
||||
(require 'cus-load))
|
||||
(ignore-errors
|
||||
(require 'cus-start))
|
||||
(dolist (load (get symbol 'custom-loads))
|
||||
(cond ((symbolp load) (condition-case nil (require load) (error nil)))
|
||||
(cond ((symbolp load) (ignore-errors (require load)))
|
||||
;; This is subsumed by the test below, but it's much faster.
|
||||
((assoc load load-history))
|
||||
;; This was just (assoc (locate-library load) load-history)
|
||||
|
@ -658,7 +653,7 @@ The result is that the change is treated as having been made through Custom."
|
|||
;; We are still loading it when we call this,
|
||||
;; and it is not in load-history yet.
|
||||
((equal load "cus-edit"))
|
||||
(t (condition-case nil (load load) (error nil))))))))
|
||||
(t (ignore-errors (load load))))))))
|
||||
|
||||
(defvar custom-local-buffer nil
|
||||
"Non-nil, in a Customization buffer, means customize a specific buffer.
|
||||
|
@ -691,16 +686,12 @@ this sets the local binding in that buffer instead."
|
|||
|
||||
(defun custom-quote (sexp)
|
||||
"Quote SEXP if it is not self quoting."
|
||||
(if (or (memq sexp '(t nil))
|
||||
(keywordp sexp)
|
||||
(and (listp sexp)
|
||||
(memq (car sexp) '(lambda)))
|
||||
(stringp sexp)
|
||||
(numberp sexp)
|
||||
(vectorp sexp)
|
||||
;;; (and (fboundp 'characterp)
|
||||
;;; (characterp sexp))
|
||||
)
|
||||
;; Can't use `macroexp-quote' because it is loaded after `custom.el'
|
||||
;; during bootstrap. See `loadup.el'.
|
||||
(if (and (not (consp sexp))
|
||||
(or (keywordp sexp)
|
||||
(not (symbolp sexp))
|
||||
(booleanp sexp)))
|
||||
sexp
|
||||
(list 'quote sexp)))
|
||||
|
||||
|
@ -715,18 +706,16 @@ To actually save the value, call `custom-save-all'.
|
|||
|
||||
Return non-nil if the `saved-value' property actually changed."
|
||||
(custom-load-symbol symbol)
|
||||
(let* ((get (or (get symbol 'custom-get) 'default-value))
|
||||
(let* ((get (or (get symbol 'custom-get) #'default-value))
|
||||
(value (funcall get symbol))
|
||||
(saved (get symbol 'saved-value))
|
||||
(standard (get symbol 'standard-value))
|
||||
(comment (get symbol 'customized-variable-comment)))
|
||||
;; Save default value if different from standard value.
|
||||
(if (or (null standard)
|
||||
(not (equal value (condition-case nil
|
||||
(eval (car standard))
|
||||
(error nil)))))
|
||||
(put symbol 'saved-value (list (custom-quote value)))
|
||||
(put symbol 'saved-value nil))
|
||||
(put symbol 'saved-value
|
||||
(unless (and standard
|
||||
(equal value (ignore-errors (eval (car standard)))))
|
||||
(list (custom-quote value))))
|
||||
;; Clear customized information (set, but not saved).
|
||||
(put symbol 'customized-value nil)
|
||||
;; Save any comment that might have been set.
|
||||
|
@ -744,15 +733,14 @@ default value. Otherwise, set it to nil.
|
|||
|
||||
Return non-nil if the `customized-value' property actually changed."
|
||||
(custom-load-symbol symbol)
|
||||
(let* ((get (or (get symbol 'custom-get) 'default-value))
|
||||
(let* ((get (or (get symbol 'custom-get) #'default-value))
|
||||
(value (funcall get symbol))
|
||||
(customized (get symbol 'customized-value))
|
||||
(old (or (get symbol 'saved-value) (get symbol 'standard-value))))
|
||||
;; Mark default value as set if different from old value.
|
||||
(if (not (and old
|
||||
(equal value (condition-case nil
|
||||
(eval (car old))
|
||||
(error nil)))))
|
||||
(equal value (ignore-errors
|
||||
(eval (car old))))))
|
||||
(progn (put symbol 'customized-value (list (custom-quote value)))
|
||||
(custom-push-theme 'theme-value symbol 'user 'set
|
||||
(custom-quote value)))
|
||||
|
@ -776,7 +764,7 @@ E.g. dumped variables whose default depends on run-time information."
|
|||
;; always do the funcall step, even if symbol was not bound before.
|
||||
(or (default-boundp symbol)
|
||||
(eval `(defvar ,symbol nil))) ; reset below, so any value is fine
|
||||
(funcall (or (get symbol 'custom-set) 'set-default)
|
||||
(funcall (or (get symbol 'custom-set) #'set-default)
|
||||
symbol
|
||||
(eval (car (or (get symbol 'saved-value) (get symbol 'standard-value))))))
|
||||
|
||||
|
@ -946,7 +934,7 @@ the default value for the SYMBOL to the value of EXP.
|
|||
REQUEST is a list of features we must require in order to
|
||||
handle SYMBOL properly.
|
||||
COMMENT is a comment string about SYMBOL."
|
||||
(apply 'custom-theme-set-variables 'user args))
|
||||
(apply #'custom-theme-set-variables 'user args))
|
||||
|
||||
(defun custom-theme-set-variables (theme &rest args)
|
||||
"Initialize variables for theme THEME according to settings in ARGS.
|
||||
|
@ -994,8 +982,8 @@ COMMENT is a comment string about SYMBOL."
|
|||
set)
|
||||
(when requests
|
||||
(put symbol 'custom-requests requests)
|
||||
(mapc 'require requests))
|
||||
(setq set (or (get symbol 'custom-set) 'custom-set-default))
|
||||
(mapc #'require requests))
|
||||
(setq set (or (get symbol 'custom-set) #'custom-set-default))
|
||||
(put symbol 'saved-value (list value))
|
||||
(put symbol 'saved-variable-comment comment)
|
||||
;; Allow for errors in the case where the setter has
|
||||
|
@ -1091,26 +1079,29 @@ list, in which A occurs before B if B was defined with a
|
|||
;; they were used to supply keyword-value pairs like `:immediate',
|
||||
;; `:variable-reset-string', etc. We don't use any of these, so ignore them.
|
||||
|
||||
(defmacro deftheme (theme &optional doc &rest ignored)
|
||||
(defmacro deftheme (theme &optional doc &rest _ignored)
|
||||
"Declare THEME to be a Custom theme.
|
||||
The optional argument DOC is a doc string describing the theme.
|
||||
|
||||
Any theme `foo' should be defined in a file called `foo-theme.el';
|
||||
see `custom-make-theme-feature' for more information."
|
||||
(declare (doc-string 2))
|
||||
(declare (doc-string 2)
|
||||
(advertised-calling-convention (theme &optional doc) "22.1"))
|
||||
(let ((feature (custom-make-theme-feature theme)))
|
||||
;; It is better not to use backquote in this file,
|
||||
;; because that makes a bootstrapping problem
|
||||
;; if you need to recompile all the Lisp files using interpreted code.
|
||||
(list 'custom-declare-theme (list 'quote theme) (list 'quote feature) doc)))
|
||||
|
||||
(defun custom-declare-theme (theme feature &optional doc &rest ignored)
|
||||
(defun custom-declare-theme (theme feature &optional doc &rest _ignored)
|
||||
"Like `deftheme', but THEME is evaluated as a normal argument.
|
||||
FEATURE is the feature this theme provides. Normally, this is a symbol
|
||||
created from THEME by `custom-make-theme-feature'."
|
||||
(declare (advertised-calling-convention (theme feature &optional doc) "22.1"))
|
||||
(unless (custom-theme-name-valid-p theme)
|
||||
(error "Custom theme cannot be named %S" theme))
|
||||
(add-to-list 'custom-known-themes theme)
|
||||
(unless (memq theme custom-known-themes)
|
||||
(push theme custom-known-themes))
|
||||
(put theme 'theme-feature feature)
|
||||
(when doc (put theme 'theme-documentation doc)))
|
||||
|
||||
|
@ -1218,7 +1209,7 @@ Return t if THEME was successfully loaded, nil otherwise."
|
|||
(interactive
|
||||
(list
|
||||
(intern (completing-read "Load custom theme: "
|
||||
(mapcar 'symbol-name
|
||||
(mapcar #'symbol-name
|
||||
(custom-available-themes))))
|
||||
nil nil))
|
||||
(unless (custom-theme-name-valid-p theme)
|
||||
|
@ -1233,43 +1224,47 @@ Return t if THEME was successfully loaded, nil otherwise."
|
|||
(put theme 'theme-settings nil)
|
||||
(put theme 'theme-feature nil)
|
||||
(put theme 'theme-documentation nil))
|
||||
(let ((fn (locate-file (concat (symbol-name theme) "-theme.el")
|
||||
(custom-theme--load-path)
|
||||
'("" "c"))))
|
||||
(unless fn
|
||||
(error "Unable to find theme file for `%s'" theme))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents fn)
|
||||
;; Check file safety with `custom-safe-themes', prompting the
|
||||
;; user if necessary.
|
||||
(when (or no-confirm
|
||||
(eq custom-safe-themes t)
|
||||
(and (memq 'default custom-safe-themes)
|
||||
(equal (file-name-directory fn)
|
||||
(expand-file-name "themes/" data-directory)))
|
||||
(let ((hash (secure-hash 'sha256 (current-buffer))))
|
||||
(or (member hash custom-safe-themes)
|
||||
(custom-theme-load-confirm hash))))
|
||||
(let ((custom--inhibit-theme-enable t)
|
||||
(buffer-file-name fn)) ;For load-history.
|
||||
(eval-buffer))
|
||||
;; Optimization: if the theme changes the `default' face, put that
|
||||
;; entry first. This avoids some `frame-set-background-mode' rigmarole
|
||||
;; by assigning the new background immediately.
|
||||
(let* ((settings (get theme 'theme-settings))
|
||||
(tail settings)
|
||||
found)
|
||||
(while (and tail (not found))
|
||||
(and (eq (nth 0 (car tail)) 'theme-face)
|
||||
(eq (nth 1 (car tail)) 'default)
|
||||
(setq found (car tail)))
|
||||
(setq tail (cdr tail)))
|
||||
(if found
|
||||
(put theme 'theme-settings (cons found (delq found settings)))))
|
||||
;; Finally, enable the theme.
|
||||
(unless no-enable
|
||||
(enable-theme theme))
|
||||
t))))
|
||||
(let ((file (locate-file (concat (symbol-name theme) "-theme.el")
|
||||
(custom-theme--load-path)
|
||||
'("" "c")))
|
||||
(custom--inhibit-theme-enable t))
|
||||
;; Check file safety with `custom-safe-themes', prompting the
|
||||
;; user if necessary.
|
||||
(cond ((not file)
|
||||
(error "Unable to find theme file for `%s'" theme))
|
||||
((or no-confirm
|
||||
(eq custom-safe-themes t)
|
||||
(and (memq 'default custom-safe-themes)
|
||||
(equal (file-name-directory file)
|
||||
(expand-file-name "themes/" data-directory))))
|
||||
;; Theme is safe; load byte-compiled version if available.
|
||||
(load (file-name-sans-extension file) nil t nil t))
|
||||
((with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(let ((hash (secure-hash 'sha256 (current-buffer))))
|
||||
(when (or (member hash custom-safe-themes)
|
||||
(custom-theme-load-confirm hash))
|
||||
(eval-buffer nil nil file)
|
||||
t))))
|
||||
(t
|
||||
(error "Unable to load theme `%s'" theme))))
|
||||
;; Optimization: if the theme changes the `default' face, put that
|
||||
;; entry first. This avoids some `frame-set-background-mode' rigmarole
|
||||
;; by assigning the new background immediately.
|
||||
(let* ((settings (get theme 'theme-settings))
|
||||
(tail settings)
|
||||
found)
|
||||
(while (and tail (not found))
|
||||
(and (eq (nth 0 (car tail)) 'theme-face)
|
||||
(eq (nth 1 (car tail)) 'default)
|
||||
(setq found (car tail)))
|
||||
(setq tail (cdr tail)))
|
||||
(when found
|
||||
(put theme 'theme-settings (cons found (delq found settings)))))
|
||||
;; Finally, enable the theme.
|
||||
(unless no-enable
|
||||
(enable-theme theme))
|
||||
t)
|
||||
|
||||
(defun custom-theme-load-confirm (hash)
|
||||
"Query the user about loading a Custom theme that may not be safe.
|
||||
|
@ -1292,11 +1287,9 @@ query also about adding HASH to `custom-safe-themes'."
|
|||
(defun custom-theme-name-valid-p (name)
|
||||
"Return t if NAME is a valid name for a Custom theme, nil otherwise.
|
||||
NAME should be a symbol."
|
||||
(and (symbolp name)
|
||||
name
|
||||
(not (or (zerop (length (symbol-name name)))
|
||||
(eq name 'user)
|
||||
(eq name 'changed)))))
|
||||
(and (not (memq name '(nil user changed)))
|
||||
(symbolp name)
|
||||
(not (string= "" (symbol-name name)))))
|
||||
|
||||
(defun custom-available-themes ()
|
||||
"Return a list of Custom themes available for loading.
|
||||
|
@ -1307,19 +1300,25 @@ The returned symbols may not correspond to themes that have been
|
|||
loaded, and no effort is made to check that the files contain
|
||||
valid Custom themes. For a list of loaded themes, check the
|
||||
variable `custom-known-themes'."
|
||||
(let (sym themes)
|
||||
(let ((suffix "-theme\\.el\\'")
|
||||
themes)
|
||||
(dolist (dir (custom-theme--load-path))
|
||||
(when (file-directory-p dir)
|
||||
(dolist (file (file-expand-wildcards
|
||||
(expand-file-name "*-theme.el" dir) t))
|
||||
(setq file (file-name-nondirectory file))
|
||||
(and (string-match "\\`\\(.+\\)-theme.el\\'" file)
|
||||
(setq sym (intern (match-string 1 file)))
|
||||
(custom-theme-name-valid-p sym)
|
||||
(push sym themes)))))
|
||||
(nreverse (delete-dups themes))))
|
||||
;; `custom-theme--load-path' promises DIR exists and is a
|
||||
;; directory, but `custom.el' is loaded too early during
|
||||
;; bootstrap to use `cl-lib' macros, so guard with
|
||||
;; `file-directory-p' instead of calling `cl-assert'.
|
||||
(dolist (file (and (file-directory-p dir)
|
||||
(directory-files dir nil suffix)))
|
||||
(let ((theme (intern (substring file 0 (string-match-p suffix file)))))
|
||||
(and (custom-theme-name-valid-p theme)
|
||||
(not (memq theme themes))
|
||||
(push theme themes)))))
|
||||
(nreverse themes)))
|
||||
|
||||
(defun custom-theme--load-path ()
|
||||
"Expand `custom-theme-load-path' into a list of directories.
|
||||
Members of `custom-theme-load-path' that either don't exist or
|
||||
are not directories are omitted from the expansion."
|
||||
(let (lpath)
|
||||
(dolist (f custom-theme-load-path)
|
||||
(cond ((eq f 'custom-theme-directory)
|
||||
|
@ -1346,8 +1345,8 @@ function runs. To disable other themes, use `disable-theme'."
|
|||
(completing-read
|
||||
"Enable custom theme: "
|
||||
obarray (lambda (sym) (get sym 'theme-settings)) t))))
|
||||
(if (not (custom-theme-p theme))
|
||||
(error "Undefined Custom theme %s" theme))
|
||||
(unless (custom-theme-p theme)
|
||||
(error "Undefined Custom theme %s" theme))
|
||||
(let ((settings (get theme 'theme-settings)))
|
||||
;; Loop through theme settings, recalculating vars/faces.
|
||||
(dolist (s settings)
|
||||
|
@ -1387,23 +1386,23 @@ Setting this variable through Customize calls `enable-theme' or
|
|||
(let (failures)
|
||||
(setq themes (delq 'user (delete-dups themes)))
|
||||
;; Disable all themes not in THEMES.
|
||||
(if (boundp symbol)
|
||||
(dolist (theme (symbol-value symbol))
|
||||
(if (not (memq theme themes))
|
||||
(disable-theme theme))))
|
||||
(dolist (theme (and (boundp symbol)
|
||||
(symbol-value symbol)))
|
||||
(unless (memq theme themes)
|
||||
(disable-theme theme)))
|
||||
;; Call `enable-theme' or `load-theme' on each of THEMES.
|
||||
(dolist (theme (reverse themes))
|
||||
(condition-case nil
|
||||
(if (custom-theme-p theme)
|
||||
(enable-theme theme)
|
||||
(load-theme theme))
|
||||
(error (setq failures (cons theme failures)
|
||||
themes (delq theme themes)))))
|
||||
(error (push theme failures)
|
||||
(setq themes (delq theme themes)))))
|
||||
(enable-theme 'user)
|
||||
(custom-set-default symbol themes)
|
||||
(if failures
|
||||
(message "Failed to enable theme: %s"
|
||||
(mapconcat 'symbol-name failures ", "))))))
|
||||
(when failures
|
||||
(message "Failed to enable theme(s): %s"
|
||||
(mapconcat #'symbol-name failures ", "))))))
|
||||
|
||||
(defsubst custom-theme-enabled-p (theme)
|
||||
"Return non-nil if THEME is enabled."
|
||||
|
@ -1415,7 +1414,7 @@ See `custom-enabled-themes' for a list of enabled themes."
|
|||
(interactive (list (intern
|
||||
(completing-read
|
||||
"Disable custom theme: "
|
||||
(mapcar 'symbol-name custom-enabled-themes)
|
||||
(mapcar #'symbol-name custom-enabled-themes)
|
||||
nil t))))
|
||||
(when (custom-theme-enabled-p theme)
|
||||
(let ((settings (get theme 'theme-settings)))
|
||||
|
@ -1431,23 +1430,23 @@ See `custom-enabled-themes' for a list of enabled themes."
|
|||
;; If the face spec specified by this theme is in the
|
||||
;; saved-face property, reset that property.
|
||||
(when (equal (nth 3 s) (get symbol 'saved-face))
|
||||
(put symbol 'saved-face (and val (cadr (car val)))))))))
|
||||
;; Recompute faces on all frames.
|
||||
(dolist (frame (frame-list))
|
||||
;; We must reset the fg and bg color frame parameters, or
|
||||
;; `face-set-after-frame-default' will use the existing
|
||||
;; parameters, which could be from the disabled theme.
|
||||
(set-frame-parameter frame 'background-color
|
||||
(custom--frame-color-default
|
||||
frame :background "background" "Background"
|
||||
"unspecified-bg" "white"))
|
||||
(set-frame-parameter frame 'foreground-color
|
||||
(custom--frame-color-default
|
||||
frame :foreground "foreground" "Foreground"
|
||||
"unspecified-fg" "black"))
|
||||
(face-set-after-frame-default frame))
|
||||
(setq custom-enabled-themes
|
||||
(delq theme custom-enabled-themes)))))
|
||||
(put symbol 'saved-face (cadar val))))))))
|
||||
;; Recompute faces on all frames.
|
||||
(dolist (frame (frame-list))
|
||||
;; We must reset the fg and bg color frame parameters, or
|
||||
;; `face-set-after-frame-default' will use the existing
|
||||
;; parameters, which could be from the disabled theme.
|
||||
(set-frame-parameter frame 'background-color
|
||||
(custom--frame-color-default
|
||||
frame :background "background" "Background"
|
||||
"unspecified-bg" "white"))
|
||||
(set-frame-parameter frame 'foreground-color
|
||||
(custom--frame-color-default
|
||||
frame :foreground "foreground" "Foreground"
|
||||
"unspecified-fg" "black"))
|
||||
(face-set-after-frame-default frame))
|
||||
(setq custom-enabled-themes
|
||||
(delq theme custom-enabled-themes))))
|
||||
|
||||
;; Only used if window-system not null.
|
||||
(declare-function x-get-resource "frame.c"
|
||||
|
@ -1481,7 +1480,7 @@ This function returns nil if no custom theme specifies a value for VARIABLE."
|
|||
(if (and valspec
|
||||
(or (get variable 'force-value)
|
||||
(default-boundp variable)))
|
||||
(funcall (or (get variable 'custom-set) 'set-default) variable
|
||||
(funcall (or (get variable 'custom-set) #'set-default) variable
|
||||
(eval (car valspec))))))
|
||||
|
||||
(defun custom-theme-recalc-face (face)
|
||||
|
@ -1522,7 +1521,7 @@ Each of the arguments ARGS has this form:
|
|||
(VARIABLE IGNORED)
|
||||
|
||||
This means reset VARIABLE. (The argument IGNORED is ignored)."
|
||||
(apply 'custom-theme-reset-variables 'user args))
|
||||
(apply #'custom-theme-reset-variables 'user args))
|
||||
|
||||
;;; The End.
|
||||
|
||||
|
|
|
@ -1989,6 +1989,19 @@ Optional arg HOW-TO determines how to treat the target.
|
|||
dired-dirs)))
|
||||
|
||||
|
||||
|
||||
;; We use this function in `dired-create-directory' and
|
||||
;; `dired-create-empty-file'; the return value is the new entry
|
||||
;; in the updated Dired buffer.
|
||||
(defun dired--find-topmost-parent-dir (filename)
|
||||
"Return the topmost nonexistent parent dir of FILENAME.
|
||||
FILENAME is a full file name."
|
||||
(let ((try filename) new)
|
||||
(while (and try (not (file-exists-p try)) (not (equal new try)))
|
||||
(setq new try
|
||||
try (directory-file-name (file-name-directory try))))
|
||||
new))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-create-directory (directory)
|
||||
"Create a directory called DIRECTORY.
|
||||
|
@ -1997,18 +2010,32 @@ If DIRECTORY already exists, signal an error."
|
|||
(interactive
|
||||
(list (read-file-name "Create directory: " (dired-current-directory))))
|
||||
(let* ((expanded (directory-file-name (expand-file-name directory)))
|
||||
(try expanded) new)
|
||||
new)
|
||||
(if (file-exists-p expanded)
|
||||
(error "Cannot create directory %s: file exists" expanded))
|
||||
;; Find the topmost nonexistent parent dir (variable `new')
|
||||
(while (and try (not (file-exists-p try)) (not (equal new try)))
|
||||
(setq new try
|
||||
try (directory-file-name (file-name-directory try))))
|
||||
(setq new (dired--find-topmost-parent-dir expanded))
|
||||
(make-directory expanded t)
|
||||
(when new
|
||||
(dired-add-file new)
|
||||
(dired-move-to-filename))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-create-empty-file (file)
|
||||
"Create an empty file called FILE.
|
||||
Add a new entry for the new file in the Dired buffer.
|
||||
Parent directories of FILE are created as needed.
|
||||
If FILE already exists, signal an error."
|
||||
(interactive (list (read-file-name "Create empty file: ")))
|
||||
(let* ((expanded (expand-file-name file))
|
||||
new)
|
||||
(if (file-exists-p expanded)
|
||||
(error "Cannot create file %s: file exists" expanded))
|
||||
(setq new (dired--find-topmost-parent-dir expanded))
|
||||
(make-empty-file file 'parents)
|
||||
(when new
|
||||
(dired-add-file new)
|
||||
(dired-move-to-filename))))
|
||||
|
||||
(defun dired-into-dir-with-symlinks (target)
|
||||
(and (file-directory-p target)
|
||||
(not (file-symlink-p target))))
|
||||
|
|
|
@ -1802,6 +1802,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
|
|||
(define-key map [menu-bar immediate create-directory]
|
||||
'(menu-item "Create Directory..." dired-create-directory
|
||||
:help "Create a directory"))
|
||||
(define-key map [menu-bar immediate create-empty-file]
|
||||
'(menu-item "Create Empty file..." dired-create-empty-file
|
||||
:help "Create an empty file"))
|
||||
(define-key map [menu-bar immediate wdired-mode]
|
||||
'(menu-item "Edit File Names" wdired-change-to-wdired-mode
|
||||
:help "Put a Dired buffer in a mode in which filenames are editable"
|
||||
|
|
916
lisp/emacs-lisp/backtrace.el
Normal file
916
lisp/emacs-lisp/backtrace.el
Normal file
|
@ -0,0 +1,916 @@
|
|||
;;; backtrace.el --- generic major mode for Elisp backtraces -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Gemini Lasswell
|
||||
;; Keywords: lisp, tools, maint
|
||||
;; Version: 1.0
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs 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 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file defines Backtrace mode, a generic major mode for displaying
|
||||
;; Elisp stack backtraces, which can be used as is or inherited from
|
||||
;; by another mode.
|
||||
|
||||
;; For usage information, see the documentation of `backtrace-mode'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
(eval-when-compile (require 'pcase))
|
||||
(eval-when-compile (require 'subr-x)) ; if-let
|
||||
(require 'help-mode) ; Define `help-function-def' button type.
|
||||
(require 'lisp-mode)
|
||||
|
||||
;;; Options
|
||||
|
||||
(defgroup backtrace nil
|
||||
"Viewing of Elisp backtraces."
|
||||
:group 'lisp)
|
||||
|
||||
(defcustom backtrace-fontify t
|
||||
"If non-nil, fontify Backtrace buffers.
|
||||
Set to nil to disable fontification, which may be necessary in
|
||||
order to debug the code that does fontification."
|
||||
:type 'boolean
|
||||
:group 'backtrace
|
||||
:version "27.1")
|
||||
|
||||
(defcustom backtrace-line-length 5000
|
||||
"Target length for lines in Backtrace buffers.
|
||||
Backtrace mode will attempt to abbreviate printing of backtrace
|
||||
frames to make them shorter than this, but success is not
|
||||
guaranteed. If set to nil or zero, Backtrace mode will not
|
||||
abbreviate the forms it prints."
|
||||
:type 'integer
|
||||
:group 'backtrace
|
||||
:version "27.1")
|
||||
|
||||
;;; Backtrace frame data structure
|
||||
|
||||
(cl-defstruct
|
||||
(backtrace-frame
|
||||
(:constructor backtrace-make-frame))
|
||||
evald ; Non-nil if argument evaluation is complete.
|
||||
fun ; The function called/to call in this frame.
|
||||
args ; Either evaluated or unevaluated arguments to the function.
|
||||
flags ; A plist, possible properties are :debug-on-exit and :source-available.
|
||||
locals ; An alist containing variable names and values.
|
||||
buffer ; If non-nil, the buffer in use by eval-buffer or eval-region.
|
||||
pos ; The position in the buffer.
|
||||
)
|
||||
|
||||
(cl-defun backtrace-get-frames
|
||||
(&optional base &key (constructor #'backtrace-make-frame))
|
||||
"Collect all frames of current backtrace into a list.
|
||||
The list will contain objects made by CONSTRUCTOR, which
|
||||
defaults to `backtrace-make-frame' and which, if provided, should
|
||||
be the constructor of a structure which includes
|
||||
`backtrace-frame'. If non-nil, BASE should be a function, and
|
||||
frames before its nearest activation frame are discarded."
|
||||
(let ((frames nil)
|
||||
(eval-buffers eval-buffer-list))
|
||||
(mapbacktrace (lambda (evald fun args flags)
|
||||
(push (funcall constructor
|
||||
:evald evald :fun fun
|
||||
:args args :flags flags)
|
||||
frames))
|
||||
(or base 'backtrace-get-frames))
|
||||
(setq frames (nreverse frames))
|
||||
;; Add local variables to each frame, and the buffer position
|
||||
;; to frames containing eval-buffer or eval-region.
|
||||
(dotimes (idx (length frames))
|
||||
(let ((frame (nth idx frames)))
|
||||
;; `backtrace--locals' gives an error when idx is 0. But the
|
||||
;; locals for frame 0 are not needed, because when we get here
|
||||
;; from debug-on-entry, the locals aren't bound yet, and when
|
||||
;; coming from Edebug or ERT there is an Edebug or ERT
|
||||
;; function at frame 0.
|
||||
(when (> idx 0)
|
||||
(setf (backtrace-frame-locals frame)
|
||||
(backtrace--locals idx (or base 'backtrace-get-frames))))
|
||||
(when (and eval-buffers (memq (backtrace-frame-fun frame)
|
||||
'(eval-buffer eval-region)))
|
||||
;; This will get the wrong result if there are two nested
|
||||
;; eval-region calls for the same buffer. That's not a very
|
||||
;; useful case.
|
||||
(with-current-buffer (pop eval-buffers)
|
||||
(setf (backtrace-frame-buffer frame) (current-buffer))
|
||||
(setf (backtrace-frame-pos frame) (point))))))
|
||||
frames))
|
||||
|
||||
;; Button definition for jumping to a buffer position.
|
||||
|
||||
(define-button-type 'backtrace-buffer-pos
|
||||
'action #'backtrace--pop-to-buffer-pos
|
||||
'help-echo "mouse-2, RET: Show reading position")
|
||||
|
||||
(defun backtrace--pop-to-buffer-pos (button)
|
||||
"Pop to the buffer and position for the BUTTON at point."
|
||||
(let* ((buffer (button-get button 'backtrace-buffer))
|
||||
(pos (button-get button 'backtrace-pos)))
|
||||
(if (buffer-live-p buffer)
|
||||
(progn
|
||||
(pop-to-buffer buffer)
|
||||
(goto-char (max (point-min) (min (point-max) pos))))
|
||||
(message "Buffer has been killed"))))
|
||||
|
||||
;; Font Locking support
|
||||
|
||||
(defconst backtrace--font-lock-keywords
|
||||
'((backtrace--match-ellipsis-in-string
|
||||
(1 'button prepend)))
|
||||
"Expressions to fontify in Backtrace mode.
|
||||
Fontify these in addition to the expressions Emacs Lisp mode
|
||||
fontifies.")
|
||||
|
||||
(defconst backtrace-font-lock-keywords
|
||||
(append lisp-el-font-lock-keywords-for-backtraces
|
||||
backtrace--font-lock-keywords)
|
||||
"Default expressions to highlight in Backtrace mode.")
|
||||
(defconst backtrace-font-lock-keywords-1
|
||||
(append lisp-el-font-lock-keywords-for-backtraces-1
|
||||
backtrace--font-lock-keywords)
|
||||
"Subdued level highlighting for Backtrace mode.")
|
||||
(defconst backtrace-font-lock-keywords-2
|
||||
(append lisp-el-font-lock-keywords-for-backtraces-2
|
||||
backtrace--font-lock-keywords)
|
||||
"Gaudy level highlighting for Backtrace mode.")
|
||||
|
||||
(defun backtrace--match-ellipsis-in-string (bound)
|
||||
;; Fontify ellipses within strings as buttons.
|
||||
;; This is necessary because ellipses are text property buttons
|
||||
;; instead of overlay buttons, which is done because there could
|
||||
;; be a large number of them.
|
||||
(when (re-search-forward "\\(\\.\\.\\.\\)\"" bound t)
|
||||
(and (get-text-property (- (point) 2) 'cl-print-ellipsis)
|
||||
(get-text-property (- (point) 3) 'cl-print-ellipsis)
|
||||
(get-text-property (- (point) 4) 'cl-print-ellipsis))))
|
||||
|
||||
;;; Xref support
|
||||
|
||||
(defun backtrace--xref-backend () 'elisp)
|
||||
|
||||
;;; Backtrace mode variables
|
||||
|
||||
(defvar-local backtrace-frames nil
|
||||
"Stack frames displayed in the current Backtrace buffer.
|
||||
This should be a list of `backtrace-frame' objects.")
|
||||
|
||||
(defvar-local backtrace-view nil
|
||||
"A plist describing how to render backtrace frames.
|
||||
Possible entries are :show-flags, :show-locals and :print-circle.")
|
||||
|
||||
(defvar-local backtrace-insert-header-function nil
|
||||
"Function for inserting a header for the current Backtrace buffer.
|
||||
If nil, no header will be created. Note that Backtrace buffers
|
||||
are fontified as in Emacs Lisp Mode, the header text included.")
|
||||
|
||||
(defvar backtrace-revert-hook nil
|
||||
"Hook run before reverting a Backtrace buffer.
|
||||
This is commonly used to recompute `backtrace-frames'.")
|
||||
|
||||
(defvar-local backtrace-print-function #'cl-prin1
|
||||
"Function used to print values in the current Backtrace buffer.")
|
||||
|
||||
(defvar-local backtrace-goto-source-functions nil
|
||||
"Abnormal hook used to jump to the source code for the current frame.
|
||||
Each hook function is called with no argument, and should return
|
||||
non-nil if it is able to switch to the buffer containing the
|
||||
source code. Execution of the hook will stop if one of the
|
||||
functions returns non-nil. When adding a function to this hook,
|
||||
you should also set the :source-available flag for the backtrace
|
||||
frames where the source code location is known.")
|
||||
|
||||
(defvar backtrace-mode-map
|
||||
(let ((map (copy-keymap special-mode-map)))
|
||||
(set-keymap-parent map button-buffer-map)
|
||||
(define-key map "n" 'backtrace-forward-frame)
|
||||
(define-key map "p" 'backtrace-backward-frame)
|
||||
(define-key map "v" 'backtrace-toggle-locals)
|
||||
(define-key map "#" 'backtrace-toggle-print-circle)
|
||||
(define-key map "s" 'backtrace-goto-source)
|
||||
(define-key map "\C-m" 'backtrace-help-follow-symbol)
|
||||
(define-key map "+" 'backtrace-multi-line)
|
||||
(define-key map "-" 'backtrace-single-line)
|
||||
(define-key map "." 'backtrace-expand-ellipses)
|
||||
(define-key map [follow-link] 'mouse-face)
|
||||
(define-key map [mouse-2] 'mouse-select-window)
|
||||
(easy-menu-define nil map ""
|
||||
'("Backtrace"
|
||||
["Next Frame" backtrace-forward-frame
|
||||
:help "Move cursor forwards to the start of a backtrace frame"]
|
||||
["Previous Frame" backtrace-backward-frame
|
||||
:help "Move cursor backwards to the start of a backtrace frame"]
|
||||
"--"
|
||||
["Show Variables" backtrace-toggle-locals
|
||||
:style toggle
|
||||
:active (backtrace-get-index)
|
||||
:selected (plist-get (backtrace-get-view) :show-locals)
|
||||
:help "Show or hide the local variables for the frame at point"]
|
||||
["Expand \"...\"s" backtrace-expand-ellipses
|
||||
:help "Expand all the abbreviated forms in the current frame"]
|
||||
["Show on Multiple Lines" backtrace-multi-line
|
||||
:help "Use line breaks and indentation to make a form more readable"]
|
||||
["Show on Single Line" backtrace-single-line]
|
||||
"--"
|
||||
["Go to Source" backtrace-goto-source
|
||||
:active (and (backtrace-get-index)
|
||||
(plist-get (backtrace-frame-flags
|
||||
(nth (backtrace-get-index) backtrace-frames))
|
||||
:source-available))
|
||||
:help "Show the source code for the current frame"]
|
||||
["Help for Symbol" backtrace-help-follow-symbol
|
||||
:help "Show help for symbol at point"]
|
||||
["Describe Backtrace Mode" describe-mode
|
||||
:help "Display documentation for backtrace-mode"]))
|
||||
map)
|
||||
"Local keymap for `backtrace-mode' buffers.")
|
||||
|
||||
(defconst backtrace--flags-width 2
|
||||
"Width in characters of the flags for a backtrace frame.")
|
||||
|
||||
;;; Navigation and Text Properties
|
||||
|
||||
;; This mode uses the following text properties:
|
||||
;; backtrace-index: The index into the buffer-local variable
|
||||
;; `backtrace-frames' for the frame at point, or nil if outside of a
|
||||
;; frame (in the buffer header).
|
||||
;; backtrace-view: A plist describing how the frame is printed. See
|
||||
;; the docstring for the buffer-local variable `backtrace-view.
|
||||
;; backtrace-section: The part of a frame which point is in. Either
|
||||
;; `func' or `locals'. At the moment just used to show and hide the
|
||||
;; local variables. Derived modes which do additional printing
|
||||
;; could define their own frame sections.
|
||||
;; backtrace-form: A value applied to each printed representation of a
|
||||
;; top-level s-expression, which needs to be different for sexps
|
||||
;; printed adjacent to each other, so the limits can be quickly
|
||||
;; found for pretty-printing.
|
||||
|
||||
(defsubst backtrace-get-index (&optional pos)
|
||||
"Return the index of the backtrace frame at POS.
|
||||
The value is an index into `backtrace-frames', or nil.
|
||||
POS, if omitted or nil, defaults to point."
|
||||
(get-text-property (or pos (point)) 'backtrace-index))
|
||||
|
||||
(defsubst backtrace-get-section (&optional pos)
|
||||
"Return the section of a backtrace frame at POS.
|
||||
POS, if omitted or nil, defaults to point."
|
||||
(get-text-property (or pos (point)) 'backtrace-section))
|
||||
|
||||
(defsubst backtrace-get-view (&optional pos)
|
||||
"Return the view plist of the backtrace frame at POS.
|
||||
POS, if omitted or nil, defaults to point."
|
||||
(get-text-property (or pos (point)) 'backtrace-view))
|
||||
|
||||
(defsubst backtrace-get-form (&optional pos)
|
||||
"Return the backtrace form data for the form printed at POS.
|
||||
POS, if omitted or nil, defaults to point."
|
||||
(get-text-property (or pos (point)) 'backtrace-form))
|
||||
|
||||
(defun backtrace-get-frame-start (&optional pos)
|
||||
"Return the beginning position of the frame at POS in the buffer.
|
||||
POS, if omitted or nil, defaults to point."
|
||||
(let ((posn (or pos (point))))
|
||||
(if (or (= (point-min) posn)
|
||||
(not (eq (backtrace-get-index posn)
|
||||
(backtrace-get-index (1- posn)))))
|
||||
posn
|
||||
(previous-single-property-change posn 'backtrace-index nil (point-min)))))
|
||||
|
||||
(defun backtrace-get-frame-end (&optional pos)
|
||||
"Return the position of the end of the frame at POS in the buffer.
|
||||
POS, if omitted or nil, defaults to point."
|
||||
(next-single-property-change (or pos (point))
|
||||
'backtrace-index nil (point-max)))
|
||||
|
||||
(defun backtrace-forward-frame ()
|
||||
"Move forward to the beginning of the next frame."
|
||||
(interactive)
|
||||
(let ((max (backtrace-get-frame-end)))
|
||||
(when (= max (point-max))
|
||||
(user-error "No next stack frame"))
|
||||
(goto-char max)))
|
||||
|
||||
(defun backtrace-backward-frame ()
|
||||
"Move backward to the start of a stack frame."
|
||||
(interactive)
|
||||
(let ((current-index (backtrace-get-index))
|
||||
(min (backtrace-get-frame-start)))
|
||||
(if (or (and (/= (point) (point-max)) (null current-index))
|
||||
(= min (point-min))
|
||||
(and (= min (point))
|
||||
(null (backtrace-get-index (1- min)))))
|
||||
(user-error "No previous stack frame"))
|
||||
(if (= min (point))
|
||||
(goto-char (backtrace-get-frame-start (1- min)))
|
||||
(goto-char min))))
|
||||
|
||||
;; Other Backtrace mode commands
|
||||
|
||||
(defun backtrace-revert (&rest _ignored)
|
||||
"The `revert-buffer-function' for `backtrace-mode'.
|
||||
It runs `backtrace-revert-hook', then calls `backtrace-print'."
|
||||
(interactive)
|
||||
(unless (derived-mode-p 'backtrace-mode)
|
||||
(error "The current buffer is not in Backtrace mode"))
|
||||
(run-hooks 'backtrace-revert-hook)
|
||||
(backtrace-print t))
|
||||
|
||||
(defmacro backtrace--with-output-variables (view &rest body)
|
||||
"Bind output variables according to VIEW and execute BODY."
|
||||
(declare (indent 1))
|
||||
`(let ((print-escape-control-characters t)
|
||||
(print-escape-newlines t)
|
||||
(print-circle (plist-get ,view :print-circle))
|
||||
(standard-output (current-buffer)))
|
||||
,@body))
|
||||
|
||||
(defun backtrace-toggle-locals (&optional all)
|
||||
"Toggle the display of local variables for the backtrace frame at point.
|
||||
With prefix argument ALL, toggle the value of :show-locals in
|
||||
`backtrace-view', which affects all of the backtrace frames in
|
||||
the buffer."
|
||||
(interactive "P")
|
||||
(if all
|
||||
(let ((pos (make-marker))
|
||||
(visible (not (plist-get backtrace-view :show-locals))))
|
||||
(setq backtrace-view (plist-put backtrace-view :show-locals visible))
|
||||
(set-marker-insertion-type pos t)
|
||||
(set-marker pos (point))
|
||||
(goto-char (point-min))
|
||||
;; Skip the header.
|
||||
(unless (backtrace-get-index)
|
||||
(goto-char (backtrace-get-frame-end)))
|
||||
(while (< (point) (point-max))
|
||||
(backtrace--set-frame-locals-visible visible)
|
||||
(goto-char (backtrace-get-frame-end)))
|
||||
(goto-char pos)
|
||||
(when (invisible-p pos)
|
||||
(goto-char (backtrace-get-frame-start))))
|
||||
(let ((index (backtrace-get-index)))
|
||||
(unless index
|
||||
(user-error "Not in a stack frame"))
|
||||
(backtrace--set-frame-locals-visible
|
||||
(not (plist-get (backtrace-get-view) :show-locals))))))
|
||||
|
||||
(defun backtrace--set-frame-locals-visible (visible)
|
||||
"Set the visibility of the local vars for the frame at point to VISIBLE."
|
||||
(let ((pos (point))
|
||||
(index (backtrace-get-index))
|
||||
(start (backtrace-get-frame-start))
|
||||
(end (backtrace-get-frame-end))
|
||||
(view (copy-sequence (backtrace-get-view)))
|
||||
(inhibit-read-only t))
|
||||
(setq view (plist-put view :show-locals visible))
|
||||
(goto-char (backtrace-get-frame-start))
|
||||
(while (not (or (= (point) end)
|
||||
(eq (backtrace-get-section) 'locals)))
|
||||
(goto-char (next-single-property-change (point)
|
||||
'backtrace-section nil end)))
|
||||
(cond
|
||||
((and (= (point) end) visible)
|
||||
;; The locals section doesn't exist so create it.
|
||||
(let ((standard-output (current-buffer)))
|
||||
(backtrace--with-output-variables view
|
||||
(backtrace--print-locals
|
||||
(nth index backtrace-frames) view))
|
||||
(add-text-properties end (point) `(backtrace-index ,index))
|
||||
(goto-char pos)))
|
||||
((/= (point) end)
|
||||
;; The locals section does exist, so add or remove the overlay.
|
||||
(backtrace--set-locals-visible-overlay (point) end visible)
|
||||
(goto-char (if (invisible-p pos) start pos))))
|
||||
(add-text-properties start (backtrace-get-frame-end)
|
||||
`(backtrace-view ,view))))
|
||||
|
||||
(defun backtrace--set-locals-visible-overlay (beg end visible)
|
||||
(backtrace--change-button-skip beg end (not visible))
|
||||
(if visible
|
||||
(remove-overlays beg end 'invisible t)
|
||||
(let ((o (make-overlay beg end)))
|
||||
(overlay-put o 'invisible t)
|
||||
(overlay-put o 'evaporate t))))
|
||||
|
||||
(defun backtrace--change-button-skip (beg end value)
|
||||
"Change the skip property on all buttons between BEG and END.
|
||||
Set it to VALUE unless the button is a `backtrace-ellipsis' button."
|
||||
(let ((inhibit-read-only t))
|
||||
(setq beg (next-button beg))
|
||||
(while (and beg (< beg end))
|
||||
(unless (eq (button-type beg) 'backtrace-ellipsis)
|
||||
(button-put beg 'skip value))
|
||||
(setq beg (next-button beg)))))
|
||||
|
||||
(defun backtrace-toggle-print-circle (&optional all)
|
||||
"Toggle `print-circle' for the backtrace frame at point.
|
||||
With prefix argument ALL, toggle the value of :print-circle in
|
||||
`backtrace-view', which affects all of the backtrace frames in
|
||||
the buffer."
|
||||
(interactive "P")
|
||||
(backtrace--toggle-feature :print-circle all))
|
||||
|
||||
(defun backtrace--toggle-feature (feature all)
|
||||
"Toggle FEATURE for the current backtrace frame or for the buffer.
|
||||
FEATURE should be one of the options in `backtrace-view'. If ALL
|
||||
is non-nil, toggle FEATURE for all frames in the buffer. After
|
||||
toggling the feature, reprint the affected frame(s). Afterwards
|
||||
position point at the start of the frame it was in before."
|
||||
(if all
|
||||
(let ((index (backtrace-get-index))
|
||||
(pos (point))
|
||||
(at-end (= (point) (point-max)))
|
||||
(value (not (plist-get backtrace-view feature))))
|
||||
(setq backtrace-view (plist-put backtrace-view feature value))
|
||||
(goto-char (point-min))
|
||||
;; Skip the header.
|
||||
(unless (backtrace-get-index)
|
||||
(goto-char (backtrace-get-frame-end)))
|
||||
(while (< (point) (point-max))
|
||||
(backtrace--set-feature feature value)
|
||||
(goto-char (backtrace-get-frame-end)))
|
||||
(if (not index)
|
||||
(goto-char (if at-end (point-max) pos))
|
||||
(goto-char (point-min))
|
||||
(while (and (not (eql index (backtrace-get-index)))
|
||||
(< (point) (point-max)))
|
||||
(goto-char (backtrace-get-frame-end)))))
|
||||
(let ((index (backtrace-get-index)))
|
||||
(unless index
|
||||
(user-error "Not in a stack frame"))
|
||||
(backtrace--set-feature feature
|
||||
(not (plist-get (backtrace-get-view) feature))))))
|
||||
|
||||
(defun backtrace--set-feature (feature value)
|
||||
"Set FEATURE in the view plist of the frame at point to VALUE.
|
||||
Reprint the frame with the new view plist."
|
||||
(let ((inhibit-read-only t)
|
||||
(view (copy-sequence (backtrace-get-view)))
|
||||
(index (backtrace-get-index))
|
||||
(min (backtrace-get-frame-start))
|
||||
(max (backtrace-get-frame-end)))
|
||||
(setq view (plist-put view feature value))
|
||||
(delete-region min max)
|
||||
(goto-char min)
|
||||
(backtrace-print-frame (nth index backtrace-frames) view)
|
||||
(add-text-properties min (point)
|
||||
`(backtrace-index ,index backtrace-view ,view))
|
||||
(goto-char min)))
|
||||
|
||||
(defun backtrace-expand-ellipsis (button)
|
||||
"Expand display of the elided form at BUTTON."
|
||||
(interactive)
|
||||
(goto-char (button-start button))
|
||||
(unless (get-text-property (point) 'cl-print-ellipsis)
|
||||
(if (and (> (point) (point-min))
|
||||
(get-text-property (1- (point)) 'cl-print-ellipsis))
|
||||
(backward-char)
|
||||
(user-error "No ellipsis to expand here")))
|
||||
(let* ((end (next-single-property-change (point) 'cl-print-ellipsis))
|
||||
(begin (previous-single-property-change end 'cl-print-ellipsis))
|
||||
(value (get-text-property begin 'cl-print-ellipsis))
|
||||
(props (backtrace-get-text-properties begin))
|
||||
(inhibit-read-only t))
|
||||
(backtrace--with-output-variables (backtrace-get-view)
|
||||
(delete-region begin end)
|
||||
(insert (cl-print-to-string-with-limit #'cl-print-expand-ellipsis value
|
||||
backtrace-line-length))
|
||||
(setq end (point))
|
||||
(goto-char begin)
|
||||
(while (< (point) end)
|
||||
(let ((next (next-single-property-change (point) 'cl-print-ellipsis
|
||||
nil end)))
|
||||
(when (get-text-property (point) 'cl-print-ellipsis)
|
||||
(make-text-button (point) next :type 'backtrace-ellipsis))
|
||||
(goto-char next)))
|
||||
(goto-char begin)
|
||||
(add-text-properties begin end props))))
|
||||
|
||||
(defun backtrace-expand-ellipses (&optional no-limit)
|
||||
"Expand display of all \"...\"s in the backtrace frame at point.
|
||||
\\<backtrace-mode-map>
|
||||
Each ellipsis will be limited to `backtrace-line-length'
|
||||
characters in its expansion. With optional prefix argument
|
||||
NO-LIMIT, do not limit the number of characters. Note that with
|
||||
or without the argument, using this command can result in very
|
||||
long lines and very poor display performance. If this happens
|
||||
and is a problem, use `\\[revert-buffer]' to return to the
|
||||
initial state of the Backtrace buffer."
|
||||
(interactive "P")
|
||||
(save-excursion
|
||||
(let ((start (backtrace-get-frame-start))
|
||||
(end (backtrace-get-frame-end))
|
||||
(backtrace-line-length (unless no-limit backtrace-line-length)))
|
||||
(goto-char end)
|
||||
(while (> (point) start)
|
||||
(let ((next (previous-single-property-change (point) 'cl-print-ellipsis
|
||||
nil start)))
|
||||
(when (get-text-property (point) 'cl-print-ellipsis)
|
||||
(push-button (point)))
|
||||
(goto-char next))))))
|
||||
|
||||
(defun backtrace-multi-line ()
|
||||
"Show the top level s-expression at point on multiple lines with indentation."
|
||||
(interactive)
|
||||
(backtrace--reformat-sexp #'backtrace--multi-line))
|
||||
|
||||
(defun backtrace--multi-line ()
|
||||
"Pretty print the current buffer, then remove the trailing newline."
|
||||
(set-syntax-table emacs-lisp-mode-syntax-table)
|
||||
(pp-buffer)
|
||||
(goto-char (1- (point-max)))
|
||||
(delete-char 1))
|
||||
|
||||
(defun backtrace-single-line ()
|
||||
"Show the top level s-expression at point on one line."
|
||||
(interactive)
|
||||
(backtrace--reformat-sexp #'backtrace--single-line))
|
||||
|
||||
(defun backtrace--single-line ()
|
||||
"Replace line breaks and following indentation with spaces.
|
||||
Works on the current buffer."
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\n[[:blank:]]*" nil t)
|
||||
(replace-match " ")))
|
||||
|
||||
(defun backtrace--reformat-sexp (format-function)
|
||||
"Reformat the top level sexp at point.
|
||||
Locate the top level sexp at or following point on the same line,
|
||||
and reformat it with FORMAT-FUNCTION, preserving the location of
|
||||
point within the sexp. If no sexp is found before the end of
|
||||
the line or buffer, signal an error.
|
||||
|
||||
FORMAT-FUNCTION will be called without arguments, with the
|
||||
current buffer set to a temporary buffer containing only the
|
||||
content of the sexp."
|
||||
(let* ((orig-pos (point))
|
||||
(pos (point))
|
||||
(tag (backtrace-get-form pos))
|
||||
(end (next-single-property-change pos 'backtrace-form))
|
||||
(begin (previous-single-property-change end 'backtrace-form
|
||||
nil (point-min))))
|
||||
(unless tag
|
||||
(when (or (= end (point-max)) (> end (point-at-eol)))
|
||||
(user-error "No form here to reformat"))
|
||||
(goto-char end)
|
||||
(setq pos end
|
||||
end (next-single-property-change pos 'backtrace-form)
|
||||
begin (previous-single-property-change end 'backtrace-form
|
||||
nil (point-min))))
|
||||
(let* ((offset (when (>= orig-pos begin) (- orig-pos begin)))
|
||||
(offset-marker (when offset (make-marker)))
|
||||
(content (buffer-substring begin end))
|
||||
(props (backtrace-get-text-properties begin))
|
||||
(inhibit-read-only t))
|
||||
(delete-region begin end)
|
||||
(insert (with-temp-buffer
|
||||
(insert content)
|
||||
(when offset
|
||||
(set-marker-insertion-type offset-marker t)
|
||||
(set-marker offset-marker (+ (point-min) offset)))
|
||||
(funcall format-function)
|
||||
(when offset
|
||||
(setq offset (- (marker-position offset-marker) (point-min))))
|
||||
(buffer-string)))
|
||||
(when offset
|
||||
(set-marker offset-marker (+ begin offset)))
|
||||
(save-excursion
|
||||
(goto-char begin)
|
||||
(indent-sexp))
|
||||
(add-text-properties begin (point) props)
|
||||
(if offset
|
||||
(goto-char (marker-position offset-marker))
|
||||
(goto-char orig-pos)))))
|
||||
|
||||
(defun backtrace-get-text-properties (pos)
|
||||
"Return a plist of backtrace-mode's text properties at POS."
|
||||
(apply #'append
|
||||
(mapcar (lambda (prop)
|
||||
(list prop (get-text-property pos prop)))
|
||||
'(backtrace-section backtrace-index backtrace-view
|
||||
backtrace-form))))
|
||||
|
||||
(defun backtrace-goto-source ()
|
||||
"If its location is known, jump to the source code for the frame at point."
|
||||
(interactive)
|
||||
(let* ((index (or (backtrace-get-index) (user-error "Not in a stack frame")))
|
||||
(frame (nth index backtrace-frames))
|
||||
(source-available (plist-get (backtrace-frame-flags frame)
|
||||
:source-available)))
|
||||
(unless (and source-available
|
||||
(catch 'done
|
||||
(dolist (func backtrace-goto-source-functions)
|
||||
(when (funcall func)
|
||||
(throw 'done t)))))
|
||||
(user-error "Source code location not known"))))
|
||||
|
||||
(defun backtrace-help-follow-symbol (&optional pos)
|
||||
"Follow cross-reference at POS, defaulting to point.
|
||||
For the cross-reference format, see `help-make-xrefs'."
|
||||
(interactive "d")
|
||||
(unless pos
|
||||
(setq pos (point)))
|
||||
(unless (push-button pos)
|
||||
;; Check if the symbol under point is a function or variable.
|
||||
(let ((sym
|
||||
(intern
|
||||
(save-excursion
|
||||
(goto-char pos) (skip-syntax-backward "w_")
|
||||
(buffer-substring (point)
|
||||
(progn (skip-syntax-forward "w_")
|
||||
(point)))))))
|
||||
(when (or (boundp sym) (fboundp sym) (facep sym))
|
||||
(describe-symbol sym)))))
|
||||
|
||||
;; Print backtrace frames
|
||||
|
||||
(defun backtrace-print (&optional remember-pos)
|
||||
"Populate the current Backtrace mode buffer.
|
||||
This erases the buffer and inserts printed representations of the
|
||||
frames. Optional argument REMEMBER-POS, if non-nil, means to
|
||||
move point to the entry with the same ID element as the current
|
||||
line and recenter window line accordingly."
|
||||
(let ((inhibit-read-only t)
|
||||
entry-index saved-pt window-line)
|
||||
(and remember-pos
|
||||
(setq entry-index (backtrace-get-index))
|
||||
(when (eq (window-buffer) (current-buffer))
|
||||
(setq window-line
|
||||
(count-screen-lines (window-start) (point)))))
|
||||
(erase-buffer)
|
||||
(when backtrace-insert-header-function
|
||||
(funcall backtrace-insert-header-function))
|
||||
(dotimes (idx (length backtrace-frames))
|
||||
(let ((beg (point))
|
||||
(elt (nth idx backtrace-frames)))
|
||||
(and entry-index
|
||||
(equal entry-index idx)
|
||||
(setq entry-index nil
|
||||
saved-pt (point)))
|
||||
(backtrace-print-frame elt backtrace-view)
|
||||
(add-text-properties
|
||||
beg (point)
|
||||
`(backtrace-index ,idx backtrace-view ,backtrace-view))))
|
||||
(set-buffer-modified-p nil)
|
||||
;; If REMEMBER-POS was specified, move to the "old" location.
|
||||
(if saved-pt
|
||||
(progn (goto-char saved-pt)
|
||||
(when window-line
|
||||
(recenter window-line)))
|
||||
(goto-char (point-min)))))
|
||||
|
||||
;; Define button type used for ...'s.
|
||||
;; Set skip property so you don't have to TAB through 100 of them to
|
||||
;; get to the next function name.
|
||||
(define-button-type 'backtrace-ellipsis
|
||||
'skip t 'action #'backtrace-expand-ellipsis
|
||||
'help-echo "mouse-2, RET: expand this ellipsis")
|
||||
|
||||
(defun backtrace-print-to-string (obj &optional limit)
|
||||
"Return a printed representation of OBJ formatted for backtraces.
|
||||
Attempt to get the length of the returned string under LIMIT
|
||||
charcters with appropriate settings of `print-level' and
|
||||
`print-length.' LIMIT defaults to `backtrace-line-length'."
|
||||
(backtrace--with-output-variables backtrace-view
|
||||
(backtrace--print-to-string obj limit)))
|
||||
|
||||
(defun backtrace--print-to-string (sexp &optional limit)
|
||||
;; This is for use by callers who wrap the call with
|
||||
;; backtrace--with-output-variables.
|
||||
(setq limit (or limit backtrace-line-length))
|
||||
(with-temp-buffer
|
||||
(insert (cl-print-to-string-with-limit #'backtrace--print sexp limit))
|
||||
;; Add a unique backtrace-form property.
|
||||
(put-text-property (point-min) (point) 'backtrace-form (gensym))
|
||||
;; Make buttons from all the "..."s. Since there might be many of
|
||||
;; them, use text property buttons.
|
||||
(goto-char (point-min))
|
||||
(while (< (point) (point-max))
|
||||
(let ((end (next-single-property-change (point) 'cl-print-ellipsis
|
||||
nil (point-max))))
|
||||
(when (get-text-property (point) 'cl-print-ellipsis)
|
||||
(make-text-button (point) end :type 'backtrace-ellipsis))
|
||||
(goto-char end)))
|
||||
(buffer-string)))
|
||||
|
||||
(defun backtrace-print-frame (frame view)
|
||||
"Insert a backtrace FRAME at point formatted according to VIEW.
|
||||
Tag the sections of the frame with the `backtrace-section' text
|
||||
property for use by navigation."
|
||||
(backtrace--with-output-variables view
|
||||
(backtrace--print-flags frame view)
|
||||
(backtrace--print-func-and-args frame view)
|
||||
(backtrace--print-locals frame view)))
|
||||
|
||||
(defun backtrace--print-flags (frame view)
|
||||
"Print the flags of a backtrace FRAME if enabled in VIEW."
|
||||
(let ((beg (point))
|
||||
(flag (plist-get (backtrace-frame-flags frame) :debug-on-exit))
|
||||
(source (plist-get (backtrace-frame-flags frame) :source-available)))
|
||||
(when (plist-get view :show-flags)
|
||||
(when source (insert ">"))
|
||||
(when flag (insert "*")))
|
||||
(insert (make-string (- backtrace--flags-width (- (point) beg)) ?\s))
|
||||
(put-text-property beg (point) 'backtrace-section 'func)))
|
||||
|
||||
(defun backtrace--print-func-and-args (frame _view)
|
||||
"Print the function, arguments and buffer position of a backtrace FRAME.
|
||||
Format it according to VIEW."
|
||||
(let* ((beg (point))
|
||||
(evald (backtrace-frame-evald frame))
|
||||
(fun (backtrace-frame-fun frame))
|
||||
(args (backtrace-frame-args frame))
|
||||
(def (and (symbolp fun) (fboundp fun) (symbol-function fun)))
|
||||
(fun-file (or (symbol-file fun 'defun)
|
||||
(and (subrp def)
|
||||
(not (eq 'unevalled (cdr (subr-arity def))))
|
||||
(find-lisp-object-file-name fun def))))
|
||||
(fun-pt (point)))
|
||||
(cond
|
||||
((and evald (not debugger-stack-frame-as-list))
|
||||
(if (atom fun)
|
||||
(funcall backtrace-print-function fun)
|
||||
(insert
|
||||
(backtrace--print-to-string fun (when args (/ backtrace-line-length 2)))))
|
||||
(if args
|
||||
(insert (backtrace--print-to-string
|
||||
args (max (truncate (/ backtrace-line-length 5))
|
||||
(- backtrace-line-length (- (point) beg)))))
|
||||
;; The backtrace-form property is so that backtrace-multi-line
|
||||
;; will find it. backtrace-multi-line doesn't do anything
|
||||
;; useful with it, just being consistent.
|
||||
(let ((start (point)))
|
||||
(insert "()")
|
||||
(put-text-property start (point) 'backtrace-form t))))
|
||||
(t
|
||||
(let ((fun-and-args (cons fun args)))
|
||||
(insert (backtrace--print-to-string fun-and-args)))
|
||||
(cl-incf fun-pt)))
|
||||
(when fun-file
|
||||
(make-text-button fun-pt (+ fun-pt (length (symbol-name fun)))
|
||||
:type 'help-function-def
|
||||
'help-args (list fun fun-file)))
|
||||
;; After any frame that uses eval-buffer, insert a comment that
|
||||
;; states the buffer position it's reading at.
|
||||
(when (backtrace-frame-pos frame)
|
||||
(insert " ; Reading at ")
|
||||
(let ((pos (point)))
|
||||
(insert (format "buffer position %d" (backtrace-frame-pos frame)))
|
||||
(make-button pos (point) :type 'backtrace-buffer-pos
|
||||
'backtrace-buffer (backtrace-frame-buffer frame)
|
||||
'backtrace-pos (backtrace-frame-pos frame))))
|
||||
(insert "\n")
|
||||
(put-text-property beg (point) 'backtrace-section 'func)))
|
||||
|
||||
(defun backtrace--print-locals (frame view)
|
||||
"Print a backtrace FRAME's local variables according to VIEW.
|
||||
Print them only if :show-locals is non-nil in the VIEW plist."
|
||||
(when (plist-get view :show-locals)
|
||||
(let* ((beg (point))
|
||||
(locals (backtrace-frame-locals frame)))
|
||||
(if (null locals)
|
||||
(insert " [no locals]\n")
|
||||
(pcase-dolist (`(,symbol . ,value) locals)
|
||||
(insert " ")
|
||||
(backtrace--print symbol)
|
||||
(insert " = ")
|
||||
(insert (backtrace--print-to-string value))
|
||||
(insert "\n")))
|
||||
(put-text-property beg (point) 'backtrace-section 'locals))))
|
||||
|
||||
(defun backtrace--print (obj &optional stream)
|
||||
"Attempt to print OBJ to STREAM using `backtrace-print-function'.
|
||||
Fall back to `prin1' if there is an error."
|
||||
(condition-case err
|
||||
(funcall backtrace-print-function obj stream)
|
||||
(error
|
||||
(message "Error in backtrace printer: %S" err)
|
||||
(prin1 obj stream))))
|
||||
|
||||
(defun backtrace-update-flags ()
|
||||
"Update the display of the flags in the backtrace frame at point."
|
||||
(let ((view (backtrace-get-view))
|
||||
(begin (backtrace-get-frame-start)))
|
||||
(when (plist-get view :show-flags)
|
||||
(save-excursion
|
||||
(goto-char begin)
|
||||
(let ((props (backtrace-get-text-properties begin))
|
||||
(inhibit-read-only t)
|
||||
(standard-output (current-buffer)))
|
||||
(delete-char backtrace--flags-width)
|
||||
(backtrace--print-flags (nth (backtrace-get-index) backtrace-frames)
|
||||
view)
|
||||
(add-text-properties begin (point) props))))))
|
||||
|
||||
(defun backtrace--filter-visible (beg end &optional _delete)
|
||||
"Return the visible text between BEG and END."
|
||||
(let ((result ""))
|
||||
(while (< beg end)
|
||||
(let ((next (next-single-char-property-change beg 'invisible)))
|
||||
(unless (get-char-property beg 'invisible)
|
||||
(setq result (concat result (buffer-substring beg (min end next)))))
|
||||
(setq beg next)))
|
||||
result))
|
||||
|
||||
;;; The mode definition
|
||||
|
||||
(define-derived-mode backtrace-mode special-mode "Backtrace"
|
||||
"Generic major mode for examining an Elisp stack backtrace.
|
||||
This mode can be used directly, or other major modes can be
|
||||
derived from it, using `define-derived-mode'.
|
||||
|
||||
In this major mode, the buffer contains some optional lines of
|
||||
header text followed by backtrace frames, each consisting of one
|
||||
or more whole lines.
|
||||
|
||||
Letters in this mode do not insert themselves; instead they are
|
||||
commands.
|
||||
\\<backtrace-mode-map>
|
||||
\\{backtrace-mode-map}
|
||||
|
||||
A mode which inherits from Backtrace mode, or a command which
|
||||
creates a backtrace-mode buffer, should usually do the following:
|
||||
|
||||
- Set `backtrace-revert-hook', if the buffer contents need
|
||||
to be specially recomputed prior to `revert-buffer'.
|
||||
- Maybe set `backtrace-insert-header-function' to a function to create
|
||||
header text for the buffer.
|
||||
- Set `backtrace-frames' (see below).
|
||||
- Maybe modify `backtrace-view' (see below).
|
||||
- Maybe set `backtrace-print-function'.
|
||||
|
||||
A command which creates or switches to a Backtrace mode buffer,
|
||||
such as `ert-results-pop-to-backtrace-for-test-at-point', should
|
||||
initialize `backtrace-frames' to a list of `backtrace-frame'
|
||||
objects (`backtrace-get-frames' is provided for that purpose, if
|
||||
desired), and may optionally modify `backtrace-view', which is a
|
||||
plist describing the appearance of the backtrace. Finally, it
|
||||
should call `backtrace-print'.
|
||||
|
||||
`backtrace-print' calls `backtrace-insert-header-function'
|
||||
followed by `backtrace-print-frame', once for each stack frame."
|
||||
:syntax-table emacs-lisp-mode-syntax-table
|
||||
(when backtrace-fontify
|
||||
(setq font-lock-defaults
|
||||
'((backtrace-font-lock-keywords
|
||||
backtrace-font-lock-keywords-1
|
||||
backtrace-font-lock-keywords-2)
|
||||
nil nil nil nil
|
||||
(font-lock-syntactic-face-function
|
||||
. lisp-font-lock-syntactic-face-function))))
|
||||
(setq truncate-lines t)
|
||||
(buffer-disable-undo)
|
||||
;; In debug.el, from 1998 to 2009 this was set to nil, reason stated
|
||||
;; was because of bytecode. Since 2009 it's been set to t, but the
|
||||
;; default is t so I think this isn't necessary.
|
||||
;; (set-buffer-multibyte t)
|
||||
(setq-local revert-buffer-function #'backtrace-revert)
|
||||
(setq-local filter-buffer-substring-function #'backtrace--filter-visible)
|
||||
(setq-local indent-line-function 'lisp-indent-line)
|
||||
(setq-local indent-region-function 'lisp-indent-region)
|
||||
(add-hook 'xref-backend-functions #'backtrace--xref-backend nil t))
|
||||
|
||||
(put 'backtrace-mode 'mode-class 'special)
|
||||
|
||||
;;; Backtrace printing
|
||||
|
||||
;;;###autoload
|
||||
(defun backtrace ()
|
||||
"Print a trace of Lisp function calls currently active.
|
||||
Output stream used is value of `standard-output'."
|
||||
(princ (backtrace-to-string (backtrace-get-frames 'backtrace)))
|
||||
nil)
|
||||
|
||||
(defun backtrace-to-string(&optional frames)
|
||||
"Format FRAMES, a list of `backtrace-frame' objects, for output.
|
||||
Return the result as a string. If FRAMES is nil, use all
|
||||
function calls currently active."
|
||||
(unless frames (setq frames (backtrace-get-frames 'backtrace-to-string)))
|
||||
(let ((backtrace-fontify nil))
|
||||
(with-temp-buffer
|
||||
(backtrace-mode)
|
||||
(setq backtrace-view '(:show-flags t)
|
||||
backtrace-frames frames
|
||||
backtrace-print-function #'cl-prin1)
|
||||
(backtrace-print)
|
||||
(substring-no-properties (filter-buffer-substring (point-min)
|
||||
(point-max))))))
|
||||
|
||||
(provide 'backtrace)
|
||||
|
||||
;;; backtrace.el ends here
|
|
@ -2083,10 +2083,7 @@ This is like `cl-flet', but for macros instead of functions.
|
|||
|
||||
\(fn ((NAME ARGLIST BODY...) ...) FORM...)"
|
||||
(declare (indent 1)
|
||||
(debug
|
||||
((&rest (&define name (&rest arg) cl-declarations-or-string
|
||||
def-body))
|
||||
cl-declarations body)))
|
||||
(debug (cl-macrolet-expr)))
|
||||
(if (cdr bindings)
|
||||
`(cl-macrolet (,(car bindings)) (cl-macrolet ,(cdr bindings) ,@body))
|
||||
(if (null bindings) (macroexp-progn body)
|
||||
|
|
|
@ -55,10 +55,19 @@ call other entry points instead, such as `cl-prin1'."
|
|||
;; we should only use it for objects which don't have nesting.
|
||||
(prin1 object stream))
|
||||
|
||||
(cl-defgeneric cl-print-object-contents (_object _start _stream)
|
||||
"Dispatcher to print the contents of OBJECT on STREAM.
|
||||
Print the contents starting with the item at START, without
|
||||
delimiters."
|
||||
;; Every cl-print-object method which can print an ellipsis should
|
||||
;; have a matching cl-print-object-contents method to expand an
|
||||
;; ellipsis.
|
||||
(error "Missing cl-print-object-contents method"))
|
||||
|
||||
(cl-defmethod cl-print-object ((object cons) stream)
|
||||
(if (and cl-print--depth (natnump print-level)
|
||||
(> cl-print--depth print-level))
|
||||
(princ "..." stream)
|
||||
(cl-print-insert-ellipsis object 0 stream)
|
||||
(let ((car (pop object))
|
||||
(count 1))
|
||||
(if (and print-quoted
|
||||
|
@ -84,23 +93,60 @@ call other entry points instead, such as `cl-prin1'."
|
|||
(princ " " stream)
|
||||
(if (or (not (natnump print-length)) (> print-length count))
|
||||
(cl-print-object (pop object) stream)
|
||||
(princ "..." stream)
|
||||
(cl-print-insert-ellipsis object print-length stream)
|
||||
(setq object nil))
|
||||
(cl-incf count))
|
||||
(when object
|
||||
(princ " . " stream) (cl-print-object object stream))
|
||||
(princ ")" stream)))))
|
||||
|
||||
(cl-defmethod cl-print-object-contents ((object cons) _start stream)
|
||||
(let ((count 0))
|
||||
(while (and (consp object)
|
||||
(not (cond
|
||||
(cl-print--number-table
|
||||
(numberp (gethash object cl-print--number-table)))
|
||||
((memq object cl-print--currently-printing))
|
||||
(t (push object cl-print--currently-printing)
|
||||
nil))))
|
||||
(unless (zerop count)
|
||||
(princ " " stream))
|
||||
(if (or (not (natnump print-length)) (> print-length count))
|
||||
(cl-print-object (pop object) stream)
|
||||
(cl-print-insert-ellipsis object print-length stream)
|
||||
(setq object nil))
|
||||
(cl-incf count))
|
||||
(when object
|
||||
(princ " . " stream) (cl-print-object object stream))))
|
||||
|
||||
(cl-defmethod cl-print-object ((object vector) stream)
|
||||
(princ "[" stream)
|
||||
(let ((count (length object)))
|
||||
(dotimes (i (if (natnump print-length)
|
||||
(min print-length count) count))
|
||||
(unless (zerop i) (princ " " stream))
|
||||
(cl-print-object (aref object i) stream))
|
||||
(when (and (natnump print-length) (< print-length count))
|
||||
(princ " ..." stream)))
|
||||
(princ "]" stream))
|
||||
(if (and cl-print--depth (natnump print-level)
|
||||
(> cl-print--depth print-level))
|
||||
(cl-print-insert-ellipsis object 0 stream)
|
||||
(princ "[" stream)
|
||||
(let* ((len (length object))
|
||||
(limit (if (natnump print-length)
|
||||
(min print-length len) len)))
|
||||
(dotimes (i limit)
|
||||
(unless (zerop i) (princ " " stream))
|
||||
(cl-print-object (aref object i) stream))
|
||||
(when (< limit len)
|
||||
(princ " " stream)
|
||||
(cl-print-insert-ellipsis object limit stream)))
|
||||
(princ "]" stream)))
|
||||
|
||||
(cl-defmethod cl-print-object-contents ((object vector) start stream)
|
||||
(let* ((len (length object))
|
||||
(limit (if (natnump print-length)
|
||||
(min (+ start print-length) len) len))
|
||||
(i start))
|
||||
(while (< i limit)
|
||||
(unless (= i start) (princ " " stream))
|
||||
(cl-print-object (aref object i) stream)
|
||||
(cl-incf i))
|
||||
(when (< limit len)
|
||||
(princ " " stream)
|
||||
(cl-print-insert-ellipsis object limit stream))))
|
||||
|
||||
(cl-defmethod cl-print-object ((object hash-table) stream)
|
||||
(princ "#<hash-table " stream)
|
||||
|
@ -109,7 +155,7 @@ call other entry points instead, such as `cl-prin1'."
|
|||
(princ (hash-table-count object) stream)
|
||||
(princ "/" stream)
|
||||
(princ (hash-table-size object) stream)
|
||||
(princ (format " 0x%x" (sxhash object)) stream)
|
||||
(princ (format " %#x" (sxhash object)) stream)
|
||||
(princ ">" stream))
|
||||
|
||||
(define-button-type 'help-byte-code
|
||||
|
@ -166,7 +212,7 @@ into a button whose action shows the function's disassembly.")
|
|||
(let ((button-start (and cl-print-compiled-button
|
||||
(bufferp stream)
|
||||
(with-current-buffer stream (point)))))
|
||||
(princ (format "#<bytecode 0x%x>" (sxhash object)) stream)
|
||||
(princ (format "#<bytecode %#x>" (sxhash object)) stream)
|
||||
(when (eq cl-print-compiled 'static)
|
||||
(princ " " stream)
|
||||
(cl-print-object (aref object 2) stream))
|
||||
|
@ -199,21 +245,135 @@ into a button whose action shows the function's disassembly.")
|
|||
(princ ")" stream)))
|
||||
|
||||
(cl-defmethod cl-print-object ((object cl-structure-object) stream)
|
||||
(princ "#s(" stream)
|
||||
(if (and cl-print--depth (natnump print-level)
|
||||
(> cl-print--depth print-level))
|
||||
(cl-print-insert-ellipsis object 0 stream)
|
||||
(princ "#s(" stream)
|
||||
(let* ((class (cl-find-class (type-of object)))
|
||||
(slots (cl--struct-class-slots class))
|
||||
(len (length slots))
|
||||
(limit (if (natnump print-length)
|
||||
(min print-length len) len)))
|
||||
(princ (cl--struct-class-name class) stream)
|
||||
(dotimes (i limit)
|
||||
(let ((slot (aref slots i)))
|
||||
(princ " :" stream)
|
||||
(princ (cl--slot-descriptor-name slot) stream)
|
||||
(princ " " stream)
|
||||
(cl-print-object (aref object (1+ i)) stream)))
|
||||
(when (< limit len)
|
||||
(princ " " stream)
|
||||
(cl-print-insert-ellipsis object limit stream)))
|
||||
(princ ")" stream)))
|
||||
|
||||
(cl-defmethod cl-print-object-contents ((object cl-structure-object) start stream)
|
||||
(let* ((class (cl-find-class (type-of object)))
|
||||
(slots (cl--struct-class-slots class))
|
||||
(count (length slots)))
|
||||
(princ (cl--struct-class-name class) stream)
|
||||
(dotimes (i (if (natnump print-length)
|
||||
(min print-length count) count))
|
||||
(len (length slots))
|
||||
(limit (if (natnump print-length)
|
||||
(min (+ start print-length) len) len))
|
||||
(i start))
|
||||
(while (< i limit)
|
||||
(let ((slot (aref slots i)))
|
||||
(princ " :" stream)
|
||||
(unless (= i start) (princ " " stream))
|
||||
(princ ":" stream)
|
||||
(princ (cl--slot-descriptor-name slot) stream)
|
||||
(princ " " stream)
|
||||
(cl-print-object (aref object (1+ i)) stream)))
|
||||
(when (and (natnump print-length) (< print-length count))
|
||||
(princ " ..." stream)))
|
||||
(princ ")" stream))
|
||||
(cl-print-object (aref object (1+ i)) stream))
|
||||
(cl-incf i))
|
||||
(when (< limit len)
|
||||
(princ " " stream)
|
||||
(cl-print-insert-ellipsis object limit stream))))
|
||||
|
||||
(cl-defmethod cl-print-object ((object string) stream)
|
||||
(unless stream (setq stream standard-output))
|
||||
(let* ((has-properties (or (text-properties-at 0 object)
|
||||
(next-property-change 0 object)))
|
||||
(len (length object))
|
||||
(limit (if (natnump print-length) (min print-length len) len)))
|
||||
(if (and has-properties
|
||||
cl-print--depth
|
||||
(natnump print-level)
|
||||
(> cl-print--depth print-level))
|
||||
(cl-print-insert-ellipsis object 0 stream)
|
||||
;; Print all or part of the string
|
||||
(when has-properties
|
||||
(princ "#(" stream))
|
||||
(if (= limit len)
|
||||
(prin1 (if has-properties (substring-no-properties object) object)
|
||||
stream)
|
||||
(let ((part (concat (substring-no-properties object 0 limit) "...")))
|
||||
(prin1 part stream)
|
||||
(when (bufferp stream)
|
||||
(with-current-buffer stream
|
||||
(cl-print-propertize-ellipsis object limit
|
||||
(- (point) 4)
|
||||
(- (point) 1) stream)))))
|
||||
;; Print the property list.
|
||||
(when has-properties
|
||||
(let* ((interval-limit (and (natnump print-length)
|
||||
(max 1 (/ print-length 3))))
|
||||
(interval-count 0)
|
||||
(start-pos (if (text-properties-at 0 object)
|
||||
0 (next-property-change 0 object)))
|
||||
(end-pos (next-property-change start-pos object len)))
|
||||
(while (and (or (null interval-limit)
|
||||
(< interval-count interval-limit))
|
||||
(< start-pos len))
|
||||
(let ((props (text-properties-at start-pos object)))
|
||||
(when props
|
||||
(princ " " stream) (princ start-pos stream)
|
||||
(princ " " stream) (princ end-pos stream)
|
||||
(princ " " stream) (cl-print-object props stream)
|
||||
(cl-incf interval-count))
|
||||
(setq start-pos end-pos
|
||||
end-pos (next-property-change start-pos object len))))
|
||||
(when (< start-pos len)
|
||||
(princ " " stream)
|
||||
(cl-print-insert-ellipsis object (list start-pos) stream)))
|
||||
(princ ")" stream)))))
|
||||
|
||||
(cl-defmethod cl-print-object-contents ((object string) start stream)
|
||||
;; If START is an integer, it is an index into the string, and the
|
||||
;; ellipsis that needs to be expanded is part of the string. If
|
||||
;; START is a cons, its car is an index into the string, and the
|
||||
;; ellipsis that needs to be expanded is in the property list.
|
||||
(let* ((len (length object)))
|
||||
(if (atom start)
|
||||
;; Print part of the string.
|
||||
(let* ((limit (if (natnump print-length)
|
||||
(min (+ start print-length) len) len))
|
||||
(substr (substring-no-properties object start limit))
|
||||
(printed (prin1-to-string substr))
|
||||
(trimmed (substring printed 1 (1- (length printed)))))
|
||||
(princ trimmed)
|
||||
(when (< limit len)
|
||||
(cl-print-insert-ellipsis object limit stream)))
|
||||
|
||||
;; Print part of the property list.
|
||||
(let* ((first t)
|
||||
(interval-limit (and (natnump print-length)
|
||||
(max 1 (/ print-length 3))))
|
||||
(interval-count 0)
|
||||
(start-pos (car start))
|
||||
(end-pos (next-property-change start-pos object len)))
|
||||
(while (and (or (null interval-limit)
|
||||
(< interval-count interval-limit))
|
||||
(< start-pos len))
|
||||
(let ((props (text-properties-at start-pos object)))
|
||||
(when props
|
||||
(if first
|
||||
(setq first nil)
|
||||
(princ " " stream))
|
||||
(princ start-pos stream)
|
||||
(princ " " stream) (princ end-pos stream)
|
||||
(princ " " stream) (cl-print-object props stream)
|
||||
(cl-incf interval-count))
|
||||
(setq start-pos end-pos
|
||||
end-pos (next-property-change start-pos object len))))
|
||||
(when (< start-pos len)
|
||||
(princ " " stream)
|
||||
(cl-print-insert-ellipsis object (list start-pos) stream))))))
|
||||
|
||||
;;; Circularity and sharing.
|
||||
|
||||
|
@ -275,8 +435,17 @@ into a button whose action shows the function's disassembly.")
|
|||
(push cdr stack)
|
||||
(push car stack))
|
||||
((pred stringp)
|
||||
;; We presumably won't print its text-properties.
|
||||
nil)
|
||||
(let* ((len (length object))
|
||||
(start (if (text-properties-at 0 object)
|
||||
0 (next-property-change 0 object)))
|
||||
(end (and start
|
||||
(next-property-change start object len))))
|
||||
(while (and start (< start len))
|
||||
(let ((props (text-properties-at start object)))
|
||||
(when props
|
||||
(push props stack))
|
||||
(setq start end
|
||||
end (next-property-change start object len))))))
|
||||
((or (pred arrayp) (pred byte-code-function-p))
|
||||
;; FIXME: Inefficient for char-tables!
|
||||
(dotimes (i (length object))
|
||||
|
@ -291,6 +460,48 @@ into a button whose action shows the function's disassembly.")
|
|||
(cl-print--find-sharing object print-number-table)))
|
||||
print-number-table))
|
||||
|
||||
(defun cl-print-insert-ellipsis (object start stream)
|
||||
"Print \"...\" to STREAM with the `cl-print-ellipsis' text property.
|
||||
Save state in the text property in order to print the elided part
|
||||
of OBJECT later. START should be 0 if the whole OBJECT is being
|
||||
elided, otherwise it should be an index or other pointer into the
|
||||
internals of OBJECT which can be passed to
|
||||
`cl-print-object-contents' at a future time."
|
||||
(unless stream (setq stream standard-output))
|
||||
(let ((ellipsis-start (and (bufferp stream)
|
||||
(with-current-buffer stream (point)))))
|
||||
(princ "..." stream)
|
||||
(when ellipsis-start
|
||||
(with-current-buffer stream
|
||||
(cl-print-propertize-ellipsis object start ellipsis-start (point)
|
||||
stream)))))
|
||||
|
||||
(defun cl-print-propertize-ellipsis (object start beg end stream)
|
||||
"Add the `cl-print-ellipsis' property between BEG and END.
|
||||
STREAM should be a buffer. OBJECT and START are as described in
|
||||
`cl-print-insert-ellipsis'."
|
||||
(let ((value (list object start cl-print--number-table
|
||||
cl-print--currently-printing)))
|
||||
(with-current-buffer stream
|
||||
(put-text-property beg end 'cl-print-ellipsis value stream))))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-print-expand-ellipsis (value stream)
|
||||
"Print the expansion of an ellipsis to STREAM.
|
||||
VALUE should be the value of the `cl-print-ellipsis' text property
|
||||
which was attached to the ellipsis by `cl-prin1'."
|
||||
(let ((cl-print--depth 1)
|
||||
(object (nth 0 value))
|
||||
(start (nth 1 value))
|
||||
(cl-print--number-table (nth 2 value))
|
||||
(print-number-table (nth 2 value))
|
||||
(cl-print--currently-printing (nth 3 value)))
|
||||
(when (eq object (car cl-print--currently-printing))
|
||||
(pop cl-print--currently-printing))
|
||||
(if (equal start 0)
|
||||
(cl-print-object object stream)
|
||||
(cl-print-object-contents object start stream))))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-prin1 (object &optional stream)
|
||||
"Print OBJECT on STREAM according to its type.
|
||||
|
@ -313,5 +524,45 @@ node `(elisp)Output Variables'."
|
|||
(cl-prin1 object (current-buffer))
|
||||
(buffer-string)))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-print-to-string-with-limit (print-function value limit)
|
||||
"Return a string containing a printed representation of VALUE.
|
||||
Attempt to get the length of the returned string under LIMIT
|
||||
characters with appropriate settings of `print-level' and
|
||||
`print-length.' Use PRINT-FUNCTION to print, which should take
|
||||
the arguments VALUE and STREAM and which should respect
|
||||
`print-length' and `print-level'. LIMIT may be nil or zero in
|
||||
which case PRINT-FUNCTION will be called with `print-level' and
|
||||
`print-length' bound to nil.
|
||||
|
||||
Use this function with `cl-prin1' to print an object,
|
||||
abbreviating it with ellipses to fit within a size limit. Use
|
||||
this function with `cl-prin1-expand-ellipsis' to expand an
|
||||
ellipsis, abbreviating the expansion to stay within a size
|
||||
limit."
|
||||
(setq limit (and (natnump limit)
|
||||
(not (zerop limit))
|
||||
limit))
|
||||
;; Since this is used by the debugger when stack space may be
|
||||
;; limited, if you increase print-level here, add more depth in
|
||||
;; call_debugger (bug#31919).
|
||||
(let* ((print-length (when limit (min limit 50)))
|
||||
(print-level (when limit (min 8 (truncate (log limit)))))
|
||||
(delta (when limit
|
||||
(max 1 (truncate (/ print-length print-level))))))
|
||||
(with-temp-buffer
|
||||
(catch 'done
|
||||
(while t
|
||||
(erase-buffer)
|
||||
(funcall print-function value (current-buffer))
|
||||
;; Stop when either print-level is too low or the value is
|
||||
;; successfully printed in the space allowed.
|
||||
(when (or (not limit)
|
||||
(< (- (point-max) (point-min)) limit)
|
||||
(= print-level 2))
|
||||
(throw 'done (buffer-string)))
|
||||
(cl-decf print-level)
|
||||
(cl-decf print-length delta))))))
|
||||
|
||||
(provide 'cl-print)
|
||||
;;; cl-print.el ends here
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'backtrace)
|
||||
(require 'button)
|
||||
|
||||
(defgroup debugger nil
|
||||
|
@ -133,6 +134,25 @@ where CAUSE can be:
|
|||
- exit: called because of exit of a flagged function.
|
||||
- error: called because of `debug-on-error'.")
|
||||
|
||||
(cl-defstruct (debugger--buffer-state
|
||||
(:constructor debugger--save-buffer-state
|
||||
(&aux (mode major-mode)
|
||||
(header backtrace-insert-header-function)
|
||||
(frames backtrace-frames)
|
||||
(content (buffer-string))
|
||||
(pos (point)))))
|
||||
mode header frames content pos)
|
||||
|
||||
(defun debugger--restore-buffer-state (state)
|
||||
(unless (derived-mode-p (debugger--buffer-state-mode state))
|
||||
(funcall (debugger--buffer-state-mode state)))
|
||||
(setq backtrace-insert-header-function (debugger--buffer-state-header state)
|
||||
backtrace-frames (debugger--buffer-state-frames state))
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(insert (debugger--buffer-state-content state)))
|
||||
(goto-char (debugger--buffer-state-pos state)))
|
||||
|
||||
;;;###autoload
|
||||
(setq debugger 'debug)
|
||||
;;;###autoload
|
||||
|
@ -174,7 +194,7 @@ first will be printed into the backtrace buffer."
|
|||
(debugger-previous-state
|
||||
(if (get-buffer "*Backtrace*")
|
||||
(with-current-buffer (get-buffer "*Backtrace*")
|
||||
(list major-mode (buffer-string)))))
|
||||
(debugger--save-buffer-state))))
|
||||
(debugger-args args)
|
||||
(debugger-buffer (get-buffer-create "*Backtrace*"))
|
||||
(debugger-old-buffer (current-buffer))
|
||||
|
@ -236,7 +256,8 @@ first will be printed into the backtrace buffer."
|
|||
(window-total-height debugger-window)))
|
||||
(error nil)))
|
||||
(setq debugger-previous-window debugger-window))
|
||||
(debugger-mode)
|
||||
(unless (derived-mode-p 'debugger-mode)
|
||||
(debugger-mode))
|
||||
(debugger-setup-buffer debugger-args)
|
||||
(when noninteractive
|
||||
;; If the backtrace is long, save the beginning
|
||||
|
@ -280,15 +301,14 @@ first will be printed into the backtrace buffer."
|
|||
(setq debugger-previous-window nil))
|
||||
;; Restore previous state of debugger-buffer in case we were
|
||||
;; in a recursive invocation of the debugger, otherwise just
|
||||
;; erase the buffer and put it into fundamental mode.
|
||||
;; erase the buffer.
|
||||
(when (buffer-live-p debugger-buffer)
|
||||
(with-current-buffer debugger-buffer
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(if (null debugger-previous-state)
|
||||
(fundamental-mode)
|
||||
(insert (nth 1 debugger-previous-state))
|
||||
(funcall (nth 0 debugger-previous-state))))))
|
||||
(if debugger-previous-state
|
||||
(debugger--restore-buffer-state debugger-previous-state)
|
||||
(setq backtrace-insert-header-function nil)
|
||||
(setq backtrace-frames nil)
|
||||
(backtrace-print))))
|
||||
(with-timeout-unsuspend debugger-with-timeout-suspend)
|
||||
(set-match-data debugger-outer-match-data)))
|
||||
(setq debug-on-next-call debugger-step-after-exit)
|
||||
|
@ -301,112 +321,80 @@ first will be printed into the backtrace buffer."
|
|||
(message "Error in debug printer: %S" err)
|
||||
(prin1 obj stream))))
|
||||
|
||||
(defun debugger-insert-backtrace (frames do-xrefs)
|
||||
"Format and insert the backtrace FRAMES at point.
|
||||
Make functions into cross-reference buttons if DO-XREFS is non-nil."
|
||||
(let ((standard-output (current-buffer))
|
||||
(eval-buffers eval-buffer-list))
|
||||
(require 'help-mode) ; Define `help-function-def' button type.
|
||||
(pcase-dolist (`(,evald ,fun ,args ,flags) frames)
|
||||
(insert (if (plist-get flags :debug-on-exit)
|
||||
"* " " "))
|
||||
(let ((fun-file (and do-xrefs (symbol-file fun 'defun)))
|
||||
(fun-pt (point)))
|
||||
(cond
|
||||
((and evald (not debugger-stack-frame-as-list))
|
||||
(debugger--print fun)
|
||||
(if args (debugger--print args) (princ "()")))
|
||||
(t
|
||||
(debugger--print (cons fun args))
|
||||
(cl-incf fun-pt)))
|
||||
(when fun-file
|
||||
(make-text-button fun-pt (+ fun-pt (length (symbol-name fun)))
|
||||
:type 'help-function-def
|
||||
'help-args (list fun fun-file))))
|
||||
;; After any frame that uses eval-buffer, insert a line that
|
||||
;; states the buffer position it's reading at.
|
||||
(when (and eval-buffers (memq fun '(eval-buffer eval-region)))
|
||||
(insert (format " ; Reading at buffer position %d"
|
||||
;; This will get the wrong result if there are
|
||||
;; two nested eval-region calls for the same
|
||||
;; buffer. That's not a very useful case.
|
||||
(with-current-buffer (pop eval-buffers)
|
||||
(point)))))
|
||||
(insert "\n"))))
|
||||
|
||||
(defun debugger-setup-buffer (args)
|
||||
"Initialize the `*Backtrace*' buffer for entry to the debugger.
|
||||
That buffer should be current already."
|
||||
(setq buffer-read-only nil)
|
||||
(erase-buffer)
|
||||
(set-buffer-multibyte t) ;Why was it nil ? -stef
|
||||
(setq buffer-undo-list t)
|
||||
That buffer should be current already and in debugger-mode."
|
||||
(setq backtrace-frames (nthcdr
|
||||
;; Remove debug--implement-debug-on-entry and the
|
||||
;; advice's `apply' frame.
|
||||
(if (eq (car args) 'debug) 3 1)
|
||||
(backtrace-get-frames 'debug)))
|
||||
(when (eq (car-safe args) 'exit)
|
||||
(setq debugger-value (nth 1 args))
|
||||
(setf (cl-getf (backtrace-frame-flags (car backtrace-frames))
|
||||
:debug-on-exit)
|
||||
nil))
|
||||
|
||||
(setq backtrace-view (plist-put backtrace-view :show-flags t)
|
||||
backtrace-insert-header-function (lambda ()
|
||||
(debugger--insert-header args))
|
||||
backtrace-print-function debugger-print-function)
|
||||
(backtrace-print)
|
||||
;; Place point on "stack frame 0" (bug#15101).
|
||||
(goto-char (point-min))
|
||||
(search-forward ":" (line-end-position) t)
|
||||
(when (and (< (point) (line-end-position))
|
||||
(= (char-after) ?\s))
|
||||
(forward-char)))
|
||||
|
||||
(defun debugger--insert-header (args)
|
||||
"Insert the header for the debugger's Backtrace buffer.
|
||||
Include the reason for debugger entry from ARGS."
|
||||
(insert "Debugger entered")
|
||||
(let ((frames (nthcdr
|
||||
;; Remove debug--implement-debug-on-entry and the
|
||||
;; advice's `apply' frame.
|
||||
(if (eq (car args) 'debug) 3 1)
|
||||
(backtrace-frames 'debug)))
|
||||
(print-escape-newlines t)
|
||||
(print-escape-control-characters t)
|
||||
;; If you increase print-level, add more depth in call_debugger.
|
||||
(print-level 8)
|
||||
(print-length 50)
|
||||
(pos (point)))
|
||||
(pcase (car args)
|
||||
;; lambda is for debug-on-call when a function call is next.
|
||||
;; debug is for debug-on-entry function called.
|
||||
((or `lambda `debug)
|
||||
(insert "--entering a function:\n")
|
||||
(setq pos (1- (point))))
|
||||
;; Exiting a function.
|
||||
(`exit
|
||||
(insert "--returning value: ")
|
||||
(setq pos (point))
|
||||
(setq debugger-value (nth 1 args))
|
||||
(debugger--print debugger-value (current-buffer))
|
||||
(setf (cl-getf (nth 3 (car frames)) :debug-on-exit) nil)
|
||||
(insert ?\n))
|
||||
;; Watchpoint triggered.
|
||||
((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args)))
|
||||
(insert
|
||||
"--"
|
||||
(pcase details
|
||||
(`(makunbound nil) (format "making %s void" symbol))
|
||||
(`(makunbound ,buffer) (format "killing local value of %s in buffer %s"
|
||||
symbol buffer))
|
||||
(`(defvaralias ,_) (format "aliasing %s to %s" symbol newval))
|
||||
(`(let ,_) (format "let-binding %s to %S" symbol newval))
|
||||
(`(unlet ,_) (format "ending let-binding of %s" symbol))
|
||||
(`(set nil) (format "setting %s to %S" symbol newval))
|
||||
(`(set ,buffer) (format "setting %s in buffer %s to %S"
|
||||
symbol buffer newval))
|
||||
(_ (error "unrecognized watchpoint triggered %S" (cdr args))))
|
||||
": ")
|
||||
(setq pos (point))
|
||||
(insert ?\n))
|
||||
;; Debugger entered for an error.
|
||||
(`error
|
||||
(insert "--Lisp error: ")
|
||||
(setq pos (point))
|
||||
(debugger--print (nth 1 args) (current-buffer))
|
||||
(insert ?\n))
|
||||
;; debug-on-call, when the next thing is an eval.
|
||||
(`t
|
||||
(insert "--beginning evaluation of function call form:\n")
|
||||
(setq pos (1- (point))))
|
||||
;; User calls debug directly.
|
||||
(_
|
||||
(insert ": ")
|
||||
(setq pos (point))
|
||||
(debugger--print
|
||||
(if (eq (car args) 'nil)
|
||||
(cdr args) args)
|
||||
(current-buffer))
|
||||
(insert ?\n)))
|
||||
(debugger-insert-backtrace frames t)
|
||||
;; Place point on "stack frame 0" (bug#15101).
|
||||
(goto-char pos)))
|
||||
(pcase (car args)
|
||||
;; lambda is for debug-on-call when a function call is next.
|
||||
;; debug is for debug-on-entry function called.
|
||||
((or `lambda `debug)
|
||||
(insert "--entering a function:\n"))
|
||||
;; Exiting a function.
|
||||
(`exit
|
||||
(insert "--returning value: ")
|
||||
(insert (backtrace-print-to-string debugger-value))
|
||||
(insert ?\n))
|
||||
;; Watchpoint triggered.
|
||||
((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args)))
|
||||
(insert
|
||||
"--"
|
||||
(pcase details
|
||||
(`(makunbound nil) (format "making %s void" symbol))
|
||||
(`(makunbound ,buffer) (format "killing local value of %s in buffer %s"
|
||||
symbol buffer))
|
||||
(`(defvaralias ,_) (format "aliasing %s to %s" symbol newval))
|
||||
(`(let ,_) (format "let-binding %s to %s" symbol
|
||||
(backtrace-print-to-string newval)))
|
||||
(`(unlet ,_) (format "ending let-binding of %s" symbol))
|
||||
(`(set nil) (format "setting %s to %s" symbol
|
||||
(backtrace-print-to-string newval)))
|
||||
(`(set ,buffer) (format "setting %s in buffer %s to %s"
|
||||
symbol buffer
|
||||
(backtrace-print-to-string newval)))
|
||||
(_ (error "unrecognized watchpoint triggered %S" (cdr args))))
|
||||
": ")
|
||||
(insert ?\n))
|
||||
;; Debugger entered for an error.
|
||||
(`error
|
||||
(insert "--Lisp error: ")
|
||||
(insert (backtrace-print-to-string (nth 1 args)))
|
||||
(insert ?\n))
|
||||
;; debug-on-call, when the next thing is an eval.
|
||||
(`t
|
||||
(insert "--beginning evaluation of function call form:\n"))
|
||||
;; User calls debug directly.
|
||||
(_
|
||||
(insert ": ")
|
||||
(insert (backtrace-print-to-string (if (eq (car args) 'nil)
|
||||
(cdr args) args)))
|
||||
(insert ?\n))))
|
||||
|
||||
|
||||
(defun debugger-step-through ()
|
||||
|
@ -426,12 +414,12 @@ Enter another debugger on next entry to eval, apply or funcall."
|
|||
(unless debugger-may-continue
|
||||
(error "Cannot continue"))
|
||||
(message "Continuing.")
|
||||
(save-excursion
|
||||
;; Check to see if we've flagged some frame for debug-on-exit, in which
|
||||
;; case we'll probably come back to the debugger soon.
|
||||
(goto-char (point-min))
|
||||
(if (re-search-forward "^\\* " nil t)
|
||||
(setq debugger-will-be-back t)))
|
||||
|
||||
;; Check to see if we've flagged some frame for debug-on-exit, in which
|
||||
;; case we'll probably come back to the debugger soon.
|
||||
(dolist (frame backtrace-frames)
|
||||
(when (plist-get (backtrace-frame-flags frame) :debug-on-exit)
|
||||
(setq debugger-will-be-back t)))
|
||||
(exit-recursive-edit))
|
||||
|
||||
(defun debugger-return-value (val)
|
||||
|
@ -446,12 +434,11 @@ will be used, such as in a debug on exit from a frame."
|
|||
(setq debugger-value val)
|
||||
(princ "Returning " t)
|
||||
(debugger--print debugger-value)
|
||||
(save-excursion
|
||||
;; Check to see if we've flagged some frame for debug-on-exit, in which
|
||||
;; case we'll probably come back to the debugger soon.
|
||||
(goto-char (point-min))
|
||||
(if (re-search-forward "^\\* " nil t)
|
||||
(setq debugger-will-be-back t)))
|
||||
(dolist (frame backtrace-frames)
|
||||
(when (plist-get (backtrace-frame-flags frame) :debug-on-exit)
|
||||
(setq debugger-will-be-back t)))
|
||||
(exit-recursive-edit))
|
||||
|
||||
(defun debugger-jump ()
|
||||
|
@ -473,63 +460,40 @@ removes itself from that hook."
|
|||
|
||||
(defun debugger-frame-number (&optional skip-base)
|
||||
"Return number of frames in backtrace before the one point points at."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(if (looking-at " *;;;\\|[a-z]")
|
||||
(error "This line is not a function call"))
|
||||
(let ((opoint (point))
|
||||
(count 0))
|
||||
(unless skip-base
|
||||
(let ((index (backtrace-get-index))
|
||||
(count 0))
|
||||
(unless index
|
||||
(error "This line is not a function call"))
|
||||
(unless skip-base
|
||||
(while (not (eq (cadr (backtrace-frame count)) 'debug))
|
||||
(setq count (1+ count)))
|
||||
;; Skip debug--implement-debug-on-entry frame.
|
||||
(when (eq 'debug--implement-debug-on-entry
|
||||
(cadr (backtrace-frame (1+ count))))
|
||||
(setq count (+ 2 count))))
|
||||
(goto-char (point-min))
|
||||
(when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):")
|
||||
(goto-char (match-end 0))
|
||||
(forward-sexp 1))
|
||||
(forward-line 1)
|
||||
(while (progn
|
||||
(forward-char 2)
|
||||
(cond ((debugger--locals-visible-p)
|
||||
(goto-char (next-single-char-property-change
|
||||
(point) 'locals-visible)))
|
||||
((= (following-char) ?\()
|
||||
(forward-sexp 1))
|
||||
(t
|
||||
(forward-sexp 2)))
|
||||
(forward-line 1)
|
||||
(<= (point) opoint))
|
||||
(if (looking-at " *;;;")
|
||||
(forward-line 1))
|
||||
(setq count (1+ count)))
|
||||
count)))
|
||||
(+ count index)))
|
||||
|
||||
(defun debugger-frame ()
|
||||
"Request entry to debugger when this frame exits.
|
||||
Applies to the frame whose line point is on in the backtrace."
|
||||
(interactive)
|
||||
(backtrace-debug (debugger-frame-number) t)
|
||||
(beginning-of-line)
|
||||
(if (= (following-char) ? )
|
||||
(let ((inhibit-read-only t))
|
||||
(delete-char 1)
|
||||
(insert ?*)))
|
||||
(beginning-of-line))
|
||||
(setf
|
||||
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
|
||||
:debug-on-exit)
|
||||
t)
|
||||
(backtrace-update-flags))
|
||||
|
||||
(defun debugger-frame-clear ()
|
||||
"Do not enter debugger when this frame exits.
|
||||
Applies to the frame whose line point is on in the backtrace."
|
||||
(interactive)
|
||||
(backtrace-debug (debugger-frame-number) nil)
|
||||
(beginning-of-line)
|
||||
(if (= (following-char) ?*)
|
||||
(let ((inhibit-read-only t))
|
||||
(delete-char 1)
|
||||
(insert ? )))
|
||||
(beginning-of-line))
|
||||
(setf
|
||||
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
|
||||
:debug-on-exit)
|
||||
nil)
|
||||
(backtrace-update-flags))
|
||||
|
||||
(defmacro debugger-env-macro (&rest body)
|
||||
"Run BODY in original environment."
|
||||
|
@ -564,69 +528,10 @@ The environment used is the one when entering the activation frame at point."
|
|||
(let ((str (eval-expression-print-format val)))
|
||||
(if str (princ str t))))))))
|
||||
|
||||
(defun debugger--locals-visible-p ()
|
||||
"Are the local variables of the current stack frame visible?"
|
||||
(save-excursion
|
||||
(move-to-column 2)
|
||||
(get-text-property (point) 'locals-visible)))
|
||||
|
||||
(defun debugger--insert-locals (locals)
|
||||
"Insert the local variables LOCALS at point."
|
||||
(cond ((null locals)
|
||||
(insert "\n [no locals]"))
|
||||
(t
|
||||
(let ((print-escape-newlines t))
|
||||
(dolist (s+v locals)
|
||||
(let ((symbol (car s+v))
|
||||
(value (cdr s+v)))
|
||||
(insert "\n ")
|
||||
(prin1 symbol (current-buffer))
|
||||
(insert " = ")
|
||||
(debugger--print value (current-buffer))))))))
|
||||
|
||||
(defun debugger--show-locals ()
|
||||
"For the frame at point, insert locals and add text properties."
|
||||
(let* ((nframe (1+ (debugger-frame-number 'skip-base)))
|
||||
(base (debugger--backtrace-base))
|
||||
(locals (backtrace--locals nframe base))
|
||||
(inhibit-read-only t))
|
||||
(save-excursion
|
||||
(let ((start (progn
|
||||
(move-to-column 2)
|
||||
(point))))
|
||||
(end-of-line)
|
||||
(debugger--insert-locals locals)
|
||||
(add-text-properties start (point) '(locals-visible t))))))
|
||||
|
||||
(defun debugger--hide-locals ()
|
||||
"Delete local variables and remove the text property."
|
||||
(let* ((col (current-column))
|
||||
(end (progn
|
||||
(move-to-column 2)
|
||||
(next-single-char-property-change (point) 'locals-visible)))
|
||||
(start (previous-single-char-property-change end 'locals-visible))
|
||||
(inhibit-read-only t))
|
||||
(remove-text-properties start end '(locals-visible))
|
||||
(goto-char start)
|
||||
(end-of-line)
|
||||
(delete-region (point) end)
|
||||
(move-to-column col)))
|
||||
|
||||
(defun debugger-toggle-locals ()
|
||||
"Show or hide local variables of the current stack frame."
|
||||
(interactive)
|
||||
(cond ((debugger--locals-visible-p)
|
||||
(debugger--hide-locals))
|
||||
(t
|
||||
(debugger--show-locals))))
|
||||
|
||||
|
||||
(defvar debugger-mode-map
|
||||
(let ((map (make-keymap))
|
||||
(menu-map (make-sparse-keymap)))
|
||||
(set-keymap-parent map button-buffer-map)
|
||||
(suppress-keymap map)
|
||||
(define-key map "-" 'negative-argument)
|
||||
(let ((map (make-keymap)))
|
||||
(set-keymap-parent map backtrace-mode-map)
|
||||
(define-key map "b" 'debugger-frame)
|
||||
(define-key map "c" 'debugger-continue)
|
||||
(define-key map "j" 'debugger-jump)
|
||||
|
@ -634,63 +539,47 @@ The environment used is the one when entering the activation frame at point."
|
|||
(define-key map "u" 'debugger-frame-clear)
|
||||
(define-key map "d" 'debugger-step-through)
|
||||
(define-key map "l" 'debugger-list-functions)
|
||||
(define-key map "h" 'describe-mode)
|
||||
(define-key map "q" 'top-level)
|
||||
(define-key map "q" 'debugger-quit)
|
||||
(define-key map "e" 'debugger-eval-expression)
|
||||
(define-key map "v" 'debugger-toggle-locals) ; "v" is for "variables".
|
||||
(define-key map " " 'next-line)
|
||||
(define-key map "R" 'debugger-record-expression)
|
||||
(define-key map "\C-m" 'debug-help-follow)
|
||||
(define-key map [mouse-2] 'push-button)
|
||||
(define-key map [menu-bar debugger] (cons "Debugger" menu-map))
|
||||
(define-key menu-map [deb-top]
|
||||
'(menu-item "Quit" top-level
|
||||
:help "Quit debugging and return to top level"))
|
||||
(define-key menu-map [deb-s0] '("--"))
|
||||
(define-key menu-map [deb-descr]
|
||||
'(menu-item "Describe Debugger Mode" describe-mode
|
||||
:help "Display documentation for debugger-mode"))
|
||||
(define-key menu-map [deb-hfol]
|
||||
'(menu-item "Help Follow" debug-help-follow
|
||||
:help "Follow cross-reference"))
|
||||
(define-key menu-map [deb-nxt]
|
||||
'(menu-item "Next Line" next-line
|
||||
:help "Move cursor down"))
|
||||
(define-key menu-map [deb-s1] '("--"))
|
||||
(define-key menu-map [deb-lfunc]
|
||||
'(menu-item "List debug on entry functions" debugger-list-functions
|
||||
:help "Display a list of all the functions now set to debug on entry"))
|
||||
(define-key menu-map [deb-fclear]
|
||||
'(menu-item "Cancel debug frame" debugger-frame-clear
|
||||
:help "Do not enter debugger when this frame exits"))
|
||||
(define-key menu-map [deb-frame]
|
||||
'(menu-item "Debug frame" debugger-frame
|
||||
:help "Request entry to debugger when this frame exits"))
|
||||
(define-key menu-map [deb-s2] '("--"))
|
||||
(define-key menu-map [deb-ret]
|
||||
'(menu-item "Return value..." debugger-return-value
|
||||
:help "Continue, specifying value to return."))
|
||||
(define-key menu-map [deb-rec]
|
||||
'(menu-item "Display and Record Expression" debugger-record-expression
|
||||
:help "Display a variable's value and record it in `*Backtrace-record*' buffer"))
|
||||
(define-key menu-map [deb-eval]
|
||||
'(menu-item "Eval Expression..." debugger-eval-expression
|
||||
:help "Eval an expression, in an environment like that outside the debugger"))
|
||||
(define-key menu-map [deb-jump]
|
||||
'(menu-item "Jump" debugger-jump
|
||||
:help "Continue to exit from this frame, with all debug-on-entry suspended"))
|
||||
(define-key menu-map [deb-cont]
|
||||
'(menu-item "Continue" debugger-continue
|
||||
:help "Continue, evaluating this expression without stopping"))
|
||||
(define-key menu-map [deb-step]
|
||||
'(menu-item "Step through" debugger-step-through
|
||||
:help "Proceed, stepping through subexpressions of this expression"))
|
||||
(easy-menu-define nil map ""
|
||||
'("Debugger"
|
||||
["Step through" debugger-step-through
|
||||
:help "Proceed, stepping through subexpressions of this expression"]
|
||||
["Continue" debugger-continue
|
||||
:help "Continue, evaluating this expression without stopping"]
|
||||
["Jump" debugger-jump
|
||||
:help "Continue to exit from this frame, with all debug-on-entry suspended"]
|
||||
["Eval Expression..." debugger-eval-expression
|
||||
:help "Eval an expression, in an environment like that outside the debugger"]
|
||||
["Display and Record Expression" debugger-record-expression
|
||||
:help "Display a variable's value and record it in `*Backtrace-record*' buffer"]
|
||||
["Return value..." debugger-return-value
|
||||
:help "Continue, specifying value to return."]
|
||||
"--"
|
||||
["Debug frame" debugger-frame
|
||||
:help "Request entry to debugger when this frame exits"]
|
||||
["Cancel debug frame" debugger-frame-clear
|
||||
:help "Do not enter debugger when this frame exits"]
|
||||
["List debug on entry functions" debugger-list-functions
|
||||
:help "Display a list of all the functions now set to debug on entry"]
|
||||
"--"
|
||||
["Next Line" next-line
|
||||
:help "Move cursor down"]
|
||||
["Help for Symbol" backtrace-help-follow-symbol
|
||||
:help "Show help for symbol at point"]
|
||||
["Describe Debugger Mode" describe-mode
|
||||
:help "Display documentation for debugger-mode"]
|
||||
"--"
|
||||
["Quit" debugger-quit
|
||||
:help "Quit debugging and return to top level"]))
|
||||
map))
|
||||
|
||||
(put 'debugger-mode 'mode-class 'special)
|
||||
|
||||
(define-derived-mode debugger-mode fundamental-mode "Debugger"
|
||||
"Mode for backtrace buffers, selected in debugger.
|
||||
(define-derived-mode debugger-mode backtrace-mode "Debugger"
|
||||
"Mode for debugging Emacs Lisp using a backtrace.
|
||||
\\<debugger-mode-map>
|
||||
A line starts with `*' if exiting that frame will call the debugger.
|
||||
Type \\[debugger-frame] or \\[debugger-frame-clear] to set or remove the `*'.
|
||||
|
@ -704,8 +593,6 @@ which functions will enter the debugger when called.
|
|||
|
||||
Complete list of commands:
|
||||
\\{debugger-mode-map}"
|
||||
(setq truncate-lines t)
|
||||
(set-syntax-table emacs-lisp-mode-syntax-table)
|
||||
(add-hook 'kill-buffer-hook
|
||||
(lambda () (if (> (recursion-depth) 0) (top-level)))
|
||||
nil t)
|
||||
|
@ -732,27 +619,6 @@ Complete list of commands:
|
|||
(buffer-substring (line-beginning-position 0)
|
||||
(line-end-position 0)))))
|
||||
|
||||
(defun debug-help-follow (&optional pos)
|
||||
"Follow cross-reference at POS, defaulting to point.
|
||||
|
||||
For the cross-reference format, see `help-make-xrefs'."
|
||||
(interactive "d")
|
||||
;; Ideally we'd just do (call-interactively 'help-follow) except that this
|
||||
;; assumes we're already in a *Help* buffer and reuses it, so it ends up
|
||||
;; incorrectly "reusing" the *Backtrace* buffer to show the help info.
|
||||
(unless pos
|
||||
(setq pos (point)))
|
||||
(unless (push-button pos)
|
||||
;; check if the symbol under point is a function or variable
|
||||
(let ((sym
|
||||
(intern
|
||||
(save-excursion
|
||||
(goto-char pos) (skip-syntax-backward "w_")
|
||||
(buffer-substring (point)
|
||||
(progn (skip-syntax-forward "w_")
|
||||
(point)))))))
|
||||
(when (or (boundp sym) (fboundp sym) (facep sym))
|
||||
(describe-symbol sym)))))
|
||||
|
||||
;; When you change this, you may also need to change the number of
|
||||
;; frames that the debugger skips.
|
||||
|
@ -853,6 +719,13 @@ To specify a nil argument interactively, exit with an empty minibuffer."
|
|||
;;(princ "be set to debug on entry, even if it is in the list.")
|
||||
)))))
|
||||
|
||||
(defun debugger-quit ()
|
||||
"Quit debugging and return to the top level."
|
||||
(interactive)
|
||||
(if (= (recursion-depth) 0)
|
||||
(quit-window)
|
||||
(top-level)))
|
||||
|
||||
(defun debug--implement-debug-watch (symbol newval op where)
|
||||
"Conditionally call the debugger.
|
||||
This function is called when SYMBOL's value is modified."
|
||||
|
|
|
@ -474,22 +474,26 @@ See `%s' for more information on %s."
|
|||
|
||||
;; The function that calls TURN-ON in each buffer.
|
||||
(defun ,MODE-enable-in-buffers ()
|
||||
(dolist (buf ,MODE-buffers)
|
||||
(when (buffer-live-p buf)
|
||||
(with-current-buffer buf
|
||||
(unless ,MODE-set-explicitly
|
||||
(unless (eq ,MODE-major-mode major-mode)
|
||||
(if ,mode
|
||||
(progn
|
||||
(,mode -1)
|
||||
(funcall #',turn-on))
|
||||
(funcall #',turn-on))))
|
||||
(setq ,MODE-major-mode major-mode)))))
|
||||
(let ((buffers ,MODE-buffers))
|
||||
;; Clear MODE-buffers to avoid scanning the same list of
|
||||
;; buffers in recursive calls to MODE-enable-in-buffers.
|
||||
;; Otherwise it could lead to infinite recursion.
|
||||
(setq ,MODE-buffers nil)
|
||||
(dolist (buf buffers)
|
||||
(when (buffer-live-p buf)
|
||||
(with-current-buffer buf
|
||||
(unless ,MODE-set-explicitly
|
||||
(unless (eq ,MODE-major-mode major-mode)
|
||||
(if ,mode
|
||||
(progn
|
||||
(,mode -1)
|
||||
(funcall #',turn-on))
|
||||
(funcall #',turn-on))))
|
||||
(setq ,MODE-major-mode major-mode))))))
|
||||
(put ',MODE-enable-in-buffers 'definition-name ',global-mode)
|
||||
|
||||
(defun ,MODE-check-buffers ()
|
||||
(,MODE-enable-in-buffers)
|
||||
(setq ,MODE-buffers nil)
|
||||
(remove-hook 'post-command-hook ',MODE-check-buffers))
|
||||
(put ',MODE-check-buffers 'definition-name ',global-mode)
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'backtrace)
|
||||
(require 'macroexp)
|
||||
(require 'cl-lib)
|
||||
(eval-when-compile (require 'pcase))
|
||||
|
@ -206,8 +207,7 @@ Use this with caution since it is not debugged."
|
|||
"Non-nil if Edebug should unwrap results of expressions.
|
||||
That is, Edebug will try to remove its own instrumentation from the result.
|
||||
This is useful when debugging macros where the results of expressions
|
||||
are instrumented expressions. But don't do this when results might be
|
||||
circular or an infinite loop will result."
|
||||
are instrumented expressions."
|
||||
:type 'boolean
|
||||
:group 'edebug)
|
||||
|
||||
|
@ -1198,6 +1198,8 @@ purpose by adding an entry to this alist, and setting
|
|||
(defvar edebug-inside-func) ;; whether code is inside function context.
|
||||
;; Currently def-form sets this to nil; def-body sets it to t.
|
||||
|
||||
(defvar edebug--cl-macrolet-defs) ;; Fully defined below.
|
||||
|
||||
(defun edebug-interactive-p-name ()
|
||||
;; Return a unique symbol for the variable used to store the
|
||||
;; status of interactive-p for this function.
|
||||
|
@ -1263,25 +1265,59 @@ purpose by adding an entry to this alist, and setting
|
|||
(defun edebug-unwrap (sexp)
|
||||
"Return the unwrapped SEXP or return it as is if it is not wrapped.
|
||||
The SEXP might be the result of wrapping a body, which is a list of
|
||||
expressions; a `progn' form will be returned enclosing these forms."
|
||||
(if (consp sexp)
|
||||
(cond
|
||||
((eq 'edebug-after (car sexp))
|
||||
(nth 3 sexp))
|
||||
((eq 'edebug-enter (car sexp))
|
||||
(macroexp-progn (nthcdr 2 (nth 1 (nth 3 sexp)))))
|
||||
(t sexp);; otherwise it is not wrapped, so just return it.
|
||||
)
|
||||
sexp))
|
||||
expressions; a `progn' form will be returned enclosing these forms.
|
||||
Does not unwrap inside vectors, records, structures, or hash tables."
|
||||
(pcase sexp
|
||||
(`(edebug-after ,_before-form ,_after-index ,form)
|
||||
form)
|
||||
(`(lambda ,args (edebug-enter ',_sym ,_arglist
|
||||
(function (lambda nil . ,body))))
|
||||
`(lambda ,args ,@body))
|
||||
(`(closure ,env ,args (edebug-enter ',_sym ,_arglist
|
||||
(function (lambda nil . ,body))))
|
||||
`(closure ,env ,args ,@body))
|
||||
(`(edebug-enter ',_sym ,_args (function (lambda nil . ,body)))
|
||||
(macroexp-progn body))
|
||||
(_ sexp)))
|
||||
|
||||
(defun edebug-unwrap* (sexp)
|
||||
"Return the SEXP recursively unwrapped."
|
||||
(let ((ht (make-hash-table :test 'eq)))
|
||||
(edebug--unwrap1 sexp ht)))
|
||||
|
||||
(defun edebug--unwrap1 (sexp hash-table)
|
||||
"Unwrap SEXP using HASH-TABLE of things already unwrapped.
|
||||
HASH-TABLE contains the results of unwrapping cons cells within
|
||||
SEXP, which are reused to avoid infinite loops when SEXP is or
|
||||
contains a circular object."
|
||||
(let ((new-sexp (edebug-unwrap sexp)))
|
||||
(while (not (eq sexp new-sexp))
|
||||
(setq sexp new-sexp
|
||||
new-sexp (edebug-unwrap sexp)))
|
||||
(if (consp new-sexp)
|
||||
(mapcar #'edebug-unwrap* new-sexp)
|
||||
(let ((result (gethash new-sexp hash-table nil)))
|
||||
(unless result
|
||||
(let ((remainder new-sexp)
|
||||
current)
|
||||
(setq result (cons nil nil)
|
||||
current result)
|
||||
(while
|
||||
(progn
|
||||
(puthash remainder current hash-table)
|
||||
(setf (car current)
|
||||
(edebug--unwrap1 (car remainder) hash-table))
|
||||
(setq remainder (cdr remainder))
|
||||
(cond
|
||||
((atom remainder)
|
||||
(setf (cdr current)
|
||||
(edebug--unwrap1 remainder hash-table))
|
||||
nil)
|
||||
((gethash remainder hash-table nil)
|
||||
(setf (cdr current) (gethash remainder hash-table nil))
|
||||
nil)
|
||||
(t (setq current
|
||||
(setf (cdr current) (cons nil nil)))))))))
|
||||
result)
|
||||
new-sexp)))
|
||||
|
||||
|
||||
|
@ -1463,6 +1499,11 @@ expressions; a `progn' form will be returned enclosing these forms."
|
|||
;; Helper for edebug-list-form
|
||||
(let ((spec (get-edebug-spec head)))
|
||||
(cond
|
||||
;; Treat cl-macrolet bindings like macros with no spec.
|
||||
((member head edebug--cl-macrolet-defs)
|
||||
(if edebug-eval-macro-args
|
||||
(edebug-forms cursor)
|
||||
(edebug-sexps cursor)))
|
||||
(spec
|
||||
(cond
|
||||
((consp spec)
|
||||
|
@ -1651,6 +1692,9 @@ expressions; a `progn' form will be returned enclosing these forms."
|
|||
;; (function . edebug-match-function)
|
||||
(lambda-expr . edebug-match-lambda-expr)
|
||||
(cl-generic-method-args . edebug-match-cl-generic-method-args)
|
||||
(cl-macrolet-expr . edebug-match-cl-macrolet-expr)
|
||||
(cl-macrolet-name . edebug-match-cl-macrolet-name)
|
||||
(cl-macrolet-body . edebug-match-cl-macrolet-body)
|
||||
(¬ . edebug-match-¬)
|
||||
(&key . edebug-match-&key)
|
||||
(place . edebug-match-place)
|
||||
|
@ -1954,6 +1998,43 @@ expressions; a `progn' form will be returned enclosing these forms."
|
|||
(edebug-move-cursor cursor)
|
||||
(list args)))
|
||||
|
||||
(defvar edebug--cl-macrolet-defs nil
|
||||
"List of symbols found within the bindings of enclosing `cl-macrolet' forms.")
|
||||
(defvar edebug--current-cl-macrolet-defs nil
|
||||
"List of symbols found within the bindings of the current `cl-macrolet' form.")
|
||||
|
||||
(defun edebug-match-cl-macrolet-expr (cursor)
|
||||
"Match a `cl-macrolet' form at CURSOR."
|
||||
(let (edebug--current-cl-macrolet-defs)
|
||||
(edebug-match cursor
|
||||
'((&rest (&define cl-macrolet-name cl-macro-list
|
||||
cl-declarations-or-string
|
||||
def-body))
|
||||
cl-declarations cl-macrolet-body))))
|
||||
|
||||
(defun edebug-match-cl-macrolet-name (cursor)
|
||||
"Match the name in a `cl-macrolet' binding at CURSOR.
|
||||
Collect the names in `edebug--cl-macrolet-defs' where they
|
||||
will be checked by `edebug-list-form-args' and treated as
|
||||
macros without a spec."
|
||||
(let ((name (edebug-top-element-required cursor "Expected name")))
|
||||
(when (not (symbolp name))
|
||||
(edebug-no-match cursor "Bad name:" name))
|
||||
;; Change edebug-def-name to avoid conflicts with
|
||||
;; names at global scope.
|
||||
(setq edebug-def-name (gensym "edebug-anon"))
|
||||
(edebug-move-cursor cursor)
|
||||
(push name edebug--current-cl-macrolet-defs)
|
||||
(list name)))
|
||||
|
||||
(defun edebug-match-cl-macrolet-body (cursor)
|
||||
"Match the body of a `cl-macrolet' expression at CURSOR.
|
||||
Put the definitions collected in `edebug--current-cl-macrolet-defs'
|
||||
into `edebug--cl-macrolet-defs' which is checked in `edebug-list-form-args'."
|
||||
(let ((edebug--cl-macrolet-defs (nconc edebug--current-cl-macrolet-defs
|
||||
edebug--cl-macrolet-defs)))
|
||||
(edebug-match-body cursor)))
|
||||
|
||||
(defun edebug-match-arg (cursor)
|
||||
;; set the def-args bound in edebug-defining-form
|
||||
(let ((edebug-arg (edebug-top-element-required cursor "Expected arg")))
|
||||
|
@ -3611,7 +3692,7 @@ be installed in `emacs-lisp-mode-map'.")
|
|||
|
||||
;; misc
|
||||
(define-key map "?" 'edebug-help)
|
||||
(define-key map "d" 'edebug-backtrace)
|
||||
(define-key map "d" 'edebug-pop-to-backtrace)
|
||||
|
||||
(define-key map "-" 'negative-argument)
|
||||
|
||||
|
@ -3869,8 +3950,10 @@ Global commands prefixed by `global-edebug-prefix':
|
|||
;; (setq debugger 'debug) ; use the standard debugger
|
||||
|
||||
;; Note that debug and its utilities must be byte-compiled to work,
|
||||
;; since they depend on the backtrace looking a certain way. But
|
||||
;; edebug is not dependent on this, yet.
|
||||
;; since they depend on the backtrace looking a certain way. Edebug
|
||||
;; will work if not byte-compiled, but it will not be able correctly
|
||||
;; remove its instrumentation from backtraces unless it is
|
||||
;; byte-compiled.
|
||||
|
||||
(defun edebug (&optional arg-mode &rest args)
|
||||
"Replacement for `debug'.
|
||||
|
@ -3900,49 +3983,136 @@ Otherwise call `debug' normally."
|
|||
(apply #'debug arg-mode args)
|
||||
))
|
||||
|
||||
;;; Backtrace buffer
|
||||
|
||||
(defun edebug-backtrace ()
|
||||
"Display a non-working backtrace. Better than nothing..."
|
||||
(defvar-local edebug-backtrace-frames nil
|
||||
"Stack frames of the current Edebug Backtrace buffer without instrumentation.
|
||||
This should be a list of `edebug---frame' objects.")
|
||||
(defvar-local edebug-instrumented-backtrace-frames nil
|
||||
"Stack frames of the current Edebug Backtrace buffer with instrumentation.
|
||||
This should be a list of `edebug---frame' objects.")
|
||||
|
||||
;; Data structure for backtrace frames with information
|
||||
;; from Edebug instrumentation found in the backtrace.
|
||||
(cl-defstruct
|
||||
(edebug--frame
|
||||
(:constructor edebug--make-frame)
|
||||
(:include backtrace-frame))
|
||||
def-name before-index after-index)
|
||||
|
||||
(defun edebug-pop-to-backtrace ()
|
||||
"Display the current backtrace in a `backtrace-mode' window."
|
||||
(interactive)
|
||||
(if (or (not edebug-backtrace-buffer)
|
||||
(null (buffer-name edebug-backtrace-buffer)))
|
||||
(setq edebug-backtrace-buffer
|
||||
(generate-new-buffer "*Backtrace*"))
|
||||
(generate-new-buffer "*Edebug Backtrace*"))
|
||||
;; Else, could just display edebug-backtrace-buffer.
|
||||
)
|
||||
(with-output-to-temp-buffer (buffer-name edebug-backtrace-buffer)
|
||||
(setq edebug-backtrace-buffer standard-output)
|
||||
(let ((print-escape-newlines t)
|
||||
(print-length 50) ; FIXME cf edebug-safe-prin1-to-string
|
||||
last-ok-point)
|
||||
(backtrace)
|
||||
(pop-to-buffer edebug-backtrace-buffer)
|
||||
(unless (derived-mode-p 'backtrace-mode)
|
||||
(backtrace-mode)
|
||||
(add-hook 'backtrace-goto-source-functions 'edebug--backtrace-goto-source))
|
||||
(setq edebug-instrumented-backtrace-frames
|
||||
(backtrace-get-frames 'edebug-debugger
|
||||
:constructor #'edebug--make-frame)
|
||||
edebug-backtrace-frames (edebug--strip-instrumentation
|
||||
edebug-instrumented-backtrace-frames)
|
||||
backtrace-frames edebug-backtrace-frames)
|
||||
(backtrace-print)
|
||||
(goto-char (point-min)))
|
||||
|
||||
;; Clean up the backtrace.
|
||||
;; Not quite right for current edebug scheme.
|
||||
(set-buffer edebug-backtrace-buffer)
|
||||
(setq truncate-lines t)
|
||||
(goto-char (point-min))
|
||||
(setq last-ok-point (point))
|
||||
(if t (progn
|
||||
(defun edebug--strip-instrumentation (frames)
|
||||
"Return a new list of backtrace frames with instrumentation removed.
|
||||
Remove frames for Edebug's functions and the lambdas in
|
||||
`edebug-enter' wrappers. Fill in the def-name, before-index
|
||||
and after-index fields in both FRAMES and the returned list
|
||||
of deinstrumented frames, for those frames where the source
|
||||
code location is known."
|
||||
(let (skip-next-lambda def-name before-index after-index results
|
||||
(index (length frames)))
|
||||
(dolist (frame (reverse frames))
|
||||
(let ((new-frame (copy-edebug--frame frame))
|
||||
(fun (edebug--frame-fun frame))
|
||||
(args (edebug--frame-args frame)))
|
||||
(cl-decf index)
|
||||
(pcase fun
|
||||
('edebug-enter
|
||||
(setq skip-next-lambda t
|
||||
def-name (nth 0 args)))
|
||||
('edebug-after
|
||||
(setq before-index (if (consp (nth 0 args))
|
||||
(nth 1 (nth 0 args))
|
||||
(nth 0 args))
|
||||
after-index (nth 1 args)))
|
||||
((pred edebug--symbol-not-prefixed-p)
|
||||
(edebug--unwrap-frame new-frame)
|
||||
(edebug--add-source-info new-frame def-name before-index after-index)
|
||||
(edebug--add-source-info frame def-name before-index after-index)
|
||||
(push new-frame results)
|
||||
(setq before-index nil
|
||||
after-index nil))
|
||||
(`(,(or 'lambda 'closure) . ,_)
|
||||
(unless skip-next-lambda
|
||||
(edebug--unwrap-frame new-frame)
|
||||
(edebug--add-source-info frame def-name before-index after-index)
|
||||
(edebug--add-source-info new-frame def-name before-index after-index)
|
||||
(push new-frame results))
|
||||
(setq before-index nil
|
||||
after-index nil
|
||||
skip-next-lambda nil)))))
|
||||
results))
|
||||
|
||||
;; Delete interspersed edebug internals.
|
||||
(while (re-search-forward "^ (?edebug" nil t)
|
||||
(beginning-of-line)
|
||||
(cond
|
||||
((looking-at "^ (edebug-after")
|
||||
;; Previous lines may contain code, so just delete this line.
|
||||
(setq last-ok-point (point))
|
||||
(forward-line 1)
|
||||
(delete-region last-ok-point (point)))
|
||||
(defun edebug--symbol-not-prefixed-p (sym)
|
||||
"Return non-nil if SYM is a symbol not prefixed by \"edebug-\"."
|
||||
(and (symbolp sym)
|
||||
(not (string-prefix-p "edebug-" (symbol-name sym)))))
|
||||
|
||||
((looking-at (if debugger-stack-frame-as-list
|
||||
"^ (edebug"
|
||||
"^ edebug"))
|
||||
(forward-line 1)
|
||||
(delete-region last-ok-point (point))
|
||||
)))
|
||||
)))))
|
||||
(defun edebug--unwrap-frame (frame)
|
||||
"Remove Edebug's instrumentation from FRAME.
|
||||
Strip it from the function and any unevaluated arguments."
|
||||
(setf (edebug--frame-fun frame) (edebug-unwrap* (edebug--frame-fun frame)))
|
||||
(unless (edebug--frame-evald frame)
|
||||
(let (results)
|
||||
(dolist (arg (edebug--frame-args frame))
|
||||
(push (edebug-unwrap* arg) results))
|
||||
(setf (edebug--frame-args frame) (nreverse results)))))
|
||||
|
||||
(defun edebug--add-source-info (frame def-name before-index after-index)
|
||||
"Update FRAME with the additional info needed by an edebug--frame.
|
||||
Save DEF-NAME, BEFORE-INDEX and AFTER-INDEX in FRAME."
|
||||
(when (and before-index def-name)
|
||||
(setf (edebug--frame-flags frame)
|
||||
(plist-put (copy-sequence (edebug--frame-flags frame))
|
||||
:source-available t)))
|
||||
(setf (edebug--frame-def-name frame) (and before-index def-name))
|
||||
(setf (edebug--frame-before-index frame) before-index)
|
||||
(setf (edebug--frame-after-index frame) after-index))
|
||||
|
||||
(defun edebug--backtrace-goto-source ()
|
||||
(let* ((index (backtrace-get-index))
|
||||
(frame (nth index backtrace-frames)))
|
||||
(when (edebug--frame-def-name frame)
|
||||
(let* ((data (get (edebug--frame-def-name frame) 'edebug))
|
||||
(marker (nth 0 data))
|
||||
(offsets (nth 2 data)))
|
||||
(pop-to-buffer (marker-buffer marker))
|
||||
(goto-char (+ (marker-position marker)
|
||||
(aref offsets (edebug--frame-before-index frame))))))))
|
||||
|
||||
(defun edebug-backtrace-show-instrumentation ()
|
||||
"Show Edebug's instrumentation in an Edebug Backtrace buffer."
|
||||
(interactive)
|
||||
(unless (eq backtrace-frames edebug-instrumented-backtrace-frames)
|
||||
(setq backtrace-frames edebug-instrumented-backtrace-frames)
|
||||
(revert-buffer)))
|
||||
|
||||
(defun edebug-backtrace-hide-instrumentation ()
|
||||
"Hide Edebug's instrumentation in an Edebug Backtrace buffer."
|
||||
(interactive)
|
||||
(unless (eq backtrace-frames edebug-backtrace-frames)
|
||||
(setq backtrace-frames edebug-backtrace-frames)
|
||||
(revert-buffer)))
|
||||
|
||||
;;; Trace display
|
||||
|
||||
|
@ -4116,7 +4286,7 @@ It is removed when you hit any char."
|
|||
["Bounce to Current Point" edebug-bounce-point t]
|
||||
["View Outside Windows" edebug-view-outside t]
|
||||
["Previous Result" edebug-previous-result t]
|
||||
["Show Backtrace" edebug-backtrace t]
|
||||
["Show Backtrace" edebug-pop-to-backtrace t]
|
||||
["Display Freq Count" edebug-display-freq-count t])
|
||||
|
||||
("Eval"
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
(require 'cl-lib)
|
||||
(require 'button)
|
||||
(require 'debug)
|
||||
(require 'backtrace)
|
||||
(require 'easymenu)
|
||||
(require 'ewoc)
|
||||
(require 'find-func)
|
||||
|
@ -677,13 +678,6 @@ and is displayed in front of the value of MESSAGE-FORM."
|
|||
(cl-defstruct (ert-test-aborted-with-non-local-exit
|
||||
(:include ert-test-result)))
|
||||
|
||||
(defun ert--print-backtrace (backtrace do-xrefs)
|
||||
"Format the backtrace BACKTRACE to the current buffer."
|
||||
(let ((print-escape-newlines t)
|
||||
(print-level 8)
|
||||
(print-length 50))
|
||||
(debugger-insert-backtrace backtrace do-xrefs)))
|
||||
|
||||
;; A container for the state of the execution of a single test and
|
||||
;; environment data needed during its execution.
|
||||
(cl-defstruct ert--test-execution-info
|
||||
|
@ -732,7 +726,7 @@ run. ARGS are the arguments to `debugger'."
|
|||
;; use.
|
||||
;;
|
||||
;; Grab the frames above the debugger.
|
||||
(backtrace (cdr (backtrace-frames debugger)))
|
||||
(backtrace (cdr (backtrace-get-frames debugger)))
|
||||
(infos (reverse ert--infos)))
|
||||
(setf (ert--test-execution-info-result info)
|
||||
(cl-ecase type
|
||||
|
@ -1406,9 +1400,8 @@ Returns the stats object."
|
|||
(ert-test-result-with-condition
|
||||
(message "Test %S backtrace:" (ert-test-name test))
|
||||
(with-temp-buffer
|
||||
(ert--print-backtrace
|
||||
(ert-test-result-with-condition-backtrace result)
|
||||
nil)
|
||||
(insert (backtrace-to-string
|
||||
(ert-test-result-with-condition-backtrace result)))
|
||||
(if (not ert-batch-backtrace-right-margin)
|
||||
(message "%s"
|
||||
(buffer-substring-no-properties (point-min)
|
||||
|
@ -2450,20 +2443,20 @@ To be used in the ERT results buffer."
|
|||
(cl-etypecase result
|
||||
(ert-test-passed (error "Test passed, no backtrace available"))
|
||||
(ert-test-result-with-condition
|
||||
(let ((backtrace (ert-test-result-with-condition-backtrace result))
|
||||
(buffer (get-buffer-create "*ERT Backtrace*")))
|
||||
(let ((buffer (get-buffer-create "*ERT Backtrace*")))
|
||||
(pop-to-buffer buffer)
|
||||
(let ((inhibit-read-only t))
|
||||
(buffer-disable-undo)
|
||||
(erase-buffer)
|
||||
(ert-simple-view-mode)
|
||||
(set-buffer-multibyte t) ; mimic debugger-setup-buffer
|
||||
(setq truncate-lines t)
|
||||
(ert--print-backtrace backtrace t)
|
||||
(goto-char (point-min))
|
||||
(insert (substitute-command-keys "Backtrace for test `"))
|
||||
(ert-insert-test-name-button (ert-test-name test))
|
||||
(insert (substitute-command-keys "':\n"))))))))
|
||||
(unless (derived-mode-p 'backtrace-mode)
|
||||
(backtrace-mode))
|
||||
(setq backtrace-insert-header-function
|
||||
(lambda () (ert--insert-backtrace-header (ert-test-name test)))
|
||||
backtrace-frames (ert-test-result-with-condition-backtrace result))
|
||||
(backtrace-print)
|
||||
(goto-char (point-min)))))))
|
||||
|
||||
(defun ert--insert-backtrace-header (name)
|
||||
(insert (substitute-command-keys "Backtrace for test `"))
|
||||
(ert-insert-test-name-button name)
|
||||
(insert (substitute-command-keys "':\n")))
|
||||
|
||||
(defun ert-results-pop-to-messages-for-test-at-point ()
|
||||
"Display the part of the *Messages* buffer generated during the test at point.
|
||||
|
|
|
@ -517,6 +517,16 @@ This will generate compile-time constants from BINDINGS."
|
|||
(defvar lisp-cl-font-lock-keywords lisp-cl-font-lock-keywords-1
|
||||
"Default expressions to highlight in Lisp modes.")
|
||||
|
||||
;; Support backtrace mode.
|
||||
(defconst lisp-el-font-lock-keywords-for-backtraces lisp-el-font-lock-keywords
|
||||
"Default highlighting from Emacs Lisp mod used in Backtrace mode.")
|
||||
(defconst lisp-el-font-lock-keywords-for-backtraces-1 lisp-el-font-lock-keywords-1
|
||||
"Subdued highlighting from Emacs Lisp mode used in Backtrace mode.")
|
||||
(defconst lisp-el-font-lock-keywords-for-backtraces-2
|
||||
(remove (assoc 'lisp--match-hidden-arg lisp-el-font-lock-keywords-2)
|
||||
lisp-el-font-lock-keywords-2)
|
||||
"Gaudy highlighting from Emacs Lisp mode used in Backtrace mode.")
|
||||
|
||||
(defun lisp-string-in-doc-position-p (listbeg startpos)
|
||||
"Return true if a doc string may occur at STARTPOS inside a list.
|
||||
LISTBEG is the position of the start of the innermost list
|
||||
|
@ -1196,7 +1206,21 @@ ENDPOS is encountered."
|
|||
(if endpos endpos
|
||||
;; Get error now if we don't have a complete sexp
|
||||
;; after point.
|
||||
(save-excursion (forward-sexp 1) (point)))))
|
||||
(save-excursion
|
||||
(let ((eol (line-end-position)))
|
||||
(forward-sexp 1)
|
||||
;; We actually look for a sexp which ends
|
||||
;; after the current line so that we properly
|
||||
;; indent things like #s(...). This might not
|
||||
;; be needed if Bug#15998 is fixed.
|
||||
(condition-case ()
|
||||
(while (and (< (point) eol) (not (eobp)))
|
||||
(forward-sexp 1))
|
||||
;; But don't signal an error for incomplete
|
||||
;; sexps following the first complete sexp
|
||||
;; after point.
|
||||
(scan-error nil)))
|
||||
(point)))))
|
||||
(save-excursion
|
||||
(while (let ((indent (lisp-indent-calc-next parse-state))
|
||||
(ppss (lisp-indent-state-ppss parse-state)))
|
||||
|
|
|
@ -257,10 +257,15 @@ C-g to quit (cancel the whole command);
|
|||
;; either long or short answers.
|
||||
|
||||
;; For backward compatibility check if short y/n answers are preferred.
|
||||
(defcustom read-answer-short (eq (symbol-function 'yes-or-no-p) 'y-or-n-p)
|
||||
"If non-nil, accept short answers to the question."
|
||||
:type 'boolean
|
||||
:version "27.1"
|
||||
(defcustom read-answer-short 'auto
|
||||
"If non-nil, `read-answer' accepts single-character answers.
|
||||
If t, accept short (single key-press) answers to the question.
|
||||
If nil, require long answers. If `auto', accept short answers if
|
||||
the function cell of `yes-or-no-p' is set to `y-or-on-p'."
|
||||
:type '(choice (const :tag "Accept short answers" t)
|
||||
(const :tag "Require long answer" nil)
|
||||
(const :tag "Guess preference" auto))
|
||||
:version "26.2"
|
||||
:group 'minibuffer)
|
||||
|
||||
(defconst read-answer-map--memoize (make-hash-table :weakness 'key :test 'equal))
|
||||
|
@ -290,8 +295,9 @@ When `read-answer-short' is non-nil, accept short answers.
|
|||
Return a long answer even in case of accepting short ones.
|
||||
|
||||
When `use-dialog-box' is t, pop up a dialog window to get user input."
|
||||
(custom-reevaluate-setting 'read-answer-short)
|
||||
(let* ((short read-answer-short)
|
||||
(let* ((short (if (eq read-answer-short 'auto)
|
||||
(eq (symbol-function 'yes-or-no-p) 'y-or-n-p)
|
||||
read-answer-short))
|
||||
(answers-with-help
|
||||
(if (assoc "help" answers)
|
||||
answers
|
||||
|
|
|
@ -1183,24 +1183,28 @@ enclosed in `(and ...)'.
|
|||
|
||||
|
||||
(pcase-defmacro rx (&rest regexps)
|
||||
"Build a `pcase' pattern matching `rx' regexps.
|
||||
The REGEXPS are interpreted as by `rx'. The pattern matches if
|
||||
the regular expression so constructed matches EXPVAL, as if
|
||||
by `string-match'.
|
||||
"Build a `pcase' pattern matching `rx' REGEXPS in sexp form.
|
||||
The REGEXPS are interpreted as in `rx'. The pattern matches any
|
||||
string that is a match for the regular expression so constructed,
|
||||
as if by `string-match'.
|
||||
|
||||
In addition to the usual `rx' constructs, REGEXPS can contain the
|
||||
following constructs:
|
||||
|
||||
(let VAR FORM...) creates a new explicitly numbered submatch
|
||||
that matches FORM and binds the match to
|
||||
VAR.
|
||||
(backref VAR) creates a backreference to the submatch
|
||||
introduced by a previous (let VAR ...)
|
||||
construct.
|
||||
(let REF SEXP...) creates a new explicitly named reference to
|
||||
a submatch that matches regular expressions
|
||||
SEXP, and binds the match to REF.
|
||||
(backref REF) creates a backreference to the submatch
|
||||
introduced by a previous (let REF ...)
|
||||
construct. REF can be the same symbol
|
||||
in the first argument of the corresponding
|
||||
(let REF ...) construct, or it can be a
|
||||
submatch number. It matches the referenced
|
||||
submatch.
|
||||
|
||||
The VARs are associated with explicitly numbered submatches
|
||||
starting from 1. Multiple occurrences of the same VAR refer to
|
||||
the same submatch.
|
||||
The REFs are associated with explicitly named submatches starting
|
||||
from 1. Multiple occurrences of the same REF refer to the same
|
||||
submatch.
|
||||
|
||||
If a case matches, the match data is modified as usual so you can
|
||||
use it in the case body, but you still have to pass the correct
|
||||
|
|
|
@ -211,7 +211,7 @@ The variable list SPEC is the same as in `if-let'."
|
|||
|
||||
(defsubst string-join (strings &optional separator)
|
||||
"Join all STRINGS using SEPARATOR."
|
||||
(mapconcat 'identity strings separator))
|
||||
(mapconcat #'identity strings separator))
|
||||
|
||||
(define-obsolete-function-alias 'string-reverse 'reverse "25.1")
|
||||
|
||||
|
@ -219,17 +219,17 @@ The variable list SPEC is the same as in `if-let'."
|
|||
"Trim STRING of leading string matching REGEXP.
|
||||
|
||||
REGEXP defaults to \"[ \\t\\n\\r]+\"."
|
||||
(if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+")"\\)") string)
|
||||
(replace-match "" t t string)
|
||||
(if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
|
||||
(substring string (match-end 0))
|
||||
string))
|
||||
|
||||
(defsubst string-trim-right (string &optional regexp)
|
||||
"Trim STRING of trailing string matching REGEXP.
|
||||
|
||||
REGEXP defaults to \"[ \\t\\n\\r]+\"."
|
||||
(if (string-match (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'") string)
|
||||
(replace-match "" t t string)
|
||||
string))
|
||||
(let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
|
||||
string)))
|
||||
(if i (substring string 0 i) string)))
|
||||
|
||||
(defsubst string-trim (string &optional trim-left trim-right)
|
||||
"Trim STRING of leading and trailing strings matching TRIM-LEFT and TRIM-RIGHT.
|
||||
|
|
|
@ -113,11 +113,11 @@ Changes ENV by side-effect, and returns its new value."
|
|||
(not keep-empty)
|
||||
env
|
||||
(stringp (car env))
|
||||
(string-match pattern (car env)))
|
||||
(string-match-p pattern (car env)))
|
||||
(cdr env)
|
||||
;; Try to find existing entry for VARIABLE in ENV.
|
||||
(while (and scan (stringp (car scan)))
|
||||
(when (string-match pattern (car scan))
|
||||
(when (string-match-p pattern (car scan))
|
||||
(if value
|
||||
(setcar scan (concat variable "=" value))
|
||||
(if keep-empty
|
||||
|
@ -184,7 +184,7 @@ a side-effect."
|
|||
(setq variable (encode-coding-string variable locale-coding-system)))
|
||||
(if (and value (multibyte-string-p value))
|
||||
(setq value (encode-coding-string value locale-coding-system)))
|
||||
(if (string-match "=" variable)
|
||||
(if (string-match-p "=" variable)
|
||||
(error "Environment variable name `%s' contains `='" variable))
|
||||
(if (string-equal "TZ" variable)
|
||||
(set-time-zone-rule value))
|
||||
|
|
|
@ -98,11 +98,14 @@ Note that the buffer name starts with a space."
|
|||
:type 'boolean)
|
||||
|
||||
(defconst epg-gpg-minimum-version "1.4.3")
|
||||
(defconst epg-gpg2-minimum-version "2.1.6")
|
||||
|
||||
(defconst epg-config--program-alist
|
||||
`((OpenPGP
|
||||
epg-gpg-program
|
||||
("gpg2" . "2.1.6") ("gpg" . ,epg-gpg-minimum-version))
|
||||
("gpg2" . ,epg-gpg2-minimum-version)
|
||||
("gpg" . ((,epg-gpg-minimum-version . "2.0")
|
||||
,epg-gpg2-minimum-version)))
|
||||
(CMS
|
||||
epg-gpgsm-program
|
||||
("gpgsm" . "2.0.4")))
|
||||
|
@ -228,14 +231,26 @@ version requirement is met."
|
|||
(epg-config--make-gpg-configuration epg-gpg-program))
|
||||
|
||||
;;;###autoload
|
||||
(defun epg-check-configuration (config &optional minimum-version)
|
||||
"Verify that a sufficient version of GnuPG is installed."
|
||||
(defun epg-check-configuration (config &optional req-versions)
|
||||
"Verify that a sufficient version of GnuPG is installed.
|
||||
CONFIG should be a `epg-configuration' object (a plist).
|
||||
REQ-VERSIONS should be a list with elements of the form (MIN
|
||||
. MAX) where MIN and MAX are version strings indicating a
|
||||
semi-open range of acceptable versions. REQ-VERSIONS may also be
|
||||
a single minimum version string."
|
||||
(let ((version (alist-get 'version config)))
|
||||
(unless (stringp version)
|
||||
(error "Undetermined version: %S" version))
|
||||
(unless (version<= (or minimum-version
|
||||
epg-gpg-minimum-version)
|
||||
version)
|
||||
(catch 'version-ok
|
||||
(pcase-dolist ((or `(,min . ,max)
|
||||
(and min (let max nil)))
|
||||
(if (listp req-versions) req-versions
|
||||
(list req-versions)))
|
||||
(when (and (version<= (or min epg-gpg-minimum-version)
|
||||
version)
|
||||
(or (null max)
|
||||
(version< version max)))
|
||||
(throw 'version-ok t)))
|
||||
(error "Unsupported version: %s" version))))
|
||||
|
||||
;;;###autoload
|
||||
|
|
|
@ -407,6 +407,7 @@ in the minibuffer:
|
|||
nil))))
|
||||
|
||||
(put 'eshell/cd 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/cd 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell-add-to-dir-ring (path)
|
||||
"Add PATH to the last-dir-ring, if applicable."
|
||||
|
@ -470,6 +471,7 @@ in the minibuffer:
|
|||
nil)
|
||||
|
||||
(put 'eshell/pushd 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/pushd 'eshell-filename-arguments t)
|
||||
|
||||
;;; popd [+n]
|
||||
(defun eshell/popd (&rest args)
|
||||
|
@ -500,6 +502,7 @@ in the minibuffer:
|
|||
nil)
|
||||
|
||||
(put 'eshell/popd 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/pop 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell/dirs (&optional if-verbose)
|
||||
"Implementation of dirs in Lisp."
|
||||
|
|
|
@ -334,6 +334,7 @@ instead."
|
|||
(apply 'eshell-do-ls args)))
|
||||
|
||||
(put 'eshell/ls 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/ls 'eshell-filename-arguments t)
|
||||
|
||||
(declare-function eshell-glob-regexp "em-glob" (pattern))
|
||||
|
||||
|
|
|
@ -307,6 +307,7 @@ Remove (unlink) the FILE(s).")
|
|||
nil))
|
||||
|
||||
(put 'eshell/rm 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/rm 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell/mkdir (&rest args)
|
||||
"Implementation of mkdir in Lisp."
|
||||
|
@ -324,6 +325,7 @@ Create the DIRECTORY(ies), if they do not already exist.")
|
|||
nil))
|
||||
|
||||
(put 'eshell/mkdir 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/mkdir 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell/rmdir (&rest args)
|
||||
"Implementation of rmdir in Lisp."
|
||||
|
@ -340,6 +342,7 @@ Remove the DIRECTORY(ies), if they are empty.")
|
|||
nil))
|
||||
|
||||
(put 'eshell/rmdir 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/rmdir 'eshell-filename-arguments t)
|
||||
|
||||
(defvar no-dereference)
|
||||
|
||||
|
@ -524,6 +527,7 @@ Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
|
|||
eshell-mv-overwrite-files))))
|
||||
|
||||
(put 'eshell/mv 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/mv 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell/cp (&rest args)
|
||||
"Implementation of cp in Lisp."
|
||||
|
@ -561,6 +565,7 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
|
|||
eshell-cp-overwrite-files preserve)))
|
||||
|
||||
(put 'eshell/cp 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/cp 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell/ln (&rest args)
|
||||
"Implementation of ln in Lisp."
|
||||
|
@ -593,6 +598,7 @@ with `--symbolic'. When creating hard links, each TARGET must exist.")
|
|||
eshell-ln-overwrite-files))))
|
||||
|
||||
(put 'eshell/ln 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/ln 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell/cat (&rest args)
|
||||
"Implementation of cat in Lisp.
|
||||
|
@ -645,6 +651,7 @@ Concatenate FILE(s), or standard input, to standard output.")
|
|||
(setq eshell-ensure-newline-p nil))))
|
||||
|
||||
(put 'eshell/cat 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/cat 'eshell-filename-arguments t)
|
||||
|
||||
;; special front-end functions for compilation-mode buffers
|
||||
|
||||
|
@ -927,6 +934,8 @@ Summarize disk usage of each FILE, recursively for directories.")
|
|||
(eshell-print (concat (eshell-du-size-string size)
|
||||
"total\n"))))))))
|
||||
|
||||
(put 'eshell/du 'eshell-filename-arguments t)
|
||||
|
||||
(defvar eshell-time-start nil)
|
||||
|
||||
(defun eshell-show-elapsed-time ()
|
||||
|
@ -1029,6 +1038,7 @@ Show wall-clock time elapsed during execution of COMMAND.")
|
|||
nil)
|
||||
|
||||
(put 'eshell/diff 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/diff 'eshell-filename-arguments t)
|
||||
|
||||
(defvar locate-history-list)
|
||||
|
||||
|
|
|
@ -1304,27 +1304,36 @@ messages, and errors."
|
|||
"Insert Lisp OBJECT, using ARGS if a function."
|
||||
(catch 'eshell-external ; deferred to an external command
|
||||
(let* ((eshell-ensure-newline-p (eshell-interactive-output-p))
|
||||
(result
|
||||
(if (functionp object)
|
||||
(progn
|
||||
(setq eshell-last-arguments args
|
||||
eshell-last-command-name
|
||||
(concat "#<function " (symbol-name object) ">"))
|
||||
;; if any of the arguments are flagged as numbers
|
||||
;; waiting for conversion, convert them now
|
||||
(unless (get object 'eshell-no-numeric-conversions)
|
||||
(while args
|
||||
(let ((arg (car args)))
|
||||
(if (and (stringp arg)
|
||||
(> (length arg) 0)
|
||||
(not (text-property-not-all
|
||||
0 (length arg) 'number t arg)))
|
||||
(setcar args (string-to-number arg))))
|
||||
(setq args (cdr args))))
|
||||
(eshell-apply object eshell-last-arguments))
|
||||
(setq eshell-last-arguments args
|
||||
eshell-last-command-name "#<Lisp object>")
|
||||
(eshell-eval object))))
|
||||
(result
|
||||
(if (functionp object)
|
||||
(progn
|
||||
(setq eshell-last-arguments args
|
||||
eshell-last-command-name
|
||||
(concat "#<function " (symbol-name object) ">"))
|
||||
(let ((numeric (not (get object
|
||||
'eshell-no-numeric-conversions)))
|
||||
(fname-args (get object 'eshell-filename-arguments)))
|
||||
(when (or numeric fname-args)
|
||||
(while args
|
||||
(let ((arg (car args)))
|
||||
(cond ((and numeric (stringp arg) (> (length arg) 0)
|
||||
(text-property-any 0 (length arg)
|
||||
'number t arg))
|
||||
;; If any of the arguments are
|
||||
;; flagged as numbers waiting for
|
||||
;; conversion, convert them now.
|
||||
(setcar args (string-to-number arg)))
|
||||
((and fname-args (stringp arg)
|
||||
(string-equal arg "~"))
|
||||
;; If any of the arguments match "~",
|
||||
;; prepend "./" to treat it as a
|
||||
;; regular file name.
|
||||
(setcar args (concat "./" arg)))))
|
||||
(setq args (cdr args)))))
|
||||
(eshell-apply object eshell-last-arguments))
|
||||
(setq eshell-last-arguments args
|
||||
eshell-last-command-name "#<Lisp object>")
|
||||
(eshell-eval object))))
|
||||
(if (and eshell-ensure-newline-p
|
||||
(save-excursion
|
||||
(goto-char eshell-last-output-end)
|
||||
|
|
|
@ -259,6 +259,7 @@ Adds the given PATH to $PATH.")
|
|||
(eshell-printn dir)))))
|
||||
|
||||
(put 'eshell/addpath 'eshell-no-numeric-conversions t)
|
||||
(put 'eshell/addpath 'eshell-filename-arguments t)
|
||||
|
||||
(defun eshell-script-interpreter (file)
|
||||
"Extract the script to run from FILE, if it has #!<interp> in it.
|
||||
|
|
|
@ -1830,7 +1830,7 @@ killed."
|
|||
;; Don't use `find-file' because it may end up using another window
|
||||
;; in some corner cases, e.g. when the selected window is
|
||||
;; softly-dedicated.
|
||||
(let ((newbuf (find-file-noselect filename wildcards)))
|
||||
(let ((newbuf (find-file-noselect filename nil nil wildcards)))
|
||||
(switch-to-buffer newbuf)))
|
||||
(when (eq obuf (current-buffer))
|
||||
;; This executes if find-file gets an error
|
||||
|
@ -1954,7 +1954,7 @@ started Emacs, set `abbreviated-home-dir' to nil so it will be recalculated)."
|
|||
(save-match-data
|
||||
(string-match "^[a-zA-`]:/$" filename))))
|
||||
(equal (get 'abbreviated-home-dir 'home)
|
||||
(expand-file-name "~")))
|
||||
(save-match-data (expand-file-name "~"))))
|
||||
(setq filename
|
||||
(concat "~"
|
||||
(match-string 1 filename)
|
||||
|
@ -5091,6 +5091,9 @@ Before and after saving the buffer, this function runs
|
|||
(make-directory dir t)
|
||||
(error "Canceled")))
|
||||
(setq setmodes (basic-save-buffer-1)))))
|
||||
;; We are hunting a nasty error, which happens on hydra.
|
||||
;; Adding traces might help.
|
||||
(if (getenv "BUG_32226") (message "BUG_32226"))
|
||||
;; Now we have saved the current buffer. Let's make sure
|
||||
;; that buffer-file-coding-system is fixed to what
|
||||
;; actually used for saving by binding it locally.
|
||||
|
@ -5519,6 +5522,21 @@ raised."
|
|||
(dolist (dir create-list)
|
||||
(files--ensure-directory dir)))))))
|
||||
|
||||
(defun make-empty-file (filename &optional parents)
|
||||
"Create an empty file FILENAME.
|
||||
Optional arg PARENTS, if non-nil then creates parent dirs as needed.
|
||||
|
||||
If called interactively, then PARENTS is non-nil."
|
||||
(interactive
|
||||
(let ((filename (read-file-name "Create empty file: ")))
|
||||
(list filename t)))
|
||||
(when (and (file-exists-p filename) (null parents))
|
||||
(signal 'file-already-exists `("File exists" ,filename)))
|
||||
(let ((paren-dir (file-name-directory filename)))
|
||||
(when (and paren-dir (not (file-exists-p paren-dir)))
|
||||
(make-directory paren-dir parents)))
|
||||
(write-region "" nil filename nil 0))
|
||||
|
||||
(defconst directory-files-no-dot-files-regexp
|
||||
"^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
|
||||
"Regexp matching any file name except \".\" and \"..\".")
|
||||
|
|
|
@ -539,6 +539,8 @@ Compare using `equal'."
|
|||
(setq tail next)))
|
||||
(cons acopy bcopy)))
|
||||
|
||||
(define-obsolete-function-alias 'format-proper-list-p 'proper-list-p "27.1")
|
||||
|
||||
(defun format-reorder (items order)
|
||||
"Arrange ITEMS to follow partial ORDER.
|
||||
Elements of ITEMS equal to elements of ORDER will be rearranged
|
||||
|
|
|
@ -1626,6 +1626,12 @@ resources when reading email groups (and therefore stops
|
|||
tracking), but allows loading external resources when reading
|
||||
from NNTP newsgroups and the like.
|
||||
|
||||
People controlling these external resources won't be able to tell
|
||||
that any one person in particular has read the message (since
|
||||
it's in a public venue, many people will end up loading that
|
||||
resource), but they'll be able to tell that somebody from your IP
|
||||
address has accessed the resource.
|
||||
|
||||
This can also be a function to be evaluated. If so, it will be
|
||||
called with the group name as the parameter, and should return a
|
||||
regexp."
|
||||
|
|
|
@ -4310,10 +4310,10 @@ If SELECT-ARTICLES, only select those articles from GROUP."
|
|||
If FORCE-NEW is not nil, enter HEADER into the DEPENDENCIES table even
|
||||
if it was already present.
|
||||
|
||||
If `gnus-summary-ignore-duplicates' is nil then duplicate Message-IDs
|
||||
will not be entered in the DEPENDENCIES table. Otherwise duplicate
|
||||
Message-IDs will be renamed to a unique Message-ID before being
|
||||
entered.
|
||||
If `gnus-summary-ignore-duplicates' is non-nil then duplicate
|
||||
Message-IDs will not be entered in the DEPENDENCIES table.
|
||||
Otherwise duplicate Message-IDs will be renamed to a unique
|
||||
Message-ID before being entered.
|
||||
|
||||
Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise."
|
||||
(let* ((id (mail-header-id header))
|
||||
|
|
14
lisp/ielm.el
14
lisp/ielm.el
|
@ -612,17 +612,19 @@ Customized bindings may be defined in `ielm-map', which currently contains:
|
|||
;;; User command
|
||||
|
||||
;;;###autoload
|
||||
(defun ielm nil
|
||||
(defun ielm (&optional buf-name)
|
||||
"Interactively evaluate Emacs Lisp expressions.
|
||||
Switches to the buffer `*ielm*', or creates it if it does not exist.
|
||||
Switches to the buffer named BUF-NAME if provided (`*ielm*' by default),
|
||||
or creates it if it does not exist.
|
||||
See `inferior-emacs-lisp-mode' for details."
|
||||
(interactive)
|
||||
(let (old-point)
|
||||
(unless (comint-check-proc "*ielm*")
|
||||
(with-current-buffer (get-buffer-create "*ielm*")
|
||||
(let (old-point
|
||||
(buf-name (or buf-name "*ielm*")))
|
||||
(unless (comint-check-proc buf-name)
|
||||
(with-current-buffer (get-buffer-create buf-name)
|
||||
(unless (zerop (buffer-size)) (setq old-point (point)))
|
||||
(inferior-emacs-lisp-mode)))
|
||||
(pop-to-buffer-same-window "*ielm*")
|
||||
(pop-to-buffer-same-window buf-name)
|
||||
(when old-point (push-mark old-point))))
|
||||
|
||||
(provide 'ielm)
|
||||
|
|
|
@ -832,15 +832,14 @@ depending on PATTERNS."
|
|||
(dolist (item index-alist)
|
||||
(when (listp item)
|
||||
(setcdr item (sort (cdr item) 'imenu--sort-by-position))))
|
||||
(let ((main-element (assq nil index-alist)))
|
||||
(nconc (delq main-element (delq 'dummy index-alist))
|
||||
(cdr main-element)))
|
||||
;; Remove any empty menus. That can happen because of skipping
|
||||
;; things inside comments or strings.
|
||||
(when (consp (car index-alist))
|
||||
(setq index-alist (cl-delete-if-not
|
||||
(lambda (it) (cdr it))
|
||||
index-alist)))))
|
||||
(setq index-alist (cl-delete-if
|
||||
(lambda (it) (and (consp it) (null (cdr it))))
|
||||
index-alist))
|
||||
(let ((main-element (assq nil index-alist)))
|
||||
(nconc (delq main-element (delq 'dummy index-alist))
|
||||
(cdr main-element)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;
|
||||
|
|
|
@ -292,7 +292,8 @@ indentation by specifying a large negative ARG."
|
|||
"Indent current line to COLUMN.
|
||||
This function removes or adds spaces and tabs at beginning of line
|
||||
only if necessary. It leaves point at end of indentation."
|
||||
(back-to-indentation)
|
||||
(beginning-of-line 1)
|
||||
(skip-chars-forward " \t")
|
||||
(let ((cur-col (current-column)))
|
||||
(cond ((< cur-col column)
|
||||
(if (>= (- column (* (/ cur-col tab-width) tab-width)) tab-width)
|
||||
|
@ -303,8 +304,10 @@ only if necessary. It leaves point at end of indentation."
|
|||
(delete-region (progn (move-to-column column t) (point))
|
||||
;; The `move-to-column' call may replace
|
||||
;; tabs with spaces, so we can't reuse the
|
||||
;; previous `back-to-indentation' point.
|
||||
(progn (back-to-indentation) (point)))))))
|
||||
;; previous start point.
|
||||
(progn (beginning-of-line 1)
|
||||
(skip-chars-forward " \t")
|
||||
(point)))))))
|
||||
|
||||
(defun current-left-margin ()
|
||||
"Return the left margin to use for this line.
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
("cns11643.92p7-0" . chinese-cns11643-7)
|
||||
("big5" . big5)
|
||||
("viscii" . viscii)
|
||||
("tis620" . tis620-2533)
|
||||
("tis620" . thai-iso8859-11)
|
||||
("microsoft-cp1251" . windows-1251)
|
||||
("koi8-r" . koi8-r)
|
||||
("jisx0213.2000-1" . japanese-jisx0213-1)
|
||||
|
@ -139,7 +139,7 @@
|
|||
(cyrillic-iso8859-5 . iso-8859-5)
|
||||
(greek-iso8859-7 . iso-8859-7)
|
||||
(arabic-iso8859-6 . iso-8859-6)
|
||||
(thai-tis620 . tis620-2533)
|
||||
(thai-tis620 . thai-iso8859-11)
|
||||
(latin-jisx0201 . jisx0201)
|
||||
(katakana-jisx0201 . jisx0201)
|
||||
(chinese-big5-1 . big5)
|
||||
|
@ -1233,11 +1233,12 @@ Done when `mouse-set-font' is called."
|
|||
(latin-iso8859-15 . latin)
|
||||
(latin-iso8859-16 . latin)
|
||||
(latin-jisx0201 . latin)
|
||||
(thai-iso8859-11 . thai)
|
||||
(thai-tis620 . thai)
|
||||
(cyrillic-iso8859-5 . cyrillic)
|
||||
(arabic-iso8859-6 . arabic)
|
||||
(greek-iso8859-7 . latin)
|
||||
(hebrew-iso8859-8 . latin)
|
||||
(greek-iso8859-7 . greek)
|
||||
(hebrew-iso8859-8 . hebrew)
|
||||
(katakana-jisx0201 . kana)
|
||||
(chinese-gb2312 . han)
|
||||
(chinese-gbk . han)
|
||||
|
|
|
@ -300,8 +300,7 @@ wrong, use this command again to toggle back to the right mode."
|
|||
(cmd (key-binding keyseq))
|
||||
prefix)
|
||||
;; read-key-sequence ignores quit, so make an explicit check.
|
||||
;; Like many places, this assumes quit == C-g, but it need not be.
|
||||
(if (equal last-input-event ?\C-g)
|
||||
(if (equal last-input-event (nth 3 (current-input-mode)))
|
||||
(keyboard-quit))
|
||||
(when (memq cmd '(universal-argument digit-argument))
|
||||
(call-interactively cmd)
|
||||
|
@ -314,16 +313,16 @@ wrong, use this command again to toggle back to the right mode."
|
|||
(let ((current-prefix-arg prefix-arg)
|
||||
;; Have to bind `last-command-event' here so that
|
||||
;; `digit-argument', for instance, can compute the
|
||||
;; prefix arg.
|
||||
;; `prefix-arg'.
|
||||
(last-command-event (aref keyseq 0)))
|
||||
(call-interactively cmd)))
|
||||
|
||||
;; This is the final call to `universal-argument-other-key', which
|
||||
;; set's the final `prefix-arg.
|
||||
;; sets the final `prefix-arg'.
|
||||
(let ((current-prefix-arg prefix-arg))
|
||||
(call-interactively cmd))
|
||||
|
||||
;; Read the command to execute with the given prefix arg.
|
||||
;; Read the command to execute with the given `prefix-arg'.
|
||||
(setq prefix prefix-arg
|
||||
keyseq (read-key-sequence nil t)
|
||||
cmd (key-binding keyseq)))
|
||||
|
|
|
@ -201,6 +201,7 @@
|
|||
;; plus nbsp
|
||||
(define-iso-single-byte-charset 'iso-8859-11 'thai-iso8859-11
|
||||
"ISO/IEC 8859/11" "Latin/Thai" 166 ?T nil "8859-11")
|
||||
(define-charset-alias 'tis620-2533 'thai-iso8859-11)
|
||||
|
||||
;; 8859-12 doesn't (yet?) exist.
|
||||
|
||||
|
@ -229,14 +230,6 @@
|
|||
:code-space [32 127]
|
||||
:code-offset #x0E00)
|
||||
|
||||
;; Fixme: doc for this, c.f. above
|
||||
(define-charset 'tis620-2533
|
||||
"TIS620.2533"
|
||||
:short-name "TIS620.2533"
|
||||
:ascii-compatible-p t
|
||||
:code-space [0 255]
|
||||
:superset '(ascii eight-bit-control (thai-tis620 . 128)))
|
||||
|
||||
(define-charset 'jisx0201
|
||||
"JISX0201"
|
||||
:short-name "JISX0201"
|
||||
|
|
|
@ -355,7 +355,8 @@ meanings of these arguments."
|
|||
(:iso-revision-number "ISO revision number: "
|
||||
number-to-string)
|
||||
(:supplementary-p
|
||||
"Used only as a parent of some other charset." nil)))
|
||||
"Used only as a parent or a subset of some other charset,
|
||||
or provided just for backward compatibility." nil)))
|
||||
(let ((val (get-charset-property charset (car elt))))
|
||||
(when val
|
||||
(if (cadr elt) (insert (cadr elt)))
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue